using System.Globalization;
namespace System.Reflection.Emit {
- public class ModuleBuilder : Module {
- #region Sync with reflection.h
- private IntPtr dynamic_image;
+ [ComVisible (true)]
+ [ComDefaultInterface (typeof (_ModuleBuilder))]
+ [ClassInterface (ClassInterfaceType.None)]
+ public class ModuleBuilder : Module, _ModuleBuilder {
+
+#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;
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;
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)
+ 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);
+ }
}
public override string FullyQualifiedName {get { return fqname;}}
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);
}
public TypeBuilder DefineType (string name, TypeAttributes attr) {
+ if ((attr & TypeAttributes.Interface) != 0)
+ return DefineType (name, attr, null, null);
return DefineType (name, attr, typeof(object), null);
}
return DefineType (name, attr, parent, null);
}
- 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 void AddType (TypeBuilder tb)
+ {
if (types != null) {
if (types.Length == num_types) {
TypeBuilder[] new_types = new TypeBuilder [types.Length * 2];
} else {
types = new TypeBuilder [1];
}
- types [num_types] = res;
+ types [num_types] = tb;
num_types ++;
- name_cache.Add (name, res);
+ }
+
+ 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);
+
+ 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];
+ }
+ [ComVisible (true)]
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) {
}
public EnumBuilder DefineEnum( string name, TypeAttributes visibility, Type underlyingType) {
+ if (name_cache.Contains (name))
+ throw new ArgumentException ("Duplicate type name within an assembly.");
+
EnumBuilder eb = new EnumBuilder (this, name, visibility, underlyingType);
+ TypeBuilder res = eb.GetTypeBuilder ();
+ AddType (res);
+ name_cache.Add (name, res);
return eb;
}
+ [ComVisible (true)]
public override Type GetType( string className) {
return GetType (className, false, false);
}
+ [ComVisible (true)]
public override Type GetType( string className, bool ignoreCase) {
return GetType (className, false, ignoreCase);
}
}
return null;
}
-
- public override Type GetType (string className, bool throwOnError, bool ignoreCase) {
+
+ [ComVisible (true)]
+ 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) {
cattrs [0] = customBuilder;
}
}
+
+ [ComVisible (true)]
public void SetCustomAttribute( ConstructorInfo con, byte[] binaryAttribute) {
SetCustomAttribute (new CustomAttributeBuilder (con, binaryAttribute));
}
public ISymbolWriter GetSymWriter () {
- return null;
+ return symbolWriter;
}
- public ISymbolDocumentWriter DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType) {
- return null;
+ public ISymbolDocumentWriter DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType)
+ {
+ if (symbolWriter != null)
+ return symbolWriter.DefineDocument (url, language, languageVendor, documentType);
+ else
+ return null;
}
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));
}
-
+ [ComVisible (true)]
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));
}
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);
// The constant 0x80000000 is internal to Mono, it means `make executable'
//
File.SetAttributes (fileName, (FileAttributes) (unchecked ((int) 0x80000000)));
+
+ if (types != null && symbolWriter != null) {
+ for (int i = 0; i < num_types; ++i)
+ types [i].GenerateDebugInfo (symbolWriter);
+ symbolWriter.Close ();
+ }
}
internal string FileName {
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 ();
+ }
+
+ void _ModuleBuilder.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _ModuleBuilder.GetTypeInfoCount (out uint pcTInfo)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _ModuleBuilder.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException ();
}
}
}
}
}
+