Esempio n. 1
0
        public void Run(ILFunction function, ILTransformContext context)
        {
            var insts = LivenessHelper.GetInstructions(function);

            if (insts.Count == 1)
            {
                // empty body, skip method
                return;
            }

            // skip marked methods
            //if (function.CecilMethod.CustomAttributes.Any(x => x.AttributeType.Name == "ManualRefCounting"))
            if (function.Method.GetAttributes().Any(x => x.AttributeType.Name == "ManualRefCounting"))
            {
                return;
            }

            IEnumerable <ILVariable> vars = function.Variables;

            var usedVars = new List <ILVariable>();

            foreach (var v in vars)
            {
                //var aliasSource = TypeInference.GetAliasSource(v);

                //// don't ref count parameters like this. Todo check for out and ref parameters (does O work already?)
                //if (aliasSource?.Kind == VariableKind.Parameter && aliasSource.StackType == StackType.O)
                //	continue;

                // no typeof intermediate variables
                if (v.StoreInstructions.Count == 1 && (v.StoreInstructions.First() as StLoc)?.Value is LdTypeToken)
                {
                    continue;
                }

                // skip variables that only contain NULL, etc
                if (TypeInference.GetVariableType(v) == null)
                {
                    continue;
                }

                // only reference types or valuetypes that require ref counting
                if (TypeInference.GetVariableType(v).Kind == TypeKind.Pointer)
                {
                    continue;

                    var pType    = TypeInference.GetVariableType(v) as ICSharpCode.Decompiler.TypeSystem.PointerType;
                    var elemType = pType.ElementType;

                    //if (!elemType.IsReferenceType.Value)
                    //	continue;
                    if (!elemType.IsReferenceType.Value && !elemType.GetMethods().Any(x => x.Name.EndsWith("_AddRef")))
                    {
                        continue;
                    }
                }
                else
                {
                    if (!TypeInference.GetVariableType(v).IsReferenceType.Value&& !TypeInference.GetVariableType(v).GetMethods().Any(x => x.Name.EndsWith("_AddRef")))
                    {
                        continue;
                    }
                }


                // references are not supported in C
                Debug.Assert(TypeInference.GetVariableType(v).Kind != TypeKind.ByReference);


                //todo: are the following two needed?
                //if (TypeInference.GetVariableType(v).Kind == TypeKind.Pointer)
                //	continue;

                //if (TypeInference.GetVariableType(v).Kind == TypeKind.ByReference)
                //	continue;

                usedVars.Add(v);
            }

            vars = usedVars.ToArray();

            var liveDebug = DebugLiveness.DebugLocalLiveness(function, vars);

            AddRefCountingLocalLiveness(insts, vars);

            ILAstDebugPrinter.DebugIlAst(function, "after_ref", liveDebug);

            // Add casts to make compiler happy
            // Todo: I would prefer to access base field insead. No easy representation at this stage though.
            // Todo: move to own optimization
            foreach (var c in function.Body.Descendants.OfType <CallInstruction>())
            {
                for (int idx = 0; idx < c.Method.Parameters.Count; idx++)
                {
                    var p     = c.Method.Parameters[idx];
                    var value = c.Arguments[idx];

                    var argType = TypeInference.GetInstType(value);
                    var pType   = p.Type;

                    if (argType != null && argType != pType)
                    {
                        value.ReplaceWith(new CastClass(value.Clone(), pType));
                    }
                }
            }
        }
Esempio n. 2
0
        public static IEnumerable <EcsFile> Run(MethodReference entryPoint)
        {
            var usedTypes = GetUsedTypesOrdered(entryPoint).ToList();

            var moduleParameter = new ModuleParameters {
                Kind = ModuleKind.Dll, AssemblyResolver = entryPoint.Module.AssemblyResolver
            };
            var mod = ModuleDefinition.CreateModule("test", moduleParameter);

            // copy search path from old assembly

            // todo move to new transform, discovery transform?
            foreach (var t in usedTypes)
            {
                t.IsNestedPrivate = false;
            }

            foreach (var t in usedTypes)
            {
                mod.Types.Add(t);
            }

            (new NewobjTransform()).TransformIL(usedTypes);
            //(new ArrayTransform()).TransformIL(usedTypes);
            (new FinalizerOptimization()).TransformIL(usedTypes);
            (new VirtualCallOptimization()).TransformIL(usedTypes);
            (new MainNoReturnCodeTransform()).TransformIL(usedTypes);
            RenameTransform.Rename(usedTypes);
            (new ThisParameterTransform()).TransformIL(usedTypes);
            (new DelegateTransform()).TransformIL(usedTypes);
            (new StringLiteralOptimization()).GlobalOptimization(usedTypes);
            (new ValueTypeOptimization()).TransformIL(usedTypes);
            (new IsInstanceOptimization()).TransformIL(usedTypes); // has to be before Interface Optimization (IsInterface is set to false there)
            (new InterfaceOptimization()).TransformIL(usedTypes);
            (new FinalizerImplementationOptimization()).TransformIL(usedTypes);
            (new ExceptionTransform()).TransformIL(usedTypes);
            (new StripExternalAnnotations()).TransformIL(usedTypes);
            //(new StripTryCatch()).TransformIL(usedTypes);

            // do this after ExceptionTransform as it will create default values.
            (new PrimitiveDefaultValues()).TransformIL(usedTypes);



            ILAstDebugPrinter.ClearLogs();

            ReferenceImportHelper.ImportReferences(mod);
            mod.Write(@"logs\compacted.dll");

            File.Copy("ESharpCore.dll", @"logs\ESharpCore.dll");

            // todo, just disabled temporarly because of poiter types resolving to null?? Should this happen?
            ReferenceChecker.CheckReferences(mod);

            var files = (new DecompilerService()).Generate(usedTypes, @"logs\compacted.dll").ToList();

            // file optimization
            var fileOptimizationContext = new FileOptimizationContext {
                UsedTypes = usedTypes
            };

            TypeEnumGenerator.FileOptimization(files, fileOptimizationContext);

            IncludeCFiles.Run(files);

            var mergedFiles = CMerger.MergeIntoSingleFile(files);

            return(mergedFiles);
        }