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); }
/// <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 Label GetLabel(object key, FleeILGenerator ilg, ShortCircuitInfo info) { if (info.HasLabel(key)) { return(info.FindLabel(key)); } return(info.AddLabel(key, ilg.DefineLabel())); }