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); }
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)); }
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)); }
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)); }
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); }
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)); }
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); } }
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); }
private void AddEdge( Dictionary <VirtualRegister, List <VirtualRegister> > graph, VirtualRegister register1, VirtualRegister register2) { graph[register1].Add(register2); graph[register2].Add(register1); }
public ConditionalJumpInstruction(VirtualRegister register, string label) : base(new List <VirtualRegister> { register }) { this.register = register; this.Label = label; }
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); }
private Instruction GetDefinition(VirtualRegister register) { return(new InstructionMock( new List <VirtualRegister>(), new List <VirtualRegister> { register }, new List <Tuple <VirtualRegister, VirtualRegister> >())); }
public VirtualRegister PopStack() { VirtualRegister r = m_stack.Pop(); if (r is TemporaryRegister || r.RegisterNumber < 0) { m_stackDepth--; } return(r); }
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; }
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))); }
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; }
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); }
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)); }
public PopInstruction(VirtualRegister register) : base( new List <VirtualRegister> { HardwareRegister.RSP }, new List <VirtualRegister> { HardwareRegister.RSP, register }) { this.register = register; }
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; }
public IntegerImmediateValueInstruction( VirtualRegister result, long value) : base( new List <VirtualRegister>(), new List <VirtualRegister> { result }) { this.result = result; this.value = value; }
public BooleanImmediateValueInstruction( VirtualRegister result, bool value) : base( new List <VirtualRegister>(), new List <VirtualRegister> { result }) { this.result = result; this.value = value; }
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); } }
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) })); }
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); }
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)); }
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; }
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; }
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); }