예제 #1
0
        public void TestOperation()
        {
            var aReg   = new VirtualRegister();
            var bReg   = new VirtualRegister();
            var outReg = new VirtualRegister();

            var instructions = new List <CodeBlock>();

            var block = new List <Instruction>()
            {
                this.GetDefinition(aReg),
                this.GetDefinition(bReg),
                this.GetOperation(aReg, bReg, outReg)
            };

            this.AddRetBlock(instructions, block);

            var registers = new List <VirtualRegister>()
            {
                aReg, bReg, outReg
            };

            var interferenceGraph = this.GetEmptyGraph(registers);
            var copyGraph         = this.GetEmptyGraph(registers);

            this.AddEdge(interferenceGraph, aReg, bReg);

            this.AddEdge(copyGraph, aReg, outReg);
            this.AddEdge(copyGraph, bReg, outReg);

            this.CheckAnswer(instructions, interferenceGraph, copyGraph);
        }
예제 #2
0
        public void TestUnused()
        {
            var aReg = new VirtualRegister();
            var bReg = new VirtualRegister();
            var cReg = new VirtualRegister();

            var instructions = new List <CodeBlock>();

            var block = new List <Instruction>()
            {
                this.GetDefinition(aReg),
                this.GetDefinition(bReg),
                this.GetDefinition(cReg),
                this.GetDefinition(aReg),
                this.GetDefinition(bReg),
                this.GetDefinition(cReg)
            };

            this.AddRetBlock(instructions, block);

            var registers = new List <VirtualRegister>()
            {
                aReg, bReg, cReg
            };
            var emptyGraph = this.GetEmptyGraph(registers);

            this.CheckAnswer(instructions, emptyGraph, emptyGraph);
        }
        public override Instruction Emit(VirtualRegister result, IReadOnlyList <object> fill, string label)
        {
            var lhs = fill.GetRegister(0);
            var rhs = fill.GetRegister(1);

            return(new LogicalOperationGeneralInstruction(lhs, rhs, result, this.operationType));
        }
예제 #4
0
        public override Instruction Emit(VirtualRegister result, IReadOnlyList <object> fill, string label)
        {
            var uses    = fill.GetCollection(0);
            var defines = fill.GetCollection(1);

            return(new UsesDefinesInstruction(uses, defines));
        }
예제 #5
0
        public override Instruction Emit(VirtualRegister result, IReadOnlyList <object> fill, string label)
        {
            var lhs = fill.GetRegister(0);
            var rhs = fill.GetRegister(1);

            return(new MulInstruction(lhs, rhs, result));
        }
예제 #6
0
        public ILabel AllocateStruct(Function.Function function, StructType structType, ILocation target, ILabel after)
        {
            if (structType.Fields.Count == 0)
            {
                return(after);
            }

            var allocateFunctionName = NameMangler.GetMangledName("allocate", new List <AST.DataType>()
            {
                IntType.Instance
            }, null);

            var allocateFunc = new Function.Function(
                null,
                allocateFunctionName,
                new List <AST.VariableDeclaration>()
            {
                new AST.VariableDeclaration(null, IntType.Instance, "size", null)
            },
                isEntryPoint: false,
                isForeign: true);

            var sizeRegister = new VirtualRegister();

            var call = this.callGenerator.GenerateCall(target, new List <VirtualRegister>()
            {
                sizeRegister
            }, after, callerFunction: function, function: allocateFunc);

            var writeSize  = new RegisterWrite(sizeRegister, new IntegerImmediateValue(structType.Fields.Count * 8));
            var startLabel = this.labelFactory.GetLabel(new Tree(writeSize, new UnconditionalJump(call)));

            return(startLabel);
        }
예제 #7
0
        public override Instruction Emit(VirtualRegister result, IReadOnlyList <object> fill, string label)
        {
            var to   = fill.GetRegister(0);
            var from = fill.GetRegister(1);

            return(new MovRegisterMemoryInstruction(to, from));
        }
예제 #8
0
        private GenericOperand RetrieveOperand()
        {
            GenericOperand      operand = stack.Peek().Item1.Item1;
            bool                byref   = stack.Peek().Item1.Item2;
            InstructionSelector parent  = stack.Peek().Item2;

            stack.Pop();

            if (parent != this)
            {
                if (byref)
                {
                    arguments.Add(operand);
                    return(operand);
                }
                else
                {
                    VirtualRegister argument = operand as VirtualRegister;
                    argument = new VirtualRegister(argument.UnderlyingType, argument.StateSpace);
                    parent.AddInitialization(operand, argument);
                    arguments.Add(argument);
                    return(argument);
                }
            }
            else
            {
                return(operand);
            }
        }
