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)); }
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)); }