Merge pull request #496 from nicolas-raoul/unit-test-for-issue2907
[mono.git] / mcs / class / corlib / System.Reflection.Emit / ModuleBuilder.cs
1
2 //
3 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the
7 // "Software"), to deal in the Software without restriction, including
8 // without limitation the rights to use, copy, modify, merge, publish,
9 // distribute, sublicense, and/or sell copies of the Software, and to
10 // permit persons to whom the Software is furnished to do so, subject to
11 // the following conditions:
12 // 
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
15 // 
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24
25 //
26 // System.Reflection.Emit/ModuleBuilder.cs
27 //
28 // Author:
29 //   Paolo Molaro (lupus@ximian.com)
30 //
31 // (C) 2001 Ximian, Inc.  http://www.ximian.com
32 //
33
34 #if !FULL_AOT_RUNTIME
35 using System;
36 using System.Reflection;
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.Runtime.CompilerServices;
40 using System.Runtime.InteropServices;
41 using System.Diagnostics.SymbolStore;
42 using System.IO;
43 using System.Resources;
44 using System.Globalization;
45
46 namespace System.Reflection.Emit {
47         [ComVisible (true)]
48         [ComDefaultInterface (typeof (_ModuleBuilder))]
49         [ClassInterface (ClassInterfaceType.None)]
50         [StructLayout (LayoutKind.Sequential)]
51         public class ModuleBuilder : Module, _ModuleBuilder {
52
53 #pragma warning disable 169, 414
54                 #region Sync with object-internals.h
55                 private UIntPtr dynamic_image; /* GC-tracked */
56                 private int num_types;
57                 private TypeBuilder[] types;
58                 private CustomAttributeBuilder[] cattrs;
59                 private byte[] guid;
60                 private int table_idx;
61                 internal AssemblyBuilder assemblyb;
62                 private MethodBuilder[] global_methods;
63                 private FieldBuilder[] global_fields;
64                 bool is_main;
65                 private MonoResource[] resources;
66                 #endregion
67 #pragma warning restore 169, 414
68                 
69                 private TypeBuilder global_type;
70                 private Type global_type_created;
71                 Hashtable name_cache;
72                 Dictionary<string, int> us_string_cache;
73                 private int[] table_indexes;
74                 bool transient;
75                 ModuleBuilderTokenGenerator token_gen;
76                 Hashtable resource_writers;
77                 ISymbolWriter symbolWriter;
78
79                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
80                 private static extern void basic_init (ModuleBuilder ab);
81
82                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
83                 private static extern void set_wrappers_type (ModuleBuilder mb, Type ab);
84
85                 internal ModuleBuilder (AssemblyBuilder assb, string name, string fullyqname, bool emitSymbolInfo, bool transient) {
86                         this.name = this.scopename = name;
87                         this.fqname = fullyqname;
88                         this.assembly = this.assemblyb = assb;
89                         this.transient = transient;
90                         // to keep mcs fast we do not want CryptoConfig wo be involved to create the RNG
91                         guid = Guid.FastNewGuidArray ();
92                         // guid = Guid.NewGuid().ToByteArray ();
93                         table_idx = get_next_table_index (this, 0x00, true);
94                         name_cache = new Hashtable ();
95                         us_string_cache = new Dictionary<string, int> (512);
96
97                         basic_init (this);
98
99                         CreateGlobalType ();
100
101                         if (assb.IsRun) {
102                                 TypeBuilder tb = new TypeBuilder (this, TypeAttributes.Abstract, 0xFFFFFF); /*last valid token*/
103                                 Type type = tb.CreateType ();
104                                 set_wrappers_type (this, type);
105                         }
106
107                         if (emitSymbolInfo) {
108 #if MOONLIGHT
109                                 symbolWriter = new Mono.CompilerServices.SymbolWriter.SymbolWriterImpl (this);
110 #else
111                                 Assembly asm = Assembly.LoadWithPartialName ("Mono.CompilerServices.SymbolWriter");
112                                 if (asm == null)
113                                         throw new TypeLoadException ("The assembly for default symbol writer cannot be loaded");
114
115                                 Type t = asm.GetType ("Mono.CompilerServices.SymbolWriter.SymbolWriterImpl", true);
116                                 symbolWriter = (ISymbolWriter) Activator.CreateInstance (t, new object[] { this });
117 #endif
118                                 string fileName = fqname;
119                                 if (assemblyb.AssemblyDir != null)
120                                         fileName = Path.Combine (assemblyb.AssemblyDir, fileName);
121                                 symbolWriter.Initialize (IntPtr.Zero, fileName, true);
122                         }
123                 }
124
125                 public override string FullyQualifiedName {get { return fqname;}}
126
127                 public bool IsTransient () {
128                         return transient;
129                 }
130
131                 public void CreateGlobalFunctions () 
132                 {
133                         if (global_type_created != null)
134                                 throw new InvalidOperationException ("global methods already created");
135                         if (global_type != null)
136                                 global_type_created = global_type.CreateType ();
137                 }
138
139                 public FieldBuilder DefineInitializedData( string name, byte[] data, FieldAttributes attributes) {
140                         if (data == null)
141                                 throw new ArgumentNullException ("data");
142
143                         FieldBuilder fb = DefineUninitializedData (name, data.Length, 
144                                                                                                            attributes | FieldAttributes.HasFieldRVA);
145                         fb.SetRVAData (data);
146
147                         return fb;
148                 }
149
150                 public FieldBuilder DefineUninitializedData (string name, int size, FieldAttributes attributes)
151                 {
152                         if (name == null)
153                                 throw new ArgumentNullException ("name");
154                         if (global_type_created != null)
155                                 throw new InvalidOperationException ("global fields already created");
156                         if ((size <= 0) || (size > 0x3f0000))
157                                 throw new ArgumentException ("size", "Data size must be > 0 and < 0x3f0000");
158
159                         CreateGlobalType ();
160
161                         string typeName = "$ArrayType$" + size;
162                         Type datablobtype = GetType (typeName, false, false);
163                         if (datablobtype == null) {
164                                 TypeBuilder tb = DefineType (typeName, 
165                                     TypeAttributes.Public|TypeAttributes.ExplicitLayout|TypeAttributes.Sealed,
166                                         assemblyb.corlib_value_type, null, PackingSize.Size1, size);
167                                 tb.CreateType ();
168                                 datablobtype = tb;
169                         }
170                         FieldBuilder fb = global_type.DefineField (name, datablobtype, attributes|FieldAttributes.Static);
171
172                         if (global_fields != null) {
173                                 FieldBuilder[] new_fields = new FieldBuilder [global_fields.Length+1];
174                                 System.Array.Copy (global_fields, new_fields, global_fields.Length);
175                                 new_fields [global_fields.Length] = fb;
176                                 global_fields = new_fields;
177                         } else {
178                                 global_fields = new FieldBuilder [1];
179                                 global_fields [0] = fb;
180                         }
181                         return fb;
182                 }
183
184                 private void addGlobalMethod (MethodBuilder mb) {
185                         if (global_methods != null) {
186                                 MethodBuilder[] new_methods = new MethodBuilder [global_methods.Length+1];
187                                 System.Array.Copy (global_methods, new_methods, global_methods.Length);
188                                 new_methods [global_methods.Length] = mb;
189                                 global_methods = new_methods;
190                         } else {
191                                 global_methods = new MethodBuilder [1];
192                                 global_methods [0] = mb;
193                         }
194                 }
195
196                 public MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
197                 {
198                         return DefineGlobalMethod (name, attributes, CallingConventions.Standard, returnType, parameterTypes);
199                 }
200
201                 public MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) {
202                         return DefineGlobalMethod (name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null);
203                 }
204
205                 public MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
206                 {
207                         if (name == null)
208                                 throw new ArgumentNullException ("name");
209                         if ((attributes & MethodAttributes.Static) == 0)
210                                 throw new ArgumentException ("global methods must be static");
211                         if (global_type_created != null)
212                                 throw new InvalidOperationException ("global methods already created");
213                         CreateGlobalType ();
214                         MethodBuilder mb = global_type.DefineMethod (name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
215
216                         addGlobalMethod (mb);
217                         return mb;
218                 }
219
220                 public MethodBuilder DefinePInvokeMethod (string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) {
221                         return DefinePInvokeMethod (name, dllName, name, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
222                 }
223
224                 public MethodBuilder DefinePInvokeMethod (string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) {
225                         if (name == null)
226                                 throw new ArgumentNullException ("name");
227                         if ((attributes & MethodAttributes.Static) == 0)
228                                 throw new ArgumentException ("global methods must be static");
229                         if (global_type_created != null)
230                                 throw new InvalidOperationException ("global methods already created");
231                         CreateGlobalType ();
232                         MethodBuilder mb = global_type.DefinePInvokeMethod (name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
233
234                         addGlobalMethod (mb);
235                         return mb;
236                 }                       
237
238                 public TypeBuilder DefineType (string name) {
239                         return DefineType (name, 0);
240                 }
241
242                 public TypeBuilder DefineType (string name, TypeAttributes attr) {
243                         if ((attr & TypeAttributes.Interface) != 0)
244                                 return DefineType (name, attr, null, null);
245                         return DefineType (name, attr, typeof(object), null);
246                 }
247
248                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent) {
249                         return DefineType (name, attr, parent, null);
250                 }
251
252                 private void AddType (TypeBuilder tb)
253                 {
254                         if (types != null) {
255                                 if (types.Length == num_types) {
256                                         TypeBuilder[] new_types = new TypeBuilder [types.Length * 2];
257                                         System.Array.Copy (types, new_types, num_types);
258                                         types = new_types;
259                                 }
260                         } else {
261                                 types = new TypeBuilder [1];
262                         }
263                         types [num_types] = tb;
264                         num_types ++;
265                 }
266
267                 private TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packingSize, int typesize) {
268                         if (name == null)
269                                 throw new ArgumentNullException ("fullname");
270                         if (name_cache.ContainsKey (name))
271                                 throw new ArgumentException ("Duplicate type name within an assembly.");
272                         TypeBuilder res = new TypeBuilder (this, name, attr, parent, interfaces, packingSize, typesize, null);
273                         AddType (res);
274
275                         name_cache.Add (name, res);
276                         
277                         return res;
278                 }
279
280                 internal void RegisterTypeName (TypeBuilder tb, string name)
281                 {
282                         name_cache.Add (name, tb);
283                 }
284                 
285                 internal TypeBuilder GetRegisteredType (string name)
286                 {
287                         return (TypeBuilder) name_cache [name];
288                 }
289
290                 [ComVisible (true)]
291                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces) {
292                         return DefineType (name, attr, parent, interfaces, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
293                 }
294
295                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, int typesize) {
296                         return DefineType (name, attr, parent, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
297                 }
298
299                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packsize) {
300                         return DefineType (name, attr, parent, null, packsize, TypeBuilder.UnspecifiedTypeSize);
301                 }
302
303                 public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize) {
304                         return DefineType (name, attr, parent, null, packingSize, typesize);
305                 }
306
307                 public MethodInfo GetArrayMethod( Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) {
308                         return new MonoArrayMethod (arrayClass, methodName, callingConvention, returnType, parameterTypes);
309                 }
310
311                 public EnumBuilder DefineEnum( string name, TypeAttributes visibility, Type underlyingType) {
312                         if (name_cache.Contains (name))
313                                 throw new ArgumentException ("Duplicate type name within an assembly.");
314
315                         EnumBuilder eb = new EnumBuilder (this, name, visibility, underlyingType);
316                         TypeBuilder res = eb.GetTypeBuilder ();
317                         AddType (res);
318                         name_cache.Add (name, res);
319                         return eb;
320                 }
321
322                 [ComVisible (true)]
323                 public override Type GetType( string className) {
324                         return GetType (className, false, false);
325                 }
326                 
327                 [ComVisible (true)]
328                 public override Type GetType( string className, bool ignoreCase) {
329                         return GetType (className, false, ignoreCase);
330                 }
331
332                 private TypeBuilder search_in_array (TypeBuilder[] arr, int validElementsInArray, string className) {
333                         int i;
334                         for (i = 0; i < validElementsInArray; ++i) {
335                                 if (String.Compare (className, arr [i].FullName, true, CultureInfo.InvariantCulture) == 0) {
336                                         return arr [i];
337                                 }
338                         }
339                         return null;
340                 }
341
342                 private TypeBuilder search_nested_in_array (TypeBuilder[] arr, int validElementsInArray, string className) {
343                         int i;
344                         for (i = 0; i < validElementsInArray; ++i) {
345                                 if (String.Compare (className, arr [i].Name, true, CultureInfo.InvariantCulture) == 0)
346                                         return arr [i];
347                         }
348                         return null;
349                 }
350
351                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
352                 private static extern Type create_modified_type (TypeBuilder tb, string modifiers);
353
354                 static readonly char [] type_modifiers = {'&', '[', '*'};
355
356                 private TypeBuilder GetMaybeNested (TypeBuilder t, string className) {
357                         int subt;
358                         string pname, rname;
359
360                         subt = className.IndexOf ('+');
361                         if (subt < 0) {
362                                 if (t.subtypes != null)
363                                         return search_nested_in_array (t.subtypes, t.subtypes.Length, className);
364                                 return null;
365                         }
366                         if (t.subtypes != null) {
367                                 pname = className.Substring (0, subt);
368                                 rname = className.Substring (subt + 1);
369                                 TypeBuilder result = search_nested_in_array (t.subtypes, t.subtypes.Length, pname);
370                                 if (result != null)
371                                         return GetMaybeNested (result, rname);
372                         }
373                         return null;
374                 }
375
376                 [ComVisible (true)]
377                 public override Type GetType (string className, bool throwOnError, bool ignoreCase)
378                 {
379                         if (className == null)
380                                 throw new ArgumentNullException ("className");
381                         if (className.Length == 0)
382                                 throw new ArgumentException ("className");
383
384                         int subt;
385                         string orig = className;
386                         string modifiers;
387                         TypeBuilder result = null;
388
389                         if (types == null && throwOnError)
390                                 throw new TypeLoadException (className);
391
392                         subt = className.IndexOfAny (type_modifiers);
393                         if (subt >= 0) {
394                                 modifiers = className.Substring (subt);
395                                 className = className.Substring (0, subt);
396                         } else
397                                 modifiers = null;
398
399                         if (!ignoreCase) {
400                                 result =  name_cache [className] as TypeBuilder;
401                         } else {
402                                 subt = className.IndexOf ('+');
403                                 if (subt < 0) {
404                                         if (types != null)
405                                                 result = search_in_array (types, num_types,  className);
406                                 } else {
407                                         string pname, rname;
408                                         pname = className.Substring (0, subt);
409                                         rname = className.Substring (subt + 1);
410                                         result = search_in_array (types, num_types, pname);
411                                         if (result != null)
412                                                 result = GetMaybeNested (result, rname);
413                                 }
414                         }
415                         if ((result == null) && throwOnError)
416                                 throw new TypeLoadException (orig);
417                         if (result != null && (modifiers != null)) {
418                                 Type mt = create_modified_type (result, modifiers);
419                                 result = mt as TypeBuilder;
420                                 if (result == null)
421                                         return mt;
422                         }
423                         if (result != null && result.is_created)
424                                 return result.CreateType ();
425                         else
426                                 return result;
427                 }
428
429                 internal int get_next_table_index (object obj, int table, bool inc) {
430                         if (table_indexes == null) {
431                                 table_indexes = new int [64];
432                                 for (int i=0; i < 64; ++i)
433                                         table_indexes [i] = 1;
434                                 /* allow room for .<Module> in TypeDef table */
435                                 table_indexes [0x02] = 2;
436                         }
437                         // Console.WriteLine ("getindex for table "+table.ToString()+" got "+table_indexes [table].ToString());
438                         if (inc)
439                                 return table_indexes [table]++;
440                         return table_indexes [table];
441                 }
442
443                 public void SetCustomAttribute( CustomAttributeBuilder customBuilder) {
444                         if (cattrs != null) {
445                                 CustomAttributeBuilder[] new_array = new CustomAttributeBuilder [cattrs.Length + 1];
446                                 cattrs.CopyTo (new_array, 0);
447                                 new_array [cattrs.Length] = customBuilder;
448                                 cattrs = new_array;
449                         } else {
450                                 cattrs = new CustomAttributeBuilder [1];
451                                 cattrs [0] = customBuilder;
452                         }
453                 }
454
455                 [ComVisible (true)]
456                 public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
457                         SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
458                 }
459
460                 public ISymbolWriter GetSymWriter () {
461                         return symbolWriter;
462                 }
463
464                 public ISymbolDocumentWriter DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType)
465                 {
466                         if (symbolWriter != null)
467                                 return symbolWriter.DefineDocument (url, language, languageVendor, documentType);
468                         else
469                                 return null;
470                 }
471
472                 public override Type [] GetTypes ()
473                 {
474                         if (types == null)
475                                 return Type.EmptyTypes;
476
477                         int n = num_types;
478                         Type [] copy = new Type [n];
479                         Array.Copy (types, copy, n);
480
481                         // MS replaces the typebuilders with their created types
482                         for (int i = 0; i < copy.Length; ++i)
483                                 if (types [i].is_created)
484                                         copy [i] = types [i].CreateType ();
485
486                         return copy;
487                 }
488
489                 public IResourceWriter DefineResource (string name, string description, ResourceAttributes attribute)
490                 {
491                         if (name == null)
492                                 throw new ArgumentNullException ("name");
493                         if (name == String.Empty)
494                                 throw new ArgumentException ("name cannot be empty");
495                         if (transient)
496                                 throw new InvalidOperationException ("The module is transient");
497                         if (!assemblyb.IsSave)
498                                 throw new InvalidOperationException ("The assembly is transient");
499                         ResourceWriter writer = new ResourceWriter (new MemoryStream ());
500                         if (resource_writers == null)
501                                 resource_writers = new Hashtable ();
502                         resource_writers [name] = writer;
503
504                         // The data is filled out later
505                         if (resources != null) {
506                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
507                                 System.Array.Copy(resources, new_r, resources.Length);
508                                 resources = new_r;
509                         } else {
510                                 resources = new MonoResource [1];
511                         }
512                         int p = resources.Length - 1;
513                         resources [p].name = name;
514                         resources [p].attrs = attribute;
515
516                         return writer;
517                 }
518
519                 public IResourceWriter DefineResource (string name, string description)
520                 {
521                         return DefineResource (name, description, ResourceAttributes.Public);
522                 }
523
524                 [MonoTODO]
525                 public void DefineUnmanagedResource (byte[] resource)
526                 {
527                         if (resource == null)
528                                 throw new ArgumentNullException ("resource");
529
530                         throw new NotImplementedException ();
531                 }
532
533                 [MonoTODO]
534                 public void DefineUnmanagedResource (string resourceFileName)
535                 {
536                         if (resourceFileName == null)
537                                 throw new ArgumentNullException ("resourceFileName");
538                         if (resourceFileName == String.Empty)
539                                 throw new ArgumentException ("resourceFileName");
540                         if (!File.Exists (resourceFileName) || Directory.Exists (resourceFileName))
541                                 throw new FileNotFoundException ("File '" + resourceFileName + "' does not exists or is a directory.");
542
543                         throw new NotImplementedException ();
544                 }
545
546                 public void DefineManifestResource (string name, Stream stream, ResourceAttributes attribute) {
547                         if (name == null)
548                                 throw new ArgumentNullException ("name");
549                         if (name == String.Empty)
550                                 throw new ArgumentException ("name cannot be empty");
551                         if (stream == null)
552                                 throw new ArgumentNullException ("stream");
553                         if (transient)
554                                 throw new InvalidOperationException ("The module is transient");
555                         if (!assemblyb.IsSave)
556                                 throw new InvalidOperationException ("The assembly is transient");
557
558                         if (resources != null) {
559                                 MonoResource[] new_r = new MonoResource [resources.Length + 1];
560                                 System.Array.Copy(resources, new_r, resources.Length);
561                                 resources = new_r;
562                         } else {
563                                 resources = new MonoResource [1];
564                         }
565                         int p = resources.Length - 1;
566                         resources [p].name = name;
567                         resources [p].attrs = attribute;
568                         resources [p].stream = stream;
569                 }
570
571                 [MonoTODO]
572                 public void SetSymCustomAttribute (string name, byte[] data)
573                 {
574                         throw new NotImplementedException ();
575                 }
576
577                 [MonoTODO]
578                 public void SetUserEntryPoint (MethodInfo entryPoint)
579                 {
580                         if (entryPoint == null)
581                                 throw new ArgumentNullException ("entryPoint");
582                         if (entryPoint.DeclaringType.Module != this)
583                                 throw new InvalidOperationException ("entryPoint is not contained in this module");
584                         throw new NotImplementedException ();
585                 }
586
587                 public MethodToken GetMethodToken (MethodInfo method)
588                 {
589                         if (method == null)
590                                 throw new ArgumentNullException ("method");
591                         if (method.DeclaringType.Module != this)
592                                 throw new InvalidOperationException ("The method is not in this module");
593                         return new MethodToken (GetToken (method));
594                 }
595
596                 public MethodToken GetArrayMethodToken (Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
597                 {
598                         return GetMethodToken (GetArrayMethod (arrayClass, methodName, callingConvention, returnType, parameterTypes));
599                 }
600
601                 [ComVisible (true)]
602                 public MethodToken GetConstructorToken (ConstructorInfo con)
603                 {
604                         if (con == null)
605                                 throw new ArgumentNullException ("con");
606                         if (con.DeclaringType.Module != this)
607                                 throw new InvalidOperationException ("The constructor is not in this module");
608                         return new MethodToken (GetToken (con));
609                 }
610
611                 public FieldToken GetFieldToken (FieldInfo field)
612                 {
613                         if (field == null)
614                                 throw new ArgumentNullException ("field");
615                         if (field.DeclaringType.Module != this)
616                                 throw new InvalidOperationException ("The method is not in this module");
617                         return new FieldToken (GetToken (field));
618                 }
619
620                 [MonoTODO]
621                 public SignatureToken GetSignatureToken (byte[] sigBytes, int sigLength)
622                 {
623                         throw new NotImplementedException ();
624                 }
625
626                 public SignatureToken GetSignatureToken (SignatureHelper sigHelper)
627                 {
628                         if (sigHelper == null)
629                                 throw new ArgumentNullException ("sigHelper");
630                         return new SignatureToken (GetToken (sigHelper));
631                 }
632
633                 public StringToken GetStringConstant (string str)
634                 {
635                         if (str == null)
636                                 throw new ArgumentNullException ("str");
637                         return new StringToken (GetToken (str));
638                 }
639
640                 public TypeToken GetTypeToken (Type type)
641                 {
642                         if (type == null)
643                                 throw new ArgumentNullException ("type");
644                         if (type.IsByRef)
645                                 throw new ArgumentException ("type can't be a byref type", "type");
646                         if (!IsTransient () && (type.Module is ModuleBuilder) && ((ModuleBuilder)type.Module).IsTransient ())
647                                 throw new InvalidOperationException ("a non-transient module can't reference a transient module");
648                         return new TypeToken (GetToken (type));
649                 }
650
651                 public TypeToken GetTypeToken (string name)
652                 {
653                         return GetTypeToken (GetType (name));
654                 }
655
656                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
657                 private static extern int getUSIndex (ModuleBuilder mb, string str);
658
659                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
660                 private static extern int getToken (ModuleBuilder mb, object obj, bool create_open_instance);
661
662                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
663                 private static extern int getMethodToken (ModuleBuilder mb, MethodInfo method,
664                                                           Type[] opt_param_types);
665
666                 internal int GetToken (string str)
667                 {
668                         int result;
669                         if (!us_string_cache.TryGetValue (str, out result)) {
670                                 result = getUSIndex (this, str);
671                                 us_string_cache [str] = result;
672                         }
673                         
674                         return result;
675                 }
676
677                 internal int GetToken (MemberInfo member) {
678                         return getToken (this, member, true);
679                 }
680
681                 internal int GetToken (MemberInfo member, bool create_open_instance) {
682                         return getToken (this, member, create_open_instance);
683                 }
684
685                 internal int GetToken (MethodInfo method, Type[] opt_param_types) {
686                         return getMethodToken (this, method, opt_param_types);
687                 }
688
689                 internal int GetToken (SignatureHelper helper) {
690                         return getToken (this, helper, true);
691                 }
692
693                 /*
694                  * Register the token->obj mapping with the runtime so the Module.Resolve... 
695                  * methods will work for obj.
696                  */
697                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
698                 internal extern void RegisterToken (object obj, int token);
699
700                 internal TokenGenerator GetTokenGenerator () {
701                         if (token_gen == null)
702                                 token_gen = new ModuleBuilderTokenGenerator (this);
703                         return token_gen;
704                 }
705
706                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
707                 private static extern void build_metadata (ModuleBuilder mb);
708
709                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
710                 private extern void WriteToFile (IntPtr handle);
711
712                 internal void Save ()
713                 {
714                         if (transient && !is_main)
715                                 return;
716
717                         if (types != null) {
718                                 for (int i = 0; i < num_types; ++i)
719                                         if (!types [i].is_created)
720                                                 throw new NotSupportedException ("Type '" + types [i].FullName + "' was not completed.");
721                         }
722
723                         if ((global_type != null) && (global_type_created == null))
724                                 global_type_created = global_type.CreateType ();
725
726                         if (resources != null) {
727                                 for (int i = 0; i < resources.Length; ++i) {
728                                         IResourceWriter rwriter;
729                                         if (resource_writers != null && (rwriter = resource_writers [resources [i].name] as IResourceWriter) != null) {
730                                                 ResourceWriter writer = (ResourceWriter)rwriter;
731                                                 writer.Generate ();
732                                                 MemoryStream mstream = (MemoryStream)writer.Stream;
733                                                 resources [i].data = new byte [mstream.Length];
734                                                 mstream.Seek (0, SeekOrigin.Begin);
735                                                 mstream.Read (resources [i].data, 0, (int)mstream.Length);
736                                                 continue;
737                                         }
738                                         Stream stream = resources [i].stream;
739
740                                         // According to MSDN docs, the stream is read during assembly save, not earlier
741                                         if (stream != null) {
742                                                 try {
743                                                         long len = stream.Length;
744                                                         resources [i].data = new byte [len];
745                                                         stream.Seek (0, SeekOrigin.Begin);
746                                                         stream.Read (resources [i].data, 0, (int)len);
747                                                 } catch {
748                                                         /* do something */
749                                                 }
750                                         }
751                                 }
752                         }
753
754                         build_metadata (this);
755
756                         string fileName = fqname;
757                         if (assemblyb.AssemblyDir != null)
758                                 fileName = Path.Combine (assemblyb.AssemblyDir, fileName);
759
760                         try {
761                                 // We mmap the file, so unlink the previous version since it may be in use
762                                 File.Delete (fileName);
763                         } catch {
764                                 // We can safely ignore
765                         }
766                         using (FileStream file = new FileStream (fileName, FileMode.Create, FileAccess.Write))
767                                 WriteToFile (file.Handle);
768                         
769                         //
770                         // The constant 0x80000000 is internal to Mono, it means `make executable'
771                         //
772                         File.SetAttributes (fileName, (FileAttributes) (unchecked ((int) 0x80000000)));
773                         
774                         if (types != null && symbolWriter != null) {
775                                 for (int i = 0; i < num_types; ++i)
776                                         types [i].GenerateDebugInfo (symbolWriter);
777                                 symbolWriter.Close ();
778                         }
779                 }
780
781                 internal string FileName {
782                         get {
783                                 return fqname;
784                         }
785                 }
786
787                 internal bool IsMain {
788                         set {
789                                 is_main = value;
790                         }
791                 }
792
793                 internal void CreateGlobalType () {
794                         if (global_type == null)
795                                 global_type = new TypeBuilder (this, 0, 1);
796                 }
797
798                 internal override Guid GetModuleVersionId ()
799                 {
800                         return new Guid (guid);
801                 }
802
803                 // Used by mcs, the symbol writer, and mdb through reflection
804                 internal static Guid Mono_GetGuid (ModuleBuilder mb)
805                 {
806                         return mb.GetModuleVersionId ();
807                 }
808
809                 void _ModuleBuilder.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
810                 {
811                         throw new NotImplementedException ();
812                 }
813
814                 void _ModuleBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
815                 {
816                         throw new NotImplementedException ();
817                 }
818
819                 void _ModuleBuilder.GetTypeInfoCount (out uint pcTInfo)
820                 {
821                         throw new NotImplementedException ();
822                 }
823
824                 void _ModuleBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
825                 {
826                         throw new NotImplementedException ();
827                 }
828
829 #if NET_4_0 || MOONLIGHT || MOBILE
830                 public override Assembly Assembly {
831                         get { return assemblyb; }
832                 }
833
834                 public override string Name {
835                         get { return name; }
836                 }
837
838                 public override string ScopeName {
839                         get { return name; }
840                 }
841
842                 public override Guid ModuleVersionId {
843                         get {
844                                 return GetModuleVersionId ();
845                         }
846                 }
847
848                 //XXX resource modules can't be defined with ModuleBuilder
849                 public override bool IsResource ()
850                 {
851                         return false;
852                 }
853
854                 protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) 
855                 {
856                         if (global_type_created == null)
857                                 return null;
858                         if (types == null)
859                                 return global_type_created.GetMethod (name);
860                         return global_type_created.GetMethod (name, bindingAttr, binder, callConvention, types, modifiers);
861                 }
862
863                 public override FieldInfo ResolveField (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
864                         ResolveTokenError error;
865
866                         IntPtr handle = ResolveFieldToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
867                         if (handle == IntPtr.Zero)
868                                 throw resolve_token_exception (metadataToken, error, "Field");
869                         else
870                                 return FieldInfo.GetFieldFromHandle (new RuntimeFieldHandle (handle));
871                 }
872
873                 public override MemberInfo ResolveMember (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
874
875                         ResolveTokenError error;
876
877                         MemberInfo m = ResolveMemberToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
878                         if (m == null)
879                                 throw resolve_token_exception (metadataToken, error, "MemberInfo");
880                         else
881                                 return m;
882                 }
883
884                 public override MethodBase ResolveMethod (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
885                         ResolveTokenError error;
886
887                         IntPtr handle = ResolveMethodToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
888                         if (handle == IntPtr.Zero)
889                                 throw resolve_token_exception (metadataToken, error, "MethodBase");
890                         else
891                                 return MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (handle));
892                 }
893
894                 public override string ResolveString (int metadataToken) {
895                         ResolveTokenError error;
896
897                         string s = ResolveStringToken (_impl, metadataToken, out error);
898                         if (s == null)
899                                 throw resolve_token_exception (metadataToken, error, "string");
900                         else
901                                 return s;
902                 }
903
904                 public override byte[] ResolveSignature (int metadataToken) {
905                         ResolveTokenError error;
906
907                     byte[] res = ResolveSignature (_impl, metadataToken, out error);
908                         if (res == null)
909                                 throw resolve_token_exception (metadataToken, error, "signature");
910                         else
911                                 return res;
912                 }
913
914                 public override Type ResolveType (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
915                         ResolveTokenError error;
916
917                         IntPtr handle = ResolveTypeToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
918                         if (handle == IntPtr.Zero)
919                                 throw resolve_token_exception (metadataToken, error, "Type");
920                         else
921                                 return Type.GetTypeFromHandle (new RuntimeTypeHandle (handle));
922                 }
923
924                 public override bool Equals (object obj)
925                 {
926                         return base.Equals (obj);
927                 }
928
929                 public override int GetHashCode ()
930                 {
931                         return base.GetHashCode ();
932                 }
933
934                 public override bool IsDefined (Type attributeType, bool inherit)
935                 {
936                         return base.IsDefined (attributeType, inherit);
937                 }
938
939                 public override object[] GetCustomAttributes (bool inherit)
940                 {
941                         return base.GetCustomAttributes (inherit);
942                 }
943
944                 public override object[] GetCustomAttributes (Type attributeType, bool inherit)
945                 {
946                         return base.GetCustomAttributes (attributeType, inherit);
947                 }
948
949                 public override FieldInfo GetField (string name, BindingFlags bindingAttr)
950                 {
951                         return base.GetField (name, bindingAttr);
952                 }
953
954                 public override FieldInfo[] GetFields (BindingFlags bindingFlags)
955                 {
956                         return base.GetFields (bindingFlags);
957                 }
958
959                 public override MethodInfo[] GetMethods (BindingFlags bindingFlags)
960                 {
961                         return base.GetMethods (bindingFlags);
962                 }
963
964                 public override int MetadataToken {
965                         get {
966                                 return base.MetadataToken;
967                         }
968                 }
969 #endif
970         }
971
972         internal class ModuleBuilderTokenGenerator : TokenGenerator {
973
974                 private ModuleBuilder mb;
975
976                 public ModuleBuilderTokenGenerator (ModuleBuilder mb) {
977                         this.mb = mb;
978                 }
979
980                 public int GetToken (string str) {
981                         return mb.GetToken (str);
982                 }
983
984                 public int GetToken (MemberInfo member, bool create_open_instance) {
985                         return mb.GetToken (member, create_open_instance);
986                 }
987
988                 public int GetToken (MethodInfo method, Type[] opt_param_types) {
989                         return mb.GetToken (method, opt_param_types);
990                 }
991
992                 public int GetToken (SignatureHelper helper) {
993                         return mb.GetToken (helper);
994                 }
995         }
996 }
997
998 #endif