public SwitchBlock(NodeBlock source, ControlBlock defaultCase, List <Case> cases, ControlBlock join) : base(source) { defaultCase_ = defaultCase; cases_ = cases; join_ = join; }
public WhileLoop(ControlType type, NodeBlock source, ControlBlock body, ControlBlock join) : base(source) { body_ = body; join_ = join; type_ = type; }
public WhileLoop(ControlType type, LogicChain logic, ControlBlock body, ControlBlock join) : base(null) { body_ = body; join_ = join; logic_ = logic; type_ = type; }
public IfBlock(NodeBlock source, bool invert, ControlBlock trueArm, ControlBlock falseArm, ControlBlock join) : base(source) { trueArm_ = trueArm; falseArm_ = falseArm; join_ = join; invert_ = invert; }
public void write(ControlBlock root) { writeSignature(root.source); outputLine("{"); increaseIndent(); writeBlock(root); decreaseIndent(); outputLine("}"); }
public IfBlock(NodeBlock source, LogicChain chain, ControlBlock trueArm, ControlBlock falseArm, ControlBlock join) : base(source) { trueArm_ = trueArm; falseArm_ = falseArm; join_ = join; invert_ = invert; logic_ = logic; }
private IfBlock traverseIf(NodeBlock block, DJumpCondition jcc) { if (HasSharedTarget(block, jcc)) { return(traverseComplexIf(block, jcc)); } NodeBlock trueTarget = (jcc.spop == SPOpcode.jzer) ? jcc.falseTarget : jcc.trueTarget; NodeBlock falseTarget = (jcc.spop == SPOpcode.jzer) ? jcc.trueTarget : jcc.falseTarget; NodeBlock joinTarget = findJoinOfSimpleIf(block, jcc); // If there is no join block (both arms terminate control flow), // eliminate one arm and use the other as a join point. if (joinTarget == null) { joinTarget = falseTarget; } // If the false target is equivalent to the join point, eliminate // it. if (BlockAnalysis.EffectiveTarget(falseTarget) == joinTarget) { falseTarget = null; } // If the true target is equivalent to the join point, promote // the false target to the true target and undo the inversion. bool invert = false; if (BlockAnalysis.EffectiveTarget(trueTarget) == joinTarget) { trueTarget = falseTarget; falseTarget = null; invert ^= true; } // If there is always a true target and a join target. pushScope(joinTarget); ControlBlock trueArm = traverseBlock(trueTarget); popScope(); ControlBlock joinArm = traverseJoin(joinTarget); if (falseTarget == null) { return(new IfBlock(block, invert, trueArm, joinArm)); } pushScope(joinTarget); ControlBlock falseArm = traverseBlock(falseTarget); popScope(); return(new IfBlock(block, invert, trueArm, falseArm, joinArm)); }
private ControlBlock traverseLoop(NodeBlock block) { DNode last = block.nodes.last; NodeBlock effectiveHeader = block; LogicChain chain = null; if (last.type == NodeType.JumpCondition) { DJumpCondition jcc = (DJumpCondition)last; if (HasSharedTarget(block, jcc)) { chain = buildLogicChain(block, null, out effectiveHeader); } } last = effectiveHeader.nodes.last; //Debug.Assert(last.type == NodeType.JumpCondition); if (last.type == NodeType.JumpCondition) { // Assert that the backedge is a straight jump. //Debug.Assert(BlockAnalysis.GetSingleTarget(graph_[block.lir.backedge.id]) == block); NodeBlock join, body, cond; ControlType type = findLoopJoinAndBody(block, effectiveHeader, out join, out body, out cond); ControlBlock joinArm = traverseBlock(join); ControlBlock bodyArm = null; if (body != null) { pushScope(block); pushScope(cond); bodyArm = traverseBlockNoLoop(body); popScope(); popScope(); } if (chain != null) { return(new WhileLoop(type, chain, bodyArm, joinArm)); } return(new WhileLoop(type, cond, bodyArm, joinArm)); } return(null); }
private ControlBlock traverseSwitch(NodeBlock block, DSwitch switch_) { var dominators = new List <LBlock>(); for (int i = 0; i < block.lir.idominated.Length; i++) { dominators.Add(block.lir.idominated[i]); } dominators.Remove(switch_.defaultCase); for (int i = 0; i < switch_.numCases; i++) { dominators.Remove(switch_.getCase(i).target); } NodeBlock join = null; if (dominators.Count > 0) { //Debug.Assert(dominators.Count == 1); join = graph_[dominators[dominators.Count - 1].id]; } ControlBlock joinArm = null; if (join != null) { joinArm = traverseBlock(join); } pushScope(join); var cases = new List <SwitchBlock.Case>(); ControlBlock defaultArm = traverseBlock(graph_[switch_.defaultCase.id]); for (int i = 0; i < switch_.numCases; i++) { ControlBlock arm = traverseBlock(graph_[switch_.getCase(i).target.id]); cases.Add(new SwitchBlock.Case(switch_.getCase(i).value, arm)); } popScope(); return(new SwitchBlock(block, defaultArm, cases, joinArm)); }
private void writeBlock(ControlBlock block) { if (block == null) { return; } switch (block.type) { case ControlType.If: writeIf((IfBlock)block); break; case ControlType.WhileLoop: writeWhileLoop((WhileLoop)block); break; case ControlType.DoWhileLoop: writeDoWhileLoop((WhileLoop)block); break; case ControlType.Statement: writeStatementBlock((StatementBlock)block); break; case ControlType.Return: writeStatements(block.source); writeReturn((DReturn)block.source.nodes.last); break; case ControlType.Switch: writeSwitch((SwitchBlock)block); break; default: Debug.Assert(false); break; } }
private ControlBlock traverseBlockNoLoop(NodeBlock block) { if (block == null) { return(null); } DNode last = block.nodes.last; if (last.type == NodeType.JumpCondition) { return(traverseIf(block, (DJumpCondition)last)); } if (last.type == NodeType.Jump) { DJump jump = (DJump)last; NodeBlock target = BlockAnalysis.EffectiveTarget(jump.target); ControlBlock next = null; if (!isJoin(target)) { next = traverseBlock(target); } return(new StatementBlock(block, next)); } if (last.type == NodeType.Switch) { return(traverseSwitch(block, (DSwitch)last)); } //Debug.Assert(last.type == NodeType.Return); return(new ReturnBlock(block)); }
public Case(int value, ControlBlock target) { value_ = value; target_ = target; }
public StatementBlock(NodeBlock source, ControlBlock next) : base(source) { next_ = next; }
public SwitchBlock(NodeBlock source, ControlBlock defaultCase, List<Case> cases, ControlBlock join) : base(source) { defaultCase_ = defaultCase; cases_ = cases; join_ = join; }
private IfBlock traverseComplexIf(NodeBlock block, DJumpCondition jcc) { // Degenerate case: using || or &&, or any combination thereof, // will generate a chain of n+1 conditional blocks, where each // |n| has a target to a shared "success" block, setting a // phony variable. We decompose this giant mess into the intended // sequence of expressions. NodeBlock join; LogicChain chain = buildLogicChain(block, null, out join); DJumpCondition finalJcc = (DJumpCondition)join.nodes.last; //Debug.Assert(finalJcc.spop == SPOpcode.jzer); // The final conditional should have the normal dominator // properties: 2 or 3 idoms, depending on the number of arms. // Because of critical edge splitting, we may have 3 idoms // even if there are only actually two arms. NodeBlock joinBlock = findJoinOfSimpleIf(join, finalJcc); // If an AND chain reaches its end, the result is 1. jzer tests // for zero, so this is effectively testing (!success). // If an OR expression reaches its end, the result is 0. jzer // tests for zero, so this is effectively testing if (failure). // // In both cases, the true target represents a failure, so flip // the targets around. NodeBlock trueBlock = finalJcc.falseTarget; NodeBlock falseBlock = finalJcc.trueTarget; // If there is no join block, both arms terminate control flow, // eliminate one arm and use the other as a join point. if (joinBlock == null) { joinBlock = falseBlock; } if (join.lir.idominated.Length == 2 || BlockAnalysis.EffectiveTarget(falseBlock) == joinBlock) { if (join.lir.idominated.Length == 3) { joinBlock = BlockAnalysis.EffectiveTarget(falseBlock); } // One-armed structure. pushScope(joinBlock); ControlBlock trueArm1 = traverseBlock(trueBlock); popScope(); ControlBlock joinArm1 = traverseBlock(joinBlock); return(new IfBlock(block, chain, trueArm1, joinArm1)); } //Debug.Assert(join.lir.idominated.Length == 3); pushScope(joinBlock); ControlBlock trueArm2 = traverseBlock(trueBlock); ControlBlock falseArm = traverseBlock(falseBlock); popScope(); ControlBlock joinArm2 = traverseBlock(joinBlock); return(new IfBlock(block, chain, trueArm2, falseArm, joinArm2)); }