Example #1
0
        /// <summary>
        /// Emits the given operation at the current position of the new IL stream. Also tracks any referenced local definitions,
        /// so that this.localVariables will contain the exact list of locals used in the new method body.
        /// </summary>
        /// <param name="operation"></param>
        protected virtual void EmitOperation(IOperation operation)
        {
            Contract.Requires(operation != null);

            var operationCode = operation.OperationCode;
            var value         = operation.Value;

            switch (operationCode)
            {
            case OperationCode.Beq:
            case OperationCode.Bge:
            case OperationCode.Bge_Un:
            case OperationCode.Bgt:
            case OperationCode.Bgt_Un:
            case OperationCode.Ble:
            case OperationCode.Ble_Un:
            case OperationCode.Blt:
            case OperationCode.Blt_Un:
            case OperationCode.Bne_Un:
            case OperationCode.Br:
            case OperationCode.Br_S:
            case OperationCode.Brfalse:
            case OperationCode.Brtrue:
            case OperationCode.Leave:
            case OperationCode.Beq_S:
            case OperationCode.Bge_S:
            case OperationCode.Bge_Un_S:
            case OperationCode.Bgt_S:
            case OperationCode.Bgt_Un_S:
            case OperationCode.Ble_S:
            case OperationCode.Ble_Un_S:
            case OperationCode.Blt_S:
            case OperationCode.Blt_Un_S:
            case OperationCode.Bne_Un_S:
            case OperationCode.Brfalse_S:
            case OperationCode.Brtrue_S:
            case OperationCode.Leave_S:
                operationCode = ILGenerator.LongVersionOf(operationCode);
                Contract.Assume(operation.Value is uint);
                value = this.GetLabelFor(+(uint)operation.Value);
                break;

            case OperationCode.Switch:
                uint[] offsets = operation.Value as uint[];
                Contract.Assume(offsets != null);
                var n = offsets.Length;
                ILGeneratorLabel[] labels = new ILGeneratorLabel[n];
                for (int i = 0; i < n; i++)
                {
                    var offset = offsets[i];
                    labels[i] = this.GetLabelFor(offset);
                }
                value = labels;
                break;

            //Avoid the short forms because the locals can get reordered.
            case OperationCode.Ldloc_0:
            case OperationCode.Ldloc_1:
            case OperationCode.Ldloc_2:
            case OperationCode.Ldloc_3:
            case OperationCode.Ldloc_S:
                operationCode = OperationCode.Ldloc;
                break;

            case OperationCode.Ldloca_S:
                operationCode = OperationCode.Ldloca;
                break;

            case OperationCode.Stloc_0:
            case OperationCode.Stloc_1:
            case OperationCode.Stloc_2:
            case OperationCode.Stloc_3:
            case OperationCode.Stloc_S:
                operationCode = OperationCode.Stloc;
                break;
            }
            this.generator.Emit(operationCode, value);
        }