Esempio n. 1
0
        //
        // 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());
        }
Esempio n. 2
0
    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");
    }
Esempio n. 3
0
        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);
            }
        }
Esempio n. 4
0
        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");
        }
Esempio n. 5
0
        /// <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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
            }
        }
Esempio n. 8
0
        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);
        }