public void Run(Block block, BlockTransformContext context) { for (int i = 0; i < block.Instructions.Count; i++) { ILVariable v; ILInstruction copiedExpr; if (block.Instructions[i].MatchStLoc(out v, out copiedExpr)) { if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) { // dead store to stack if (SemanticHelper.IsPure(copiedExpr.Flags)) { // no-op -> delete context.Step("remove dead store to stack: no-op -> delete", block.Instructions[i]); block.Instructions.RemoveAt(i--); } else { // evaluate the value for its side-effects context.Step("remove dead store to stack: evaluate the value for its side-effects", block.Instructions[i]); copiedExpr.AddILRange(block.Instructions[i].ILRange); block.Instructions[i] = copiedExpr; } } else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) { DoPropagate(v, copiedExpr, block, ref i, context); } } } }
public void Run(Block block, BlockTransformContext context) { for (int i = 0; i < block.Instructions.Count; i++) { ILVariable v; ILInstruction copiedExpr; if (block.Instructions[i].MatchStLoc(out v, out copiedExpr)) { if (v.IsSingleDefinition && v.LoadCount == 0 && v.Kind == VariableKind.StackSlot) { // dead store to stack if (copiedExpr.Flags == InstructionFlags.None) { // no-op -> delete block.Instructions.RemoveAt(i--); } else { // evaluate the value for its side-effects block.Instructions[i] = copiedExpr; } } else if (v.IsSingleDefinition && CanPerformCopyPropagation(v, copiedExpr)) { DoPropagate(v, copiedExpr, block, ref i, context); } } } }
void IBlockTransform.Run(Block block, BlockTransformContext context) { this.context = context; for (int i = block.Instructions.Count - 1; i >= 0; i--) { if (TransformPostIncDecOperatorOnAddress(block, i) || TransformPostIncDecOnStaticField(block, i) || TransformCSharp4PostIncDecOperatorOnAddress(block, i)) { block.Instructions.RemoveAt(i); continue; } if (TransformPostIncDecOperator(block, i)) { block.Instructions.RemoveAt(i); continue; } if (TransformInlineAssignmentStObj(block, i)) { continue; } if (TransformInlineCompoundAssignmentCall(block, i)) { continue; } if (TransformRoslynCompoundAssignmentCall(block, i)) { continue; } } }
void IBlockTransform.Run(Block block, BlockTransformContext context) { if (!context.Settings.LockStatement) { return; } this.context = context; for (int i = block.Instructions.Count - 1; i >= 0; i--) { if (!TransformLockRoslyn(block, i)) { if (!TransformLockV4(block, i)) { if (!TransformLockV2(block, i)) { TransformLockMCS(block, i); } } } // This happens in some cases: // Use correct index after transformation. if (i >= block.Instructions.Count) { i = block.Instructions.Count; } } }
public void Run(Block block, BlockTransformContext context) { this.context = context; if (!context.Settings.AnonymousMethods) { return; } for (int i = block.Instructions.Count - 1; i >= 0; i--) { if (block.Instructions[i] is IfInstruction inst) { if (CachedDelegateInitializationWithField(inst)) { block.Instructions.RemoveAt(i); continue; } if (CachedDelegateInitializationWithLocal(inst)) { ILInlining.InlineOneIfPossible(block, i, InliningOptions.Aggressive, context); continue; } if (CachedDelegateInitializationRoslynInStaticWithLocal(inst) || CachedDelegateInitializationRoslynWithLocal(inst)) { block.Instructions.RemoveAt(i); continue; } } } }
void IBlockTransform.Run(Block block, BlockTransformContext context) { this.context = context; for (int i = block.Instructions.Count - 1; i >= 0; i--) { DoTransform(block, i); } }
public void Run(Block block, BlockTransformContext context) { var ctx = new StatementTransformContext(context); int pos = 0; ctx.rerunPosition = block.Instructions.Count - 1; while (pos >= 0) { if (ctx.rerunPosition != null) { Debug.Assert(ctx.rerunPosition >= pos); #if DEBUG for (; pos < ctx.rerunPosition; ++pos) { block.Instructions[pos].ResetDirty(); } #else pos = ctx.rerunPosition.Value; #endif Debug.Assert(pos == ctx.rerunPosition); ctx.rerunPosition = null; } foreach (var transform in children) { transform.Run(block, pos, ctx); #if DEBUG block.Instructions[pos].CheckInvariant(ILPhase.Normal); for (int i = Math.Max(0, pos - 100); i < pos; ++i) { if (block.Instructions[i].IsDirty) { Debug.Fail($"{transform.GetType().Name} modified an instruction before pos"); } } #endif if (ctx.rerunCurrentPosition) { ctx.rerunCurrentPosition = false; ctx.RequestRerun(pos); } if (ctx.rerunPosition != null) { break; } } if (ctx.rerunPosition == null) { pos--; } } // This invariant can be surprisingly expensive to check if the block has thousands // of instructions and is frequently modified by transforms (invalidating the flags each time) // so we'll check this only once at the end of the block. Debug.Assert(block.HasFlag(InstructionFlags.EndPointUnreachable)); }
void IBlockTransform.Run(Block block, BlockTransformContext context) { this.context = context; for (int i = block.Instructions.Count - 1; i >= 0; i--) { if (TransformNullCoalescing(block, i)) { block.Instructions.RemoveAt(i); continue; } } }
public void Run(Block block, BlockTransformContext context) { var ctx = new StatementTransformContext(context); int pos = 0; ctx.rerunPosition = block.Instructions.Count - 1; while (pos >= 0) { if (ctx.rerunPosition != null) { Debug.Assert(ctx.rerunPosition >= pos); #if DEBUG for (; pos < ctx.rerunPosition; ++pos) { block.Instructions[pos].ResetDirty(); } #else pos = ctx.rerunPosition.Value; #endif Debug.Assert(pos == ctx.rerunPosition); ctx.rerunPosition = null; } foreach (var transform in children) { Debug.Assert(block.HasFlag(InstructionFlags.EndPointUnreachable)); transform.Run(block, pos, ctx); #if DEBUG block.Instructions[pos].CheckInvariant(ILPhase.Normal); for (int i = Math.Max(0, pos - 100); i < pos; ++i) { if (block.Instructions[i].IsDirty) { Debug.Fail($"{transform.GetType().Name} modified an instruction before pos"); } } #endif if (ctx.rerunCurrentPosition) { ctx.rerunCurrentPosition = false; ctx.RequestRerun(pos); } if (ctx.rerunPosition != null) { break; } } if (ctx.rerunPosition == null) { pos--; } } }
public void Run(ILFunction function, ILTransformContext context) { var blockContext = new BlockTransformContext(context); blockContext.Function = function; foreach (var container in function.Descendants.OfType <BlockContainer>().ToList()) { context.CancellationToken.ThrowIfCancellationRequested(); blockContext.ControlFlowGraph = new ControlFlowGraph(container, context.CancellationToken); VisitBlock(blockContext.ControlFlowGraph.GetNode(container.EntryPoint), blockContext); // TODO: handle unreachable code? } }
void IBlockTransform.Run(Block block, BlockTransformContext context) { this.context = context; for (int i = block.Instructions.Count - 1; i >= 0; i--) { DoTransform(block, i); // This happens in some cases: // Use correct index after transformation. if (i >= block.Instructions.Count) { i = block.Instructions.Count; } } }
public void Run(ILFunction function, ILTransformContext context) { if (running) throw new InvalidOperationException("Reentrancy detected. Transforms (and the CSharpDecompiler) are neither neither thread-safe nor re-entrant."); try { running = true; var blockContext = new BlockTransformContext(context); Debug.Assert(blockContext.Function == function); foreach (var container in function.Descendants.OfType<BlockContainer>().ToList()) { context.CancellationToken.ThrowIfCancellationRequested(); blockContext.ControlFlowGraph = new ControlFlowGraph(container, context.CancellationToken); VisitBlock(blockContext.ControlFlowGraph.GetNode(container.EntryPoint), blockContext); // TODO: handle unreachable code? } } finally { running = false; } }
void IBlockTransform.Run(Block block, BlockTransformContext context) { if (!context.Settings.UsingStatement) { return; } this.context = context; for (int i = block.Instructions.Count - 1; i >= 0; i--) { if (!TransformUsing(block, i) && !TransformUsingVB(block, i)) { continue; } // This happens in some cases: // Use correct index after transformation. if (i >= block.Instructions.Count) { i = block.Instructions.Count; } } }
void VisitBlock(ControlFlowNode cfgNode, BlockTransformContext context) { Block block = (Block)cfgNode.UserData; context.StepStartGroup(block.Label, block); context.ControlFlowNode = cfgNode; context.Block = block; block.RunTransforms(PreOrderTransforms, context); // First, process the children in the dominator tree. // The ConditionDetection transform requires dominated blocks to // be already processed. foreach (var child in cfgNode.DominatorTreeChildren) { VisitBlock(child, context); } context.ControlFlowNode = cfgNode; context.Block = block; block.RunTransforms(PostOrderTransforms, context); context.StepEndGroup(); }
public void Run(Block block, BlockTransformContext context) { if (running) { throw new InvalidOperationException("LoopingBlockTransform already running. Transforms (and the CSharpDecompiler) are neither neither thread-safe nor re-entrant."); } running = true; try { int count = 1; do { block.ResetDirty(); block.RunTransforms(children, context); if (block.IsDirty) { context.Step($"Block is dirty; running loop iteration #{++count}.", block); } } while (block.IsDirty); } finally { running = false; } }
void IBlockTransform.Run(Block block, BlockTransformContext context) { if (!context.Settings.UsingStatement) { return; } this.context = context; for (int i = block.Instructions.Count - 1; i >= 0; i--) { if (TransformUsing(block, i)) { continue; } if (TransformUsingVB(block, i)) { continue; } if (TransformAsyncUsing(block, i)) { continue; } } }
public void Run(Block block, BlockTransformContext context) { InlineAllInBlock(context.Function, block, context); }
internal static bool IsPotentialClosure(BlockTransformContext context, NewObj inst) { var decompilationContext = new SimpleTypeResolveContext(context.TypeSystem.Resolve(context.Function.Method)); return(IsPotentialClosure(decompilationContext.CurrentTypeDefinition, inst.Method.DeclaringTypeDefinition)); }
public void Run(Block block, BlockTransformContext context) { new NullableLiftingTransform(context).RunBlock(block); }
public void Run(Block block, BlockTransformContext context) { InlineAllInBlock(block, context); }
public void Run(Block block, BlockTransformContext context) { RunOnBlock(block, context); }
public void Run(Block block, BlockTransformContext context) { this.context = context; Default(block); }
public StatementTransformContext(BlockTransformContext blockContext) : base(blockContext) { this.BlockContext = blockContext ?? throw new ArgumentNullException(nameof(blockContext)); }