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