public void Run(ILFunction function, ILTransformContext context) { try { if (this.context != null) { throw new InvalidOperationException("Reentrancy in " + nameof(TransformDisplayClassUsage)); } this.context = context; var decompilationContext = new SimpleTypeResolveContext(context.Function.Method); // Traverse nested functions in post-order: // Inner functions are transformed before outer functions foreach (var f in function.Descendants.OfType <ILFunction>()) { foreach (var v in f.Variables.ToArray()) { if (context.Settings.YieldReturn && HandleMonoStateMachine(function, v, decompilationContext, f)) { continue; } if ((context.Settings.AnonymousMethods || context.Settings.ExpressionTrees) && IsClosure(context, v, out ITypeDefinition closureType, out var inst)) { if (!CanRemoveAllReferencesTo(context, v)) { continue; } instructionsToRemove.Add(inst); AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false); continue; } if (context.Settings.LocalFunctions && f.Kind == ILFunctionKind.LocalFunction && v.Kind == VariableKind.Parameter && v.Index > -1 && f.Method.Parameters[v.Index.Value] is IParameter p && LocalFunctionDecompiler.IsClosureParameter(p, decompilationContext)) { AddOrUpdateDisplayClass(f, v, ((ByReferenceType)p.Type).ElementType.GetDefinition(), f.Body, localFunctionClosureParameter: true); continue; } AnalyzeUseSites(v); } } VisitILFunction(function); if (instructionsToRemove.Count > 0) { context.Step($"Remove instructions", function); foreach (var store in instructionsToRemove) { if (store.Parent is Block containingBlock) { containingBlock.Instructions.Remove(store); } } } RemoveDeadVariableInit.ResetHasInitialValueFlag(function, context); } finally { instructionsToRemove.Clear(); displayClasses.Clear(); fieldAssignmentsWithVariableValue.Clear(); this.context = null; } }
public void Run(ILFunction function, ILTransformContext context) { try { if (this.context != null || this.currentFunction != null) { throw new InvalidOperationException("Reentrancy in " + nameof(TransformDisplayClassUsage)); } this.context = context; var decompilationContext = new SimpleTypeResolveContext(context.Function.Method); // Traverse nested functions in post-order: // Inner functions are transformed before outer functions foreach (var f in function.Descendants.OfType <ILFunction>()) { foreach (var v in f.Variables.ToArray()) { if (HandleMonoStateMachine(function, v, decompilationContext, f)) { continue; } if (IsClosure(v, out ITypeDefinition closureType, out var inst)) { AddOrUpdateDisplayClass(f, v, closureType, inst, localFunctionClosureParameter: false); } if (context.Settings.LocalFunctions && f.Kind == ILFunctionKind.LocalFunction && v.Kind == VariableKind.Parameter && v.Index > -1 && f.Method.Parameters[v.Index.Value] is IParameter p && LocalFunctionDecompiler.IsClosureParameter(p, decompilationContext)) { AddOrUpdateDisplayClass(f, v, ((ByReferenceType)p.Type).ElementType.GetDefinition(), f.Body, localFunctionClosureParameter: true); } } foreach (var displayClass in displayClasses.Values.OrderByDescending(d => d.Initializer.StartILOffset).ToArray()) { context.Step($"Transform references to " + displayClass.Variable, displayClass.Initializer); this.currentFunction = f; VisitILFunction(f); } } if (instructionsToRemove.Count > 0) { context.Step($"Remove instructions", function); foreach (var store in instructionsToRemove) { if (store.Parent is Block containingBlock) { containingBlock.Instructions.Remove(store); } } } RemoveDeadVariableInit.ResetHasInitialValueFlag(function, context); } finally { instructionsToRemove.Clear(); displayClasses.Clear(); this.context = null; this.currentFunction = null; } }