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 string buildLogicChain(LogicChain chain) { string text = buildLogicExpr(chain.nodes[0]); for (int i = 1; i < chain.nodes.Count; i++) { LogicChain.Node node = chain.nodes[i]; text += " " + lgop(chain.op) + " " + buildLogicExpr(node); } return(text); }
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); }
public void append(LogicChain subChain) { nodes_.Add(new Node(subChain)); }
public Node(LogicChain subChain) { subChain_ = subChain; }
private LogicChain buildLogicChain(NodeBlock block, NodeBlock earlyExitStop, out NodeBlock join) { DJumpCondition jcc = (DJumpCondition)block.nodes.last; LogicChain chain = new LogicChain(ToLogicOp(jcc)); // Grab the true target, which will be either the "1" or "0" // branch of the AND/OR expression. NodeBlock earlyExit = BlockAnalysis.EffectiveTarget(jcc.trueTarget); NodeBlock exprBlock = block; do { do { DJumpCondition childJcc = (DJumpCondition)exprBlock.nodes.last; if (BlockAnalysis.EffectiveTarget(childJcc.trueTarget) != earlyExit) { // Parse a sub-expression. NodeBlock innerJoin; LogicChain rhs = buildLogicChain(exprBlock, earlyExit, out innerJoin); AssertInnerJoinValidity(innerJoin, earlyExit); chain.append(rhs); exprBlock = innerJoin; childJcc = (DJumpCondition)exprBlock.nodes.last; } else { chain.append(childJcc.getOperand(0)); } exprBlock = childJcc.falseTarget; } while (exprBlock.nodes.last.type == NodeType.JumpCondition); do { // We have reached the end of a sequence - a block containing // a Constant and a Jump to the join point of the sequence. //Debug.Assert(exprBlock.lir.instructions[0].op == Opcode.Constant); // The next block is the join point. NodeBlock condBlock = SingleTarget(exprBlock); var last = condBlock.nodes.last; DJumpCondition condJcc; try { condJcc = (DJumpCondition)last; } catch (Exception e) { throw new LogicChainConversionException(e.Message); } join = condBlock; // If the cond block is the tagret of the early stop, we've // gone a tad too far. This is the case for a simple // expression like (a && b) || c. if (earlyExitStop != null && SingleTarget(earlyExitStop) == condBlock) return chain; // If the true connects back to the early exit stop, we're // done. if (BlockAnalysis.EffectiveTarget(condJcc.trueTarget) == earlyExitStop) return chain; // If the true target does not have a shared target, we're // done parsing the whole logic chain. if (!HasSharedTarget(condBlock, condJcc)) return chain; // Otherwise, there is another link in the chain. This link // joins the existing chain to a new subexpression, which // actually starts hanging off the false branch of this // conditional. earlyExit = BlockAnalysis.EffectiveTarget(condJcc.trueTarget); // Build the right-hand side of the expression. NodeBlock innerJoin; LogicChain rhs = buildLogicChain(condJcc.falseTarget, earlyExit, out innerJoin); AssertInnerJoinValidity(innerJoin, earlyExit); // Build the full expression. LogicChain root = new LogicChain(ToLogicOp(condJcc)); root.append(chain); root.append(rhs); chain = root; // If the inner join's false target is a conditional, the // outer expression may continue. DJumpCondition innerJcc = (DJumpCondition)innerJoin.nodes.last; if (innerJcc.falseTarget.nodes.last.type == NodeType.JumpCondition) { exprBlock = innerJcc.falseTarget; break; } // Finally, the new expression block is always the early exit // block. It's on the "trueTarget" edge of the expression, // whereas incoming into this loop it's on the "falseTarget" // edge, but this does not matter. exprBlock = earlyExit; } while (true); } while (true); }
public WhileLoop(ControlType type, LogicChain logic, ControlBlock body, ControlBlock join) : base(null) { body_ = body; join_ = join; logic_ = logic; type_ = type; }
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)); }
private LogicChain buildLogicChain(NodeBlock block, NodeBlock earlyExitStop, out NodeBlock join) { DJumpCondition jcc = (DJumpCondition)block.nodes.last; LogicChain chain = new LogicChain(ToLogicOp(jcc)); // Grab the true target, which will be either the "1" or "0" // branch of the AND/OR expression. NodeBlock earlyExit = BlockAnalysis.EffectiveTarget(jcc.trueTarget); NodeBlock exprBlock = block; do { do { DJumpCondition childJcc = (DJumpCondition)exprBlock.nodes.last; if (BlockAnalysis.EffectiveTarget(childJcc.trueTarget) != earlyExit) { // Parse a sub-expression. NodeBlock innerJoin; LogicChain rhs = buildLogicChain(exprBlock, earlyExit, out innerJoin); AssertInnerJoinValidity(innerJoin, earlyExit); chain.append(rhs); exprBlock = innerJoin; childJcc = (DJumpCondition)exprBlock.nodes.last; } else { chain.append(childJcc.getOperand(0)); } exprBlock = childJcc.falseTarget; } while (exprBlock.nodes.last.type == NodeType.JumpCondition); do { // We have reached the end of a sequence - a block containing // a Constant and a Jump to the join point of the sequence. //Debug.Assert(exprBlock.lir.instructions[0].op == Opcode.Constant); // The next block is the join point. NodeBlock condBlock = SingleTarget(exprBlock); var last = condBlock.nodes.last; DJumpCondition condJcc; try { condJcc = (DJumpCondition)last; } catch (Exception e) { throw new LogicChainConversionException(e.Message); } join = condBlock; // If the cond block is the tagret of the early stop, we've // gone a tad too far. This is the case for a simple // expression like (a && b) || c. if (earlyExitStop != null && SingleTarget(earlyExitStop) == condBlock) { return(chain); } // If the true connects back to the early exit stop, we're // done. if (BlockAnalysis.EffectiveTarget(condJcc.trueTarget) == earlyExitStop) { return(chain); } // If the true target does not have a shared target, we're // done parsing the whole logic chain. if (!HasSharedTarget(condBlock, condJcc)) { return(chain); } // Otherwise, there is another link in the chain. This link // joins the existing chain to a new subexpression, which // actually starts hanging off the false branch of this // conditional. earlyExit = BlockAnalysis.EffectiveTarget(condJcc.trueTarget); // Build the right-hand side of the expression. NodeBlock innerJoin; LogicChain rhs = buildLogicChain(condJcc.falseTarget, earlyExit, out innerJoin); AssertInnerJoinValidity(innerJoin, earlyExit); // Build the full expression. LogicChain root = new LogicChain(ToLogicOp(condJcc)); root.append(chain); root.append(rhs); chain = root; // If the inner join's false target is a conditional, the // outer expression may continue. DJumpCondition innerJcc = (DJumpCondition)innerJoin.nodes.last; if (innerJcc.falseTarget.nodes.last.type == NodeType.JumpCondition) { exprBlock = innerJcc.falseTarget; break; } // Finally, the new expression block is always the early exit // block. It's on the "trueTarget" edge of the expression, // whereas incoming into this loop it's on the "falseTarget" // edge, but this does not matter. exprBlock = earlyExit; } while (true); } while (true); }
private string buildLogicChain(LogicChain chain) { string text = buildLogicExpr(chain.nodes[0]); for (int i = 1; i < chain.nodes.Count; i++) { LogicChain.Node node = chain.nodes[i]; text += " " + lgop(chain.op) + " " + buildLogicExpr(node); } return text; }
private string buildLogicExpr(LogicChain.Node node) { if (node.isSubChain) { string text = buildLogicChain(node.subChain); if (node.subChain.nodes.Count == 1) return text; return "(" + text + ")"; } return buildExpression(node.expression); }