/// <summary> /// Emit the end cases for a short-circuit /// </summary> /// <param name="info"></param> /// <param name="ilg"></param> /// <param name="endLabel"></param> 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); } }
private void EmitListIn(FleeILGenerator ilg, IServiceProvider services) { CompareElement ce = new CompareElement(); Label endLabel = ilg.DefineLabel(); Label trueTerminal = ilg.DefineLabel(); // Cache the operand since we will be comparing against it a lot LocalBuilder lb = ilg.DeclareLocal(MyOperand.ResultType); int targetIndex = lb.LocalIndex; MyOperand.Emit(ilg, services); Utility.EmitStoreLocal(ilg, targetIndex); // Wrap our operand in a local shim LocalBasedElement targetShim = new LocalBasedElement(MyOperand, targetIndex); // Emit the compares foreach (ExpressionElement argumentElement in MyArguments) { ce.Initialize(targetShim, argumentElement, LogicalCompareOperation.Equal); ce.Emit(ilg, services); EmitBranchToTrueTerminal(ilg, trueTerminal); } ilg.Emit(OpCodes.Ldc_I4_0); ilg.Emit(OpCodes.Br_S, endLabel); ilg.MarkLabel(trueTerminal); ilg.Emit(OpCodes.Ldc_I4_1); ilg.MarkLabel(endLabel); }
private void EmitConditional(FleeILGenerator ilg, IServiceProvider services) { Label falseLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); // Emit the condition _myCondition.Emit(ilg, services); // On false go to the false operand ilg.EmitBranchFalse(falseLabel); // Emit the true operand _myWhenTrue.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myWhenTrue.ResultType, _myResultType, ilg); // Jump to end ilg.EmitBranch(endLabel); ilg.MarkLabel(falseLabel); // Emit the false operand _myWhenFalse.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myWhenFalse.ResultType, _myResultType, ilg); // Fall through to end ilg.MarkLabel(endLabel); }
private void EmitConditional(FleeILGenerator ilg, IServiceProvider services, BranchManager bm) { Label falseLabel = bm.FindLabel("falseLabel"); Label 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); }
/// <summary> /// 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. /// </summary> /// <param name="ilg"></param> /// <param name="info"></param> /// <param name="services"></param> 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); }
/// <summary> /// 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. /// </summary> /// <param name="ilg"></param> /// <param name="info"></param> /// <param name="services"></param> private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services) { // We always have an end label Label endLabel = ilg.DefineLabel(); // 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); // only 1-3 opcodes, always a short branch ilg.EmitBranch(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.HasLabel(operand) == true) { // Yes, so mark it Label leftLabel = info.FindLabel(operand); ilg.MarkLabel(leftLabel); } // Emit the operand operand.Emit(ilg, services); }