/// <summary>
        /// Generates code for an instruction with two virtual registers
        /// </summary>
        /// <param name="destinationRegister">The destination register</param>
        /// <param name="sourceRegister">The source register</param>
        /// <param name="memoryRewrite">Determines how an instruction with two memory operands will be rewritten into one memory operand.</param>
        public void GenerateTwoRegistersInstruction(VirtualRegister destinationRegister, VirtualRegister sourceRegister,
            Action<IList<byte>, IntRegister, IntRegister> inst1,
            Action<IList<byte>, IntRegister, MemoryOperand> inst2,
            Action<IList<byte>, MemoryOperand, IntRegister> inst3,
            MemoryRewrite memoryRewrite = MemoryRewrite.MemoryOnLeft)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var regAlloc = compilationData.RegisterAllocation;

            int? op1Stack = compilationData.RegisterAllocation.GetStackIndex(destinationRegister);
            int? op2Stack = compilationData.RegisterAllocation.GetStackIndex(sourceRegister);

            if (!op1Stack.HasValue && !op2Stack.HasValue)
            {
                var op1Reg = this.GetIntRegisterForVirtual(destinationRegister).Value;
                var op2Reg = this.GetIntRegisterForVirtual(sourceRegister).Value;
                inst1(generatedCode, op1Reg, op2Reg);
            }
            else if (!op1Stack.HasValue && op2Stack.HasValue)
            {
                var op1Reg = this.GetIntRegisterForVirtual(destinationRegister).Value;
                var op2StackOffset = CalculateStackOffset(op2Stack.Value);
                inst2(generatedCode, op1Reg, new MemoryOperand(Register.BP, op2StackOffset));
            }
            else if (op1Stack.HasValue && !op2Stack.HasValue)
            {
                var op1StackOffset = CalculateStackOffset(op1Stack.Value);
                var op2Reg = this.GetIntRegisterForVirtual(sourceRegister).Value;
                inst3(generatedCode, new MemoryOperand(Register.BP, op1StackOffset), op2Reg);
            }
            else
            {
                var op1StackOffset = CalculateStackOffset(op1Stack.Value);
                var op2StackOffset = CalculateStackOffset(op2Stack.Value);

                this.RewriteMemory(
                    memoryRewrite,
                    new MemoryOperand(Register.BP, op1StackOffset),
                    new MemoryOperand(Register.BP, op2StackOffset),
                    inst2,
                    inst3);
            }
        }
        /// <summary>
        /// Rewrites two memory operand instructions
        /// </summary>
        /// <param name="memoryRewrite">The memory rewrite rule</param>
        /// <param name="destination">The destination</param>
        /// <param name="source">The source</param>
        private void RewriteMemory(MemoryRewrite memoryRewrite, MemoryOperand destination, MemoryOperand source,
            Action<IList<byte>, FloatRegister, MemoryOperand> inst1,
            Action<IList<byte>, MemoryOperand, FloatRegister> inst2)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var spillReg = this.GetFloatSpillRegister();

            if (memoryRewrite == MemoryRewrite.MemoryOnLeft)
            {
                Assembler.Move(generatedCode, spillReg, source);
                inst2(generatedCode, destination, spillReg);
            }
            else
            {
                Assembler.Move(generatedCode, spillReg, destination);
                inst1(generatedCode, spillReg, source);
                Assembler.Move(generatedCode, destination, spillReg);
            }
        }
        /// <summary>
        /// Generates code for an instruction with virtual register destination and memory source
        /// </summary>
        /// <param name="destinationRegister">The destination</param>
        /// <param name="source">The source</param>
        /// <param name="memoryRewrite">Determines how an instruction with two memory operands will be rewritten into one memory operand.</param>
        public void GenerateOneRegisterMemorySourceInstruction(VirtualRegister destinationRegister, MemoryOperand source,
            Action<IList<byte>, IntRegister, MemoryOperand> inst1,
            Action<IList<byte>, MemoryOperand, IntRegister> inst2,
            MemoryRewrite memoryRewrite = MemoryRewrite.MemoryOnLeft)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var regAlloc = compilationData.RegisterAllocation;
            int? opStack = compilationData.RegisterAllocation.GetStackIndex(destinationRegister);

            if (!opStack.HasValue)
            {
                var destinationReg = this.GetIntRegisterForVirtual(destinationRegister).Value;
                inst1(generatedCode, destinationReg, source);
            }
            else
            {
                var opStackOffset = CalculateStackOffset(opStack.Value);
                RewriteMemory(memoryRewrite, new MemoryOperand(Register.BP, opStackOffset), source, inst1, inst2);
            }
        }