In Assembly:
[mono.git] / mcs / class / corlib / System.Reflection.Emit / ModuleBuilder.cs
index 36820b23c9f14cb8554d783ecef9b5da02fcc154..672be8b6b6129c6830d81650b440bb8dc32d7280 100644 (file)
@@ -42,14 +42,14 @@ using System.Resources;
 using System.Globalization;
 
 namespace System.Reflection.Emit {
-#if NET_2_0
        [ComVisible (true)]
        [ComDefaultInterface (typeof (_ModuleBuilder))]
-#endif
        [ClassInterface (ClassInterfaceType.None)]
        public class ModuleBuilder : Module, _ModuleBuilder {
-               #region Sync with reflection.h
-               private IntPtr dynamic_image;
+
+#pragma warning disable 169, 414
+               #region Sync with object-internals.h
+               private UIntPtr dynamic_image; /* GC-tracked */
                private int num_types;
                private TypeBuilder[] types;
                private CustomAttributeBuilder[] cattrs;
@@ -61,6 +61,8 @@ namespace System.Reflection.Emit {
                bool is_main;
                private MonoResource[] resources;
                #endregion
+#pragma warning restore 169, 414
+               
                private TypeBuilder global_type;
                private Type global_type_created;
                Hashtable name_cache;
@@ -68,12 +70,15 @@ namespace System.Reflection.Emit {
                private int[] table_indexes;
                bool transient;
                ModuleBuilderTokenGenerator token_gen;
-               ArrayList resource_writers = null;
+               Hashtable resource_writers;
                ISymbolWriter symbolWriter;
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private static extern void basic_init (ModuleBuilder ab);
 
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private static extern void set_wrappers_type (ModuleBuilder mb, Type ab);
+
                internal ModuleBuilder (AssemblyBuilder assb, string name, string fullyqname, bool emitSymbolInfo, bool transient) {
                        this.name = this.scopename = name;
                        this.fqname = fullyqname;
@@ -88,17 +93,31 @@ namespace System.Reflection.Emit {
                        basic_init (this);
 
                        CreateGlobalType ();
-                       
+
+                       if (assb.IsRun) {
+                               TypeBuilder tb = new TypeBuilder (this, TypeAttributes.Abstract, 0xFFFFFF); /*last valid token*/
+                               Type type = tb.CreateType ();
+                               set_wrappers_type (this, type);
+                       }
+
                        if (emitSymbolInfo) {
+#if NET_2_1 && !MONOTOUCH
+                               symbolWriter = new Mono.CompilerServices.SymbolWriter.SymbolWriterImpl (this);
+#else
                                Assembly asm = Assembly.LoadWithPartialName ("Mono.CompilerServices.SymbolWriter");
+                               if (asm == null)
+                                       throw new ExecutionEngineException ("The assembly for default symbol writer cannot be loaded");
+
                                Type t = asm.GetType ("Mono.CompilerServices.SymbolWriter.SymbolWriterImpl");
-                               if (t != null) {
-                                       symbolWriter = (ISymbolWriter) Activator.CreateInstance (t, new object[] { this });
-                                       string fileName = fqname;
-                                       if (assemblyb.AssemblyDir != null)
-                                               fileName = Path.Combine (assemblyb.AssemblyDir, fileName);
-                                       symbolWriter.Initialize (IntPtr.Zero, fileName, true);
-                               }
+                               if (t == null)
+                                       throw new ExecutionEngineException ("The type that implements the default symbol writer interface cannot be found");
+
+                               symbolWriter = (ISymbolWriter) Activator.CreateInstance (t, new object[] { this });
+#endif
+                               string fileName = fqname;
+                               if (assemblyb.AssemblyDir != null)
+                                       fileName = Path.Combine (assemblyb.AssemblyDir, fileName);
+                               symbolWriter.Initialize (IntPtr.Zero, fileName, true);
                        }
                }
 
@@ -127,13 +146,16 @@ namespace System.Reflection.Emit {
                        return fb;
                }
 
-               public FieldBuilder DefineUninitializedData( string name, int size, FieldAttributes attributes) {
+               public FieldBuilder DefineUninitializedData (string name, int size, FieldAttributes attributes)
+               {
                        if (name == null)
                                throw new ArgumentNullException ("name");
                        if (global_type_created != null)
                                throw new InvalidOperationException ("global fields already created");
-                       if (global_type == null)
-                               global_type = new TypeBuilder (this, 0);
+                       if ((size <= 0) || (size > 0x3f0000))
+                               throw new ArgumentException ("size", "Data size must be > 0 and < 0x3f0000");
+
+                       CreateGlobalType ();
 
                        string typeName = "$ArrayType$" + size;
                        Type datablobtype = GetType (typeName, false, false);
@@ -179,12 +201,7 @@ namespace System.Reflection.Emit {
                        return DefineGlobalMethod (name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null);
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
-               public
-#else
-               internal
-#endif
-               MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+               public MethodBuilder DefineGlobalMethod (string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
                {
                        if (name == null)
                                throw new ArgumentNullException ("name");
@@ -192,8 +209,7 @@ namespace System.Reflection.Emit {
                                throw new ArgumentException ("global methods must be static");
                        if (global_type_created != null)
                                throw new InvalidOperationException ("global methods already created");
-                       if (global_type == null)
-                               global_type = new TypeBuilder (this, 0);
+                       CreateGlobalType ();
                        MethodBuilder mb = global_type.DefineMethod (name, attributes, callingConvention, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
 
                        addGlobalMethod (mb);
@@ -211,8 +227,7 @@ namespace System.Reflection.Emit {
                                throw new ArgumentException ("global methods must be static");
                        if (global_type_created != null)
                                throw new InvalidOperationException ("global methods already created");
-                       if (global_type == null)
-                               global_type = new TypeBuilder (this, 0);
+                       CreateGlobalType ();
                        MethodBuilder mb = global_type.DefinePInvokeMethod (name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
 
                        addGlobalMethod (mb);
@@ -248,23 +263,30 @@ namespace System.Reflection.Emit {
                        num_types ++;
                }
 
-               private TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packsize, int typesize) {
-                       if (name_cache.Contains (name))
-                               throw new ArgumentException ("Duplicate type name within an assembly.");
-
-                       TypeBuilder res = new TypeBuilder (this, name, attr, parent, interfaces, packsize, typesize, null);
+               private TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packingSize, int typesize) {
+                       TypeBuilder res = new TypeBuilder (this, name, attr, parent, interfaces, packingSize, typesize, null);
                        AddType (res);
-                       name_cache.Add (name, res);
+                       
+                       try {
+                               name_cache.Add (name, res);
+                       } catch {
+                               throw new ArgumentException ("Duplicate type name within an assembly.");
+                       }
+                       
                        return res;
                }
 
-               internal void RegisterTypeName (TypeBuilder tb, string name) {
+               internal void RegisterTypeName (TypeBuilder tb, string name)
+               {
                        name_cache.Add (name, tb);
                }
+               
+               internal TypeBuilder GetRegisteredType (string name)
+               {
+                       return (TypeBuilder) name_cache [name];
+               }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces) {
                        return DefineType (name, attr, parent, interfaces, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
                }
@@ -277,8 +299,8 @@ namespace System.Reflection.Emit {
                        return DefineType (name, attr, parent, null, packsize, TypeBuilder.UnspecifiedTypeSize);
                }
 
-               public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packsize, int typesize) {
-                       return DefineType (name, attr, parent, null, packsize, typesize);
+               public TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize) {
+                       return DefineType (name, attr, parent, null, packingSize, typesize);
                }
 
                public MethodInfo GetArrayMethod( Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes) {
@@ -296,16 +318,12 @@ namespace System.Reflection.Emit {
                        return eb;
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public override Type GetType( string className) {
                        return GetType (className, false, false);
                }
                
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public override Type GetType( string className, bool ignoreCase) {
                        return GetType (className, false, ignoreCase);
                }
@@ -354,10 +372,14 @@ namespace System.Reflection.Emit {
                        return null;
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif         
-               public override Type GetType (string className, bool throwOnError, bool ignoreCase) {
+               public override Type GetType (string className, bool throwOnError, bool ignoreCase)
+               {
+                       if (className == null)
+                               throw new ArgumentNullException ("className");
+                       if (className.Length == 0)
+                               throw new ArgumentException ("className");
+
                        int subt;
                        string orig = className;
                        string modifiers;
@@ -391,9 +413,16 @@ namespace System.Reflection.Emit {
                        }
                        if ((result == null) && throwOnError)
                                throw new TypeLoadException (orig);
-                       if (result != null && (modifiers != null))
-                               return create_modified_type (result, modifiers);
-                       return result;
+                       if (result != null && (modifiers != null)) {
+                               Type mt = create_modified_type (result, modifiers);
+                               result = mt as TypeBuilder;
+                               if (result == null)
+                                       return mt;
+                       }
+                       if (result != null && result.is_created)
+                               return result.CreateType ();
+                       else
+                               return result;
                }
 
                internal int get_next_table_index (object obj, int table, bool inc) {
@@ -422,9 +451,7 @@ namespace System.Reflection.Emit {
                        }
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
                        SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
                }
@@ -444,12 +471,17 @@ namespace System.Reflection.Emit {
                public override Type [] GetTypes ()
                {
                        if (types == null)
-                               return new TypeBuilder [0];
+                               return Type.EmptyTypes;
 
                        int n = num_types;
-                       TypeBuilder [] copy = new TypeBuilder [n];
+                       Type [] copy = new Type [n];
                        Array.Copy (types, copy, n);
 
+                       // MS replaces the typebuilders with their created types
+                       for (int i = 0; i < copy.Length; ++i)
+                               if (types [i].is_created)
+                                       copy [i] = types [i].CreateType ();
+
                        return copy;
                }
 
@@ -465,8 +497,8 @@ namespace System.Reflection.Emit {
                                throw new InvalidOperationException ("The assembly is transient");
                        ResourceWriter writer = new ResourceWriter (new MemoryStream ());
                        if (resource_writers == null)
-                               resource_writers = new ArrayList ();
-                       resource_writers.Add (writer);
+                               resource_writers = new Hashtable ();
+                       resource_writers [name] = writer;
 
                        // The data is filled out later
                        if (resources != null) {
@@ -510,6 +542,31 @@ namespace System.Reflection.Emit {
                        throw new NotImplementedException ();
                }
 
+               public void DefineManifestResource (string name, Stream stream, ResourceAttributes attribute) {
+                       if (name == null)
+                               throw new ArgumentNullException ("name");
+                       if (name == String.Empty)
+                               throw new ArgumentException ("name cannot be empty");
+                       if (stream == null)
+                               throw new ArgumentNullException ("stream");
+                       if (transient)
+                               throw new InvalidOperationException ("The module is transient");
+                       if (!assemblyb.IsSave)
+                               throw new InvalidOperationException ("The assembly is transient");
+
+                       if (resources != null) {
+                               MonoResource[] new_r = new MonoResource [resources.Length + 1];
+                               System.Array.Copy(resources, new_r, resources.Length);
+                               resources = new_r;
+                       } else {
+                               resources = new MonoResource [1];
+                       }
+                       int p = resources.Length - 1;
+                       resources [p].name = name;
+                       resources [p].attrs = attribute;
+                       resources [p].stream = stream;
+               }
+
                [MonoTODO]
                public void SetSymCustomAttribute (string name, byte[] data)
                {
@@ -540,9 +597,7 @@ namespace System.Reflection.Emit {
                        return GetMethodToken (GetArrayMethod (arrayClass, methodName, callingConvention, returnType, parameterTypes));
                }
 
-#if NET_2_0
                [ComVisible (true)]
-#endif
                public MethodToken GetConstructorToken (ConstructorInfo con)
                {
                        if (con == null)
@@ -590,7 +645,7 @@ namespace System.Reflection.Emit {
                        return new TypeToken (GetToken (type));
                }
 
-               public TypeToken GetTypeToken (string type)
+               public TypeToken GetTypeToken (string name)
                {
                        return GetTypeToken (GetType (name));
                }
@@ -625,6 +680,13 @@ namespace System.Reflection.Emit {
                        return getToken (this, helper);
                }
 
+               /*
+                * Register the token->obj mapping with the runtime so the Module.Resolve... 
+                * methods will work for obj.
+                */
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal extern void RegisterToken (object obj, int token);
+
                internal TokenGenerator GetTokenGenerator () {
                        if (token_gen == null)
                                token_gen = new ModuleBuilderTokenGenerator (this);
@@ -651,15 +713,32 @@ namespace System.Reflection.Emit {
                        if ((global_type != null) && (global_type_created == null))
                                global_type_created = global_type.CreateType ();
 
-                       if (resource_writers != null) {
-                               for (int i = 0; i < resource_writers.Count; ++i) {
-                                       ResourceWriter writer = (ResourceWriter)resource_writers [i];
-                                       writer.Generate ();
-                                       MemoryStream stream = (MemoryStream)writer.Stream;
-                                       resources [i].data = new byte [stream.Length];
-                                       stream.Seek (0, SeekOrigin.Begin);
-                                       stream.Read (resources [i].data, 0, (int)stream.Length);
-                               }                                       
+                       if (resources != null) {
+                               for (int i = 0; i < resources.Length; ++i) {
+                                       IResourceWriter rwriter;
+                                       if (resource_writers != null && (rwriter = resource_writers [resources [i].name] as IResourceWriter) != null) {
+                                               ResourceWriter writer = (ResourceWriter)rwriter;
+                                               writer.Generate ();
+                                               MemoryStream mstream = (MemoryStream)writer.Stream;
+                                               resources [i].data = new byte [mstream.Length];
+                                               mstream.Seek (0, SeekOrigin.Begin);
+                                               mstream.Read (resources [i].data, 0, (int)mstream.Length);
+                                               continue;
+                                       }
+                                       Stream stream = resources [i].stream;
+
+                                       // According to MSDN docs, the stream is read during assembly save, not earlier
+                                       if (stream != null) {
+                                               try {
+                                                       long len = stream.Length;
+                                                       resources [i].data = new byte [len];
+                                                       stream.Seek (0, SeekOrigin.Begin);
+                                                       stream.Read (resources [i].data, 0, (int)len);
+                                               } catch {
+                                                       /* do something */
+                                               }
+                                       }
+                               }
                        }
 
                        build_metadata (this);
@@ -667,7 +746,13 @@ namespace System.Reflection.Emit {
                        string fileName = fqname;
                        if (assemblyb.AssemblyDir != null)
                                fileName = Path.Combine (assemblyb.AssemblyDir, fileName);
-                       
+
+                       try {
+                               // We mmap the file, so unlink the previous version since it may be in use
+                               File.Delete (fileName);
+                       } catch {
+                               // We can safely ignore
+                       }
                        using (FileStream file = new FileStream (fileName, FileMode.Create, FileAccess.Write))
                                WriteToFile (file.Handle);
                        
@@ -697,12 +782,18 @@ namespace System.Reflection.Emit {
 
                internal void CreateGlobalType () {
                        if (global_type == null)
-                               global_type = new TypeBuilder (this, 0);
+                               global_type = new TypeBuilder (this, 0, 1);
+               }
+
+               internal override Guid GetModuleVersionId ()
+               {
+                       return new Guid (guid);
                }
 
+               // Used by mcs, the symbol writer, and mdb through reflection
                internal static Guid Mono_GetGuid (ModuleBuilder mb)
                {
-                       return new Guid (mb.guid);
+                       return mb.GetModuleVersionId ();
                }
 
                void _ModuleBuilder.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)