private static void ImplementEsMain(MethodDefinition newMethod, MethodDefinition[] originalTests, ModuleDefinition moduleToImport) { var il = newMethod.Body.GetILProcessor(); il.Emit(OpCodes.Ldc_I4_0); foreach (var originalTest in originalTests) { // obtain reference to ctor var testClass = moduleToImport.ImportReference(originalTest.DeclaringType); var testCtor = moduleToImport.ImportReference(originalTest.DeclaringType.Methods.First(x => x.Name == ".ctor")); il.Emit(OpCodes.Nop); // create Test fixture il.Emit(OpCodes.Newobj, testCtor); // create action il.Emit(OpCodes.Ldftn, moduleToImport.ImportReference(originalTest)); il.Emit(OpCodes.Newobj, GetCtor(typeof(ECSharp.Action), moduleToImport)); var testname = originalTest.Name; il.Emit(OpCodes.Ldstr, testname); // run test il.Emit(OpCodes.Call, moduleToImport.ImportReference(SymbolExtensions.GetMethodInfo(() => TargetTestRunner.Run(null, "")))); // add results il.Emit(OpCodes.Add); } il.Emit(OpCodes.Ret); IlHelper.UpdateIlOffsets(il.Body); }
public void TransformIL(IEnumerable <TypeDefinition> types) { foreach (var t in types.Where(x => !x.IsInterface && !x.IsAbstract)) { var finalizer = t.Methods.SingleOrDefault(x => x.Name.EndsWith("Finalize")); if (finalizer == null) { continue; } var proc = finalizer.Body.GetILProcessor(); finalizer.Body.MaxStackSize = Math.Max(finalizer.Body.MaxStackSize, 2); var ret = finalizer.Body.Instructions.LastOrDefault(); if (ret != null) { finalizer.Body.Instructions.Remove(ret); } foreach (var field in t.Fields.Where( x => !x.IsStatic && !x.FieldType.IsValueType)) { proc.Emit(OpCodes.Ldarg_0); proc.Emit(OpCodes.Ldnull); proc.Emit(OpCodes.Stfld, field); } foreach (var field in t.Fields.Where(x => x.FieldType.IsValueType && ValueTypeHelper.NeedRefCounting(x.FieldType.Resolve()))) { proc.Emit(OpCodes.Ldarg_0); proc.Emit(OpCodes.Ldflda, field); proc.Emit(OpCodes.Call, field.FieldType.Resolve().Methods.Single(x => x.Name.EndsWith("RemoveRef"))); } // call base finalizer if (!t.IsValueType && t.BaseType != null && t.BaseType.Name != "EObject") { var baseFinalizer = t.BaseType.Resolve().Methods.SingleOrDefault(x => x.Name.EndsWith("Finalize")); if (baseFinalizer != null) { proc.Emit(OpCodes.Ldarg_0); proc.Emit(OpCodes.Call, baseFinalizer); } } proc.Emit(OpCodes.Ret); IlHelper.UpdateIlOffsets(finalizer.Body); } }
IEnumerable <Instruction> CreateParametersArrayInstructions(ILProcessor processor, MethodDefinition method, VariableDefinition arrayVariable /*parameters*/) { var createArray = new List <Instruction> { processor.Create(OpCodes.Ldc_I4, method.Parameters.Count), //method.Parameters.Count processor.Create(OpCodes.Newarr, objectTypeRef), // new object[method.Parameters.Count] processor.Create(OpCodes.Stloc, arrayVariable) // var objArray = new object[method.Parameters.Count] }; foreach (var p in method.Parameters) { createArray.AddRange(IlHelper.ProcessParam(p, arrayVariable)); } return(createArray); }
public void TransformIL(IEnumerable <TypeDefinition> types) { foreach (var t in types.Where(x => !x.IsInterface && !x.IsAbstract)) { var finalizer = t.Methods.SingleOrDefault(x => x.Name == "Finalize"); if (finalizer == null) // create finalizer, if doesn't exist yet { finalizer = new MethodDefinition("Finalize", MethodAttributes.Virtual, t.Module.ImportReference(typeof(void))); t.Methods.Add(finalizer); finalizer.Body = new MethodBody(finalizer); finalizer.Body.GetILProcessor().Emit(OpCodes.Ret); } } // static finalizer //var ty = new TypeDefinition("", "StaticFieldFinalizer", TypeAttributes.Class | TypeAttributes.Abstract | TypeAttributes.Sealed); var mod = ModuleDefinition.CreateModule("CreatedModule", ModuleKind.Dll); var finalizers = new MethodDefinition("NullStaticFields", MethodAttributes.Static, mod.ImportReference(typeof(void))); // todo add to ESharpCore instead?? types.Single(x => x.Name == "EObject").Methods.Add(finalizers); finalizers.Body = new MethodBody(finalizers); finalizers.Body.MaxStackSize = 1; var procs = finalizers.Body.GetILProcessor(); foreach (var field in types.SelectMany(x => x.Fields).Where(x => x.IsStatic && !x.FieldType.IsValueType)) { procs.Emit(OpCodes.Ldnull); procs.Emit(OpCodes.Stsfld, field); IlHelper.UpdateIlOffsets(finalizers.Body); } procs.Emit(OpCodes.Ret); }
public void TransformIL(IEnumerable <TypeDefinition> types) { var resolver = new ReferenceResolver(types); foreach (var t in types) { if (t.IsValueType) { // add initobj method var nm = new MethodDefinition(t.Name + "_initobj", MethodAttributes.Static, t.Module.ImportReference((typeof(void)))); nm.Parameters.Add(new ParameterDefinition("_this", ParameterAttributes.None, new PointerType(t))); var code = "memset(_this, 0, sizeof(*_this));"; EmitSource.SourceImplementation(nm, code); t.Methods.Add(nm); if (ValueTypeHelper.NeedRefCounting(t)) { foreach (var methodName in new string[] { "AddRef", "RemoveRef" }) { // add ref adjustment methods nm = new MethodDefinition(t.Name + "_" + methodName, MethodAttributes.Static, t.Module.ImportReference((typeof(void)))); nm.Parameters.Add(new ParameterDefinition("_vt", ParameterAttributes.None, new PointerType(t))); t.Methods.Add(nm); var procs = nm.Body.GetILProcessor(); foreach (var field in t.Fields.Where(x => !x.FieldType.IsValueType)) { var refMethod = types.Single(x => x.Name == "EObject").Methods.Single(x => x.Name.EndsWith("EObject_" + methodName)); // procs.Emit(OpCodes.Ldarg_0); procs.Emit(OpCodes.Ldfld, field); procs.Emit(OpCodes.Call, refMethod); } procs.Emit(OpCodes.Ret); } } var finalizer = t.Methods.Single(x => x.Name == t.Name + "_Finalize"); //if (!ValueTypeHelper.NeedRefCounting(t)) { t.Methods.Remove(finalizer); } } foreach (var t in types) { foreach (var m in t.Methods) { // C only knows pointers but no references. Replace with pointers. foreach (var p in m.Parameters) { if (p.ParameterType is ByReferenceType rt) { p.ParameterType = new PointerType(rt.ElementType); } } if (!m.HasBody) { continue; } var newBody = new List <Instruction>(); var ilp = m.Body.GetILProcessor(); // replace default with new for (int idx = 0; idx < m.Body.Instructions.Count(); idx++) { var inst = m.Body.Instructions[idx]; newBody.Add(inst); if (inst.OpCode == OpCodes.Initobj) { var initType = inst.Operand as TypeDefinition; Debug.Assert(initType.IsValueType, initType.Name + " should be a Value Type"); // adjust ref counting before memset // todo: skip this when struct is unused. if (ValueTypeHelper.NeedRefCounting(initType)) { ilp.InsertBefore(inst, ilp.Create(OpCodes.Dup)); ilp.InsertBefore(inst, ilp.Create(OpCodes.Call, initType.Methods.Single(x => x.Name.EndsWith("RemoveRef")))); } if (initType.IsPrimitive) { ilp.InsertBefore(inst, Instruction.Create(OpCodes.Ldc_I4, 0)); ilp.Replace(inst, Instruction.Create(OpCodes.Stobj, initType)); } else { var initMethod = initType.Methods.Single(x => x.Name.EndsWith("_initobj")); ilp.Replace(inst, Instruction.Create(OpCodes.Call, initMethod)); } } // try to use pointers instead of references if (inst.OpCode == OpCodes.Ldflda) { var field = (inst.Operand as FieldDefinition); ilp.InsertAfter(inst, ilp.Create(OpCodes.Conv_I)); idx++; } } //m.Body.Instructions = newBody; IlHelper.UpdateIlOffsets(m.Body); // initalizing should be done in LocalVariableInitializaionOptimization //continue; foreach (var v in m.Body.Variables) { // remove ref for valuetypes going out of scope. if (false) // currently nor needed, done in ref counting { if (v.VariableType.Resolve().IsValueType&& ValueTypeHelper.NeedRefCounting(v.VariableType.Resolve())) { // Afaik, only one return in functions var ret = ilp.Body.Instructions.Single(x => x.OpCode == OpCodes.Ret); if (ret.Operand != v) { ilp.InsertBefore(ret, ilp.Create(OpCodes.Ldloca, v)); ilp.InsertBefore(ret, ilp.Create(OpCodes.Call, v.VariableType.Resolve().Methods.Single(x => x.Name.EndsWith("RemoveRef")))); } } } } } } }