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)); } } } }
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); }