Пример #1
0
        /// <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);
            }
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        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);
        }