Base class of a method compiler.
A method compiler is responsible for compiling a single function of an object. There are various classes derived from BaseMethodCompiler, which provide specific features, such as jit compilation, runtime optimized jitting and others. MethodCompilerBase instances are usually created by invoking CreateMethodCompiler on a specific compiler instance.
Inheritance: IMethodCompiler, IDisposable
Ejemplo n.º 1
0
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="typeSystem">The type system.</param>
 void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
 {
     var result = context.Result;
     var address = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.I4);
     context.SetInstruction(IRInstruction.Move, address, Operand.CreateUnmanagedSymbolPointer(methodCompiler.TypeSystem, Multiboot0695Stage.MultibootEBX));
     context.AppendInstruction(IRInstruction.Move, result, Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.I4, address, 0));
 }
Ejemplo n.º 2
0
        private static void PatchConstructor(BaseMethodCompiler methodCompiler)
        {
            Operand thisOperand = methodCompiler.Parameters[0];
            Operand instanceOperand = methodCompiler.Parameters[1];
            Operand methodPointerOperand = methodCompiler.Parameters[2];

            var size = methodCompiler.Architecture.NativeInstructionSize;

            MosaField methodPointerField = GetField(methodCompiler.Method.DeclaringType, "methodPointer");
            int methodPointerOffset = methodCompiler.TypeLayout.GetFieldOffset(methodPointerField);
            Operand methodPointerOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, methodPointerOffset);

            MosaField instanceField = GetField(methodCompiler.Method.DeclaringType, "instance");
            int instanceOffset = methodCompiler.TypeLayout.GetFieldOffset(instanceField);
            Operand instanceOffsetOperand = Operand.CreateConstant(methodCompiler.TypeSystem, instanceOffset);

            var context = new Context(CreateMethodStructure(methodCompiler, true));

            Operand v1 = methodCompiler.CreateVirtualRegister(thisOperand.Type);
            Operand v2 = methodCompiler.CreateVirtualRegister(methodPointerOperand.Type);
            Operand v3 = methodCompiler.CreateVirtualRegister(instanceOperand.Type);

            context.AppendInstruction(IRInstruction.LoadInteger, v1, methodCompiler.StackFrame, thisOperand);
            context.AppendInstruction(IRInstruction.LoadInteger, v2, methodCompiler.StackFrame, methodPointerOperand);
            context.AppendInstruction(IRInstruction.LoadInteger, v3, methodCompiler.StackFrame, instanceOperand);

            context.AppendInstruction(IRInstruction.StoreInteger, size, null, v1, methodPointerOffsetOperand, v2);
            context.MosaType = methodPointerOperand.Type;
            context.AppendInstruction(IRInstruction.StoreInteger, size, null, v1, instanceOffsetOperand, v3);
            context.MosaType = instanceOperand.Type;
            context.AppendInstruction(IRInstruction.Return, methodCompiler.BasicBlocks.EpilogueBlock);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var operand = context.Operand1;

            if (!operand.IsConstant)
            {
                // try to find the constant - a bit of a hack
                Context ctx = new Context(operand.Definitions[0]);

                if (ctx.Instruction == IRInstruction.Move && ctx.Operand1.IsConstant)
                {
                    operand = ctx.Operand1;
                }
            }

            Debug.Assert(operand.IsConstant);

            int irq = (int)operand.ConstantSignedLongInteger;

            // Find the method
            var method = methodCompiler.TypeSystem.DefaultLinkerType.FindMethodByName("InterruptISR" + irq.ToString());

            if (method == null)
            {
                throw new InvalidCompilerException();
            }

            context.SetInstruction(IRInstruction.Move, context.Result, Operand.CreateSymbolFromMethod(methodCompiler.TypeSystem, method));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Debug.Assert(context.Result.IsI4 | context.Result.IsU4);
            Operand zero = Operand.CreateConstant(methodCompiler.TypeSystem, 0);

            context.SetInstruction(X86.MovzxLoad, InstructionSize.Size16, context.Result, context.Operand1, zero);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var result = context.Result;
            var dividend = context.Operand1;
            var divisor = context.Operand2;

            if (result.IsR8)
            {
                var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);
                var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);
                var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R8);
                var size = InstructionSize.Size64;

                context.SetInstruction(X86.Divsd, size, xmm1, dividend, divisor);
                context.AppendInstruction(X86.Roundsd, size, xmm2, xmm1, Operand.CreateConstant(methodCompiler.TypeSystem.BuiltIn.U1, 0x3));
                context.AppendInstruction(X86.Mulsd, size, xmm3, divisor, xmm2);
                context.AppendInstruction(X86.Subsd, size, result, dividend, xmm3);
            }
            else
            {
                var xmm1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);
                var xmm2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);
                var xmm3 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.R4);
                var size = InstructionSize.Size32;

                context.SetInstruction(X86.Divss, size, xmm1, dividend, divisor);
                context.AppendInstruction(X86.Roundss, size, xmm2, xmm1, Operand.CreateConstant(methodCompiler.TypeSystem.BuiltIn.U1, 0x3));
                context.AppendInstruction(X86.Mulss, size, xmm3, divisor, xmm2);
                context.AppendInstruction(X86.Subss, size, result, dividend, xmm3);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand methodAddress = context.Operand1;
            Operand newESP = context.Operand2;

            context.SetInstruction(X86.Call, null, methodAddress);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var zero = Operand.CreateConstant(methodCompiler.TypeSystem.BuiltIn.I4, 0);
            var MultibootEAX = Operand.CreateUnmanagedSymbolPointer(methodCompiler.TypeSystem, Multiboot0695Stage.MultibootEAX);

            context.SetInstruction(IRInstruction.Load2, context.Result, MultibootEAX, zero);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand result = context.Result;
            Operand imm = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            context.SetInstruction(X86.MovCR, imm, Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.U4, control));
            context.AppendInstruction(X86.Mov, result, imm);
        }
