// // Initializes the assembly SRE domain // public void Create(Universe domain) { ResolveAssemblySecurityAttributes(); var an = CreateAssemblyName(); Builder = domain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save, Path.GetDirectoryName(file_name)); module.Create(this, CreateModuleBuilder()); }
static void Main(string[] args) { Universe universe = new Universe(); AssemblyName name = new AssemblyName("System.Core"); AssemblyBuilder ab = universe.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save); ModuleBuilder modb = ab.DefineDynamicModule("System.Core", "System.Core.dll"); TypeBuilder tb = modb.DefineType("System.Runtime.CompilerServices.ExtensionAttribute", TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed, universe.Import(typeof(Attribute))); tb.DefineDefaultConstructor(MethodAttributes.Public); tb.CreateType(); ab.Save("System.Core.dll"); }
public TableDumper(string inputFile) { universe = new Universe(UniverseOptions.None); var raw = universe.OpenRawModule(System.IO.File.OpenRead(inputFile), System.IO.Path.GetTempPath() + "/Dummy"); if (raw.IsManifestModule) { assembly = universe.LoadAssembly(raw); module = assembly.ManifestModule; } else { var ab = universe.DefineDynamicAssembly(new AssemblyName("<ModuleContainer>"), IKVM.Reflection.Emit.AssemblyBuilderAccess.ReflectionOnly); assembly = ab; module = ab.__AddModule(raw); } }
static void Main(string[] args) { Universe u = new Universe(); var asm = u.DefineDynamicAssembly(new AssemblyName("test2"), IKVM.Reflection.Emit.AssemblyBuilderAccess.Save); var mod = asm.DefineDynamicModule("test2", "test2.exe"); System.Func <System.Type, Type> L = ty => u.Load(ty.Assembly.FullName).GetType(ty.FullName); var t = mod.DefineType("test2.Test", TypeAttributes.Public, L(typeof(Totem.Library.Function))); var md = t.DefineMethod("Main", MethodAttributes.Static | MethodAttributes.Public, L(typeof(void)), Type.EmptyTypes); asm.SetEntryPoint(md); var ctor = t.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); var il = md.GetILGenerator(); il.Emit(OpCodes.Ldstr, "Click enter to start"); il.Emit(OpCodes.Call, L(typeof(System.Console)).GetMethod("WriteLine", new Type[] { L(typeof(string)) })); il.Emit(OpCodes.Call, L(typeof(System.Console)).GetMethod("ReadLine", Type.EmptyTypes)); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Callvirt, L(typeof(TotemFunction)).GetMethod("Execute")); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Call, L(typeof(System.Console)).GetMethod("ReadLine", Type.EmptyTypes)); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ret); var ctorIl = ctor.GetILGenerator(); ctorIl.Emit(OpCodes.Ldarg_0); ctorIl.Emit(OpCodes.Call, L(typeof(TotemScope)).GetProperty("Global").GetGetMethod()); ctorIl.Emit(OpCodes.Ldstr, "Main"); ctorIl.Emit(OpCodes.Ldnull); ctorIl.Emit(OpCodes.Call, L(typeof(TotemFunction)).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { L(typeof(TotemScope)), L(typeof(string)), L(typeof(TotemParameter[])) }, null)); ctorIl.Emit(OpCodes.Ret); t.CreateType(); asm.Save("test2.exe"); }
/// <summary> /// Generates the stub .exe file for starting the app /// </summary> /// <param name="config"></param> private static void GenerateExe(Config config) { var u = new Universe(); var aName = new AssemblyName(Path.GetFileNameWithoutExtension(new FileInfo(config.Output).Name)); var ab = u.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save, config.OutputPath); var mb = ab.DefineDynamicModule(config.Output, aName.Name + (aName.Name.EndsWith(".exe") ? string.Empty : ".exe")); var tb = mb.DefineType("PythonMain", IKVM.Reflection.TypeAttributes.Public); if (!string.IsNullOrEmpty(config.Win32Icon)) { ab.__DefineIconResource(File.ReadAllBytes(config.Win32Icon)); } var attributes = new List <Tuple <string, Type> > { Tuple.Create(config.FileVersion, u.Import(typeof(System.Reflection.AssemblyFileVersionAttribute))), Tuple.Create(config.ProductName, u.Import(typeof(System.Reflection.AssemblyProductAttribute))), Tuple.Create(config.ProductVersion, u.Import(typeof(System.Reflection.AssemblyInformationalVersionAttribute))), Tuple.Create(config.Copyright, u.Import(typeof(System.Reflection.AssemblyCopyrightAttribute))) }; foreach (var attr in attributes) { if (!string.IsNullOrWhiteSpace(config.FileVersion)) { CustomAttributeBuilder builder = new CustomAttributeBuilder(attr.Item2.GetConstructor(new[] { u.Import(typeof(string)) }), new object[] { attr.Item1 }); ab.SetCustomAttribute(builder); } } ab.DefineVersionInfoResource(); MethodBuilder assemblyResolveMethod = null; ILGenerator gen = null; if (config.Standalone) { ConsoleOps.Info("Generating stand alone executable"); config.Embed = true; foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies()) { var n = new AssemblyName(a.FullName); if (!a.IsDynamic && a.EntryPoint == null && (n.Name.StartsWith("IronPython") || n.Name == "Microsoft.Dynamic" || n.Name == "Microsoft.Scripting")) { ConsoleOps.Info($"\tEmbedded {n.Name} {n.Version}"); var f = new FileStream(a.Location, FileMode.Open, FileAccess.Read); mb.DefineManifestResource("Dll." + n.Name, f, IKVM.Reflection.ResourceAttributes.Public); } } foreach (var dll in config.DLLs) { var name = Path.GetFileNameWithoutExtension(dll); ConsoleOps.Info($"\tEmbedded {name}"); var f = new FileStream(dll, FileMode.Open, FileAccess.Read); mb.DefineManifestResource("Dll." + name, f, IKVM.Reflection.ResourceAttributes.Public); } // we currently do no error checking on what is passed in to the assemblyresolve event handler assemblyResolveMethod = tb.DefineMethod("AssemblyResolve", MethodAttributes.Public | MethodAttributes.Static, u.Import(typeof(System.Reflection.Assembly)), new IKVM.Reflection.Type[] { u.Import(typeof(System.Object)), u.Import(typeof(System.ResolveEventArgs)) }); gen = assemblyResolveMethod.GetILGenerator(); var s = gen.DeclareLocal(u.Import(typeof(System.IO.Stream))); // resource stream gen.Emit(OpCodes.Ldnull); gen.Emit(OpCodes.Stloc, s); var d = gen.DeclareLocal(u.Import(typeof(byte[]))); // data buffer; gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetEntryAssembly"), Type.EmptyTypes); gen.Emit(OpCodes.Ldstr, "Dll."); gen.Emit(OpCodes.Ldarg_1); // The event args gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.ResolveEventArgs)).GetMethod("get_Name"), Type.EmptyTypes); gen.Emit(OpCodes.Newobj, u.Import(typeof(System.Reflection.AssemblyName)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(string)) })); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.AssemblyName)).GetMethod("get_Name"), Type.EmptyTypes); gen.EmitCall(OpCodes.Call, u.Import(typeof(string)).GetMethod("Concat", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)) }), Type.EmptyTypes); gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetManifestResourceStream", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes); gen.Emit(OpCodes.Stloc, s); gen.Emit(OpCodes.Ldloc, s); gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.IO.Stream)).GetMethod("get_Length"), Type.EmptyTypes); gen.Emit(OpCodes.Newarr, u.Import(typeof(System.Byte))); gen.Emit(OpCodes.Stloc, d); gen.Emit(OpCodes.Ldloc, s); gen.Emit(OpCodes.Ldloc, d); gen.Emit(OpCodes.Ldc_I4_0); gen.Emit(OpCodes.Ldloc, s); gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.IO.Stream)).GetMethod("get_Length"), Type.EmptyTypes); gen.Emit(OpCodes.Conv_I4); gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.IO.Stream)).GetMethod("Read", new IKVM.Reflection.Type[] { u.Import(typeof(byte[])), u.Import(typeof(int)), u.Import(typeof(int)) }), Type.EmptyTypes); gen.Emit(OpCodes.Pop); gen.Emit(OpCodes.Ldloc, d); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("Load", new IKVM.Reflection.Type[] { u.Import(typeof(byte[])) }), Type.EmptyTypes); gen.Emit(OpCodes.Ret); // generate a static constructor to assign the AssemblyResolve handler (otherwise it tries to use IronPython before it adds the handler) // the other way of handling this would be to move the call to InitializeModule into a separate method. var staticConstructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); gen = staticConstructor.GetILGenerator(); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.AppDomain)).GetMethod("get_CurrentDomain"), Type.EmptyTypes); gen.Emit(OpCodes.Ldnull); gen.Emit(OpCodes.Ldftn, assemblyResolveMethod); gen.Emit(OpCodes.Newobj, u.Import(typeof(System.ResolveEventHandler)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(object)), u.Import(typeof(System.IntPtr)) })); gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.AppDomain)).GetMethod("add_AssemblyResolve"), Type.EmptyTypes); gen.Emit(OpCodes.Ret); } var mainMethod = tb.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, u.Import(typeof(int)), Type.EmptyTypes); if (config.Target == PEFileKinds.WindowApplication && config.UseMta) { mainMethod.SetCustomAttribute(u.Import(typeof(System.MTAThreadAttribute)).GetConstructor(Type.EmptyTypes), new byte[0]); } else if (config.Target == PEFileKinds.WindowApplication) { mainMethod.SetCustomAttribute(u.Import(typeof(System.STAThreadAttribute)).GetConstructor(Type.EmptyTypes), new byte[0]); } gen = mainMethod.GetILGenerator(); // variables for saving original working directory and return code of script var strVar = gen.DeclareLocal(u.Import(typeof(string))); var intVar = gen.DeclareLocal(u.Import(typeof(int))); LocalBuilder dictVar = null; if (config.PythonOptions.Count > 0) { var True = u.Import(typeof(ScriptingRuntimeHelpers)).GetField("True"); var False = u.Import(typeof(ScriptingRuntimeHelpers)).GetField("False"); dictVar = gen.DeclareLocal(u.Import(typeof(Dictionary <string, object>))); gen.Emit(OpCodes.Newobj, u.Import(typeof(Dictionary <string, object>)).GetConstructor(Type.EmptyTypes)); gen.Emit(OpCodes.Stloc, dictVar); foreach (var option in config.PythonOptions) { gen.Emit(OpCodes.Ldloc, dictVar); gen.Emit(OpCodes.Ldstr, option.Key); if (option.Value is int val) { if (val >= -128 && val <= 127) { gen.Emit(OpCodes.Ldc_I4_S, val); // this is more optimized } else { gen.Emit(OpCodes.Ldc_I4, val); } gen.Emit(OpCodes.Box, u.Import(typeof(System.Int32))); } else if (option.Value.Equals(ScriptingRuntimeHelpers.True)) { gen.Emit(OpCodes.Ldsfld, True); } else if (option.Value.Equals(ScriptingRuntimeHelpers.False)) { gen.Emit(OpCodes.Ldsfld, False); } gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(Dictionary <string, object>)).GetMethod("Add", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(object)) }), Type.EmptyTypes); } } Label tryStart = gen.BeginExceptionBlock(); // get the ScriptCode assembly... if (config.Embed) { // put the generated DLL into the resources for the stub exe var mem = new MemoryStream(); var rw = new ResourceWriter(mem); rw.AddResource("IPDll." + Path.GetFileNameWithoutExtension(config.Output) + ".dll", File.ReadAllBytes(Path.Combine(config.OutputPath, config.Output) + ".dll")); rw.Generate(); mem.Position = 0; mb.DefineManifestResource("IPDll.resources", mem, ResourceAttributes.Public); File.Delete(Path.Combine(config.OutputPath, config.Output) + ".dll"); // generate code to load the resource gen.Emit(OpCodes.Ldstr, "IPDll"); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetEntryAssembly"), Type.EmptyTypes); gen.Emit(OpCodes.Newobj, u.Import(typeof(System.Resources.ResourceManager)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(System.Reflection.Assembly)) })); gen.Emit(OpCodes.Ldstr, "IPDll." + Path.GetFileNameWithoutExtension(config.Output) + ".dll"); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Resources.ResourceManager)).GetMethod("GetObject", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("Load", new IKVM.Reflection.Type[] { u.Import(typeof(byte[])) }), Type.EmptyTypes); } else { // save current working directory gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Environment)).GetMethod("get_CurrentDirectory"), Type.EmptyTypes); gen.Emit(OpCodes.Stloc, strVar); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetEntryAssembly"), Type.EmptyTypes); gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Reflection.Assembly)).GetMethod("get_Location"), Type.EmptyTypes); gen.Emit(OpCodes.Newobj, u.Import(typeof(System.IO.FileInfo)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(string)) })); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.IO.FileInfo)).GetMethod("get_Directory"), Type.EmptyTypes); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.IO.DirectoryInfo)).GetMethod("get_FullName"), Type.EmptyTypes); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Environment)).GetMethod("set_CurrentDirectory"), Type.EmptyTypes); gen.Emit(OpCodes.Ldstr, config.Output + ".dll"); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.IO.Path)).GetMethod("GetFullPath", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes); // result of GetFullPath stays on the stack during the restore of the // original working directory // restore original working directory gen.Emit(OpCodes.Ldloc, strVar); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Environment)).GetMethod("set_CurrentDirectory"), Type.EmptyTypes); // for the LoadFile() call, the full path of the assembly is still is on the stack // as the result from the call to GetFullPath() gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("LoadFile", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes); } // emit module name gen.Emit(OpCodes.Ldstr, "__main__"); // main module name gen.Emit(OpCodes.Ldnull); // no references gen.Emit(OpCodes.Ldc_I4_0); // don't ignore environment variables for engine startup if (config.PythonOptions.Count > 0) { gen.Emit(OpCodes.Ldloc, dictVar); } else { gen.Emit(OpCodes.Ldnull); } // call InitializeModuleEx // (this will also run the script) // and put the return code on the stack gen.EmitCall(OpCodes.Call, u.Import(typeof(PythonOps)).GetMethod("InitializeModuleEx", new IKVM.Reflection.Type[] { u.Import(typeof(System.Reflection.Assembly)), u.Import(typeof(string)), u.Import(typeof(string[])), u.Import(typeof(bool)), u.Import(typeof(Dictionary <string, object>)) }), Type.EmptyTypes); gen.Emit(OpCodes.Stloc, intVar); gen.BeginCatchBlock(u.Import(typeof(Exception))); if (config.Target == PEFileKinds.ConsoleApplication) { gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Exception)).GetMethod("get_Message", Type.EmptyTypes), Type.EmptyTypes); gen.Emit(OpCodes.Stloc, strVar); gen.Emit(OpCodes.Ldstr, config.ErrorMessageFormat); gen.Emit(OpCodes.Ldloc, strVar); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Console)).GetMethod("WriteLine", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)) }), Type.EmptyTypes); } else { gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Exception)).GetMethod("get_Message", Type.EmptyTypes), Type.EmptyTypes); gen.Emit(OpCodes.Stloc, strVar); gen.Emit(OpCodes.Ldstr, config.ErrorMessageFormat); gen.Emit(OpCodes.Ldloc, strVar); gen.EmitCall(OpCodes.Call, u.Import(typeof(string)).GetMethod("Format", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)) }), Type.EmptyTypes); gen.Emit(OpCodes.Ldstr, "Error"); gen.Emit(OpCodes.Ldc_I4, (int)System.Windows.Forms.MessageBoxButtons.OK); gen.Emit(OpCodes.Ldc_I4, (int)System.Windows.Forms.MessageBoxIcon.Error); gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Windows.Forms.MessageBox)).GetMethod("Show", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)), u.Import(typeof(System.Windows.Forms.MessageBoxButtons)), u.Import(typeof(System.Windows.Forms.MessageBoxIcon)) }), Type.EmptyTypes); gen.Emit(OpCodes.Pop); } gen.Emit(OpCodes.Ldc_I4, -1); // return code is -1 to show failure gen.Emit(OpCodes.Stloc, intVar); gen.EndExceptionBlock(); gen.Emit(OpCodes.Ldloc, intVar); gen.Emit(OpCodes.Ret); tb.CreateType(); ab.SetEntryPoint(mainMethod, config.Target); string fileName = aName.Name.EndsWith(".exe") ? aName.Name : aName.Name + ".exe"; ab.Save(fileName, config.Platform, config.Machine); }
public override bool Execute() { PortableExecutableKinds peKind; ImageFileMachine machine; if (Platform.Equals("X86", StringComparison.OrdinalIgnoreCase)) { peKind = PortableExecutableKinds.Required32Bit; machine = ImageFileMachine.I386; } else if (Platform.Equals("amd64", StringComparison.OrdinalIgnoreCase)) { peKind = PortableExecutableKinds.PE32Plus; machine = ImageFileMachine.AMD64; } else if (Platform.Equals("arm", StringComparison.OrdinalIgnoreCase)) { peKind = PortableExecutableKinds.Unmanaged32Bit; machine = ImageFileMachine.ARM; } else { Log.LogError("Unrecognized Platform value: {0}", Platform); return(false); } foreach (var asm in References) { universe.LoadFile(asm.GetMetadata("FullPath")); } List <Export> exports = new List <Export>(); bool defFileOK = ParseDefFile(DefFile, exports); if (!defFileOK) { return(false); } AssemblyName name = new AssemblyName(OutputFile.GetMetadata("FileName")); name.Version = new Version(Version); AssemblyBuilder ab = universe.DefineDynamicAssembly(name, AssemblyBuilderAccess.Save); ModuleBuilder modb = ab.DefineDynamicModule(name.Name, OutputFile.GetMetadata("FullPath")); foreach (Export exp in exports) { ExportMethod(modb, exp); } modb.CreateGlobalFunctions(); if (Win32Resource != null) { ab.DefineUnmanagedResource(Win32Resource.GetMetadata("FullPath")); } else { if (FileDescription != null) { var ctor = universe.Import(typeof(System.Reflection.AssemblyTitleAttribute)).GetConstructor(new Type[] { universe.Import(typeof(string)) }); ab.SetCustomAttribute(new CustomAttributeBuilder(ctor, new object[] { FileDescription })); } ab.DefineVersionInfoResource(Product, Version.ToString(), Company, Copyright, null); } ab.Save(OutputFile.GetMetadata("FullPath"), peKind, machine); Log.LogMessage("{0} -> {1}", DefFile.ItemSpec, OutputFile.ItemSpec); return(true); }
private void DoIt() { AssemblyName aname = new AssemblyName(); aname.Name = Path.GetFileNameWithoutExtension(outFile); if (culture != null) { aname.CultureInfo = new CultureInfo(culture); } string fileName = Path.GetFileName(outFile); AssemblyBuilder ab; /* * Emit Manifest * */ if (isTemplateFile) { aname = ReadCustomAttributesFromTemplateFile(templateFile, aname); } if (!String.IsNullOrEmpty(title)) { AddCattr(typeof(System.Reflection.AssemblyTitleAttribute), title); } if (!String.IsNullOrEmpty(description)) { AddCattr(typeof(System.Reflection.AssemblyDescriptionAttribute), description); } if (!String.IsNullOrEmpty(company)) { AddCattr(typeof(System.Reflection.AssemblyCompanyAttribute), company); } if (!String.IsNullOrEmpty(product)) { AddCattr(typeof(System.Reflection.AssemblyProductAttribute), product); } if (!String.IsNullOrEmpty(copyright)) { AddCattr(typeof(System.Reflection.AssemblyCopyrightAttribute), copyright); } if (!String.IsNullOrEmpty(trademark)) { AddCattr(typeof(System.Reflection.AssemblyTrademarkAttribute), trademark); } SetKeyPair(aname); if (fileName != outFile) { ab = universe.DefineDynamicAssembly(aname, AssemblyBuilderAccess.Save, Path.GetDirectoryName(outFile)); } else { ab = universe.DefineDynamicAssembly(aname, AssemblyBuilderAccess.Save); } foreach (CustomAttributeBuilder cb in cattrs) { ab.SetCustomAttribute(cb); } /* * Emit modules */ foreach (ModuleInfo mod in inputFiles) { if (mod.target != null) { File.Copy(mod.fileName, mod.target, true); mod.fileName = mod.target; } bool isAssembly = false; try { AssemblyName.GetAssemblyName(mod.fileName); isAssembly = true; } catch (Exception) { } if (isAssembly) { ReportWarning(1020, "Ignoring included assembly '" + mod.fileName + "'"); } else { ab.__AddModule(universe.OpenRawModule(mod.fileName)); } } /* * Set entry point */ if (entryPoint != null) { string mainClass = entryPoint.Substring(0, entryPoint.LastIndexOf('.')); string mainMethod = entryPoint.Substring(entryPoint.LastIndexOf('.') + 1); MethodInfo mainMethodInfo = null; try { IKVM.Reflection.Type mainType = ab.GetType(mainClass); if (mainType != null) { mainMethodInfo = mainType.GetMethod(mainMethod); } } catch (Exception ex) { Console.WriteLine(ex); } if (mainMethodInfo != null) { ab.SetEntryPoint(mainMethodInfo); } else { Report(1037, "Unable to find the entry point method '" + entryPoint + "'"); } } /* * Emit resources */ ab.DefineVersionInfoResource(); if (win32IconFile != null) { try { ab.__DefineIconResource(File.ReadAllBytes(win32IconFile)); } catch (Exception ex) { Report(1031, "Error reading icon '" + win32IconFile + "' --" + ex); } } if (win32ResFile != null) { try { ab.DefineUnmanagedResource(win32ResFile); } catch (Exception ex) { Report(1019, "Metadata failure creating assembly -- " + ex); } } ModuleBuilder mainModule = null; foreach (ResourceInfo res in resources) { if (res.name == null) { res.name = Path.GetFileName(res.fileName); } foreach (ResourceInfo res2 in resources) { if ((res != res2) && (res.name == res2.name)) { Report(1046, String.Format("Resource identifier '{0}' has already been used in this assembly", res.name)); } } if (res.isEmbedded) { if (mainModule == null) { mainModule = ab.DefineDynamicModule(fileName, fileName, false); } Stream stream = new MemoryStream(File.ReadAllBytes(res.fileName)); mainModule.DefineManifestResource(res.name, stream, res.isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public); } else { if (res.target != null) { File.Copy(res.fileName, res.target, true); res.fileName = res.target; } // AddResourceFile must receive a file name and not a path. // Drop directory and give warning if we have a path. var resourceFileName = Path.GetFileName(res.fileName); if (Path.GetDirectoryName(res.fileName) != null || Path.IsPathRooted(res.fileName)) { ReportWarning(99999, String.Format("Path '{0}' in the resource name is not supported. Using just file name '{1}'", res.fileName, resourceFileName)); } ab.AddResourceFile(res.name, resourceFileName, res.isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public); } } PortableExecutableKinds pekind = PortableExecutableKinds.ILOnly; ImageFileMachine machine; switch (platform) { case Platform.X86: pekind |= PortableExecutableKinds.Required32Bit; machine = ImageFileMachine.I386; break; case Platform.X64: pekind |= PortableExecutableKinds.PE32Plus; machine = ImageFileMachine.AMD64; break; case Platform.IA64: machine = ImageFileMachine.IA64; break; case Platform.AnyCPU32Preferred: pekind |= PortableExecutableKinds.Preferred32Bit; machine = ImageFileMachine.I386; break; case Platform.Arm: machine = ImageFileMachine.ARM; break; case Platform.AnyCPU: default: machine = ImageFileMachine.I386; break; } try { ab.Save(fileName, pekind, machine); } catch (Exception ex) { Report(1019, "Metadata failure creating assembly -- " + ex); } }
private static IKVM.Reflection.Emit.AssemblyBuilder FromBinary( string assemblyName, Reader reader, Universe universe, IKVM.Reflection.Type instanceContainer, IKVM.Reflection.Type exportContainer, IEnumerable <RuntimeImport> imports ) { if (reader.ReadUInt32() != Module.Magic) { throw new ModuleLoadException("File preamble magic value is incorrect.", 0); } switch (reader.ReadUInt32()) { case 0x1: //First release case 0xd: //Final pre-release, binary format is identical with first release. break; default: throw new ModuleLoadException("Unsupported version, only version 0x1 and 0xd are accepted.", 4); } uint memoryPagesMinimum = 0; uint memoryPagesMaximum = 0; Signature[] signatures = null; Signature[] functionSignatures = null; KeyValuePair <string, uint>[] exportedFunctions = null; var previousSection = Section.None; var assembly = universe.DefineDynamicAssembly( new IKVM.Reflection.AssemblyName(assemblyName), new IKVM.Reflection.Emit.AssemblyBuilderAccess() ); var dllName = assemblyName + ".dll"; var module = assembly.DefineDynamicModule(assemblyName, dllName); const IKVM.Reflection.TypeAttributes classAttributes = IKVM.Reflection.TypeAttributes.Public | IKVM.Reflection.TypeAttributes.Class | IKVM.Reflection.TypeAttributes.BeforeFieldInit ; const IKVM.Reflection.MethodAttributes constructorAttributes = IKVM.Reflection.MethodAttributes.Public | IKVM.Reflection.MethodAttributes.HideBySig | IKVM.Reflection.MethodAttributes.SpecialName | IKVM.Reflection.MethodAttributes.RTSpecialName ; const IKVM.Reflection.MethodAttributes internalFunctionAttributes = IKVM.Reflection.MethodAttributes.Assembly | IKVM.Reflection.MethodAttributes.Static | IKVM.Reflection.MethodAttributes.HideBySig ; const IKVM.Reflection.MethodAttributes exportedFunctionAttributes = IKVM.Reflection.MethodAttributes.Public | IKVM.Reflection.MethodAttributes.Virtual | IKVM.Reflection.MethodAttributes.Final | IKVM.Reflection.MethodAttributes.HideBySig ; var exportsBuilder = module.DefineType("CompiledExports", classAttributes, exportContainer); IKVM.Reflection.MethodInfo importedMemoryProvider = null; IKVM.Reflection.Emit.FieldBuilder memory = null; IKVM.Reflection.Emit.ILGenerator instanceConstructorIL; { var instanceConstructor = exportsBuilder.DefineConstructor(constructorAttributes, IKVM.Reflection.CallingConventions.Standard, IKVM.Reflection.Type.EmptyTypes); instanceConstructorIL = instanceConstructor.GetILGenerator(); { var usableConstructor = exportContainer.GetTypeInfo().DeclaredConstructors.FirstOrDefault(c => c.GetParameters().Length == 0); if (usableConstructor != null) { instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, usableConstructor); } } } var exports = exportsBuilder.AsType(); var importedFunctions = 0; IKVM.Reflection.MethodInfo[] internalFunctions = null; Indirect[] functionElements = null; GlobalInfo[] globalGetters = null; GlobalInfo[] globalSetters = null; IKVMCompilationContext context = null; IKVM.Reflection.MethodInfo startFunction = null; var preSectionOffset = reader.Offset; while (reader.TryReadVarUInt7(out var id)) //At points where TryRead is used, the stream can safely end. { if (id != 0 && (Section)id < previousSection) { throw new ModuleLoadException($"Sections out of order; section {(Section)id} encounterd after {previousSection}.", preSectionOffset); } var payloadLength = reader.ReadVarUInt32(); switch ((Section)id) { case Section.None: { var preNameOffset = reader.Offset; reader.ReadString(reader.ReadVarUInt32()); //Name reader.ReadBytes(payloadLength - checked ((uint)(reader.Offset - preNameOffset))); //Content } break; case Section.Type: { signatures = new Signature[reader.ReadVarUInt32()]; for (var i = 0; i < signatures.Length; i++) { signatures[i] = new Signature(universe, reader, (uint)i); } } break; case Section.Import: { if (imports == null) { imports = Enumerable.Empty <RuntimeImport>(); } var importsByName = imports.ToDictionary(import => new Tuple <string, string>(import.ModuleName, import.FieldName)); var count = checked ((int)reader.ReadVarUInt32()); var functionImports = new List <IKVM.Reflection.MethodInfo>(count); var functionImportTypes = new List <Signature>(count); for (var i = 0; i < count; i++) { var moduleName = reader.ReadString(reader.ReadVarUInt32()); var fieldName = reader.ReadString(reader.ReadVarUInt32()); if (!importsByName.TryGetValue(new Tuple <string, string>(moduleName, fieldName), out var import)) { throw new CompilerException($"Import not found for {moduleName}::{fieldName}."); } var preKindOffset = reader.Offset; var kind = (ExternalKind)reader.ReadByte(); switch (kind) { case ExternalKind.Function: var typeIndex = reader.ReadVarUInt32(); if (!(import is FunctionImport functionImport)) { throw new CompilerException($"{moduleName}::{fieldName} is expected to be a function, but provided import was not."); } var signature = signatures[typeIndex]; if (!signature.Equals(functionImport.Type)) { throw new CompilerException($"{moduleName}::{fieldName} did not match the required type signature."); } functionImports.Add(functionImport.IKVMMethod); functionImportTypes.Add(signature); break; case ExternalKind.Memory: var limits = new ResizableLimits(reader); if (!(import is MemoryImport memoryImport)) { throw new CompilerException($"{moduleName}::{fieldName} is expected to be memory, but provided import was not."); } importedMemoryProvider = memoryImport.IKVMMethod; break; case ExternalKind.Table: break; case ExternalKind.Global: throw new ModuleLoadException($"Imported external kind of {kind} is not currently supported.", preKindOffset); default: throw new ModuleLoadException($"Imported external kind of {kind} is not recognized.", preKindOffset); } } importedFunctions = functionImports.Count; internalFunctions = functionImports.ToArray(); functionSignatures = functionImportTypes.ToArray(); } break; case Section.Function: { var importedFunctionCount = internalFunctions == null ? 0 : internalFunctions.Length; var functionIndexSize = checked ((int)(importedFunctionCount + reader.ReadVarUInt32())); if (functionSignatures != null) { Array.Resize(ref functionSignatures, functionIndexSize); } else { functionSignatures = new Signature[functionIndexSize]; } if (importedFunctionCount != 0) { Array.Resize(ref internalFunctions, checked (functionSignatures.Length)); } else { internalFunctions = new IKVM.Reflection.MethodInfo[functionSignatures.Length]; } for (var i = importedFunctionCount; i < functionSignatures.Length; i++) { var signature = functionSignatures[i] = signatures[reader.ReadVarUInt32()]; var parms = signature.IKVMParameterTypes.Concat(new[] { exports }).ToArray(); internalFunctions[i] = exportsBuilder.DefineMethod( $"👻 {i}", internalFunctionAttributes, IKVM.Reflection.CallingConventions.Standard, signature.IKVMReturnTypes.FirstOrDefault(), parms ); } } break; case Section.Table: { var count = reader.ReadVarUInt32(); for (var i = 0; i < count; i++) { var elementType = (ElementType)reader.ReadVarInt7(); switch (elementType) { default: throw new ModuleLoadException($"Element type {elementType} not supported.", reader.Offset - 1); case ElementType.AnyFunction: var setFlags = (ResizableLimits.Flags)reader.ReadVarUInt32(); functionElements = new Indirect[reader.ReadVarUInt32()]; if ((setFlags & ResizableLimits.Flags.Maximum) != 0) { reader.ReadVarUInt32(); //Not used. } break; } } } break; case Section.Memory: { var preCountOffset = reader.Offset; var count = reader.ReadVarUInt32(); if (count > 1) { throw new ModuleLoadException("Multiple memory values are not supported.", preCountOffset); } var setFlags = (ResizableLimits.Flags)reader.ReadVarUInt32(); memoryPagesMinimum = reader.ReadVarUInt32(); if ((setFlags & ResizableLimits.Flags.Maximum) != 0) { memoryPagesMaximum = Math.Min(reader.ReadVarUInt32(), uint.MaxValue / Memory.PageSize); } else { memoryPagesMaximum = uint.MaxValue / Memory.PageSize; } memory = exportsBuilder.DefineField("☣ Memory", universe.Import(typeof(Runtime.UnmanagedMemory)), IKVM.Reflection.FieldAttributes.Private | IKVM.Reflection.FieldAttributes.InitOnly); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); if (importedMemoryProvider == null) { Instructions.Int32Constant.Emit(instanceConstructorIL, (int)memoryPagesMinimum); Instructions.Int32Constant.Emit(instanceConstructorIL, (int)memoryPagesMaximum); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Newobj, universe.Import(typeof(uint?)).GetTypeInfo().DeclaredConstructors.Where(info => { var parms = info.GetParameters(); return(parms.Length == 1 && parms[0].ParameterType == universe.Import(typeof(uint))); }).First()); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Newobj, universe.Import(typeof(Runtime.UnmanagedMemory)).GetTypeInfo().DeclaredConstructors.Where(info => { var parms = info.GetParameters(); return(parms.Length == 2 && parms[0].ParameterType == universe.Import(typeof(uint)) && parms[1].ParameterType == universe.Import(typeof(uint?))); }).First()); } else { instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, importedMemoryProvider); } instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Stfld, memory); exportsBuilder.AddInterfaceImplementation(universe.Import(typeof(IDisposable))); List <IKVM.Reflection.Type> ikvmEmptyTypes = new List <IKVM.Reflection.Type>(); foreach (System.Type type in System.Type.EmptyTypes) { ikvmEmptyTypes.Add(universe.Import(type)); } var dispose = exportsBuilder.DefineMethod( "Dispose", IKVM.Reflection.MethodAttributes.Public | IKVM.Reflection.MethodAttributes.Virtual | IKVM.Reflection.MethodAttributes.Final | IKVM.Reflection.MethodAttributes.HideBySig | IKVM.Reflection.MethodAttributes.NewSlot, IKVM.Reflection.CallingConventions.HasThis, universe.Import(typeof(void)), ikvmEmptyTypes.ToArray() ); var disposeIL = dispose.GetILGenerator(); disposeIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); disposeIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldfld, memory); disposeIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, universe.Import(typeof(Runtime.UnmanagedMemory)) .GetTypeInfo() .DeclaredMethods .Where(info => info.ReturnType == universe.Import(typeof(void)) && info.GetParameters().Length == 0 && info.Name == nameof(Runtime.UnmanagedMemory.Dispose)) .First()); disposeIL.Emit(IKVM.Reflection.Emit.OpCodes.Ret); } break; case Section.Global: { var count = reader.ReadVarUInt32(); globalGetters = new GlobalInfo[count]; globalSetters = new GlobalInfo[count]; context = new IKVMCompilationContext( universe, exportsBuilder, memory, functionSignatures, internalFunctions, signatures, null, module, globalGetters, globalSetters ); var emptySignature = Signature.Empty; for (var i = 0; i < globalGetters.Length; i++) { var contentType = (ValueType)reader.ReadVarInt7(); var isMutable = reader.ReadVarUInt1() == 1; var getter = exportsBuilder.DefineMethod( $"🌍 Get {i}", internalFunctionAttributes, IKVM.Reflection.CallingConventions.Standard, universe.Import(contentType.ToSystemType()), isMutable ? new[] { exports } : null ); globalGetters[i] = new GlobalInfo(contentType, isMutable, getter); var il = getter.GetILGenerator(); var getterSignature = new Signature(contentType); if (isMutable == false) { context.Reset( il, getterSignature, getterSignature.RawParameterTypes ); foreach (var instruction in Instruction.ParseInitializerExpression(reader)) { instruction.CompileIKVM(context, universe); context.Previous = instruction.OpCode; } } else //Mutable { var field = exportsBuilder.DefineField( $"🌍 {i}", universe.Import(contentType.ToSystemType()), IKVM.Reflection.FieldAttributes.Private | (isMutable ? 0 : IKVM.Reflection.FieldAttributes.InitOnly) ); il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); il.Emit(IKVM.Reflection.Emit.OpCodes.Ldfld, field); il.Emit(IKVM.Reflection.Emit.OpCodes.Ret); var setter = exportsBuilder.DefineMethod( $"🌍 Set {i}", internalFunctionAttributes, IKVM.Reflection.CallingConventions.Standard, universe.Import(typeof(void)), new[] { universe.Import(contentType.ToSystemType()), exports } ); il = setter.GetILGenerator(); il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_1); il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); il.Emit(IKVM.Reflection.Emit.OpCodes.Stfld, field); il.Emit(IKVM.Reflection.Emit.OpCodes.Ret); globalSetters[i] = new GlobalInfo(contentType, isMutable, setter); context.Reset( instanceConstructorIL, emptySignature, emptySignature.RawParameterTypes ); context.EmitLoadThis(); var ended = false; foreach (var instruction in Instruction.ParseInitializerExpression(reader)) { if (ended) { throw new CompilerException("Only a single End is allowed within an initializer expression."); } if (instruction.OpCode == OpCode.End) { context.Emit(IKVM.Reflection.Emit.OpCodes.Stfld, field); ended = true; continue; } instruction.CompileIKVM(context, universe); context.Previous = instruction.OpCode; } } } } break; case Section.Export: { const IKVM.Reflection.MethodAttributes exportedPropertyAttributes = IKVM.Reflection.MethodAttributes.Public | IKVM.Reflection.MethodAttributes.HideBySig | IKVM.Reflection.MethodAttributes.SpecialName | IKVM.Reflection.MethodAttributes.Virtual | IKVM.Reflection.MethodAttributes.Final; var totalExports = reader.ReadVarUInt32(); var xFunctions = new List <KeyValuePair <string, uint> >((int)Math.Min(int.MaxValue, totalExports)); for (var i = 0; i < totalExports; i++) { var name = reader.ReadString(reader.ReadVarUInt32()); var kind = (ExternalKind)reader.ReadByte(); var preIndexOffset = reader.Offset; var index = reader.ReadVarUInt32(); switch (kind) { case ExternalKind.Function: xFunctions.Add(new KeyValuePair <string, uint>(name, index)); break; case ExternalKind.Table: throw new NotSupportedException($"Unsupported export kind {kind}."); case ExternalKind.Memory: if (index != 0) { throw new ModuleLoadException($"Exported memory must be of index 0, found {index}.", preIndexOffset); } if (memory == null) { throw new CompilerException("Cannot export linear memory when linear memory is not defined."); } { var memoryGetter = exportsBuilder.DefineMethod("get_" + name, exportedPropertyAttributes, IKVM.Reflection.CallingConventions.HasThis, universe.Import(typeof(Runtime.UnmanagedMemory)), IKVM.Reflection.Type.EmptyTypes ); var getterIL = memoryGetter.GetILGenerator(); getterIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); getterIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldfld, memory); getterIL.Emit(IKVM.Reflection.Emit.OpCodes.Ret); exportsBuilder.DefineProperty(name, IKVM.Reflection.PropertyAttributes.None, universe.Import(typeof(Runtime.UnmanagedMemory)), IKVM.Reflection.Type.EmptyTypes) .SetGetMethod(memoryGetter); } break; case ExternalKind.Global: if (index >= globalGetters.Length) { throw new ModuleLoadException($"Exported global index of {index} is greater than the number of globals {globalGetters.Length}.", preIndexOffset); } { var getter = globalGetters[i]; var setter = globalSetters[i]; var property = exportsBuilder.DefineProperty(name, IKVM.Reflection.PropertyAttributes.None, universe.Import(getter.Type.ToSystemType()), IKVM.Reflection.Type.EmptyTypes); var wrappedGet = exportsBuilder.DefineMethod("get_" + name, exportedPropertyAttributes, IKVM.Reflection.CallingConventions.HasThis, universe.Import(getter.Type.ToSystemType()), IKVM.Reflection.Type.EmptyTypes ); var wrappedGetIL = wrappedGet.GetILGenerator(); if (getter.IsMutable) { wrappedGetIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); } wrappedGetIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, getter.Builder); wrappedGetIL.Emit(IKVM.Reflection.Emit.OpCodes.Ret); property.SetGetMethod(wrappedGet); if (setter != null) { var wrappedSet = exportsBuilder.DefineMethod("set_" + name, exportedPropertyAttributes, IKVM.Reflection.CallingConventions.HasThis, null, new[] { universe.Import(getter.Type.ToSystemType()) } ); var wrappedSetIL = wrappedSet.GetILGenerator(); wrappedSetIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_1); wrappedSetIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); wrappedSetIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, setter.Builder); wrappedSetIL.Emit(IKVM.Reflection.Emit.OpCodes.Ret); property.SetSetMethod(wrappedSet); } } break; default: throw new NotSupportedException($"Unrecognized export kind {kind}."); } } exportedFunctions = xFunctions.ToArray(); } break; case Section.Start: { var preReadOffset = reader.Offset; var startIndex = reader.ReadVarInt32(); if (startIndex >= internalFunctions.Length) { throw new ModuleLoadException($"Start function of index {startIndex} exceeds available functions of {internalFunctions.Length}", preReadOffset); } startFunction = internalFunctions[startIndex]; } break; case Section.Element: { if (functionElements == null) { throw new ModuleLoadException("Element section found without an associated table section.", preSectionOffset); } var count = reader.ReadVarUInt32(); for (var i = 0; i < count; i++) { var preIndexOffset = reader.Offset; var index = reader.ReadVarUInt32(); if (index != 0) { throw new ModuleLoadException($"Index value of anything other than 0 is not supported, {index} found.", preIndexOffset); } { var preInitializerOffset = reader.Offset; var initializer = Instruction.ParseInitializerExpression(reader).ToArray(); if (initializer.Length != 2 || !(initializer[0] is Instructions.Int32Constant c) || c.Value != 0 || !(initializer[1] is Instructions.End)) { throw new ModuleLoadException("Initializer expression support for the Element section is limited to a single Int32 constant of 0 followed by end.", preInitializerOffset); } } var preElementsOffset = reader.Offset; var elements = reader.ReadVarUInt32(); if (elements != functionElements.Length) { throw new ModuleLoadException($"Element count {elements} does not match the indication provided by the earlier table {functionElements.Length}.", preElementsOffset); } for (var j = 0; j < functionElements.Length; j++) { var functionIndex = reader.ReadVarUInt32(); functionElements[j] = new Indirect( functionSignatures[functionIndex].TypeIndex, (IKVM.Reflection.Emit.MethodBuilder)internalFunctions[importedFunctions + functionIndex] ); } } } break; case Section.Code: { var preBodiesIndex = reader.Offset; var functionBodies = reader.ReadVarUInt32(); if (functionBodies > 0 && (functionSignatures == null || functionSignatures.Length == importedFunctions)) { throw new ModuleLoadException("Code section is invalid when Function section is missing.", preBodiesIndex); } if (functionBodies != functionSignatures.Length - importedFunctions) { throw new ModuleLoadException($"Code section has {functionBodies} functions described but {functionSignatures.Length - importedFunctions} were expected.", preBodiesIndex); } if (context == null) //Might have been created by the Global section, if present. { context = new IKVMCompilationContext( universe, exportsBuilder, memory, functionSignatures, internalFunctions, signatures, functionElements, module, globalGetters, globalSetters ); } for (var functionBodyIndex = 0; functionBodyIndex < functionBodies; functionBodyIndex++) { var signature = functionSignatures[importedFunctions + functionBodyIndex]; var byteLength = reader.ReadVarUInt32(); var startingOffset = reader.Offset; var locals = new Local[reader.ReadVarUInt32()]; for (var localIndex = 0; localIndex < locals.Length; localIndex++) { locals[localIndex] = new Local(reader); } var il = ((IKVM.Reflection.Emit.MethodBuilder)internalFunctions[importedFunctions + functionBodyIndex]).GetILGenerator(); context.Reset( il, signature, signature.RawParameterTypes.Concat( locals .SelectMany(local => Enumerable.Range(0, checked ((int)local.Count)).Select(_ => local.Type)) ).ToArray() ); foreach (var local in locals.SelectMany(local => Enumerable.Range(0, checked ((int)local.Count)).Select(_ => local.Type))) { il.DeclareLocal(universe.Import(local.ToSystemType())); } foreach (var instruction in Instruction.Parse(reader)) { instruction.CompileIKVM(context, universe); context.Previous = instruction.OpCode; } if (reader.Offset - startingOffset != byteLength) { throw new ModuleLoadException($"Instruction sequence reader ended after readering {reader.Offset - startingOffset} characters, expected {byteLength}.", reader.Offset); } } } break; case Section.Data: { if (memory == null) { throw new ModuleLoadException("Data section cannot be used unless a memory section is defined.", preSectionOffset); } var count = reader.ReadVarUInt32(); if (context == null) //Would only be null if there is no Global or Code section, but have to check. { context = new IKVMCompilationContext( universe, exportsBuilder, memory, new Signature[0], new IKVM.Reflection.MethodInfo[0], new Signature[0], functionElements, module, globalGetters, globalSetters ); } context.Reset( instanceConstructorIL, Signature.Empty, Signature.Empty.RawParameterTypes ); var block = new Instructions.Block(BlockType.Int32); var address = instanceConstructorIL.DeclareLocal(universe.Import(typeof(uint))); for (var i = 0; i < count; i++) { var startingOffset = reader.Offset; { var index = reader.ReadVarUInt32(); if (index != 0) { throw new ModuleLoadException($"Data index must be 0, found {index}.", startingOffset); } } block.CompileIKVM(context, universe); //Prevents "end" instruction of the initializer expression from becoming a return. foreach (var instruction in Instruction.ParseInitializerExpression(reader)) { instruction.CompileIKVM(context, universe); context.Previous = instruction.OpCode; } context.Stack.Pop(); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Stloc, address); var data = reader.ReadBytes(reader.ReadVarUInt32()); //Ensure sufficient memory is allocated, error if max is exceeded. instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldloc, address); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4, data.Length); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Add_Ovf_Un); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, Instructions.MemoryImmediateInstruction.IKVMCreateRangeCheck(HelperMethod.RangeCheck8, context, universe)); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Pop); if (data.Length > 0x3f0000) //Limitation of DefineInitializedData, can be corrected by splitting the data. { throw new NotSupportedException($"Data segment {i} is length {data.Length}, exceeding the current implementation limit of 4128768."); } var field = exportsBuilder.DefineInitializedData($"☣ Data {i}", data, IKVM.Reflection.FieldAttributes.Assembly | IKVM.Reflection.FieldAttributes.InitOnly); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldfld, memory); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, Runtime.UnmanagedMemory.IKVMStartGetter(universe)); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldloc, address); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Conv_I); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Add_Ovf_Un); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldsflda, field); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldc_I4, data.Length); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Cpblk); } } break; default: throw new ModuleLoadException($"Unrecognized section type {(Section)id}.", preSectionOffset); } previousSection = (Section)id; } if (exportedFunctions != null) { for (var i = 0; i < exportedFunctions.Length; i++) { var exported = exportedFunctions[i]; var signature = functionSignatures[exported.Value]; List <IKVM.Reflection.Type> signaturearray = new List <IKVM.Reflection.Type>(); foreach (var s in signature.ParameterTypes) { signaturearray.Add(universe.Import(s)); } var method = exportsBuilder.DefineMethod( exported.Key, exportedFunctionAttributes, IKVM.Reflection.CallingConventions.HasThis, universe.Import(signature.ReturnTypes.FirstOrDefault()), signaturearray.ToArray() ); var il = method.GetILGenerator(); for (var parm = 0; parm < signature.ParameterTypes.Length; parm++) { il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg, parm + 1); } il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); il.Emit(IKVM.Reflection.Emit.OpCodes.Call, internalFunctions[exported.Value]); il.Emit(IKVM.Reflection.Emit.OpCodes.Ret); } } if (startFunction != null) { instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Call, startFunction); } instanceConstructorIL.Emit(IKVM.Reflection.Emit.OpCodes.Ret); //Finish the constructor. var exportInfo = exportsBuilder.CreateTypeInfo(); IKVM.Reflection.TypeInfo instance; { var instanceBuilder = module.DefineType("CompiledInstance", classAttributes, instanceContainer); var instanceConstructor = instanceBuilder.DefineConstructor(constructorAttributes, IKVM.Reflection.CallingConventions.Standard, null); var il = instanceConstructor.GetILGenerator(); var memoryAllocated = checked (memoryPagesMaximum * Memory.PageSize); il.Emit(IKVM.Reflection.Emit.OpCodes.Ldarg_0); il.Emit(IKVM.Reflection.Emit.OpCodes.Newobj, exportInfo.DeclaredConstructors.First()); il.Emit(IKVM.Reflection.Emit.OpCodes.Call, instanceContainer .GetTypeInfo() .DeclaredConstructors .First(info => info.GetParameters() .FirstOrDefault() ?.ParameterType == exportContainer )); il.Emit(IKVM.Reflection.Emit.OpCodes.Ret); instance = instanceBuilder.CreateTypeInfo(); } module.CreateGlobalFunctions(); return(assembly); }