public override void visit(DJumpCondition jcc) { if (jcc.getOperand(0).type == NodeType.Binary) { DBinary binary = (DBinary)jcc.getOperand(0); propagateInputs(binary.lhs, binary.rhs); } }
private void writeDoWhileLoop(WhileLoop loop) { outputLine("do" + Environment.NewLine + "{"); increaseIndent(); if (loop.body != null) { writeBlock(loop.body); } string cond; if (loop.logic == null) { writeStatements(loop.source); decreaseIndent(); DJumpCondition jcc = (DJumpCondition)loop.source.nodes.last; cond = buildExpression(jcc.getOperand(0)); } else { decreaseIndent(); cond = buildLogicChain(loop.logic); } outputLine("}"); outputLine("while (" + cond + ");"); if (loop.join != null) { writeBlock(loop.join); } }
private void writeIf(IfBlock block) { string cond; if (block.logic == null) { writeStatements(block.source); DJumpCondition jcc = (DJumpCondition)block.source.nodes.last; if (block.invert) { if (jcc.getOperand(0).type == NodeType.Unary && ((DUnary)jcc.getOperand(0)).spop == SPOpcode.not) { cond = buildExpression(jcc.getOperand(0).getOperand(0)); } else if (jcc.getOperand(0).type == NodeType.Load) { cond = "!" + buildExpression(jcc.getOperand(0)); } else { cond = "!(" + buildExpression(jcc.getOperand(0)) + ")"; } } else { cond = buildExpression(jcc.getOperand(0)); } } else { cond = buildLogicChain(block.logic); Debug.Assert(!block.invert); } outputLine("if (" + cond + ")"); outputLine("{"); increaseIndent(); writeBlock(block.trueArm); decreaseIndent(); if (block.falseArm != null && BlockAnalysis.GetEmptyTarget(block.falseArm.source) == null) { outputLine("}"); outputLine("else"); outputLine("{"); increaseIndent(); writeBlock(block.falseArm); decreaseIndent(); } outputLine("}"); if (block.join != null) { writeBlock(block.join); } }
public override void visit(DJumpCondition jcc) { if (jcc.getOperand(0).type == NodeType.Binary) { DBinary binary = (DBinary)jcc.getOperand(0); propagateInputs(binary.lhs, binary.rhs); } }
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); }