예제 #9
0
        public void TestDiamond()
        {
            var aReg = new VirtualRegister();
            var bReg = new VirtualRegister();
            var cReg = new VirtualRegister();
            var dReg = new VirtualRegister();

            var headBlock = new List <Instruction>()
            {
                this.GetDefinition(aReg)
            };

            var leftBlock = new List <Instruction>()
            {
                this.GetOperation(aReg, aReg, bReg),
                this.GetOperation(bReg, bReg, aReg),
                this.GetOperation(aReg, aReg, bReg),
                this.GetOperation(bReg, bReg, aReg)
            };

            var rightBlock = new List <Instruction>()
            {
                this.GetDefinition(cReg),
                this.GetDefinition(cReg)
            };

            var tailBlock = new List <Instruction>()
            {
                this.GetOperation(aReg, dReg, cReg),
                this.GetDefinition(cReg)
            };

            var instructions = new List <CodeBlock>();

            var tailLabel  = this.AddRetBlock(instructions, tailBlock);
            var leftLabel  = this.AddUnconditionalJumpBlock(instructions, leftBlock, tailLabel);
            var rightLabel = this.AddUnconditionalJumpBlock(instructions, rightBlock, tailLabel);

            this.AddConditionalJumpBlock(instructions, headBlock, leftLabel, rightLabel);

            var registers = new List <VirtualRegister>()
            {
                aReg, bReg, cReg, dReg
            };

            var interferenceGraph = this.GetEmptyGraph(registers);
            var copyGraph         = this.GetEmptyGraph(registers);

            this.AddEdge(interferenceGraph, aReg, cReg);
            this.AddEdge(interferenceGraph, aReg, dReg);
            this.AddEdge(interferenceGraph, bReg, dReg);
            this.AddEdge(interferenceGraph, cReg, dReg);

            this.AddEdge(copyGraph, aReg, bReg);
            this.AddEdge(copyGraph, aReg, cReg);
            this.AddEdge(copyGraph, dReg, cReg);

            this.CheckAnswer(instructions, interferenceGraph, copyGraph);
        }
예제 #10
0
 private void AddEdge(
     Dictionary <VirtualRegister, List <VirtualRegister> > graph,
     VirtualRegister register1,
     VirtualRegister register2)
 {
     graph[register1].Add(register2);
     graph[register2].Add(register1);
 }
예제 #11
0
 public ConditionalJumpInstruction(VirtualRegister register, string label)
     : base(new List <VirtualRegister> {
     register
 })
 {
     this.register = register;
     this.Label    = label;
 }
예제 #12
0
 public void PushStack(VirtualRegister r)
 {
     m_stack.Push(r);
     if (r is TemporaryRegister || r.RegisterNumber < 0)
     {
         m_stackDepth++;
     }
     m_maxStackDepth = Math.Max(m_maxStackDepth, m_stackDepth);
 }
예제 #13
0
 private Instruction GetDefinition(VirtualRegister register)
 {
     return(new InstructionMock(
                new List <VirtualRegister>(),
                new List <VirtualRegister> {
         register
     },
                new List <Tuple <VirtualRegister, VirtualRegister> >()));
 }
예제 #14
0
        public VirtualRegister PopStack()
        {
            VirtualRegister r = m_stack.Pop();

            if (r is TemporaryRegister || r.RegisterNumber < 0)
            {
                m_stackDepth--;
            }
            return(r);
        }
예제 #15
0
 public MovRegisterMemoryInstruction(
     VirtualRegister to,
     VirtualRegister from)
     : base(new List <VirtualRegister> {
     from, to
 })                                                 // No register is written to. Only memory.
 {
     this.to   = to;
     this.from = from;
 }
