public CompilationContext( TypeBuilder exportsBuilder, FieldBuilder memory, Signature[] functionSignatures, MethodInfo[] methods, Signature[] types, Compile.Indirect[] functionElements, ModuleBuilder module, Compile.GlobalInfo[] globalGetters, Compile.GlobalInfo[] globalSetters ) { Assert(exportsBuilder != null); Assert(functionSignatures != null); Assert(methods != null); Assert(types != null); Assert(module != null); this.ExportsBuilder = exportsBuilder; this.Memory = memory; this.FunctionSignatures = functionSignatures; this.Methods = methods; this.Types = types; this.GlobalGetters = globalGetters; this.GlobalSetters = globalSetters; if (functionElements == null) { return; } //Capture the information about indirectly-callable functions. var indirectBuilder = module.DefineType("☣ Indirect", TypeAttributes.Public | //Change to something more appropriate once behavior is validated. TypeAttributes.Sealed | TypeAttributes.SequentialLayout | TypeAttributes.BeforeFieldInit, typeof(System.ValueType) ); var indirectTypeFieldBuilder = indirectBuilder.DefineField( "☣ Type", typeof(uint), FieldAttributes.Public | FieldAttributes.InitOnly); var indirectMethodFieldBuilder = indirectBuilder.DefineField( "☣ Method", typeof(IntPtr), FieldAttributes.Public | FieldAttributes.InitOnly); var indirectConstructorBuilder = indirectBuilder.DefineConstructor( MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.HasThis, new[] { typeof(uint), typeof(IntPtr), } ); var il = indirectConstructorBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Stfld, indirectTypeFieldBuilder); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Stfld, indirectMethodFieldBuilder); il.Emit(OpCodes.Ret); var indirectLocationsFieldBuilder = indirectBuilder.DefineField( "☣ Locations", typeof(IntPtr), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly); this.generator = il = indirectBuilder.DefineTypeInitializer().GetILGenerator(); Instructions.Int32Constant.Emit(this, functionElements.Length); il.Emit(OpCodes.Newarr, indirectBuilder.AsType()); for (var i = 0; i < functionElements.Length; i++) { var fe = functionElements[i]; il.Emit(OpCodes.Dup); Instructions.Int32Constant.Emit(this, i); Instructions.Int32Constant.Emit(this, checked ((int)fe.type)); il.Emit(OpCodes.Ldftn, fe.function); il.Emit(OpCodes.Newobj, indirectConstructorBuilder); il.Emit(OpCodes.Stelem, indirectBuilder.AsType()); } il.Emit(OpCodes.Stsfld, indirectLocationsFieldBuilder); il.Emit(OpCodes.Ret); var indirectGetFunctionPointer = indirectBuilder.DefineMethod( "☣ Get Function Pointer", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static, CallingConventions.Standard, typeof(IntPtr), new[] { typeof(uint), typeof(uint), } ); il = indirectGetFunctionPointer.GetILGenerator(); var value = il.DeclareLocal(indirectBuilder.AsType()); var indexOutOfRange = il.DeclareLocal(typeof(IndexOutOfRangeException)); var endTry = il.BeginExceptionBlock(); il.Emit(OpCodes.Ldsfld, indirectLocationsFieldBuilder); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldelem, indirectBuilder.AsType()); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Leave_S, endTry); il.BeginCatchBlock(typeof(IndexOutOfRangeException)); il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Ldstr, "index"); il.Emit(OpCodes.Ldloc_1); il.Emit(OpCodes.Newobj, typeof(IndexOutOfRangeException).GetTypeInfo().DeclaredConstructors.First(c => { var parms = c.GetParameters(); return (parms.Length == 2 && parms[0].ParameterType == typeof(string) && parms[1].ParameterType == typeof(Exception) ); })); il.Emit(OpCodes.Throw); il.EndExceptionBlock(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldfld, indirectTypeFieldBuilder); var match = il.DefineLabel(); il.Emit(OpCodes.Beq_S, match); il.Emit(OpCodes.Ldstr, "Type mismatch"); il.Emit(OpCodes.Ldstr, "type"); il.Emit(OpCodes.Newobj, typeof(ArgumentException).GetTypeInfo().DeclaredConstructors.First(c => { var parms = c.GetParameters(); return (parms.Length == 2 && parms[0].ParameterType == typeof(string) && parms[1].ParameterType == typeof(string) ); })); il.Emit(OpCodes.Throw); il.MarkLabel(match); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ldfld, indirectMethodFieldBuilder); il.Emit(OpCodes.Ret); this.helperMethods.Add(HelperMethod.GetFunctionPointer, indirectGetFunctionPointer); indirectBuilder.CreateTypeInfo(); this.generator = null; }