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