private bool IsAlwaysBranch(Opcode next)
        {
            JumpIfOpcode opcode = next as JumpIfOpcode;

            if (opcode != null)
            {
                if (opcode.Test)
                {
                    Opcode opcode3;
                    Opcode jump = opcode.Jump;
                    if (jump == null)
                    {
                        return(false);
                    }
                    if (jump.TestFlag(OpcodeFlags.Branch))
                    {
                        OpcodeList branches = ((BranchOpcode)jump).Branches;
                        for (int i = 0; i < branches.Count; i++)
                        {
                            opcode3 = branches[i].Next;
                            if ((opcode3 != null) && !opcode3.TestFlag(OpcodeFlags.Result))
                            {
                                return(true);
                            }
                        }
                        return(false);
                    }
                    opcode3 = opcode.Jump.Next;
                    if ((opcode3 != null) && opcode3.TestFlag(OpcodeFlags.Result))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            if (OpcodeID.BlockEnd == next.ID)
            {
                return(!next.Next.TestFlag(OpcodeFlags.Result));
            }
            return(!next.TestFlag(OpcodeFlags.Result));
        }
Exemplo n.º 2
0
        bool IsAlwaysBranch(Opcode next)
        {
            Fx.Assert(null != next, "");

            // Opcodes subsequent to matching literals must obviously be branched to.
            // The question is whether we should branch to the opcodes following those literals that do *not* match.
            // Naturally, the answer depends on the sort of opcode that succeeds the literal.
            //
            // If the literal is within a boolean conjunction, the succeeding opcode will either be a JumpIfNot
            // Or a BlockEnd.
            //
            // -If the JumpIfNot is multiway, then always evaluate if it contains ANY non-result only opcodes.
            // -If JumpIfNot(False) -i.e. AND - only evaluate if the opcode succeeding the jump is NOT a result opcode.
            // -If JumpIfNot(True) - i.e. OR - always evaluate
            //
            // -If BlockEnd - evaluate only if not followed by a result
            //
            // When branching for matching literals, we push trues onto the ValueStack corresponding to the items that
            // matched. When branching for non-matching literals, we push ALL FALSE values... and then eval.

            // is it a the termination of a conditional?
            JumpIfOpcode jump = next as JumpIfOpcode;

            if (null != jump)
            {
                // Is the conditional JumpIfNot(False) = i.e. OR?
                if (!jump.Test)
                {
                    return(true);
                }

                // Does the conditional actually jump to anything? Should never be the case, but paranoia demands..
                Opcode jumpTo = jump.Jump;
                if (null == jumpTo)
                {
                    return(false);
                }

                // Lets see where the jump will take us
                Opcode postJump;
                if (jumpTo.TestFlag(OpcodeFlags.Branch))
                {
                    // Multiway jump
                    OpcodeList branches = ((BranchOpcode)jumpTo).Branches;
                    for (int i = 0; i < branches.Count; ++i)
                    {
                        postJump = branches[i].Next;
                        if (null != postJump && !postJump.TestFlag(OpcodeFlags.Result))
                        {
                            // There is at least one jump here that leads to a non-result.
                            // For now, this dooms everybody to being branched to, whether or not their respective literals
                            // matched
                            return(true);
                        }
                    }
                    return(false);
                }

                // single jump
                postJump = jump.Jump.Next;
                if (null != postJump && postJump.TestFlag(OpcodeFlags.Result))
                {
                    return(false);
                }

                return(true);
            }

            // If the next opcode is a BlockEnd, then only bother processing if what follows the block is not a result
            if (OpcodeID.BlockEnd == next.ID)
            {
                Fx.Assert(null != next.Next, "");
                return(!next.Next.TestFlag(OpcodeFlags.Result));
            }

            // The literal is not inside a boolean conjunction
            // If the literal is not followed by a result, then we must do further processing after the branch
            return(!next.TestFlag(OpcodeFlags.Result));
        }