Merge pull request #5668 from kumpera/wasm-work-p4
[mono.git] / mcs / mcs / reflection.cs
1 //
2 // reflection.cs: System.Reflection and System.Reflection.Emit specific implementations
3 //
4 // Author: Marek Safar (marek.safar@gmail.com)
5 //
6 // Dual licensed under the terms of the MIT X11 or GNU GPL
7 //
8 // Copyright 2009-2010 Novell, Inc. 
9 //
10 //
11
12 using System;
13 using System.Collections.Generic;
14 using System.Reflection;
15 using System.IO;
16 using System.Runtime.CompilerServices;
17 using System.Reflection.Emit;
18 using System.Security;
19
20 namespace Mono.CSharp
21 {
22 #if STATIC
23         public class ReflectionImporter
24         {
25                 public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin)
26                 {
27                         throw new NotSupportedException ();
28                 }
29
30                 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
31                 {
32                         throw new NotSupportedException ();
33                 }
34
35                 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
36                 {
37                         throw new NotSupportedException ();
38                 }
39
40                 public TypeSpec ImportType (Type type)
41                 {
42                         throw new NotSupportedException ();
43                 }
44         }
45 #else
46         public sealed class ReflectionImporter : MetadataImporter
47         {
48                 public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin)
49                         : base (module)
50                 {
51                         IgnoreCompilerGeneratedField = false;
52
53                         Initialize (builtin);
54                 }
55
56                 public override void AddCompiledType (TypeBuilder builder, TypeSpec spec)
57                 {
58                 }
59
60                 protected override MemberKind DetermineKindFromBaseType (Type baseType)
61                 {
62                         if (baseType == typeof (ValueType))
63                                 return MemberKind.Struct;
64
65                         if (baseType == typeof (System.Enum))
66                                 return MemberKind.Enum;
67
68                         if (baseType == typeof (MulticastDelegate))
69                                 return MemberKind.Delegate;
70
71                         return MemberKind.Class;
72                 }
73
74                 protected override bool HasVolatileModifier (Type[] modifiers)
75                 {
76                         foreach (var t in modifiers) {
77                                 if (t == typeof (IsVolatile))
78                                         return true;
79                         }
80
81                         return false;
82                 }
83
84                 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
85                 {
86                         // It can be used more than once when importing same assembly
87                         // into 2 or more global aliases
88                 GetAssemblyDefinition (assembly);
89
90                         //
91                         // This part tries to simulate loading of top-level
92                         // types only, any missing dependencies are ignores here.
93                         // Full error report is reported later when the type is
94                         // actually used
95                         //
96                         Type[] all_types;
97                         try {
98                                 all_types = assembly.GetTypes ();
99                         } catch (ReflectionTypeLoadException e) {
100                                 all_types = e.Types;
101                         }
102
103                         ImportTypes (all_types, targetNamespace, true);
104                 }
105
106                 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
107                 {
108                         var module_definition = new ImportedModuleDefinition (module);
109                         module_definition.ReadAttributes ();
110
111                         Type[] all_types;
112                         try {
113                                 all_types = module.GetTypes ();
114                         } catch (ReflectionTypeLoadException e) {
115                                 all_types = e.Types;
116                         }
117
118                         ImportTypes (all_types, targetNamespace, false);
119
120                         return module_definition;
121                 }
122
123                 void Initialize (BuiltinTypes builtin)
124                 {
125                         //
126                         // Setup mapping for build-in types to avoid duplication of their definition
127                         //
128                         compiled_types.Add (typeof (object), builtin.Object);
129                         compiled_types.Add (typeof (System.ValueType), builtin.ValueType);
130                         compiled_types.Add (typeof (System.Attribute), builtin.Attribute);
131
132                         compiled_types.Add (typeof (int), builtin.Int);
133                         compiled_types.Add (typeof (long), builtin.Long);
134                         compiled_types.Add (typeof (uint), builtin.UInt);
135                         compiled_types.Add (typeof (ulong), builtin.ULong);
136                         compiled_types.Add (typeof (byte), builtin.Byte);
137                         compiled_types.Add (typeof (sbyte), builtin.SByte);
138                         compiled_types.Add (typeof (short), builtin.Short);
139                         compiled_types.Add (typeof (ushort), builtin.UShort);
140
141                         compiled_types.Add (typeof (System.Collections.IEnumerator), builtin.IEnumerator);
142                         compiled_types.Add (typeof (System.Collections.IEnumerable), builtin.IEnumerable);
143                         compiled_types.Add (typeof (System.IDisposable), builtin.IDisposable);
144
145                         compiled_types.Add (typeof (char), builtin.Char);
146                         compiled_types.Add (typeof (string), builtin.String);
147                         compiled_types.Add (typeof (float), builtin.Float);
148                         compiled_types.Add (typeof (double), builtin.Double);
149                         compiled_types.Add (typeof (decimal), builtin.Decimal);
150                         compiled_types.Add (typeof (bool), builtin.Bool);
151                         compiled_types.Add (typeof (System.IntPtr), builtin.IntPtr);
152                         compiled_types.Add (typeof (System.UIntPtr), builtin.UIntPtr);
153
154                         compiled_types.Add (typeof (System.MulticastDelegate), builtin.MulticastDelegate);
155                         compiled_types.Add (typeof (System.Delegate), builtin.Delegate);
156                         compiled_types.Add (typeof (System.Enum), builtin.Enum);
157                         compiled_types.Add (typeof (System.Array), builtin.Array);
158                         compiled_types.Add (typeof (void), builtin.Void);
159                         compiled_types.Add (typeof (System.Type), builtin.Type);
160                         compiled_types.Add (typeof (System.Exception), builtin.Exception);
161                         compiled_types.Add (typeof (System.RuntimeFieldHandle), builtin.RuntimeFieldHandle);
162                         compiled_types.Add (typeof (System.RuntimeTypeHandle), builtin.RuntimeTypeHandle);
163                 }
164         }
165
166         [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Explicit)]
167         struct SingleConverter
168         {
169                 [System.Runtime.InteropServices.FieldOffset (0)]
170                 int i;
171
172 #pragma warning disable 414
173                 [System.Runtime.InteropServices.FieldOffset (0)]
174                 float f;
175 #pragma warning restore 414
176
177                 public static int SingleToInt32Bits (float v)
178                 {
179                         SingleConverter c = new SingleConverter ();
180                         c.f = v;
181                         return c.i;
182                 }
183         }
184
185 #endif
186
187         public class AssemblyDefinitionDynamic : AssemblyDefinition
188         {
189                 //
190                 // In-memory only assembly container
191                 //
192                 public AssemblyDefinitionDynamic (ModuleContainer module, string name)
193                         : base (module, name)
194                 {
195                 }
196
197                 //
198                 // Assembly container with file output
199                 //
200                 public AssemblyDefinitionDynamic (ModuleContainer module, string name, string fileName)
201                         : base (module, name, fileName)
202                 {
203                 }
204
205                 public Module IncludeModule (string moduleFile)
206                 {
207                         return builder_extra.AddModule (moduleFile);
208                 }
209
210 #if !STATIC
211                 public override ModuleBuilder CreateModuleBuilder ()
212                 {
213                         if (file_name == null)
214                                 return Builder.DefineDynamicModule (Name, false);
215
216                         return base.CreateModuleBuilder ();
217                 }
218 #endif
219                 //
220                 // Initializes the code generator
221                 //
222                 public bool Create (AppDomain domain, AssemblyBuilderAccess access)
223                 {
224 #if STATIC || FULL_AOT_RUNTIME
225                         throw new NotSupportedException ();
226 #else
227                         ResolveAssemblySecurityAttributes ();
228                         var an = CreateAssemblyName ();
229
230                         Builder = file_name == null ?
231                                 domain.DefineDynamicAssembly (an, access) :
232                                 domain.DefineDynamicAssembly (an, access, Dirname (file_name));
233
234                         module.Create (this, CreateModuleBuilder ());
235                         builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler);
236                         return true;
237 #endif
238                 }
239
240                 static string Dirname (string name)
241                 {
242                         int pos = name.LastIndexOf ('/');
243
244                         if (pos != -1)
245                                 return name.Substring (0, pos);
246
247                         pos = name.LastIndexOf ('\\');
248                         if (pos != -1)
249                                 return name.Substring (0, pos);
250
251                         return ".";
252                 }
253
254 #if !STATIC
255                 protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
256                 {
257                         try {
258                                 var module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
259                                 var set_module_only = module_only.GetSetMethod (true);
260
261                                 set_module_only.Invoke (Builder, new object[] { true });
262                         } catch {
263                                 base.SaveModule (pekind, machine);
264                         }
265
266                         Builder.Save (file_name, pekind, machine);
267                 }
268 #endif
269         }
270
271         //
272         // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible
273         // compiler
274         //
275         class AssemblyBuilderMonoSpecific : AssemblyBuilderExtension
276         {
277                 static MethodInfo adder_method;
278                 static MethodInfo add_permission;
279                 static MethodInfo add_type_forwarder;
280                 static MethodInfo win32_icon_define;
281                 static FieldInfo assembly_version;
282                 static FieldInfo assembly_algorithm;
283                 static FieldInfo assembly_culture;
284                 static FieldInfo assembly_flags;
285
286                 AssemblyBuilder builder;
287
288                 public AssemblyBuilderMonoSpecific (AssemblyBuilder ab, CompilerContext ctx)
289                         : base (ctx)
290                 {
291                         this.builder = ab;
292                 }
293
294                 public override Module AddModule (string module)
295                 {
296                         try {
297                                 if (adder_method == null)
298                                         adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance | BindingFlags.NonPublic);
299
300                                 return (Module) adder_method.Invoke (builder, new object[] { module });
301                         } catch {
302                                 return base.AddModule (module);
303                         }
304                 }
305
306                 public override void AddPermissionRequests (PermissionSet[] permissions)
307                 {
308                         try {
309                                 if (add_permission == null)
310                                         add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
311
312                                 add_permission.Invoke (builder, permissions);
313                         } catch {
314                                 base.AddPermissionRequests (permissions);
315                         }
316                 }
317
318                 public override void AddTypeForwarder (TypeSpec type, Location loc)
319                 {
320                         try {
321                                 if (add_type_forwarder == null) {
322                                         add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder", BindingFlags.NonPublic | BindingFlags.Instance);
323                                 }
324
325                                 add_type_forwarder.Invoke (builder, new object[] { type.GetMetaInfo () });
326                         } catch {
327                                 base.AddTypeForwarder (type, loc);
328                         }
329                 }
330
331                 public override void DefineWin32IconResource (string fileName)
332                 {
333                         try {
334                                 if (win32_icon_define == null)
335                                         win32_icon_define = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.NonPublic);
336
337                                 win32_icon_define.Invoke (builder, new object[] { fileName });
338                         } catch {
339                                 base.DefineWin32IconResource (fileName);
340                         }
341                 }
342
343                 public override void SetAlgorithmId (uint value, Location loc)
344                 {
345                         try {
346                                 if (assembly_algorithm == null)
347                                         assembly_algorithm = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
348
349                                 assembly_algorithm.SetValue (builder, value);
350                         } catch {
351                                 base.SetAlgorithmId (value, loc);
352                         }
353                 }
354
355                 public override void SetCulture (string culture, Location loc)
356                 {
357                         try {
358                                 if (assembly_culture == null)
359                                         assembly_culture = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
360
361                                 assembly_culture.SetValue (builder, culture);
362                         } catch {
363                                 base.SetCulture (culture, loc);
364                         }
365                 }
366
367                 public override void SetFlags (uint flags, Location loc)
368                 {
369                         try {
370                                 if (assembly_flags == null)
371                                         assembly_flags = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
372
373                                 assembly_flags.SetValue (builder, flags);
374                         } catch {
375                                 base.SetFlags (flags, loc);
376                         }
377                 }
378
379                 public override void SetVersion (Version version, Location loc)
380                 {
381                         try {
382                                 if (assembly_version == null)
383                                         assembly_version = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField);
384
385                                 assembly_version.SetValue (builder, version.ToString (4));
386                         } catch {
387                                 base.SetVersion (version, loc);
388                         }
389                 }
390         }
391
392         //
393         // Reflection based references loader
394         //
395         class DynamicLoader : AssemblyReferencesLoader<Assembly>
396         {
397                 readonly ReflectionImporter importer;
398
399                 public DynamicLoader (ReflectionImporter importer, CompilerContext compiler)
400                         : base (compiler)
401                 {
402                         paths.Add (GetSystemDir ());
403
404                         this.importer = importer;
405                 }
406
407                 public ReflectionImporter Importer {
408                         get {
409                                 return importer;
410                         }
411                 }
412
413                 protected override string[] GetDefaultReferences ()
414                 {
415                         //
416                         // For now the "default config" is harcoded into the compiler
417                         // we can move this outside later
418                         //
419                         var default_references = new List<string> (8);
420
421                         default_references.Add ("System");
422                         default_references.Add ("System.Xml");
423 #if MOBILE
424                         default_references.Add ("System.Net");
425                         default_references.Add ("System.Windows");
426                         default_references.Add ("System.Windows.Browser");
427 #endif
428
429                         if (compiler.Settings.Version > LanguageVersion.ISO_2)
430                                 default_references.Add ("System.Core");
431                         if (compiler.Settings.Version > LanguageVersion.V_3)
432                                 default_references.Add ("Microsoft.CSharp");
433
434                         return default_references.ToArray ();
435                 }
436
437                 //
438                 // Returns the directory where the system assemblies are installed
439                 //
440                 static string GetSystemDir ()
441                 {
442                         return Path.GetDirectoryName (typeof (object).Assembly.Location);
443                 }
444
445                 public override Assembly HasObjectType (Assembly assembly)
446                 {
447                         return assembly.GetType (compiler.BuiltinTypes.Object.FullName) == null ? null : assembly;
448                 }
449
450                 public override Assembly LoadAssemblyFile (string assembly, bool isImplicitReference)
451                 {
452                         Assembly a = null;
453
454                         try {
455                                 try {
456                                         char[] path_chars = { '/', '\\' };
457
458                                         if (assembly.IndexOfAny (path_chars) != -1) {
459                                                 a = Assembly.LoadFrom (assembly);
460                                         } else {
461                                                 string ass = assembly;
462                                                 if (ass.EndsWith (".dll") || ass.EndsWith (".exe"))
463                                                         ass = assembly.Substring (0, assembly.Length - 4);
464                                                 a = Assembly.Load (ass);
465                                         }
466                                 } catch (FileNotFoundException) {
467                                         bool err = !isImplicitReference;
468                                         foreach (string dir in paths) {
469                                                 string full_path = Path.Combine (dir, assembly);
470                                                 if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
471                                                         full_path += ".dll";
472
473                                                 try {
474                                                         a = Assembly.LoadFrom (full_path);
475                                                         err = false;
476                                                         break;
477                                                 } catch (FileNotFoundException) {
478                                                 }
479                                         }
480
481                                         if (err) {
482                                                 Error_FileNotFound (assembly);
483                                                 return a;
484                                         }
485                                 }
486                         } catch (BadImageFormatException) {
487                                 Error_FileCorrupted (assembly);
488                         }
489
490                         return a;
491                 }
492
493                 Module LoadModuleFile (AssemblyDefinitionDynamic assembly, string module)
494                 {
495                         string total_log = "";
496
497                         try {
498                                 try {
499                                         return assembly.IncludeModule (module);
500                                 } catch (FileNotFoundException) {
501                                         bool err = true;
502                                         foreach (string dir in paths) {
503                                                 string full_path = Path.Combine (dir, module);
504                                                 if (!module.EndsWith (".netmodule"))
505                                                         full_path += ".netmodule";
506
507                                                 try {
508                                                         return assembly.IncludeModule (full_path);
509                                                 } catch (FileNotFoundException ff) {
510                                                         total_log += ff.FusionLog;
511                                                 }
512                                         }
513                                         if (err) {
514                                                 Error_FileNotFound (module);
515                                                 return null;
516                                         }
517                                 }
518                         } catch (BadImageFormatException) {
519                                 Error_FileCorrupted (module);
520                         }
521
522                         return null;
523                 }
524
525                 public void LoadModules (AssemblyDefinitionDynamic assembly, RootNamespace targetNamespace)
526                 {
527                         foreach (var moduleName in compiler.Settings.Modules) {
528                                 var m = LoadModuleFile (assembly, moduleName);
529                                 if (m == null)
530                                         continue;
531
532                                 var md = importer.ImportModule (m, targetNamespace);
533                                 assembly.AddModule (md);
534                         }
535                 }
536
537                 public override void LoadReferences (ModuleContainer module)
538                 {
539                         Assembly corlib;
540                         List<Tuple<RootNamespace, Assembly>> loaded;
541                         base.LoadReferencesCore (module, out corlib, out loaded);
542
543                         if (corlib == null)
544                                 return;
545
546                         importer.ImportAssembly (corlib, module.GlobalRootNamespace);
547                         foreach (var entry in loaded) {
548                                 importer.ImportAssembly (entry.Item2, entry.Item1);
549                         }
550                 }
551         }
552 }