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; } } } }
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]); 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) { 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--; } } }
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; } } }
public void Run(ILFunction function, ILTransformContext context) { if (running) { throw new InvalidOperationException("Reentrancy detected. Transforms (and the CSharpDecompiler) are 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; } }
public void Run(Block block, BlockTransformContext context) { if (running) { throw new InvalidOperationException("LoopingBlockTransform already running. Transforms (and the CSharpDecompiler) are 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 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) { InlineAllInBlock(context.Function, block, context); }
public StatementTransformContext(BlockTransformContext blockContext) : base(blockContext) { this.BlockContext = blockContext ?? throw new ArgumentNullException(nameof(blockContext)); }