void IILTransform.Run(ILFunction function, ILTransformContext context) { if (!context.Settings.AnonymousMethods) { return; } this.context = context; this.decompilationContext = new SimpleTypeResolveContext(function.Method); var orphanedVariableInits = new List <ILInstruction>(); var targetsToReplace = new List <IInstructionWithVariableOperand>(); var translatedDisplayClasses = new HashSet <ITypeDefinition>(); foreach (var block in function.Descendants.OfType <Block>()) { for (int i = block.Instructions.Count - 1; i >= 0; i--) { context.CancellationToken.ThrowIfCancellationRequested(); foreach (var call in block.Instructions[i].Descendants.OfType <NewObj>()) { ILFunction f = TransformDelegateConstruction(call, out ILInstruction target); if (f != null) { f.AddILRange(call.Arguments[0].ILRange); f.AddILRange(call.Arguments[1].ILRange); call.Arguments[0].ReplaceWith(new LdNull()); call.Arguments[1].ReplaceWith(f); if (target is IInstructionWithVariableOperand && !target.MatchLdThis()) { targetsToReplace.Add((IInstructionWithVariableOperand)target); } } } if (block.Instructions[i].MatchStLoc(out ILVariable targetVariable, out ILInstruction value)) { var newObj = value as NewObj; // TODO : it is probably not a good idea to remove *all* display-classes // is there a way to minimize the false-positives? if (newObj != null && IsInSimpleDisplayClass(newObj.Method)) { targetVariable.CaptureScope = FindBlockContainer(block); targetsToReplace.Add((IInstructionWithVariableOperand)block.Instructions[i]); translatedDisplayClasses.Add(newObj.Method.DeclaringTypeDefinition); } } } } foreach (var target in targetsToReplace.OrderByDescending(t => ((ILInstruction)t).ILRange.Start)) { function.AcceptVisitor(new TransformDisplayClassUsages(function, target, target.Variable.CaptureScope, orphanedVariableInits, translatedDisplayClasses)); } foreach (var store in orphanedVariableInits) { if (store.Parent is Block containingBlock) { containingBlock.Instructions.Remove(store); } } }
void IILTransform.Run(ILFunction function, ILTransformContext context) { if (!context.Settings.AnonymousMethods) { return; } this.context = context; this.decompilationContext = new SimpleTypeResolveContext(function.Method); var orphanedVariableInits = new List <ILInstruction>(); var targetsToReplace = new List <IInstructionWithVariableOperand>(); var translatedDisplayClasses = new HashSet <ITypeDefinition>(); var cancellationToken = context.CancellationToken; foreach (var inst in function.Descendants) { cancellationToken.ThrowIfCancellationRequested(); if (inst is NewObj call) { context.StepStartGroup($"TransformDelegateConstruction {call.StartILOffset}", call); ILFunction f = TransformDelegateConstruction(call, out ILInstruction target); if (f != null && target is IInstructionWithVariableOperand instWithVar) { if (instWithVar.Variable.Kind == VariableKind.Local) { instWithVar.Variable.Kind = VariableKind.DisplayClassLocal; } targetsToReplace.Add(instWithVar); } context.StepEndGroup(); } if (inst.MatchStLoc(out ILVariable targetVariable, out ILInstruction value)) { var newObj = value as NewObj; // TODO : it is probably not a good idea to remove *all* display-classes // is there a way to minimize the false-positives? if (newObj != null && IsInSimpleDisplayClass(newObj.Method)) { targetVariable.CaptureScope = BlockContainer.FindClosestContainer(inst); targetsToReplace.Add((IInstructionWithVariableOperand)inst); translatedDisplayClasses.Add(newObj.Method.DeclaringTypeDefinition); } } } foreach (var target in targetsToReplace.OrderByDescending(t => ((ILInstruction)t).StartILOffset)) { context.Step($"TransformDisplayClassUsages {target.Variable}", (ILInstruction)target); function.AcceptVisitor(new TransformDisplayClassUsages(function, target, target.Variable.CaptureScope, orphanedVariableInits, translatedDisplayClasses)); } context.Step($"Remove orphanedVariableInits", function); foreach (var store in orphanedVariableInits) { if (store.Parent is Block containingBlock) { containingBlock.Instructions.Remove(store); } } }
internal static void ResetHasInitialValueFlag(ILFunction function, ILTransformContext context) { var visitor = new DefiniteAssignmentVisitor(function, context.CancellationToken); function.AcceptVisitor(visitor); foreach (var v in function.Variables) { if (v.Kind != VariableKind.Parameter && !visitor.IsPotentiallyUsedUninitialized(v)) { v.HasInitialValue = false; } } }
static void CollectNamespacesFromMethodBody(IMethod method, ILFunction body, HashSet <string> namespaces) { body.AcceptVisitor(new ILCollectionVisitor(namespaces)); foreach (var v in body.Variables) { CollectNamespacesForTypeReference(v.Type, namespaces); } foreach (var node in body.Descendants) { if (node is LdsFlda staticField) { CollectNamespacesForMemberReference(staticField.Field, namespaces); } else if (node is CallInstruction call && call.Method.IsStatic) { CollectNamespacesForMemberReference(call.Method, namespaces); }
public void Run(ILFunction function, ILTransformContext context) { cancellationToken = context.CancellationToken; currentExit = NoExit; blocksPotentiallyMadeUnreachable.Clear(); function.AcceptVisitor(this); // It's possible that there are unreachable code blocks which we only // detect as such during exit point detection. // Clean them up. foreach (var block in blocksPotentiallyMadeUnreachable) { if (block.IncomingEdgeCount == 0 || block.IncomingEdgeCount == 1 && IsInfiniteLoop(block)) { block.Remove(); } } blocksPotentiallyMadeUnreachable.Clear(); }
public void Run(ILFunction function, ILTransformContext context) { cancellationToken = context.CancellationToken; currentExit = NoExit; function.AcceptVisitor(this); }