Ejemplo n.º 9
0
        private static void PatchBeginInvoke(BaseMethodCompiler methodCompiler)
        {
            var nullOperand = Operand.GetNull(methodCompiler.TypeSystem);

            var context = new Context(CreateMethodStructure(methodCompiler, true));
            context.AppendInstruction(IRInstruction.Return, null, nullOperand);
            context.AddBranchTarget(methodCompiler.BasicBlocks.EpilogueBlock);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand result = context.Result;
            Operand eax = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            context.AppendInstruction(X86.Add, eax, eax, Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.U4, GeneralPurposeRegister.ESP));
            context.AppendInstruction(X86.Mov, eax, Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.U4, eax, 0));
            context.AppendInstruction(X86.Mov, result, eax);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            // Create constant operand and pointer to variable containing the lock
            Operand const0 = Operand.CreateConstantSignedInt(methodCompiler.TypeSystem, 0x0);
            Operand locked = Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.Pointer, context.Operand1, 0);

            // Set the variable locked to 0 signifying that the lock is free
            context.SetInstruction(X86.Mov, locked, const0);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand result = context.Result;
            Operand edx = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Pointer);
            Operand operand = Operand.CreateMemoryAddress(context.Operand1.Type, edx, 0);

            context.SetInstruction(X86.Mov, edx, context.Operand1);
            context.AppendInstruction(X86.Mov, result, operand);
        }
Ejemplo n.º 13
0
 public static void Run(BaseMethodCompiler methodCompiler, IPipelineStage stage)
 {
     Run(
         methodCompiler.Trace,
         methodCompiler.FormatStageName(stage),
         methodCompiler.Method,
         methodCompiler.BasicBlocks
     );
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicInternalMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var ctor = context.Operand1;
            var thisObject = context.Operand2;
            var result = context.Result;

            context.SetInstruction(IRInstruction.Call, null, ctor, thisObject);
            context.AppendInstruction(IRInstruction.MoveInteger, result, thisObject);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand operand1 = context.Operand1;

            Operand v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            context.SetInstruction(X86.Mov, v1, operand1);
            context.AppendInstruction(X86.Mov, Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.U4, SegmentRegister.FS), v1);
        }
