Example #1
0
 public IfBlock(NodeBlock source, LogicChain chain, ControlBlock trueArm, ControlBlock falseArm, ControlBlock join)
     : base(source)
 {
     trueArm_  = trueArm;
     falseArm_ = falseArm;
     join_     = join;
     invert_   = invert;
     logic_    = logic;
 }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
 public void append(LogicChain subChain)
 {
     nodes_.Add(new Node(subChain));
 }
Example #5
0
 public Node(LogicChain subChain)
 {
     subChain_ = subChain;
 }
Example #6
0
        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);
        }
Example #7
0
 public WhileLoop(ControlType type, LogicChain logic, ControlBlock body, ControlBlock join)
     : base(null)
 {
     body_ = body;
     join_ = join;
     logic_ = logic;
     type_ = type;
 }
Example #8
0
 public IfBlock(NodeBlock source, LogicChain chain, ControlBlock trueArm, ControlBlock falseArm, ControlBlock join)
     : base(source)
 {
     trueArm_ = trueArm;
     falseArm_ = falseArm;
     join_ = join;
     invert_ = invert;
     logic_ = logic;
 }
Example #9
0
 public void append(LogicChain subChain)
 {
     nodes_.Add(new Node(subChain));
 }
Example #10
0
 public Node(LogicChain subChain)
 {
     subChain_ = subChain;
 }
Example #11
0
        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));
        }
Example #12
0
        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);
        }
Example #13
0
 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;
 }
Example #14
0
 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);
 }