public void SimpleTest() { RegisterNode[] firstUsed = {}; RegisterNode[] firstDef = { x }; Instruction firstIns = new Instruction(instructionBuilder, firstUsed, firstDef); RegisterNode[] secondUsed = {}; RegisterNode[] secondDef = { y }; Instruction secondIns = new Instruction(instructionBuilder, secondUsed, secondDef); RegisterNode[] thirdUsed = { x, y }; RegisterNode[] thirdDef = {}; Instruction thirdIns = new Instruction(instructionBuilder, thirdUsed, thirdDef); LivenessAnalysis aL = new LivenessAnalysis(); Instruction[] instructions = { firstIns, secondIns, thirdIns }; var result = aL.AnalyzeLiveness(instructions); Assert.AreEqual(2, result.Vertices.Count); Assert.AreEqual(1, result.Vertices [0].NonCopyNeighbors.Count); ICollection <string> temp = new HashSet <string>(); if (result.Vertices [0].Register.Id.CompareTo("x") == 0) { temp.Add("y"); } else { temp.Add("x"); } foreach (var v in result.Vertices[0].NonCopyNeighbors) { Assert.IsTrue(temp.Contains(v.Register.Id)); } temp.Clear(); if (result.Vertices [1].Register.Id.CompareTo("x") == 0) { temp.Add("y"); } else { temp.Add("x"); } foreach (var v in result.Vertices[1].NonCopyNeighbors) { Assert.IsTrue(temp.Contains(v.Register.Id)); } }
/// <summary> /// Construct trace for each function and then in a loop: /// - generate the whole body of the function /// - select instructions /// - analyze liveness /// - allocate registers. /// Loop untill success or MAX_ALLOC_TRY. After success - generate nasm. /// </summary> /// <returns>sequence of nasm instructions</returns> /// <param name="funcList">List of backend functions created by frontend.</param> public IEnumerable <string> FromFunctionsToNasm(IEnumerable <Function> funcList) { foreach (var f in funcList) { f.Body = TraceBuilder.BuildTrace(f.Body.First()); } var livenessAnalyzer = new LivenessAnalysis(); var regAllocator = new RegisterAllocator(Target.AllHardwareRegisters); var output = new List <string>(); foreach (var f in funcList) { int tryCount = 0; IEnumerable <Instruction> fInstr; while (true) { if (tryCount == MAX_ALLOC_TRY) { throw new ArgumentException("Your input is stupid... (or our compiler)."); } var fBody = f.GenerateTheWholeBody(); fInstr = InstructionSelection.SelectInstructions(fBody); var inGraph = livenessAnalyzer.AnalyzeLiveness(fInstr); regAllocator.AllocateRegisters(inGraph); var toCorrect = regAllocator.SpilledRegisters; if (toCorrect.Any()) { // apply changes f.MoveRegistersToMemory(toCorrect); } else { // success break; } tryCount++; } // use regAllocator.RegistersColoring to produce nasm var regMapping = regAllocator.RegistersColoring; foreach (var instr in fInstr) { output.Add(instr.ToString(regMapping)); } output.Add("\n"); } return(output); }
public void LabelJumpTest() { RegisterNode[] used = {}; RegisterNode[] def = {}; Instruction firstIns = Instruction.JumpInstruction(instructionBuilder, used, def, "third"); Instruction secondIns = new Instruction(instructionBuilder, used, def); Instruction thirdIns = Instruction.LabelInstruction(instructionBuilder, "third"); LivenessAnalysis aL = new LivenessAnalysis(); Instruction[] instructions = { firstIns, secondIns, thirdIns }; aL.AnalyzeLiveness(instructions); Assert.AreEqual(0, firstIns.PrevInstructions.Count); Assert.AreEqual(1, secondIns.PrevInstructions.Count); Assert.AreEqual(2, thirdIns.PrevInstructions.Count); }
public void SimpleTest2() { RegisterNode[] firstUsed = {}; RegisterNode[] firstDef = { x, y }; Instruction firstIns = new Instruction(instructionBuilder, firstUsed, firstDef); RegisterNode[] secondUsed = { x }; RegisterNode[] secondDef = {}; Instruction secondIns = new Instruction(instructionBuilder, secondUsed, secondDef); LivenessAnalysis aL = new LivenessAnalysis(); Instruction[] instructions = { firstIns, secondIns }; var result = aL.AnalyzeLiveness(instructions); Assert.AreEqual(2, result.Vertices.Count); Assert.AreEqual(0, result.Vertices [0].NonCopyNeighbors.Count); Assert.AreEqual(0, result.Vertices [0].CopyNeighbors.Count); Assert.AreEqual(0, result.Vertices [1].NonCopyNeighbors.Count); Assert.AreEqual(0, result.Vertices [1].CopyNeighbors.Count); }