// Emit a short/long branch for an And/Or element private static OpCode GetBranchOpcode(AndOrElement op, bool longBranch) { if (op.MyOperation == AndOrOperation.And) { if (longBranch == true) { return OpCodes.Brfalse; } else { return OpCodes.Brfalse_S; } } else { if (longBranch == true) { return OpCodes.Brtrue; } else { return OpCodes.Brtrue_S; } } }
// Get the label for a short-circuit private static Label GetShortCircuitLabel(AndOrElement current, ShortCircuitInfo info, FleeILGenerator ilg) { // We modify the given stacks so we need to clone them Stack cloneOperands = (Stack)info.Operands.Clone(); Stack cloneOperators = (Stack)info.Operators.Clone(); // Pop all siblings current.PopRightChild(cloneOperands, cloneOperators); // Go until we run out of operators while (cloneOperators.Count > 0) { // Get the top operator AndOrElement top = (AndOrElement)cloneOperators.Pop(); // Is is a different operation? if (top.MyOperation != current.MyOperation) { // Yes, so return a label to its right operand object nextOperand = cloneOperands.Pop(); return GetLabel(nextOperand, ilg, info); } else { // No, so keep going up the stack top.PopRightChild(cloneOperands, cloneOperators); } } // We've reached the end of the stack so return the label for the appropriate true/false terminal if (current.MyOperation == AndOrOperation.And) { return GetLabel(OurFalseTerminalKey, ilg, info); } else { return GetLabel(OurTrueTerminalKey, ilg, info); } }
private static void EmitBranch(AndOrElement op, FleeILGenerator ilg, Label target, ShortCircuitInfo info) { if (ilg.IsTemp == true) { info.Branches.AddBranch(ilg, target); // Temp mode; just emit a short branch and return OpCode shortBranch = GetBranchOpcode(op, false); ilg.Emit(shortBranch, target); return; } // Emit the proper branch opcode // Determine if it is a long branch bool longBranch = info.Branches.IsLongBranch(ilg, target); // Get the branch opcode OpCode brOpcode = GetBranchOpcode(op, longBranch); // Emit the branch ilg.Emit(brOpcode, target); }