예제 #16
0
        private IEnumerable <Instruction> FitTemplates(
            Node node,
            VirtualRegister result,
            IReadOnlyDictionary <ShapeKey, List <InstructionTemplate> > templateDict,
            string label)
        {
            var possibleTemplates = templateDict.TryGetValue(new ShapeKey(node.GetType()), out var value)
                ? value
                : new List <InstructionTemplate>();

            var nullTemplates = templateDict.TryGetValue(new ShapeKey(null), out var extracted)
                ? extracted
                : new List <InstructionTemplate>();

            possibleTemplates.AddRange(nullTemplates);

            var bestMatch = possibleTemplates
                            .Select(
                currentTemplate => new
                { Template = currentTemplate, Fits = this.Fit(currentTemplate.Shape, node) })
                            .FirstOrDefault(x => x.Fits != null);

            if (bestMatch == null)
            {
                throw new InstructionSelectorException($"No matching template for {node}.");
            }

            var fill = new List <object>();
            var childInstructions = Enumerable.Empty <Instruction>();

            foreach (var child in bestMatch.Fits)
            {
                object currentFill;
                if (child is Node innerNode)
                {
                    var register       = new VirtualRegister();
                    var innerTemplates = this.FitTemplates(
                        innerNode,
                        register,
                        this.templates[JumpType.NonConditional],
                        null);
                    childInstructions = childInstructions.Concat(innerTemplates);
                    currentFill       = register;
                }
                else
                {
                    currentFill = child;
                }

                fill.Add(currentFill);
            }

            return(childInstructions.Append(bestMatch.Template.Emit(result, fill, label)));
        }
예제 #17
0
 public MovRegisterRegisterInstruction(
     VirtualRegister to,
     VirtualRegister from,
     IReadOnlyCollection <VirtualRegister> uses    = null,
     IReadOnlyCollection <VirtualRegister> defines = null,
     IReadOnlyCollection <Tuple <VirtualRegister, VirtualRegister> > copies = null)
     : base(uses, defines, copies)
 {
     this.to   = to;
     this.from = from;
 }
예제 #18
0
 private GenericOperand ConvertOperand(GenericOperand operand, Type type)
 {
     if (operand.DataType != UpconvertMapping[type])
     {
         VirtualRegister target = AllocateRegister(UpconvertMapping[type]);
         code.Add(new UnaryOperation(IROpCodes.CVT, target, operand));
         ReleaseOperand(operand);
         return(target);
     }
     return(operand);
 }
예제 #19
0
        public override Instruction Emit(VirtualRegister result, IReadOnlyList <object> fill, string label)
        {
            if (label == null)
            {
                throw new TemplateCreationException("Label is null.");
            }

            var input = fill.GetRegister(0);

            return(new ConditionalJumpInstruction(input, label));
        }
예제 #20
0
파일: PopTemplate.cs 프로젝트: nobikik9/kju
 public PopInstruction(VirtualRegister register)
     : base(
         new List <VirtualRegister> {
     HardwareRegister.RSP
 },
         new List <VirtualRegister> {
     HardwareRegister.RSP, register
 })
 {
     this.register = register;
 }
예제 #21
0
 public LeaMovInstruction(
     VirtualRegister baseRegister,
     long offset,
     VirtualRegister value)
     : base(new List <VirtualRegister> {
     value, baseRegister
 })                                                            // No register is written to. Only memory.
 {
     this.baseRegister = baseRegister;
     this.offset       = offset;
     this.value        = value;
 }
예제 #22
0
 public IntegerImmediateValueInstruction(
     VirtualRegister result,
     long value)
     : base(
         new List <VirtualRegister>(),
         new List <VirtualRegister> {
     result
 })
 {
     this.result = result;
     this.value  = value;
 }
예제 #23
0
 public BooleanImmediateValueInstruction(
     VirtualRegister result,
     bool value)
     : base(
         new List <VirtualRegister>(),
         new List <VirtualRegister> {
     result
 })
 {
     this.result = result;
     this.value  = value;
 }
예제 #24
0
 private VirtualRegister MapToRegister(GenericOperand operand)
 {
     if (operand is VirtualRegister)
     {
         return(operand as VirtualRegister);
     }
     else
     {
         VirtualRegister reg = AllocateRegister(operand.DataType);
         code.Add(new UnaryOperation(IROpCodes.MOV, reg, operand));
         return(reg);
     }
 }