Ejemplo n.º 16
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand operand1 = context.Operand1;

            Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.U4, GeneralPurposeRegister.EAX);
            Operand cr = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.U4, control);

            context.SetInstruction(X86.Mov, eax, operand1);
            context.AppendInstruction(X86.MovCR, cr, eax);
        }
Ejemplo n.º 17
0
 public static void Run(BaseMethodCompiler methodCompiler, IPipelineStage stage)
 {
     Run(
         methodCompiler.InternalTrace,
         stage,
         methodCompiler.Method,
         methodCompiler.InstructionSet,
         methodCompiler.BasicBlocks
     );
 }
Ejemplo n.º 18
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand result = context.Result;
            Operand size = context.Operand1;

            Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP);

            context.SetInstruction(X86.Sub, esp, esp, size);
            context.AppendInstruction(X86.Mov, result, esp);
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand methodAddress = context.Operand1;
            Operand newESP = context.Operand2;

            Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP);
            Operand edx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EDX);

            context.SetInstruction(X86.Call, null, methodAddress);
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP);

            context.SetInstruction(X86.Mov, esp, context.Operand1);
            context.AppendInstruction(X86.Popad);
            context.AppendInstruction(X86.Add, esp, esp, Operand.CreateConstant(methodCompiler.TypeSystem, 0x08));
            context.AppendInstruction(X86.Sti);
            context.AppendInstruction(X86.IRetd);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand result = context.Result;
            Operand v1 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.Pointer);
            Operand operand = Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.U2, v1, 0);

            Debug.Assert(result.IsI4 | result.IsU4);

            context.SetInstruction(X86.Mov, v1, context.Operand1);
            context.AppendInstruction(X86.Movzx, InstructionSize.Size16, result, operand);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="methodCompiler">The method compiler.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand result = context.Result;
            Operand methodAddress = context.Operand1;
            Operand newESP = context.Operand2;

            Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);

            context.SetInstruction(X86.Call, null, methodAddress);
            context.AppendInstruction(IRInstruction.Gen, eax);
            context.AppendInstruction(X86.Mov, result, eax);
        }
Ejemplo n.º 23
0
 /// <summary>
 /// Replaces the intrinsic call site
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="typeSystem">The type system.</param>
 void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
 {
     Operand result = context.Result;
     Operand operand = context.Operand1;
     Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
     Operand ecx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX);
     Operand reg = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX);
     context.SetInstruction(X86.Mov, eax, operand);
     context.AppendInstruction(X86.Mov, ecx, methodCompiler.ConstantZero);
     context.AppendInstruction(X86.CpuId, eax, eax);
     context.AppendInstruction(X86.Mov, result, reg);
 }
Ejemplo n.º 24
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var dest = context.Operand1;

            var v0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0);
            var zero = Operand.CreateConstant(methodCompiler.TypeSystem, 0);
            var offset16 = Operand.CreateConstant(methodCompiler.TypeSystem, 16);

            context.SetInstruction(X86.PXor, InstructionSize.Size128, v0, v0, v0);
            context.AppendInstruction(X86.MovupsStore, InstructionSize.Size128, dest, zero, v0);
            context.AppendInstruction(X86.MovupsStore, InstructionSize.Size128, dest, offset16, v0);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand dest = context.Operand1;
            Operand value = context.Operand2;

            Operand v1 = methodCompiler.CreateVirtualRegister(dest.Type);
            Operand v2 = methodCompiler.CreateVirtualRegister(value.Type);
            Operand memory = Operand.CreateMemoryAddress(context.InvokeMethod.Signature.Parameters[1].ParameterType, v1, 0);

            context.SetInstruction(X86.Mov, v1, dest);
            context.AppendInstruction(X86.Mov, v2, value);
            context.AppendInstruction(X86.Mov, memory, v2);
        }
