public IUnresolvedAssembly LoadAssembly(Assembly assembly) { if (assembly == null) throw new ArgumentNullException ("assembly"); // Read assembly and module attributes IList<IUnresolvedAttribute> assemblyAttributes = new List<IUnresolvedAttribute>(); IList<IUnresolvedAttribute> moduleAttributes = new List<IUnresolvedAttribute>(); AddAttributes(assembly, assemblyAttributes); AddAttributes(assembly.ManifestModule, moduleAttributes); assemblyAttributes = interningProvider.InternList(assemblyAttributes); moduleAttributes = interningProvider.InternList(moduleAttributes); currentAssemblyDefinition = assembly; currentAssembly = new IkvmUnresolvedAssembly (assembly.FullName, DocumentationProvider); currentAssembly.Location = assembly.Location; currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes); currentAssembly.ModuleAttributes.AddRange(moduleAttributes); // Register type forwarders: foreach (var type in assembly.ManifestModule.__GetExportedTypes ()) { if (type.Assembly != assembly) { int typeParameterCount; string ns = type.Namespace; string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); ns = interningProvider.Intern(ns); name = interningProvider.Intern(name); var typeRef = new GetClassTypeReference(GetAssemblyReference(type.Assembly), ns, name, typeParameterCount); typeRef = interningProvider.Intern(typeRef); var key = new TopLevelTypeName(ns, name, typeParameterCount); currentAssembly.AddTypeForwarder(key, typeRef); } } // Create and register all types: var ikvmTypeDefs = new List<IKVM.Reflection.Type>(); var typeDefs = new List<DefaultUnresolvedTypeDefinition>(); foreach (var td in assembly.GetTypes ()) { if (td.DeclaringType != null) continue; CancellationToken.ThrowIfCancellationRequested(); if (IncludeInternalMembers || td.IsPublic) { string name = td.Name; if (name.Length == 0) continue; var t = CreateTopLevelTypeDefinition(td); ikvmTypeDefs.Add(td); typeDefs.Add(t); currentAssembly.AddTypeDefinition(t); // The registration will happen after the members are initialized } } // Initialize the type's members: for (int i = 0; i < typeDefs.Count; i++) { InitTypeDefinition(ikvmTypeDefs[i], typeDefs[i]); } // Freezing the assembly here is important: // otherwise it will be frozen when a compilation is first created // from it. But freezing has the effect of changing some collection instances // (to ReadOnlyCollection). This hidden mutation was causing a crash // when the FastSerializer was saving the assembly at the same time as // the first compilation was created from it. // By freezing the assembly now, we ensure it is usable on multiple // threads without issues. currentAssembly.Freeze(); var result = currentAssembly; currentAssembly = null; return result; }
static void Process(Assembly asm) { currentAssembly = asm; string shortName = asm.GetName().Name; string name = shortName.Replace(".", "_"); var typeList = new List<IKVM.Reflection.Type>(); headerWriter.WriteLine("/*"); headerWriter.WriteLine(" * Automatically generated by thunktool from {0}", shortName); headerWriter.WriteLine(" */"); headerWriter.WriteLine(); headerWriter.WriteLine("#ifndef __{0}_THUNKTOOL__", name.ToUpperInvariant()); headerWriter.WriteLine("#define __{0}_THUNKTOOL__", name.ToUpperInvariant()); headerWriter.WriteLine(); headerWriter.WriteLine("#include <mono/utils/mono-publib.h>"); headerWriter.WriteLine("#include <mono/metadata/assembly.h>"); headerWriter.WriteLine("#include <mono/metadata/class.h>"); headerWriter.WriteLine("#include <mono/metadata/object.h>"); headerWriter.WriteLine(); headerWriter.WriteLine("MONO_BEGIN_DECLS"); headerWriter.WriteLine(); headerWriter.WriteLine("#ifdef WIN32"); headerWriter.WriteLine("#define THUNKCALL __stdcall"); headerWriter.WriteLine("#else"); headerWriter.WriteLine("#define THUNKCALL"); headerWriter.WriteLine("#endif"); headerWriter.WriteLine(); sourceWriter.WriteLine("/*"); sourceWriter.WriteLine(" * Automatically generated by thunktool from {0}", shortName); sourceWriter.WriteLine(" */"); sourceWriter.WriteLine(); sourceWriter.WriteLine("#include <stdlib.h>"); sourceWriter.WriteLine("#include <string.h>"); sourceWriter.WriteLine("#include <assert.h>"); sourceWriter.WriteLine("#include <mono/jit/jit.h>"); sourceWriter.WriteLine("#include <mono/metadata/reflection.h>"); sourceWriter.WriteLine("#include \"{0}.h\"", outputPrefix ?? "thunks"); sourceWriter.WriteLine(); foreach (var typeInfo in asm.GetTypes ()) { currentMethods = new List<ThunkMethodInfo>(); foreach (var ctor in typeInfo.GetConstructors ()) Process(ctor); foreach (var method in typeInfo.GetMethods ()) Process(method); foreach (var prop in typeInfo.GetProperties ()) Process(prop); if (currentMethods.Count == 0) continue; headerWriter.WriteLine("MonoClass *{0}__Class;", typeInfo.Name); foreach (var m in currentMethods) { headerWriter.WriteLine(); if (wantComments) headerWriter.WriteLine("/*\n * {0}\n */", m.Comments); if (!m.IsGeneric) headerWriter.WriteLine("{0}", m.QualMethodDecl); else headerWriter.WriteLine("MonoMethod *{0}__Method;", m.QualMethodName); } headerWriter.WriteLine(); sourceWriter.WriteLine("static void\n{0}_Init (MonoClass *klass)", typeInfo.Name); sourceWriter.WriteLine("{"); sourceWriter.WriteLine("\tMonoMethod *method;\n"); sourceWriter.WriteLine("\tassert (klass && \"could not lookup class '{0}'\");", typeInfo.FullName); sourceWriter.WriteLine("\t{0}__Class = klass;", typeInfo.Name); foreach (var m in currentMethods) { sourceWriter.WriteLine(); sourceWriter.WriteLine("\tmethod = mono_class_get_method_from_name (klass, \"{0}\", -1);", m.ClrMethodName); sourceWriter.WriteLine("\tassert (method && \"could not lookup method '{0}.{1}'\");", typeInfo.FullName, m.ClrMethodName); if (!m.IsGeneric) sourceWriter.WriteLine("\t{0} = mono_method_get_unmanaged_thunk (method);", m.QualMethodName); else sourceWriter.WriteLine("\t{0}__Method = method;", m.QualMethodName); } sourceWriter.WriteLine("}\n"); typeList.Add(typeInfo); } if (typeList.Count > 0) { headerWriter.WriteLine("MonoAssembly *{0}_Assembly;", name); headerWriter.WriteLine("MonoImage *{0}_Image;", name); headerWriter.WriteLine(); headerWriter.WriteLine("void\n{0}_Init (MonoAssembly *assembly);", name); headerWriter.WriteLine(); headerWriter.WriteLine("void\n{0}_Exec (void);", name); sourceWriter.WriteLine("void\n{0}_Init (MonoAssembly *assembly)", name); sourceWriter.WriteLine("{"); sourceWriter.WriteLine("\tstatic int initialized;"); sourceWriter.WriteLine("\tMonoImage *image;"); sourceWriter.WriteLine(); sourceWriter.WriteLine("\tif (initialized) return;"); sourceWriter.WriteLine(); sourceWriter.WriteLine("\tassert (assembly && \"{0}\");", name); sourceWriter.WriteLine("\timage = mono_assembly_get_image (assembly);"); sourceWriter.WriteLine("\t{0}_Assembly = assembly;", name); sourceWriter.WriteLine("\t{0}_Image = image;", name); sourceWriter.WriteLine(); foreach (var typeInfo in typeList) { sourceWriter.WriteLine("\t{1}_Init (mono_class_from_name (image, \"{0}\", \"{1}\"));", typeInfo.Namespace, typeInfo.Name); } sourceWriter.WriteLine(); sourceWriter.WriteLine("\tinitialized = 1;"); sourceWriter.WriteLine("}"); sourceWriter.WriteLine(); sourceWriter.WriteLine("void\n{0}_Exec (void)", name); sourceWriter.WriteLine("{"); sourceWriter.WriteLine("\tstatic int initialized;"); sourceWriter.WriteLine("\tchar *arg0;"); sourceWriter.WriteLine(); sourceWriter.WriteLine("\tif (initialized) return;"); sourceWriter.WriteLine("\tassert ({0}_Assembly);", name); sourceWriter.WriteLine("\targ0 = strdup(mono_image_get_filename ({0}_Image));", name); sourceWriter.WriteLine("\tmono_jit_exec (mono_domain_get (), {0}_Assembly, 1, &arg0);", name); sourceWriter.WriteLine("\tinitialized = 1;"); sourceWriter.WriteLine("}"); } headerWriter.WriteLine(); headerWriter.WriteLine("MONO_END_DECLS"); headerWriter.WriteLine("#endif"); }