using System;
using System.Reflection;
using System.Collections;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Diagnostics.SymbolStore;
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;
bool is_main;
private MonoResource[] resources;
#endregion
+#pragma warning restore 169, 414
+
private TypeBuilder global_type;
private Type global_type_created;
Hashtable name_cache;
- Hashtable us_string_cache = new Hashtable ();
+ Dictionary<string, int> us_string_cache;
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;
// guid = Guid.NewGuid().ToByteArray ();
table_idx = get_next_table_index (this, 0x00, true);
name_cache = new Hashtable ();
+ us_string_cache = new Dictionary<string, int> (512);
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 MOONLIGHT
+ 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);
}
}
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);
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");
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);
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);
num_types ++;
}
- private TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packsize, int typesize) {
- if (name_cache.Contains (name))
+ private TypeBuilder DefineType (string name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packingSize, int typesize) {
+ if (name == null)
+ throw new ArgumentNullException ("fullname");
+ if (name_cache.ContainsKey (name))
throw new ArgumentException ("Duplicate type name within an assembly.");
-
- TypeBuilder res = new TypeBuilder (this, name, attr, parent, interfaces, packsize, typesize, null);
+ TypeBuilder res = new TypeBuilder (this, name, attr, parent, interfaces, packingSize, typesize, null);
AddType (res);
+
name_cache.Add (name, res);
+
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);
}
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) {
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);
}
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;
}
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) {
}
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
}
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;
}
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) {
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)
{
return GetMethodToken (GetArrayMethod (arrayClass, methodName, callingConvention, returnType, parameterTypes));
}
-#if NET_2_0
[ComVisible (true)]
-#endif
public MethodToken GetConstructorToken (ConstructorInfo con)
{
if (con == null)
return new TypeToken (GetToken (type));
}
- public TypeToken GetTypeToken (string type)
+ public TypeToken GetTypeToken (string name)
{
return GetTypeToken (GetType (name));
}
private static extern int getMethodToken (ModuleBuilder mb, MethodInfo method,
Type[] opt_param_types);
- internal int GetToken (string str) {
- if (us_string_cache.Contains (str))
- return (int)us_string_cache [str];
- int result = getUSIndex (this, str);
- us_string_cache [str] = result;
+ internal int GetToken (string str)
+ {
+ int result;
+ if (!us_string_cache.TryGetValue (str, out result)) {
+ result = getUSIndex (this, str);
+ us_string_cache [str] = result;
+ }
+
return result;
}
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);
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);
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);
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)
{
throw new NotImplementedException ();
}
+
+#if NET_4_0
+ public override Assembly Assembly {
+ get { return assemblyb; }
+ }
+
+ public override string Name {
+ get { return name; }
+ }
+
+ public override string ScopeName {
+ get { return name; }
+ }
+
+ public override Guid ModuleVersionId {
+ get {
+ return GetModuleVersionId ();
+ }
+ }
+
+ //XXX resource modules can't be defined with ModuleBuilder
+ public override bool IsResource ()
+ {
+ return false;
+ }
+
+ protected override MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (global_type_created == null)
+ return null;
+ if (types == null)
+ return global_type_created.GetMethod (name);
+ return global_type_created.GetMethod (name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ public override FieldInfo ResolveField (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
+ ResolveTokenError error;
+
+ IntPtr handle = ResolveFieldToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
+ if (handle == IntPtr.Zero)
+ throw resolve_token_exception (metadataToken, error, "Field");
+ else
+ return FieldInfo.GetFieldFromHandle (new RuntimeFieldHandle (handle));
+ }
+
+ public override MemberInfo ResolveMember (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
+
+ ResolveTokenError error;
+
+ MemberInfo m = ResolveMemberToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
+ if (m == null)
+ throw resolve_token_exception (metadataToken, error, "MemberInfo");
+ else
+ return m;
+ }
+
+ public override MethodBase ResolveMethod (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
+ ResolveTokenError error;
+
+ IntPtr handle = ResolveMethodToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
+ if (handle == IntPtr.Zero)
+ throw resolve_token_exception (metadataToken, error, "MethodBase");
+ else
+ return MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (handle));
+ }
+
+ public override string ResolveString (int metadataToken) {
+ ResolveTokenError error;
+
+ string s = ResolveStringToken (_impl, metadataToken, out error);
+ if (s == null)
+ throw resolve_token_exception (metadataToken, error, "string");
+ else
+ return s;
+ }
+
+ public override byte[] ResolveSignature (int metadataToken) {
+ ResolveTokenError error;
+
+ byte[] res = ResolveSignature (_impl, metadataToken, out error);
+ if (res == null)
+ throw resolve_token_exception (metadataToken, error, "signature");
+ else
+ return res;
+ }
+
+ public override Type ResolveType (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
+ ResolveTokenError error;
+
+ IntPtr handle = ResolveTypeToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
+ if (handle == IntPtr.Zero)
+ throw resolve_token_exception (metadataToken, error, "Type");
+ else
+ return Type.GetTypeFromHandle (new RuntimeTypeHandle (handle));
+ }
+
+#endif
}
internal class ModuleBuilderTokenGenerator : TokenGenerator {