Cleanup references in static mode
[mono.git] / mcs / mcs / ikvm.cs
1 //
2 // ikvm.cs: IKVM.Reflection and IKVM.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 MetaType = IKVM.Reflection.Type;
15 using IKVM.Reflection;
16 using IKVM.Reflection.Emit;
17 using System.IO;
18 using System.Configuration.Assemblies;
19
20 namespace Mono.CSharp
21 {
22 #if !STATIC
23         public class StaticImporter
24         {
25                 public StaticImporter (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 void ImportModule (Module module, RootNamespace targetNamespace)
36                 {
37                         throw new NotSupportedException ();
38                 }
39
40                 public TypeSpec ImportType (System.Type type)
41                 {
42                         throw new NotSupportedException ();
43                 }
44         }
45
46 #else
47
48         sealed class StaticImporter : MetadataImporter
49         {
50                 public StaticImporter ()
51                 {
52                 }
53
54                 protected override MemberKind DetermineKindFromBaseType (MetaType baseType)
55                 {
56                         string name = baseType.Name;
57
58                         // TODO: namespace check
59                         if (name == "ValueType")
60                                 return MemberKind.Struct;
61
62                         if (name == "Enum")
63                                 return MemberKind.Enum;
64
65                         if (name == "MulticastDelegate")
66                                 return MemberKind.Delegate;
67
68                         return MemberKind.Class;
69                 }
70
71                 protected override bool HasVolatileModifier (MetaType[] modifiers)
72                 {
73                         foreach (var t in modifiers) {
74                                 if (t.Name == "IsVolatile" && t.Namespace == CompilerServicesNamespace)
75                                         return true;
76                         }
77
78                         return false;
79                 }
80
81                 public override void GetCustomAttributeTypeName (CustomAttributeData cad, out string typeNamespace, out string typeName)
82                 {
83                         cad.__ReadTypeName (out typeNamespace, out typeName);
84                 }
85
86                 public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace)
87                 {
88                         // It can be used more than once when importing same assembly
89                         // into 2 or more global aliases
90                         var definition = GetAssemblyDefinition (assembly);
91
92                         var all_types = assembly.GetTypes ();
93                         ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod);
94                 }
95
96                 public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace)
97                 {
98                         var module_definition = new ImportedModuleDefinition (module, this);
99                         module_definition.ReadAttributes ();
100
101                         var all_types = module.GetTypes ();
102                         ImportTypes (all_types, targetNamespace, false);
103
104                         return module_definition;
105                 }
106
107                 public void InitializeBuildinTypes (BuildinTypes buildin, Assembly corlib)
108                 {
109                         //
110                         // Setup mapping for build-in types to avoid duplication of their definition
111                         //
112                         foreach (var type in buildin.AllTypes) {
113                                 buildin_types.Add (corlib.GetType (type.FullName), type);
114                         }
115                 }
116         }
117 #endif
118
119         class AssemblyDefinitionStatic : AssemblyDefinition
120         {
121                 //
122                 // Assembly container with file output
123                 //
124                 public AssemblyDefinitionStatic (ModuleContainer module, string name, string fileName)
125                         : base (module, name, fileName)
126                 {
127                 }
128
129                 //
130                 // Initializes the code generator
131                 //
132                 public bool Create (Universe domain)
133                 {
134                         ResolveAssemblySecurityAttributes ();
135                         var an = CreateAssemblyName ();
136
137                         Builder = domain.DefineDynamicAssembly (an, AssemblyBuilderAccess.Save, Path.GetDirectoryName (file_name));
138
139                         // Sets output file metadata version, this makes sense for mscorlib
140                         // compilation only but won't restrict that for now
141                         switch (RootContext.StdLibRuntimeVersion){
142                         case RuntimeVersion.v4:
143                                 Builder.__SetImageRuntimeVersion ("v4.0.30319", 0x20000);
144                                 break;
145                         case RuntimeVersion.v2:
146                                 Builder.__SetImageRuntimeVersion ("v2.0.50727", 0x20000);
147                                 break;
148                         case RuntimeVersion.v1:
149                                 // Compiler does not do any checks whether the produced metadata
150                                 // are valid in the context of 1.0 stream version
151                                 Builder.__SetImageRuntimeVersion ("v1.1.4322", 0x10000);
152                                 break;
153                         default:
154                                 throw new NotImplementedException ();
155                         }
156
157                         builder_extra = new AssemblyBuilderIKVM (Builder, Compiler);
158                         return true;
159                 }
160
161                 public Module IncludeModule (RawModule moduleFile)
162                 {
163                         return Builder.__AddModule (moduleFile);
164                 }
165
166                 protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine)
167                 {
168                         module.Builder.__Save (pekind, machine);
169                 }
170         }
171
172         class StaticLoader : AssemblyReferencesLoader<Assembly>, IDisposable
173         {
174                 readonly StaticImporter importer;
175                 readonly Universe domain;
176                 Assembly corlib;
177
178                 public StaticLoader (StaticImporter importer, CompilerContext compiler)
179                         : base (compiler)
180                 {
181                         this.importer = importer;
182                         domain = new Universe ();
183                         domain.AssemblyResolve += AssemblyReferenceResolver;
184
185                         // TODO: profile specific
186                         paths.Add (Path.GetDirectoryName (typeof (object).Assembly.Location));
187                 }
188
189                 public Assembly Corlib {
190                         get {
191                                 return corlib;
192                         }
193                         set {
194                                 corlib = value;
195                         }
196                 }
197
198                 public Universe Domain {
199                         get {
200                                 return domain;
201                         }
202                 }
203
204                 Assembly AssemblyReferenceResolver (object sender, IKVM.Reflection.ResolveEventArgs args)
205                 {
206                         if (args.Name == "mscorlib")
207                                 return corlib;
208
209                         // AssemblyReference has not been found in the domain
210                         // create missing reference and continue
211                         return new MissingAssembly (domain, args.Name);
212                 }
213
214                 public void Dispose ()
215                 {
216                         domain.Dispose ();
217                 }
218
219                 protected override string[] GetDefaultReferences ()
220                 {
221                         //
222                         // For now the "default config" is harcoded into the compiler
223                         // we can move this outside later
224                         //
225                         var default_references = new List<string> (4);
226
227                         default_references.Add ("System.dll");
228                         default_references.Add ("System.Xml.dll");
229
230                         if (RootContext.Version > LanguageVersion.ISO_2)
231                                 default_references.Add ("System.Core.dll");
232                         if (RootContext.Version > LanguageVersion.V_3)
233                                 default_references.Add ("Microsoft.CSharp.dll");
234
235                         return default_references.ToArray ();
236                 }
237
238                 public override bool HasObjectType (Assembly assembly)
239                 {
240                         return assembly.GetType (compiler.BuildinTypes.Object.FullName) != null;
241                 }
242
243                 public override Assembly LoadAssemblyFile (string fileName)
244                 {
245                         bool? has_extension = null;
246                         foreach (var path in paths) {
247                                 var file = Path.Combine (path, fileName);
248                                 if (!File.Exists (file)) {
249                                         if (!has_extension.HasValue)
250                                                 has_extension = fileName.EndsWith (".dll", StringComparison.Ordinal) || fileName.EndsWith (".exe", StringComparison.Ordinal);
251
252                                         if (has_extension.Value)
253                                                 continue;
254
255                                         file += ".dll";
256                                         if (!File.Exists (file))
257                                                 continue;
258                                 }
259
260                                 try {
261                                         using (RawModule module = domain.OpenRawModule (file)) {
262                                                 if (!module.IsManifestModule) {
263                                                         Error_AssemblyIsModule (fileName);
264                                                         return null;
265                                                 }
266
267                                                 return domain.LoadAssembly (module);
268                                         }
269                                 } catch {
270                                         Error_FileCorrupted (file);
271                                         return null;
272                                 }
273                         }
274
275                         Error_FileNotFound (fileName);
276                         return null;
277                 }
278
279                 public RawModule LoadModuleFile (string moduleName)
280                 {
281                         foreach (var path in paths) {
282                                 var file = Path.Combine (path, moduleName);
283                                 if (!File.Exists (file)) {
284                                         if (moduleName.EndsWith (".netmodule", StringComparison.Ordinal))
285                                                 continue;
286
287                                         file += ".netmodule";
288                                         if (!File.Exists (file))
289                                                 continue;
290                                 }
291
292                                 try {
293                                         return domain.OpenRawModule (file);
294                                 } catch {
295                                         Error_FileCorrupted (file);
296                                         return null;
297                                 }
298                         }
299
300                         Error_FileNotFound (moduleName);
301                         return null;                            
302                 }
303
304                 //
305                 // Optimized default assembly loader version
306                 //
307                 public override Assembly LoadAssemblyDefault (string assembly)
308                 {
309                         foreach (var path in paths) {
310                                 var file = Path.Combine (path, assembly);
311                                 if (!File.Exists (file))
312                                         continue;
313
314                                 try {
315                                         return domain.LoadFile (file);
316                                 } catch {
317                                         // Default assemblies can fail to load without error
318                                         return null;
319                                 }
320                         }
321
322                         return null;
323                 }
324
325                 public override void LoadReferences (ModuleContainer module)
326                 {
327                         List<Tuple<RootNamespace, Assembly>> loaded;
328                         base.LoadReferencesCore (module, out corlib, out loaded);
329
330                         if (corlib != null) {
331                                 importer.InitializeBuildinTypes (compiler.BuildinTypes, corlib);
332                                 importer.ImportAssembly (corlib, module.GlobalRootNamespace);
333                         }
334
335                         foreach (var entry in loaded) {
336                                 importer.ImportAssembly (entry.Item2, entry.Item1);
337                         }
338                 }
339
340                 public void LoadModules (AssemblyDefinitionStatic assembly, RootNamespace targetNamespace)
341                 {
342                         if (RootContext.Modules.Count == 0)
343                                 return;
344
345                         foreach (var moduleName in RootContext.Modules) {
346                                 var m = LoadModuleFile (moduleName);
347                                 if (m == null)
348                                         continue;
349
350                                 if (m.IsManifestModule) {
351                                         Error_FileCorrupted (moduleName);
352                                         continue;
353                                 }
354
355                                 var md = importer.ImportModule (assembly.IncludeModule (m), targetNamespace);
356                                 assembly.AddModule (md);
357                         }
358                 }
359         }
360
361         //
362         // Represents missing assembly reference
363         //
364         class MissingAssembly : Assembly
365         {
366                 class MissingModule : Module
367                 {
368                         readonly Assembly assembly;
369
370                         public MissingModule (Universe universe, Assembly assembly)
371                                 : base (universe)
372                         {
373                                 this.assembly = assembly;
374                         }
375
376                         public override int MDStreamVersion {
377                                 get {
378                                         throw new NotImplementedException ();
379                                 }
380                         }
381
382                         public override Assembly Assembly {
383                                 get {
384                                         return assembly;
385                                 }
386                         }
387
388                         public override string FullyQualifiedName {
389                                 get {
390                                         throw new NotImplementedException ();
391                                 }
392                         }
393
394                         public override string Name {
395                                 get {
396                                         throw new NotImplementedException ();
397                                 }
398                         }
399
400                         public override Guid ModuleVersionId {
401                                 get {
402                                         throw new NotImplementedException ();
403                                 }
404                         }
405
406                         public override MetaType ResolveType (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
407                         {
408                                 throw new NotImplementedException ();
409                         }
410
411                         public override MethodBase ResolveMethod (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
412                         {
413                                 throw new NotImplementedException ();
414                         }
415
416                         public override FieldInfo ResolveField (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
417                         {
418                                 throw new NotImplementedException ();
419                         }
420
421                         public override MemberInfo ResolveMember (int metadataToken, MetaType[] genericTypeArguments, MetaType[] genericMethodArguments)
422                         {
423                                 throw new NotImplementedException ();
424                         }
425
426                         public override string ResolveString (int metadataToken)
427                         {
428                                 throw new NotImplementedException ();
429                         }
430
431                         public override MetaType[] __ResolveOptionalParameterTypes (int metadataToken)
432                         {
433                                 throw new NotImplementedException ();
434                         }
435
436                         public override string ScopeName {
437                                 get {
438                                         throw new NotImplementedException ();
439                                 }
440                         }
441
442                         internal override MetaType GetTypeImpl (string typeName)
443                         {
444                                 throw new NotImplementedException ();
445                         }
446
447                         internal override void GetTypesImpl (List<MetaType> list)
448                         {
449                                 throw new NotImplementedException ();
450                         }
451
452                         public override AssemblyName[] __GetReferencedAssemblies ()
453                         {
454                                 throw new NotImplementedException ();
455                         }
456
457                         internal override MetaType GetModuleType ()
458                         {
459                                 throw new NotImplementedException ();
460                         }
461
462                         internal override IKVM.Reflection.Reader.ByteReader GetBlob (int blobIndex)
463                         {
464                                 throw new NotImplementedException ();
465                         }
466                 }
467
468                 readonly string full_name;
469                 readonly Module module;
470                 Dictionary<string, MetaType> types;
471
472                 public MissingAssembly (Universe universe, string fullName)
473                         : base (universe)
474                 {
475                         this.full_name = fullName;
476                         this.module = new MissingModule (universe, this);
477                         types = new Dictionary<string, MetaType> ();
478                 }
479
480                 public override MetaType[] GetTypes ()
481                 {
482                         throw new NotImplementedException ();
483                 }
484
485                 public override string FullName {
486                         get {
487                                 return full_name;
488                         }
489                 }
490
491                 public override AssemblyName GetName ()
492                 {
493                         throw new NotImplementedException ();
494                 }
495
496                 public override string ImageRuntimeVersion {
497                         get {
498                                 throw new NotImplementedException ();
499                         }
500                 }
501
502                 public override Module ManifestModule {
503                         get {
504                                 return module;
505                         }
506                 }
507
508                 public override MethodInfo EntryPoint {
509                         get {
510                                 throw new NotImplementedException ();
511                         }
512                 }
513
514                 public override string Location {
515                         get {
516                                 throw new NotImplementedException ();
517                         }
518                 }
519
520                 public override AssemblyName[] GetReferencedAssemblies ()
521                 {
522                         throw new NotImplementedException ();
523                 }
524
525                 public override Module[] GetModules (bool getResourceModules)
526                 {
527                         throw new NotImplementedException ();
528                 }
529
530                 public override Module[] GetLoadedModules (bool getResourceModules)
531                 {
532                         throw new NotImplementedException ();
533                 }
534
535                 public override Module GetModule (string name)
536                 {
537                         throw new NotImplementedException ();
538                 }
539
540                 public override string[] GetManifestResourceNames ()
541                 {
542                         throw new NotImplementedException ();
543                 }
544
545                 public override ManifestResourceInfo GetManifestResourceInfo (string resourceName)
546                 {
547                         throw new NotImplementedException ();
548                 }
549
550                 public override Stream GetManifestResourceStream (string resourceName)
551                 {
552                         throw new NotImplementedException ();
553                 }
554
555                 internal override MetaType GetTypeImpl (string typeName)
556                 {
557                         //
558                         // We are loading a type from missing reference
559                         // this itself is fine. The error will be reported
560                         // later when the type is actually used
561                         //
562                         MetaType t;
563                         if (!types.TryGetValue (typeName, out t)) {
564                                 t = new MissingType (typeName, this);
565                                 types.Add (typeName, t);
566                         }
567
568                         return t;
569                 }
570
571                 internal override IList<CustomAttributeData> GetCustomAttributesData (MetaType attributeType)
572                 {
573                         throw new NotImplementedException ();
574                 }
575         }
576
577         class MissingType : MetaType
578         {
579                 readonly string full_name;
580                 readonly MissingAssembly assembly;
581
582                 public MissingType (string typeName, MissingAssembly assembly)
583                 {
584                         this.full_name = typeName;
585                         this.assembly = assembly;
586                 }
587
588                 public override TypeAttributes Attributes {
589                         get {
590                                 // TODO: Don't know yet
591                                 return TypeAttributes.Public;
592                         }
593                 }
594
595                 public override MetaType BaseType {
596                         get {
597                                 return null;
598                         }
599                 }
600
601                 public override string FullName {
602                         get {
603                                 return full_name;
604                         }
605                 }
606
607                 internal override MetaType GetGenericTypeArgument (int index)
608                 {
609                         return new MissingType ("#" + index.ToString (), assembly);
610                 }
611
612                 public override bool IsGenericTypeDefinition {
613                         get {
614                                 return full_name.IndexOf ('`') > 0;
615                         }
616                 }
617
618                 public override Module Module {
619                         get {
620                                 return assembly.ManifestModule;
621                         }
622                 }
623         }
624
625         class AssemblyBuilderIKVM : AssemblyBuilderExtension
626         {
627                 readonly AssemblyBuilder builder;
628
629                 public AssemblyBuilderIKVM (AssemblyBuilder builder, CompilerContext ctx)
630                         : base (ctx)
631                 {
632                         this.builder = builder;
633                 }
634
635                 public override void AddTypeForwarder (TypeSpec type, Location loc)
636                 {
637                         builder.__AddTypeForwarder (type.GetMetaInfo ());
638                 }
639
640                 public override void DefineWin32IconResource (string fileName)
641                 {
642                         builder.__DefineIconResource (File.ReadAllBytes (fileName));
643                 }
644
645                 public override void SetAlgorithmId (uint value, Location loc)
646                 {
647                         builder.__SetAssemblyAlgorithmId ((AssemblyHashAlgorithm) value);
648                 }
649
650                 public override void SetCulture (string culture, Location loc)
651                 {
652                         builder.__SetAssemblyCulture (culture);
653                 }
654
655                 public override void SetFlags (uint flags, Location loc)
656                 {
657                         builder.__SetAssemblyFlags ((AssemblyNameFlags) flags);
658                 }
659
660                 public override void SetVersion (Version version, Location loc)
661                 {
662                         builder.__SetAssemblyVersion (version);
663                 }
664         }
665 }