예제 #25
0
 private Instruction GetOperation(VirtualRegister lhs, VirtualRegister rhs, VirtualRegister result)
 {
     return(new InstructionMock(
                new List <VirtualRegister> {
         lhs, rhs
     },
                new List <VirtualRegister> {
         result
     },
                new List <Tuple <VirtualRegister, VirtualRegister> >
     {
         new Tuple <VirtualRegister, VirtualRegister>(lhs, result),
         new Tuple <VirtualRegister, VirtualRegister>(rhs, result)
     }));
 }
예제 #26
0
        private VirtualRegister CalculateAddress(VirtualRegister array, GenericOperand index)
        {
            VirtualRegister address = AllocateRegister(array.UnderlyingType, array.StateSpace);

            index = ConvertOperand(index, array.DataType);
            int elemsize = array.UnderlyingType.SizeOf();

            code.Add(elemsize == 1 ?
                     new BinaryOperation(IROpCodes.ADD, address, index, array) as BasicBlockInstruction :
                     new MADOperation(address, index, new ImmediateValue(
                                          (ValueType)Convert.ChangeType(elemsize, array.DataType)), array) as BasicBlockInstruction);
            ReleaseOperand(array);
            ReleaseOperand(index);
            return(address);
        }
예제 #27
0
        public override Instruction Emit(VirtualRegister result, IReadOnlyList <object> fill, string label)
        {
            var constantPosition = 0;
            var registerPosition = 1;

            if (!this.leftConstant)
            {
                (constantPosition, registerPosition) = (registerPosition, constantPosition);
            }

            var constant = fill.GetBool(constantPosition);
            var register = fill.GetRegister(registerPosition);

            return(new LogicalOperationConstantInstruction(constant, register, result, this.operationType));
        }
예제 #28
0
 public MovRegisterMemoryInstruction(
     VirtualRegister result,
     VirtualRegister memoryLocation)
     : base(
         new List <VirtualRegister> {
     memoryLocation
 },
         new List <VirtualRegister> {
     result
 },
         new List <Tuple <VirtualRegister, VirtualRegister> >())
 {
     this.result         = result;
     this.memoryLocation = memoryLocation;
 }
예제 #29
0
 public AddInstruction(
     VirtualRegister input,
     long constant,
     VirtualRegister result)
     : base(
         new List <VirtualRegister> {
     input
 },
         new List <VirtualRegister> {
     result
 })
 {
     this.input    = input;
     this.constant = constant;
     this.result   = result;
 }
