예제 #1
0
        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);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
    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);
    }
예제 #4
0
        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);
        }
예제 #5
0
        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"))));
                                }
                            }
                        }
                    }
                }
            }
        }