private void EmitListIn(FleeILGenerator ilg, IServiceProvider services, BranchManager bm) { var ce = new CompareElement(); var endLabel = bm.FindLabel("endLabel"); var trueTerminal = bm.FindLabel("trueTerminal"); // Cache the operand since we will be comparing against it a lot var lb = ilg.DeclareLocal(MyOperand.ResultType); int targetIndex = lb.LocalIndex; MyOperand.Emit(ilg, services); Utility.EmitStoreLocal(ilg, targetIndex); // Wrap our operand in a local shim var targetShim = new LocalBasedElement(MyOperand, targetIndex); // Emit the compares foreach (var argumentElement in MyArguments) { ce.Initialize(targetShim, argumentElement, LogicalCompareOperation.Equal); ce.Emit(ilg, services); EmitBranchToTrueTerminal(ilg, trueTerminal, bm); } ilg.Emit(OpCodes.Ldc_I4_0); ilg.Emit(OpCodes.Br_S, endLabel); bm.MarkLabel(ilg, trueTerminal); ilg.MarkLabel(trueTerminal); ilg.Emit(OpCodes.Ldc_I4_1); bm.MarkLabel(ilg, endLabel); ilg.MarkLabel(endLabel); }
// Emit the end cases for a short-circuit private static void EmitTerminals(ShortCircuitInfo info, FleeILGenerator ilg, Label endLabel) { // Emit the false case if it was used if (info.Branches.HasLabel(OurFalseTerminalKey) == true) { Label falseLabel = info.Branches.FindLabel(OurFalseTerminalKey); // Mark the label and note its position ilg.MarkLabel(falseLabel); MarkBranchTarget(info, falseLabel, ilg); ilg.Emit(OpCodes.Ldc_I4_0); // If we also have a true terminal, then skip over it if (info.Branches.HasLabel(OurTrueTerminalKey) == true) { ilg.Emit(OpCodes.Br_S, endLabel); } } // Emit the true case if it was used if (info.Branches.HasLabel(OurTrueTerminalKey) == true) { Label trueLabel = info.Branches.FindLabel(OurTrueTerminalKey); // Mark the label and note its position ilg.MarkLabel(trueLabel); MarkBranchTarget(info, trueLabel, ilg); ilg.Emit(OpCodes.Ldc_I4_1); } }
// Emit a short-circuited logical operation sequence // The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom. // For each operand, emit it and try to find an end point for when it short-circuits. This means we go up through // the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand) // or we reach the root (emit a branch to a true/false). // Repeat the process for all operands and then emit the true/false/last operand end cases. private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services) { // We always have an end label info.Branches.GetLabel(OurEndLabelKey, ilg); // Populate our data structures this.PopulateData(info); // Emit the sequence EmitLogicalShortCircuit(ilg, info, services); // Get the last operand ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop(); // Emit it EmitOperand(terminalOperand, info, ilg, services); // And jump to the end Label endLabel = info.Branches.FindLabel(OurEndLabelKey); ilg.Emit(OpCodes.Br_S, endLabel); // Emit our true/false terminals EmitTerminals(info, ilg, endLabel); // Mark the end ilg.MarkLabel(endLabel); }
private static void EmitOperand(ExpressionElement operand, ShortCircuitInfo info, FleeILGenerator ilg, IServiceProvider services) { // Is this operand the target of a label? if (info.Branches.HasLabel(operand) == true) { // Yes, so mark it Label leftLabel = info.Branches.FindLabel(operand); ilg.MarkLabel(leftLabel); // Note the label's position MarkBranchTarget(info, leftLabel, ilg); } // Emit the operand operand.Emit(ilg, services); }
private void EmitConditional(FleeILGenerator ilg, IServiceProvider services, BranchManager bm) { var falseLabel = bm.FindLabel("falseLabel"); var endLabel = bm.FindLabel("endLabel"); // Emit the condition MyCondition.Emit(ilg, services); // On false go to the false operand if (ilg.IsTemp == true) { bm.AddBranch(ilg, falseLabel); ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else if (bm.IsLongBranch(ilg, falseLabel) == false) { ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else { ilg.Emit(OpCodes.Brfalse, falseLabel); } // Emit the true operand MyWhenTrue.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyWhenTrue.ResultType, MyResultType, ilg); // Jump to end if (ilg.IsTemp == true) { bm.AddBranch(ilg, endLabel); ilg.Emit(OpCodes.Br_S, endLabel); } else if (bm.IsLongBranch(ilg, endLabel) == false) { ilg.Emit(OpCodes.Br_S, endLabel); } else { ilg.Emit(OpCodes.Br, endLabel); } bm.MarkLabel(ilg, falseLabel); ilg.MarkLabel(falseLabel); // Emit the false operand MyWhenFalse.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyWhenFalse.ResultType, MyResultType, ilg); // Fall through to end bm.MarkLabel(ilg, endLabel); ilg.MarkLabel(endLabel); }