Ejemplo n.º 26
0
        private static Context CreateNewBlock(BaseMethodCompiler methodCompiler)
        {
            var basicBlocks = methodCompiler.BasicBlocks;

            Context context = new Context(methodCompiler.InstructionSet);
            context.AppendInstruction(null);
            context.Label = 0;

            var newblock = basicBlocks.CreateBlock(basicBlocks.Count, context.Index);
            context.BasicBlock = newblock;

            return context;
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            var dest = context.Operand1;

            // The size will be 128 bits
            var v0 = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Void, SSE2Register.XMM0);
            var memDest1 = Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.Void, dest, 0);
            var memDest2 = Operand.CreateMemoryAddress(methodCompiler.TypeSystem.BuiltIn.Void, dest, 16);

            context.SetInstruction(X86.PXor, InstructionSize.Size128, v0, v0, v0);
            context.AppendInstruction(X86.MovUPS, InstructionSize.Size128, memDest1, v0);
            context.AppendInstruction(X86.MovUPS, InstructionSize.Size128, memDest2, v0);
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand n = context.Operand1;
            Operand d = context.Operand2;
            Operand result = context.Result;
            Operand result2 = methodCompiler.CreateVirtualRegister(methodCompiler.TypeSystem.BuiltIn.U4);

            Operand op0L, op0H;

            LongOperandTransformationStage.SplitLongOperand(methodCompiler, n, out op0L, out op0H);

            context.SetInstruction2(X86.Div, result2, result, op0H, op0L, d);
        }
Ejemplo n.º 29
0
        private static Context CreateMethodStructure(BaseMethodCompiler methodCompiler, bool linkEpilogueBlock)
        {
            var basicBlocks = methodCompiler.BasicBlocks;
            CreatePrologueAndEpilogueBlocks(methodCompiler.InstructionSet, basicBlocks);

            var context = methodCompiler.InstructionSet.CreateNewBlock(basicBlocks, 0);

            basicBlocks.LinkBlocks(basicBlocks.PrologueBlock, context.BasicBlock);

            if (linkEpilogueBlock)
                basicBlocks.LinkBlocks(context.BasicBlock, basicBlocks.EpilogueBlock);

            return context;
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Replaces the intrinsic call site
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="typeSystem">The type system.</param>
        void IIntrinsicPlatformMethod.ReplaceIntrinsicCall(Context context, BaseMethodCompiler methodCompiler)
        {
            Operand v0 = context.Operand1;
            Operand v1 = context.Operand2;
            Operand v2 = context.Operand3;
            Operand v3 = context.GetOperand(3);

            Operand esp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ESP);
            Operand ebp = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBP);

            Operand eax = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EAX);
            Operand ebx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.EBX);
            Operand ecx = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.I4, GeneralPurposeRegister.ECX);

            Operand exceptionRegister = Operand.CreateCPURegister(methodCompiler.TypeSystem.BuiltIn.Object, methodCompiler.Architecture.ExceptionRegister);

            // Move all virtual registers into physical registers - necessary since stack frame pointer will change
            context.SetInstruction(X86.Mov, eax, v0);
            context.AppendInstruction(X86.Mov, ebx, v1);
            context.AppendInstruction(X86.Mov, ecx, v2);
            context.AppendInstruction(X86.Mov, exceptionRegister, v3);

            // Update the frame and stack registers
            context.AppendInstruction(X86.Mov, ebp, ecx);
            context.AppendInstruction(X86.Mov, esp, ebx);
            context.AppendInstruction(X86.Jmp, null, eax);

            // future - common code (refactor opportunity)
            context.GotoNext();

            // Remove all remaining instructions in block and clear next block list
            while (!context.IsBlockEndInstruction)
            {
                if (!context.IsEmpty)
                {
                    context.SetInstruction(X86.Nop);
                }
                context.GotoNext();
            }

            var nextBlocks = context.Block.NextBlocks;

            foreach (var next in nextBlocks)
            {
                next.PreviousBlocks.Remove(context.Block);
            }

            nextBlocks.Clear();
        }