예제 #30
0
 public LeaMovInstruction(
     VirtualRegister result,
     VirtualRegister baseRegister,
     long offset)
     : base(
         new List <VirtualRegister> {
     baseRegister
 },
         new List <VirtualRegister> {
     result
 })
 {
     this.result       = result;
     this.baseRegister = baseRegister;
     this.offset       = offset;
 }
        /// <summary>
        /// Handles the return value from a function
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="toCall">The function to call</param>
        /// <param name="returnValueRegister">The register to store the return value</param>
        public void HandleReturnValue(CompilationData compilationData, FunctionDefinition toCall, VirtualRegister returnValueRegister)
        {
            //If we have passed arguments via the stack, adjust the stack pointer.
            int numStackArgs = this.CalculateStackArguments(toCall.Parameters);
            var virtualAssembler = compilationData.VirtualAssembler;

            if (numStackArgs > 0)
            {
                Assembler.Add(
                    compilationData.Function.GeneratedCode,
                    Register.SP,
                    numStackArgs * Assembler.RegisterSize);
            }

            if (!toCall.ReturnType.IsPrimitiveType(PrimitiveTypes.Void))
            {
                if (toCall.ReturnType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    virtualAssembler.GenerateTwoRegisterFixedSourceInstruction(
                        returnValueRegister,
                        FloatRegister.XMM0,
                        Assembler.Move,
                        Assembler.Move,
                        true);
                }
                else
                {
                    virtualAssembler.GenerateTwoRegisterFixedSourceInstruction(
                        returnValueRegister,
                        Register.AX,
                        Assembler.Move,
                        Assembler.Move,
                        true);
                }
            }
        }
        /// <summary>
        /// Generates code for an instruction with a virtual register source
        /// </summary>
        /// <param name="sourceRegister">The source register</param>
        public void GenerateOneRegisterInstruction(VirtualRegister sourceRegister,
            Action<IList<byte>, IntRegister> inst1,
            Action<IList<byte>, MemoryOperand> inst2)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var regAlloc = compilationData.RegisterAllocation;
            int? opStack = compilationData.RegisterAllocation.GetStackIndex(sourceRegister);

            if (!opStack.HasValue)
            {
                var opReg = this.GetIntRegisterForVirtual(sourceRegister).Value;
                inst1(generatedCode, opReg);
            }
            else
            {
                var opStackOffset = CalculateStackOffset(opStack.Value);
                inst2(generatedCode, new MemoryOperand(Register.BP, opStackOffset));
            }
        }
        /// <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);
            }
        }
        /// <summary>
        /// Generates code for an one virtual register operand instruction with an int value
        /// </summary>
        /// <param name="destinationRegister">The destination register</param>
        /// <param name="value">The value</param>
        public void GenerateOneRegisterWithValueInstruction(VirtualRegister destinationRegister, int value,
            Action<IList<byte>, IntRegister, int> inst1,
            Action<IList<byte>, MemoryOperand, int> inst2)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var regAlloc = compilationData.RegisterAllocation;

            var opStack = regAlloc.GetStackIndex(destinationRegister);

            if (!opStack.HasValue)
            {
                var opReg = this.GetIntRegisterForVirtual(destinationRegister).Value;
                inst1(generatedCode, opReg, value);
            }
            else
            {
                var stackOp = new MemoryOperand(
                    Register.BP,
                    CalculateStackOffset(opStack.Value));
                inst2(generatedCode, stackOp, value);
            }
        }
        /// <summary>
        /// Generates code for an instruction with a fixed register destination and virtual register source
        /// </summary>
        /// <param name="destination">The destination</param>
        /// <param name="sourceRegister">The source register</param>
        /// <param name="skipIfSame">Indicates if the instruction will be skipped of destination == source.</param>
        public void GenerateTwoRegisterFixedDestinationInstruction(IntRegister destination, VirtualRegister sourceRegister,
            Action<IList<byte>, IntRegister, IntRegister> inst1,
            Action<IList<byte>, IntRegister, MemoryOperand> inst2,
            bool skipIfSame = false)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var regAlloc = compilationData.RegisterAllocation;
            int? opStack = compilationData.RegisterAllocation.GetStackIndex(sourceRegister);

            if (!opStack.HasValue)
            {
                var opReg = this.GetIntRegisterForVirtual(sourceRegister).Value;

                if (skipIfSame)
                {
                    if (destination != opReg)
                    {
                        inst1(generatedCode, destination, opReg);
                    }
                }
                else
                {
                    inst1(generatedCode, destination, opReg);
                }
            }
            else
            {
                var opStackOffset = CalculateStackOffset(opStack.Value);
                inst2(generatedCode, destination, new MemoryOperand(Register.BP, opStackOffset));
            }
        }
        /// <summary>
        /// Generates code for an instruction with a virtual register destination and fixed register source
        /// </summary>
        /// <param name="destinationRegister">The destination register</param>
        /// <param name="source">The source</param>
        /// <param name="skipIfSame">Indicates if the instruction will be skipped of destination == source.</param>
        public void GenerateTwoRegisterFixedSourceInstruction(VirtualRegister destinationRegister, FloatRegister source,
            Action<IList<byte>, FloatRegister, FloatRegister> inst1,
            Action<IList<byte>, MemoryOperand, FloatRegister> inst2,
            bool skipIfSame = false)
        {
            var generatedCode = compilationData.Function.GeneratedCode;
            var regAlloc = compilationData.RegisterAllocation;
            int? opStack = compilationData.RegisterAllocation.GetStackIndex(destinationRegister);

            if (!opStack.HasValue)
            {
                var opReg = this.GetFloatRegisterForVirtual(destinationRegister).Value;

                if (skipIfSame)
                {
                    if (opReg != source)
                    {
                        inst1(generatedCode, opReg, source);
                    }
                }
                else
                {
                    inst1(generatedCode, opReg, source);
                }
            }
            else
            {
                var opStackOffset = CalculateStackOffset(opStack.Value);
                inst2(generatedCode, new MemoryOperand(Register.BP, opStackOffset), source);
            }
        }
        /// <summary>
        /// Returns the int register for the given virtual register
        /// </summary>
        /// <param name="virtualRegister">The virtual register</param>
        /// <returns>The register or null if the register is spilled</returns>
        public IntRegister? GetIntRegisterForVirtual(VirtualRegister virtualRegister)
        {
            if (virtualRegister.Type != VirtualRegisterType.Integer)
            {
                return null;
            }

            var reg = this.compilationData.RegisterAllocation.GetRegister(virtualRegister);

            if (reg.HasValue)
            {
                return this.GetIntRegister(reg.Value);
            }
            else
            {
                return null;
            }
        }
        /// <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>
        /// Returns the register allocation information for the given virtual register
        /// </summary>
        /// <param name="virtualRegister">The virtual register</param>
        public AllocatedRegister? GetRegisterAllocation(VirtualRegister virtualRegister)
        {
            AllocatedRegister allocatedRegister;
            if (this.allocated.TryGetValue(virtualRegister, out allocatedRegister))
            {
                return allocatedRegister;
            }

            return null;
        }
        /// <summary>
        /// Returns the stack index for the given virtual register
        /// </summary>
        /// <param name="virtualRegister">The virtual register</param>
        public int? GetStackIndex(VirtualRegister virtualRegister)
        {
            SpilledRegister spilledRegister;
            if (this.Spilled.TryGetValue(virtualRegister, out spilledRegister))
            {
                return spilledRegister.StackIndex;
            }

            return null;
        }
        /// <summary>
        /// Returns the register for the given virtual register
        /// </summary>
        /// <param name="virtualRegister">The virtual register</param>
        public int? GetRegister(VirtualRegister virtualRegister)
        {
            AllocatedRegister allocatedRegister;
            if (this.allocated.TryGetValue(virtualRegister, out allocatedRegister))
            {
                return allocatedRegister.HardwareRegister;
            }

            return null;
        }
        /// <summary>
        /// Calculates the stack offset for the given virtual register
        /// </summary>
        /// <param name="virtualRegister">The virtual register</param>
        public int? CalculateStackOffset(VirtualRegister virtualRegister)
        {
            int? stackIndex = this.compilationData.RegisterAllocation.GetStackIndex(virtualRegister);

            if (stackIndex.HasValue)
            {
                return this.CalculateStackOffset(stackIndex.Value);
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// Computes the liveness for the given register
        /// </summary>
        /// <param name="backflowGraph">The backflow graph</param>
        /// <param name="basicBlock">The current block</param>
        /// <param name="startOffset">The offset in the current block</param>
        /// <param name="visited">The visited blocks</param>
        /// <param name="register">The current register</param>
        /// <param name="aliveAt">The instructions which the register is alive</param>
        private static void ComputeLiveness(
            BackflowGraph backflowGraph,
            VirtualBasicBlock basicBlock, int startOffset,
            ISet<VirtualBasicBlock> visited,
            VirtualRegister register, ISet<int> aliveAt)
        {
            if (visited.Contains(basicBlock))
            {
                return;
            }

            visited.Add(basicBlock);

            bool terminated = false;

            for (int i = startOffset; i >= 0; i--)
            {
                var instruction = basicBlock.Instructions[i];

                if (instruction.AssignRegister == register)
                {
                    if (!instruction.UsesRegisters.Contains(register))
                    {
                        aliveAt.Add(i + basicBlock.StartOffset);
                        terminated = true;
                        break;
                    }
                }

                aliveAt.Add(i + basicBlock.StartOffset);
            }

            //If we have not terminated the search, search edges flowing backwards from the current block
            if (!terminated)
            {
                ISet<VirtualBasicBlock> edges;
                if (backflowGraph.Edges.TryGetValue(basicBlock, out edges))
                {
                    foreach (var backEdge in edges)
                    {
                        ComputeLiveness(
                            backflowGraph,
                            backEdge,
                            backEdge.Instructions.Count - 1,
                            visited,
                            register,
                            aliveAt);
                    }
                }
            }
        }
        /// <summary>
        /// Makes the return value for a function
        /// </summary>
        /// <param name="compilationData">The compilation data</param>
        /// <param name="returnValueRegister">The virtual register where the return value is stored</param>
        public void MakeReturnValue(CompilationData compilationData, VirtualRegister returnValueRegister)
        {
            var def = compilationData.Function.Definition;
            var virtualAssembler = compilationData.VirtualAssembler;

            if (!def.ReturnType.IsPrimitiveType(PrimitiveTypes.Void))
            {
                if (def.ReturnType.IsPrimitiveType(PrimitiveTypes.Float))
                {
                    virtualAssembler.GenerateTwoRegisterFixedDestinationInstruction(
                       FloatRegister.XMM0,
                       returnValueRegister,
                       Assembler.Move,
                       Assembler.Move,
                       true);
                }
                else
                {
                    virtualAssembler.GenerateTwoRegisterFixedDestinationInstruction(
                       new IntRegister(Register.AX),
                       returnValueRegister,
                       Assembler.Move,
                       Assembler.Move,
                       true);
                }
            }
        }
        /// <summary>
        /// Generates code for a float instruction with two virtual registers
        /// </summary>
        /// <param name="destinationRegister">The destination register</param>
        /// <param name="sourceRegister">The source register</param>
        public void GenerateTwoRegistersFloatInstruction(VirtualRegister destinationRegister, VirtualRegister sourceRegister,
            Action<IList<byte>, FloatRegister, FloatRegister> inst1,
            Action<IList<byte>, FloatRegister, MemoryOperand> inst2)
        {
            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.GetFloatRegisterForVirtual(destinationRegister).Value;
                var op2Reg = this.GetFloatRegisterForVirtual(sourceRegister).Value;
                inst1(generatedCode, op1Reg, op2Reg);
            }
            else if (!op1Stack.HasValue && op2Stack.HasValue)
            {
                var op1Reg = this.GetFloatRegisterForVirtual(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.GetFloatRegisterForVirtual(sourceRegister).Value;
                var spillReg = this.GetFloatSpillRegister();

                Assembler.Move(generatedCode, spillReg, new MemoryOperand(Register.BP, op1StackOffset));
                inst1(generatedCode, spillReg, op2Reg);
                Assembler.Move(generatedCode, new MemoryOperand(Register.BP, op1StackOffset), spillReg);
            }
            else
            {
                var op1StackOffset = CalculateStackOffset(op1Stack.Value);
                var op2StackOffset = CalculateStackOffset(op2Stack.Value);

                this.RewriteMemory(
                    MemoryRewrite.MemoryOnRight,
                    new MemoryOperand(Register.BP, op1StackOffset),
                    new MemoryOperand(Register.BP, op2StackOffset),
                    inst2,
                    null);
            }
        }
 /// <summary>
 /// Creates a new interval
 /// </summary>
 /// <param name="start">The start of the interval</param>
 /// <param name="end">he end of the interval</param>
 /// <param name="virtualRegister">The virtual register number</param>
 public LiveInterval(int start, int end, VirtualRegister virtualRegister)
 {
     this.Start = start;
     this.End = end;
     this.VirtualRegister = virtualRegister;
 }
 /// <summary>
 /// Computes the liveness for the given register
 /// </summary>
 /// <param name="backflowGraph">The backflow graph</param>
 /// <param name="register">The register</param>
 /// <param name="useSites">The use sites</param>
 /// <param name="aliveAt">The instructions which the register is alive</param>
 private static void ComputeLiveness(BackflowGraph backflowGraph, VirtualRegister register, IList<UsageSite> useSites, ISet<int> aliveAt)
 {
     foreach (var useSite in useSites)
     {
         ComputeLiveness(
             backflowGraph,
             useSite.Block,
             useSite.Offset,
             new HashSet<VirtualBasicBlock>(),
             register,
             aliveAt);
     }
 }
 /// <summary>
 /// Returns the register for the given virtual register
 /// </summary>
 /// <param name="virtualRegister">The virtual register</param>
 /// <returns>The register or null if the register is spilled</returns>
 public HardwareRegister? GetRegisterForVirtual(VirtualRegister virtualRegister)
 {
     if (virtualRegister.Type == VirtualRegisterType.Float)
     {
         return this.GetFloatRegisterForVirtual(virtualRegister);
     }
     else
     {
         return this.GetIntRegisterForVirtual(virtualRegister);
     }
 }
        /// <summary>
        /// Returns the live interval for the given virtual register
        /// </summary>
        /// <param name="register">The virtual register</param>
        /// <param name="aliveAt">The instructions which the register is alive</param>
        private static LiveInterval GetLiveInterval(VirtualRegister register, ISet<int> aliveAt)
        {
            int start = int.MaxValue;
            int end = int.MinValue;

            foreach (var instruction in aliveAt)
            {
                start = Math.Min(start, instruction);
                end = Math.Max(end, instruction);
            }

            return new LiveInterval(start, end, register);
        }