public LabelWrapper DefineLabel()
        {
            var label = new LabelWrapper();

            AddInstruction(new ILInstruction(OpCodes.Nop, label, typeof(LabelWrapper), ILInstructionType.DefineLabel));
            return(label);
        }
        public void EmitBreak(OpCode opcode, LabelWrapper label)
        {
            if (!opcode.Name.StartsWith("b") || opcode == OpCodes.Break || opcode == OpCodes.Box)
            {
                throw new Exception("Unsupported Opcode, only 'break'-opcodes supported");
            }

            this.AddInstruction(opcode, label);
        }
        public void EmitSwitchCases(Type switchType, Type returnType, List <Tuple <object, object> > switchReturnValues)
        {
            var defaultCase = this.DefineLabel();
            var endOfMethod = this.DefineLabel();
            var switchValue = this.DeclareLocal(switchType);

            this.EmitLocal(OpCodes.Stloc, switchValue);

            var jumpTable = new LabelWrapper[switchReturnValues.Count];

            for (int i = 0; i < switchReturnValues.Count; i++)
            {
                jumpTable[i] = this.DefineLabel();
                this.EmitLocal(OpCodes.Ldloc, switchValue);
                this.EmitLoadEnumValue(switchType, switchReturnValues[i].Item1);
                if (switchType == typeof(string))
                {
                    var stringEquals = typeof(string).GetMethod("op_Equality", new[] { typeof(string), typeof(string) });
                    this.EmitCall(OpCodes.Call, stringEquals);
                    this.Emit(OpCodes.Ldc_I4_1);
                }

                this.EmitBreak(OpCodes.Beq, jumpTable[i]);
            }

            // Branch on default case
            this.EmitBreak(OpCodes.Br, defaultCase);

            for (int i = 0; i < switchReturnValues.Count; i++)
            {
                this.MarkLabel(jumpTable[i]);
                this.EmitLoadEnumValue(returnType, switchReturnValues[i].Item2);
                this.EmitBreak(OpCodes.Br, endOfMethod);
            }

            // Default case
            this.MarkLabel(defaultCase);
            this.EmitLoadEnumValue(returnType, switchReturnValues[0].Item2);

            this.MarkLabel(endOfMethod);
        }
 private void AddInstruction(OpCode opcode, LabelWrapper label)
 {
     AddInstruction(new ILInstruction(opcode, label, typeof(LabelWrapper)));
 }
 public void MarkLabel(LabelWrapper label)
 {
     AddInstruction(new ILInstruction(OpCodes.Nop, label, typeof(LabelWrapper), ILInstructionType.MarkLabel));
 }