3 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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:
13 // The above copyright notice and this permission notice shall be
14 // included in all copies or substantial portions of the Software.
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.
26 // System.Reflection.Emit/ModuleBuilder.cs
29 // Paolo Molaro (lupus@ximian.com)
31 // (C) 2001 Ximian, Inc. http://www.ximian.com
35 using System
.Reflection
;
36 using System
.Collections
;
37 using System
.Collections
.Generic
;
38 using System
.Runtime
.CompilerServices
;
39 using System
.Runtime
.InteropServices
;
40 using System
.Diagnostics
.SymbolStore
;
42 using System
.Resources
;
43 using System
.Globalization
;
45 namespace System
.Reflection
.Emit
{
47 [ComDefaultInterface (typeof (_ModuleBuilder
))]
48 [ClassInterface (ClassInterfaceType
.None
)]
49 public class ModuleBuilder
: Module
, _ModuleBuilder
{
51 #pragma warning disable 169, 414
52 #region Sync with object-internals.h
53 private UIntPtr dynamic_image
; /* GC-tracked */
54 private int num_types
;
55 private TypeBuilder
[] types
;
56 private CustomAttributeBuilder
[] cattrs
;
58 private int table_idx
;
59 internal AssemblyBuilder assemblyb
;
60 private MethodBuilder
[] global_methods
;
61 private FieldBuilder
[] global_fields
;
63 private MonoResource
[] resources
;
65 #pragma warning restore 169, 414
67 private TypeBuilder global_type
;
68 private Type global_type_created
;
70 Dictionary
<string, int> us_string_cache
;
71 private int[] table_indexes
;
73 ModuleBuilderTokenGenerator token_gen
;
74 Hashtable resource_writers
;
75 ISymbolWriter symbolWriter
;
77 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
78 private static extern void basic_init (ModuleBuilder ab
);
80 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
81 private static extern void set_wrappers_type (ModuleBuilder mb
, Type ab
);
83 internal ModuleBuilder (AssemblyBuilder assb
, string name
, string fullyqname
, bool emitSymbolInfo
, bool transient
) {
84 this.name
= this.scopename
= name
;
85 this.fqname
= fullyqname
;
86 this.assembly
= this.assemblyb
= assb
;
87 this.transient
= transient
;
88 // to keep mcs fast we do not want CryptoConfig wo be involved to create the RNG
89 guid
= Guid
.FastNewGuidArray ();
90 // guid = Guid.NewGuid().ToByteArray ();
91 table_idx
= get_next_table_index (this, 0x00, true);
92 name_cache
= new Hashtable ();
93 us_string_cache
= new Dictionary
<string, int> (512);
100 TypeBuilder tb
= new TypeBuilder (this, TypeAttributes
.Abstract
, 0xFFFFFF); /*last valid token*/
101 Type type
= tb
.CreateType ();
102 set_wrappers_type (this, type
);
105 if (emitSymbolInfo
) {
107 symbolWriter
= new Mono
.CompilerServices
.SymbolWriter
.SymbolWriterImpl (this);
109 Assembly asm
= Assembly
.LoadWithPartialName ("Mono.CompilerServices.SymbolWriter");
111 throw new ExecutionEngineException ("The assembly for default symbol writer cannot be loaded");
113 Type t
= asm
.GetType ("Mono.CompilerServices.SymbolWriter.SymbolWriterImpl");
115 throw new ExecutionEngineException ("The type that implements the default symbol writer interface cannot be found");
117 symbolWriter
= (ISymbolWriter
) Activator
.CreateInstance (t
, new object[] { this }
);
119 string fileName
= fqname
;
120 if (assemblyb
.AssemblyDir
!= null)
121 fileName
= Path
.Combine (assemblyb
.AssemblyDir
, fileName
);
122 symbolWriter
.Initialize (IntPtr
.Zero
, fileName
, true);
126 public override string FullyQualifiedName {get { return fqname;}}
128 public bool IsTransient () {
132 public void CreateGlobalFunctions ()
134 if (global_type_created
!= null)
135 throw new InvalidOperationException ("global methods already created");
136 if (global_type
!= null)
137 global_type_created
= global_type
.CreateType ();
140 public FieldBuilder
DefineInitializedData( string name
, byte[] data
, FieldAttributes attributes
) {
142 throw new ArgumentNullException ("data");
144 FieldBuilder fb
= DefineUninitializedData (name
, data
.Length
,
145 attributes
| FieldAttributes
.HasFieldRVA
);
146 fb
.SetRVAData (data
);
151 public FieldBuilder
DefineUninitializedData (string name
, int size
, FieldAttributes attributes
)
154 throw new ArgumentNullException ("name");
155 if (global_type_created
!= null)
156 throw new InvalidOperationException ("global fields already created");
157 if ((size
<= 0) || (size
> 0x3f0000))
158 throw new ArgumentException ("size", "Data size must be > 0 and < 0x3f0000");
162 string typeName
= "$ArrayType$" + size
;
163 Type datablobtype
= GetType (typeName
, false, false);
164 if (datablobtype
== null) {
165 TypeBuilder tb
= DefineType (typeName
,
166 TypeAttributes
.Public
|TypeAttributes
.ExplicitLayout
|TypeAttributes
.Sealed
,
167 assemblyb
.corlib_value_type
, null, PackingSize
.Size1
, size
);
171 FieldBuilder fb
= global_type
.DefineField (name
, datablobtype
, attributes
|FieldAttributes
.Static
);
173 if (global_fields
!= null) {
174 FieldBuilder
[] new_fields
= new FieldBuilder
[global_fields
.Length
+1];
175 System
.Array
.Copy (global_fields
, new_fields
, global_fields
.Length
);
176 new_fields
[global_fields
.Length
] = fb
;
177 global_fields
= new_fields
;
179 global_fields
= new FieldBuilder
[1];
180 global_fields
[0] = fb
;
185 private void addGlobalMethod (MethodBuilder mb
) {
186 if (global_methods
!= null) {
187 MethodBuilder
[] new_methods
= new MethodBuilder
[global_methods
.Length
+1];
188 System
.Array
.Copy (global_methods
, new_methods
, global_methods
.Length
);
189 new_methods
[global_methods
.Length
] = mb
;
190 global_methods
= new_methods
;
192 global_methods
= new MethodBuilder
[1];
193 global_methods
[0] = mb
;
197 public MethodBuilder
DefineGlobalMethod (string name
, MethodAttributes attributes
, Type returnType
, Type
[] parameterTypes
)
199 return DefineGlobalMethod (name
, attributes
, CallingConventions
.Standard
, returnType
, parameterTypes
);
202 public MethodBuilder
DefineGlobalMethod (string name
, MethodAttributes attributes
, CallingConventions callingConvention
, Type returnType
, Type
[] parameterTypes
) {
203 return DefineGlobalMethod (name
, attributes
, callingConvention
, returnType
, null, null, parameterTypes
, null, null);
206 public MethodBuilder
DefineGlobalMethod (string name
, MethodAttributes attributes
, CallingConventions callingConvention
, Type returnType
, Type
[] requiredReturnTypeCustomModifiers
, Type
[] optionalReturnTypeCustomModifiers
, Type
[] parameterTypes
, Type
[][] requiredParameterTypeCustomModifiers
, Type
[][] optionalParameterTypeCustomModifiers
)
209 throw new ArgumentNullException ("name");
210 if ((attributes
& MethodAttributes
.Static
) == 0)
211 throw new ArgumentException ("global methods must be static");
212 if (global_type_created
!= null)
213 throw new InvalidOperationException ("global methods already created");
215 MethodBuilder mb
= global_type
.DefineMethod (name
, attributes
, callingConvention
, returnType
, requiredReturnTypeCustomModifiers
, optionalReturnTypeCustomModifiers
, parameterTypes
, requiredParameterTypeCustomModifiers
, optionalParameterTypeCustomModifiers
);
217 addGlobalMethod (mb
);
221 public MethodBuilder
DefinePInvokeMethod (string name
, string dllName
, MethodAttributes attributes
, CallingConventions callingConvention
, Type returnType
, Type
[] parameterTypes
, CallingConvention nativeCallConv
, CharSet nativeCharSet
) {
222 return DefinePInvokeMethod (name
, dllName
, name
, attributes
, callingConvention
, returnType
, parameterTypes
, nativeCallConv
, nativeCharSet
);
225 public MethodBuilder
DefinePInvokeMethod (string name
, string dllName
, string entryName
, MethodAttributes attributes
, CallingConventions callingConvention
, Type returnType
, Type
[] parameterTypes
, CallingConvention nativeCallConv
, CharSet nativeCharSet
) {
227 throw new ArgumentNullException ("name");
228 if ((attributes
& MethodAttributes
.Static
) == 0)
229 throw new ArgumentException ("global methods must be static");
230 if (global_type_created
!= null)
231 throw new InvalidOperationException ("global methods already created");
233 MethodBuilder mb
= global_type
.DefinePInvokeMethod (name
, dllName
, entryName
, attributes
, callingConvention
, returnType
, parameterTypes
, nativeCallConv
, nativeCharSet
);
235 addGlobalMethod (mb
);
239 public TypeBuilder
DefineType (string name
) {
240 return DefineType (name
, 0);
243 public TypeBuilder
DefineType (string name
, TypeAttributes attr
) {
244 if ((attr
& TypeAttributes
.Interface
) != 0)
245 return DefineType (name
, attr
, null, null);
246 return DefineType (name
, attr
, typeof(object), null);
249 public TypeBuilder
DefineType (string name
, TypeAttributes attr
, Type parent
) {
250 return DefineType (name
, attr
, parent
, null);
253 private void AddType (TypeBuilder tb
)
256 if (types
.Length
== num_types
) {
257 TypeBuilder
[] new_types
= new TypeBuilder
[types
.Length
* 2];
258 System
.Array
.Copy (types
, new_types
, num_types
);
262 types
= new TypeBuilder
[1];
264 types
[num_types
] = tb
;
268 private TypeBuilder
DefineType (string name
, TypeAttributes attr
, Type parent
, Type
[] interfaces
, PackingSize packingSize
, int typesize
) {
270 throw new ArgumentNullException ("fullname");
271 if (name_cache
.ContainsKey (name
))
272 throw new ArgumentException ("Duplicate type name within an assembly.");
273 TypeBuilder res
= new TypeBuilder (this, name
, attr
, parent
, interfaces
, packingSize
, typesize
, null);
276 name_cache
.Add (name
, res
);
281 internal void RegisterTypeName (TypeBuilder tb
, string name
)
283 name_cache
.Add (name
, tb
);
286 internal TypeBuilder
GetRegisteredType (string name
)
288 return (TypeBuilder
) name_cache
[name
];
292 public TypeBuilder
DefineType (string name
, TypeAttributes attr
, Type parent
, Type
[] interfaces
) {
293 return DefineType (name
, attr
, parent
, interfaces
, PackingSize
.Unspecified
, TypeBuilder
.UnspecifiedTypeSize
);
296 public TypeBuilder
DefineType (string name
, TypeAttributes attr
, Type parent
, int typesize
) {
297 return DefineType (name
, attr
, parent
, null, PackingSize
.Unspecified
, TypeBuilder
.UnspecifiedTypeSize
);
300 public TypeBuilder
DefineType (string name
, TypeAttributes attr
, Type parent
, PackingSize packsize
) {
301 return DefineType (name
, attr
, parent
, null, packsize
, TypeBuilder
.UnspecifiedTypeSize
);
304 public TypeBuilder
DefineType (string name
, TypeAttributes attr
, Type parent
, PackingSize packingSize
, int typesize
) {
305 return DefineType (name
, attr
, parent
, null, packingSize
, typesize
);
308 public MethodInfo
GetArrayMethod( Type arrayClass
, string methodName
, CallingConventions callingConvention
, Type returnType
, Type
[] parameterTypes
) {
309 return new MonoArrayMethod (arrayClass
, methodName
, callingConvention
, returnType
, parameterTypes
);
312 public EnumBuilder
DefineEnum( string name
, TypeAttributes visibility
, Type underlyingType
) {
313 if (name_cache
.Contains (name
))
314 throw new ArgumentException ("Duplicate type name within an assembly.");
316 EnumBuilder eb
= new EnumBuilder (this, name
, visibility
, underlyingType
);
317 TypeBuilder res
= eb
.GetTypeBuilder ();
319 name_cache
.Add (name
, res
);
324 public override Type
GetType( string className
) {
325 return GetType (className
, false, false);
329 public override Type
GetType( string className
, bool ignoreCase
) {
330 return GetType (className
, false, ignoreCase
);
333 private TypeBuilder
search_in_array (TypeBuilder
[] arr
, int validElementsInArray
, string className
) {
335 for (i
= 0; i
< validElementsInArray
; ++i
) {
336 if (String
.Compare (className
, arr
[i
].FullName
, true, CultureInfo
.InvariantCulture
) == 0) {
343 private TypeBuilder
search_nested_in_array (TypeBuilder
[] arr
, int validElementsInArray
, string className
) {
345 for (i
= 0; i
< validElementsInArray
; ++i
) {
346 if (String
.Compare (className
, arr
[i
].Name
, true, CultureInfo
.InvariantCulture
) == 0)
352 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
353 private static extern Type
create_modified_type (TypeBuilder tb
, string modifiers
);
355 static readonly char [] type_modifiers
= {'&', '[', '*'}
;
357 private TypeBuilder
GetMaybeNested (TypeBuilder t
, string className
) {
361 subt
= className
.IndexOf ('+');
363 if (t
.subtypes
!= null)
364 return search_nested_in_array (t
.subtypes
, t
.subtypes
.Length
, className
);
367 if (t
.subtypes
!= null) {
368 pname
= className
.Substring (0, subt
);
369 rname
= className
.Substring (subt
+ 1);
370 TypeBuilder result
= search_nested_in_array (t
.subtypes
, t
.subtypes
.Length
, pname
);
372 return GetMaybeNested (result
, rname
);
378 public override Type
GetType (string className
, bool throwOnError
, bool ignoreCase
)
380 if (className
== null)
381 throw new ArgumentNullException ("className");
382 if (className
.Length
== 0)
383 throw new ArgumentException ("className");
386 string orig
= className
;
388 TypeBuilder result
= null;
390 if (types
== null && throwOnError
)
391 throw new TypeLoadException (className
);
393 subt
= className
.IndexOfAny (type_modifiers
);
395 modifiers
= className
.Substring (subt
);
396 className
= className
.Substring (0, subt
);
401 result
= name_cache
[className
] as TypeBuilder
;
403 subt
= className
.IndexOf ('+');
406 result
= search_in_array (types
, num_types
, className
);
409 pname
= className
.Substring (0, subt
);
410 rname
= className
.Substring (subt
+ 1);
411 result
= search_in_array (types
, num_types
, pname
);
413 result
= GetMaybeNested (result
, rname
);
416 if ((result
== null) && throwOnError
)
417 throw new TypeLoadException (orig
);
418 if (result
!= null && (modifiers
!= null)) {
419 Type mt
= create_modified_type (result
, modifiers
);
420 result
= mt
as TypeBuilder
;
424 if (result
!= null && result
.is_created
)
425 return result
.CreateType ();
430 internal int get_next_table_index (object obj
, int table
, bool inc
) {
431 if (table_indexes
== null) {
432 table_indexes
= new int [64];
433 for (int i
=0; i
< 64; ++i
)
434 table_indexes
[i
] = 1;
435 /* allow room for .<Module> in TypeDef table */
436 table_indexes
[0x02] = 2;
438 // Console.WriteLine ("getindex for table "+table.ToString()+" got "+table_indexes [table].ToString());
440 return table_indexes
[table
]++;
441 return table_indexes
[table
];
444 public void SetCustomAttribute( CustomAttributeBuilder customBuilder
) {
445 if (cattrs
!= null) {
446 CustomAttributeBuilder
[] new_array
= new CustomAttributeBuilder
[cattrs
.Length
+ 1];
447 cattrs
.CopyTo (new_array
, 0);
448 new_array
[cattrs
.Length
] = customBuilder
;
451 cattrs
= new CustomAttributeBuilder
[1];
452 cattrs
[0] = customBuilder
;
457 public void SetCustomAttribute( ConstructorInfo con
, byte[] binaryAttribute
) {
458 SetCustomAttribute (new CustomAttributeBuilder (con
, binaryAttribute
));
461 public ISymbolWriter
GetSymWriter () {
465 public ISymbolDocumentWriter
DefineDocument (string url
, Guid language
, Guid languageVendor
, Guid documentType
)
467 if (symbolWriter
!= null)
468 return symbolWriter
.DefineDocument (url
, language
, languageVendor
, documentType
);
473 public override Type
[] GetTypes ()
476 return Type
.EmptyTypes
;
479 Type
[] copy
= new Type
[n
];
480 Array
.Copy (types
, copy
, n
);
482 // MS replaces the typebuilders with their created types
483 for (int i
= 0; i
< copy
.Length
; ++i
)
484 if (types
[i
].is_created
)
485 copy
[i
] = types
[i
].CreateType ();
490 public IResourceWriter
DefineResource (string name
, string description
, ResourceAttributes attribute
)
493 throw new ArgumentNullException ("name");
494 if (name
== String
.Empty
)
495 throw new ArgumentException ("name cannot be empty");
497 throw new InvalidOperationException ("The module is transient");
498 if (!assemblyb
.IsSave
)
499 throw new InvalidOperationException ("The assembly is transient");
500 ResourceWriter writer
= new ResourceWriter (new MemoryStream ());
501 if (resource_writers
== null)
502 resource_writers
= new Hashtable ();
503 resource_writers
[name
] = writer
;
505 // The data is filled out later
506 if (resources
!= null) {
507 MonoResource
[] new_r
= new MonoResource
[resources
.Length
+ 1];
508 System
.Array
.Copy(resources
, new_r
, resources
.Length
);
511 resources
= new MonoResource
[1];
513 int p
= resources
.Length
- 1;
514 resources
[p
].name
= name
;
515 resources
[p
].attrs
= attribute
;
520 public IResourceWriter
DefineResource (string name
, string description
)
522 return DefineResource (name
, description
, ResourceAttributes
.Public
);
526 public void DefineUnmanagedResource (byte[] resource
)
528 if (resource
== null)
529 throw new ArgumentNullException ("resource");
531 throw new NotImplementedException ();
535 public void DefineUnmanagedResource (string resourceFileName
)
537 if (resourceFileName
== null)
538 throw new ArgumentNullException ("resourceFileName");
539 if (resourceFileName
== String
.Empty
)
540 throw new ArgumentException ("resourceFileName");
541 if (!File
.Exists (resourceFileName
) || Directory
.Exists (resourceFileName
))
542 throw new FileNotFoundException ("File '" + resourceFileName
+ "' does not exists or is a directory.");
544 throw new NotImplementedException ();
547 public void DefineManifestResource (string name
, Stream stream
, ResourceAttributes attribute
) {
549 throw new ArgumentNullException ("name");
550 if (name
== String
.Empty
)
551 throw new ArgumentException ("name cannot be empty");
553 throw new ArgumentNullException ("stream");
555 throw new InvalidOperationException ("The module is transient");
556 if (!assemblyb
.IsSave
)
557 throw new InvalidOperationException ("The assembly is transient");
559 if (resources
!= null) {
560 MonoResource
[] new_r
= new MonoResource
[resources
.Length
+ 1];
561 System
.Array
.Copy(resources
, new_r
, resources
.Length
);
564 resources
= new MonoResource
[1];
566 int p
= resources
.Length
- 1;
567 resources
[p
].name
= name
;
568 resources
[p
].attrs
= attribute
;
569 resources
[p
].stream
= stream
;
573 public void SetSymCustomAttribute (string name
, byte[] data
)
575 throw new NotImplementedException ();
579 public void SetUserEntryPoint (MethodInfo entryPoint
)
581 if (entryPoint
== null)
582 throw new ArgumentNullException ("entryPoint");
583 if (entryPoint
.DeclaringType
.Module
!= this)
584 throw new InvalidOperationException ("entryPoint is not contained in this module");
585 throw new NotImplementedException ();
588 public MethodToken
GetMethodToken (MethodInfo method
)
591 throw new ArgumentNullException ("method");
592 if (method
.DeclaringType
.Module
!= this)
593 throw new InvalidOperationException ("The method is not in this module");
594 return new MethodToken (GetToken (method
));
597 public MethodToken
GetArrayMethodToken (Type arrayClass
, string methodName
, CallingConventions callingConvention
, Type returnType
, Type
[] parameterTypes
)
599 return GetMethodToken (GetArrayMethod (arrayClass
, methodName
, callingConvention
, returnType
, parameterTypes
));
603 public MethodToken
GetConstructorToken (ConstructorInfo con
)
606 throw new ArgumentNullException ("con");
607 return new MethodToken (GetToken (con
));
610 public FieldToken
GetFieldToken (FieldInfo field
)
613 throw new ArgumentNullException ("field");
614 if (field
.DeclaringType
.Module
!= this)
615 throw new InvalidOperationException ("The method is not in this module");
616 return new FieldToken (GetToken (field
));
620 public SignatureToken
GetSignatureToken (byte[] sigBytes
, int sigLength
)
622 throw new NotImplementedException ();
625 public SignatureToken
GetSignatureToken (SignatureHelper sigHelper
)
627 if (sigHelper
== null)
628 throw new ArgumentNullException ("sigHelper");
629 return new SignatureToken (GetToken (sigHelper
));
632 public StringToken
GetStringConstant (string str
)
635 throw new ArgumentNullException ("str");
636 return new StringToken (GetToken (str
));
639 public TypeToken
GetTypeToken (Type type
)
642 throw new ArgumentNullException ("type");
644 throw new ArgumentException ("type can't be a byref type", "type");
645 if (!IsTransient () && (type
.Module
is ModuleBuilder
) && ((ModuleBuilder
)type
.Module
).IsTransient ())
646 throw new InvalidOperationException ("a non-transient module can't reference a transient module");
647 return new TypeToken (GetToken (type
));
650 public TypeToken
GetTypeToken (string name
)
652 return GetTypeToken (GetType (name
));
655 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
656 private static extern int getUSIndex (ModuleBuilder mb
, string str
);
658 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
659 private static extern int getToken (ModuleBuilder mb
, object obj
);
661 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
662 private static extern int getMethodToken (ModuleBuilder mb
, MethodInfo method
,
663 Type
[] opt_param_types
);
665 internal int GetToken (string str
)
668 if (!us_string_cache
.TryGetValue (str
, out result
)) {
669 result
= getUSIndex (this, str
);
670 us_string_cache
[str
] = result
;
676 internal int GetToken (MemberInfo member
) {
677 return getToken (this, member
);
680 internal int GetToken (MethodInfo method
, Type
[] opt_param_types
) {
681 return getMethodToken (this, method
, opt_param_types
);
684 internal int GetToken (SignatureHelper helper
) {
685 return getToken (this, helper
);
689 * Register the token->obj mapping with the runtime so the Module.Resolve...
690 * methods will work for obj.
692 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
693 internal extern void RegisterToken (object obj
, int token
);
695 internal TokenGenerator
GetTokenGenerator () {
696 if (token_gen
== null)
697 token_gen
= new ModuleBuilderTokenGenerator (this);
701 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
702 private static extern void build_metadata (ModuleBuilder mb
);
704 [MethodImplAttribute(MethodImplOptions
.InternalCall
)]
705 private extern void WriteToFile (IntPtr handle
);
707 internal void Save ()
709 if (transient
&& !is_main
)
713 for (int i
= 0; i
< num_types
; ++i
)
714 if (!types
[i
].is_created
)
715 throw new NotSupportedException ("Type '" + types
[i
].FullName
+ "' was not completed.");
718 if ((global_type
!= null) && (global_type_created
== null))
719 global_type_created
= global_type
.CreateType ();
721 if (resources
!= null) {
722 for (int i
= 0; i
< resources
.Length
; ++i
) {
723 IResourceWriter rwriter
;
724 if (resource_writers
!= null && (rwriter
= resource_writers
[resources
[i
].name
] as IResourceWriter
) != null) {
725 ResourceWriter writer
= (ResourceWriter
)rwriter
;
727 MemoryStream mstream
= (MemoryStream
)writer
.Stream
;
728 resources
[i
].data
= new byte [mstream
.Length
];
729 mstream
.Seek (0, SeekOrigin
.Begin
);
730 mstream
.Read (resources
[i
].data
, 0, (int)mstream
.Length
);
733 Stream stream
= resources
[i
].stream
;
735 // According to MSDN docs, the stream is read during assembly save, not earlier
736 if (stream
!= null) {
738 long len
= stream
.Length
;
739 resources
[i
].data
= new byte [len
];
740 stream
.Seek (0, SeekOrigin
.Begin
);
741 stream
.Read (resources
[i
].data
, 0, (int)len
);
749 build_metadata (this);
751 string fileName
= fqname
;
752 if (assemblyb
.AssemblyDir
!= null)
753 fileName
= Path
.Combine (assemblyb
.AssemblyDir
, fileName
);
756 // We mmap the file, so unlink the previous version since it may be in use
757 File
.Delete (fileName
);
759 // We can safely ignore
761 using (FileStream file
= new FileStream (fileName
, FileMode
.Create
, FileAccess
.Write
))
762 WriteToFile (file
.Handle
);
765 // The constant 0x80000000 is internal to Mono, it means `make executable'
767 File
.SetAttributes (fileName
, (FileAttributes
) (unchecked ((int) 0x80000000)));
769 if (types
!= null && symbolWriter
!= null) {
770 for (int i
= 0; i
< num_types
; ++i
)
771 types
[i
].GenerateDebugInfo (symbolWriter
);
772 symbolWriter
.Close ();
776 internal string FileName
{
782 internal bool IsMain
{
788 internal void CreateGlobalType () {
789 if (global_type
== null)
790 global_type
= new TypeBuilder (this, 0, 1);
793 internal override Guid
GetModuleVersionId ()
795 return new Guid (guid
);
798 // Used by mcs, the symbol writer, and mdb through reflection
799 internal static Guid
Mono_GetGuid (ModuleBuilder mb
)
801 return mb
.GetModuleVersionId ();
804 void _ModuleBuilder
.GetIDsOfNames ([In
] ref Guid riid
, IntPtr rgszNames
, uint cNames
, uint lcid
, IntPtr rgDispId
)
806 throw new NotImplementedException ();
809 void _ModuleBuilder
.GetTypeInfo (uint iTInfo
, uint lcid
, IntPtr ppTInfo
)
811 throw new NotImplementedException ();
814 void _ModuleBuilder
.GetTypeInfoCount (out uint pcTInfo
)
816 throw new NotImplementedException ();
819 void _ModuleBuilder
.Invoke (uint dispIdMember
, [In
] ref Guid riid
, uint lcid
, short wFlags
, IntPtr pDispParams
, IntPtr pVarResult
, IntPtr pExcepInfo
, IntPtr puArgErr
)
821 throw new NotImplementedException ();
825 public override Assembly Assembly
{
826 get { return assemblyb; }
829 public override string Name
{
833 public override string ScopeName
{
837 public override Guid ModuleVersionId
{
839 return GetModuleVersionId ();
843 //XXX resource modules can't be defined with ModuleBuilder
844 public override bool IsResource ()
849 protected override MethodInfo
GetMethodImpl (string name
, BindingFlags bindingAttr
, Binder binder
, CallingConventions callConvention
, Type
[] types
, ParameterModifier
[] modifiers
)
851 if (global_type_created
== null)
854 return global_type_created
.GetMethod (name
);
855 return global_type_created
.GetMethod (name
, bindingAttr
, binder
, callConvention
, types
, modifiers
);
858 public override FieldInfo
ResolveField (int metadataToken
, Type
[] genericTypeArguments
, Type
[] genericMethodArguments
) {
859 ResolveTokenError error
;
861 IntPtr handle
= ResolveFieldToken (_impl
, metadataToken
, ptrs_from_types (genericTypeArguments
), ptrs_from_types (genericMethodArguments
), out error
);
862 if (handle
== IntPtr
.Zero
)
863 throw resolve_token_exception (metadataToken
, error
, "Field");
865 return FieldInfo
.GetFieldFromHandle (new RuntimeFieldHandle (handle
));
868 public override MemberInfo
ResolveMember (int metadataToken
, Type
[] genericTypeArguments
, Type
[] genericMethodArguments
) {
870 ResolveTokenError error
;
872 MemberInfo m
= ResolveMemberToken (_impl
, metadataToken
, ptrs_from_types (genericTypeArguments
), ptrs_from_types (genericMethodArguments
), out error
);
874 throw resolve_token_exception (metadataToken
, error
, "MemberInfo");
879 public override MethodBase
ResolveMethod (int metadataToken
, Type
[] genericTypeArguments
, Type
[] genericMethodArguments
) {
880 ResolveTokenError error
;
882 IntPtr handle
= ResolveMethodToken (_impl
, metadataToken
, ptrs_from_types (genericTypeArguments
), ptrs_from_types (genericMethodArguments
), out error
);
883 if (handle
== IntPtr
.Zero
)
884 throw resolve_token_exception (metadataToken
, error
, "MethodBase");
886 return MethodBase
.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (handle
));
889 public override string ResolveString (int metadataToken
) {
890 ResolveTokenError error
;
892 string s
= ResolveStringToken (_impl
, metadataToken
, out error
);
894 throw resolve_token_exception (metadataToken
, error
, "string");
899 public override byte[] ResolveSignature (int metadataToken
) {
900 ResolveTokenError error
;
902 byte[] res
= ResolveSignature (_impl
, metadataToken
, out error
);
904 throw resolve_token_exception (metadataToken
, error
, "signature");
909 public override Type
ResolveType (int metadataToken
, Type
[] genericTypeArguments
, Type
[] genericMethodArguments
) {
910 ResolveTokenError error
;
912 IntPtr handle
= ResolveTypeToken (_impl
, metadataToken
, ptrs_from_types (genericTypeArguments
), ptrs_from_types (genericMethodArguments
), out error
);
913 if (handle
== IntPtr
.Zero
)
914 throw resolve_token_exception (metadataToken
, error
, "Type");
916 return Type
.GetTypeFromHandle (new RuntimeTypeHandle (handle
));
922 internal class ModuleBuilderTokenGenerator
: TokenGenerator
{
924 private ModuleBuilder mb
;
926 public ModuleBuilderTokenGenerator (ModuleBuilder mb
) {
930 public int GetToken (string str
) {
931 return mb
.GetToken (str
);
934 public int GetToken (MemberInfo member
) {
935 return mb
.GetToken (member
);
938 public int GetToken (MethodInfo method
, Type
[] opt_param_types
) {
939 return mb
.GetToken (method
, opt_param_types
);
942 public int GetToken (SignatureHelper helper
) {
943 return mb
.GetToken (helper
);