protected override void Run()
        {
            if (IsPlugged)
            {
                return;
            }

            trace = CreateTraceLog();

            var liveAnalysisGCEnvironment = new GCEnvironment(BasicBlocks, Architecture, MethodCompiler.LocalStack);

            LiveAnalysis = new LivenessAnalysis(liveAnalysisGCEnvironment, this, true);

            if (trace.Active)
            {
                for (int i = 0; i < LiveAnalysis.LiveRanges.Length; i++)
                {
                    var range = LiveAnalysis.LiveRanges[i];

                    trace.Log(i.ToString() + ": " + range);
                }
            }

            return;
        }
        private IEnumerable <ProcedureCompilation> CompileDeclaration(IDeclaration declaration)
        {
            switch (declaration)
            {
            case NamespaceDeclaration decl:
                foreach (var compilation in decl.Declarations.SelectMany(CompileDeclaration))
                {
                    yield return(compilation);
                }
                break;

            case Procedure procedure:
                var(transformed, parameters) = Transformer.TransformProcedureStatement(procedure.EntryPoint, procedure.Parameters);

                var cfg = CFGNode.ConstructCFG(transformed);
                LivenessAnalysis.PerformAnalysis(cfg);
                var allocation = RegisterAllocation.Generate(cfg, parameters
                                                             .Select((x, i) => (x, i)).Where(x => x.i != 1).ToDictionary(
                                                                 x => x.x,
                                                                 x => ProcedureCompilation.ParameterLocation(x.i)));

                yield return(new ProcedureCompilation(procedure, parameters, transformed, ConstantTable, FalseConstant, TrueConstant, allocation));

                break;

            case ProcedureImport import:
                Externs.Add(import.Name);
                Imports.Add(import.ImportedName);
                break;
            }
        }
        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));
            }
        }
Beispiel #4
0
        /// <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 Test()
        {
            var instructions = new[]
            {
                new M68kInstruction(M68kOpcode.Move, 4, d0),
                new M68kInstruction(M68kOpcode.Move, d0, d1),
                new M68kInstruction(M68kOpcode.Move, 1, d3),
                new M68kInstruction(M68kOpcode.Move, d1, d2),
                new M68kInstruction(M68kOpcode.Move, d2, d0),
                new M68kInstruction(M68kOpcode.Rts)
            };

            var la = new LivenessAnalysis(instructions);

            var g     = InterferenceGraphGenerator.MakeGraph(la.Nodes, RegType.Data, "D0,D1,D2,D3,D4,D5,D6,D7".Split(',').ToList());
            var graph = g.Graph;

            Assert.IsTrue(graph.Contains(new Tuple <string, string>("D1", "D3")) || graph.Contains(new Tuple <string, string>("D3", "D1")));
            Assert.IsFalse(graph.Contains(new Tuple <string, string>("D1", "D1")));
        }
        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);
        }
Beispiel #8
0
        protected override void Run()
        {
            if (MethodCompiler.IsMethodPlugged)
            {
                return;
            }

            trace = CreateTraceLog();

            var liveAnalysisGCEnvironment = new GCEnvironment(BasicBlocks, Architecture, MethodCompiler.LocalStack);

            LiveAnalysis = new LivenessAnalysis(liveAnalysisGCEnvironment, this, true);

            if (trace != null)
            {
                for (int i = 0; i < LiveAnalysis.LiveRanges.Length; i++)
                {
                    var range = LiveAnalysis.LiveRanges[i];

                    trace.Log($"{i}: {range}");
                }
            }
        }
        public void Liveness()
        {
            var instructions = new[]
            {
                new M68kInstruction(M68kOpcode.Move, 4, d0),
                new M68kInstruction(M68kOpcode.Move, d0, d1),
                new M68kInstruction(M68kOpcode.Move, 1, d3),
                new M68kInstruction(M68kOpcode.Move, d1, d2),
                new M68kInstruction(M68kOpcode.Move, d2, d0),
                //new M68kInstruction(M68kOpcode.Rts) // This would introduce D2-D7
                new M68kInstruction(M68kOpcode.Move)
                {
                    AddressingMode1 = M68kAddressingMode.Register, Register1 = d0, AddressingMode2 = M68kAddressingMode.Address,
                    FinalRegister2  = M68kRegister.SP
                }
            };

            var la = new LivenessAnalysis(instructions);

            CollectionAssert.AreEquivalent(new[] { "D0" }, la.Nodes[0].Def);
            CollectionAssert.AreEquivalent(new[] { "D2" }, la.Nodes[3].Def);

            AssertOuts(la.Nodes[0], "D0");

            AssertIns(la.Nodes[1], "D0");
            AssertOuts(la.Nodes[1], "D1");

            AssertIns(la.Nodes[2], "D1");
            AssertOuts(la.Nodes[2], "D1");

            AssertIns(la.Nodes[3], "D1");
            AssertOuts(la.Nodes[3], "D2");

            AssertIns(la.Nodes[4], "D2");
            AssertOuts(la.Nodes[4], "D0");
        }
Beispiel #10
0
 protected override void Finish()
 {
     trace        = null;
     LiveAnalysis = null;
 }
        public void BranchesTest()
        {
            var d20 = new Register {
                Type = RegType.Data, Number = 20
            };
            var d21 = new Register {
                Type = RegType.Data, Number = 21
            };
            var d22 = new Register {
                Type = RegType.Data, Number = 22
            };
            var d23 = new Register {
                Type = RegType.Data, Number = 23
            };
            var d24 = new Register {
                Type = RegType.Data, Number = 24
            };
            var d25 = new Register {
                Type = RegType.Data, Number = 25
            };

            var a7 = new Register {
                Type = RegType.Address, Number = 7
            };
            var a8 = new Register {
                Type = RegType.Address, Number = 7
            };
            var a15 = new Register {
                Type = RegType.Address, Number = 15
            };
            var a16 = new Register {
                Type = RegType.Address, Number = 15
            };

            var instructions = new[]
            {
                new M68kInstruction(M68kOpcode.Move, d20, d21),
                new M68kInstruction(M68kOpcode.Add, -1, d21),
                new M68kInstruction(M68kOpcode.Jmp)
                {
                    TargetLabel = "for$body0$7"
                },
                new M68kInstruction(M68kOpcode.Label)
                {
                    Label = "for$body0"
                },
                new M68kInstruction(M68kOpcode.Label)
                {
                    Label = "for$body0$7"
                },
                new M68kInstruction(M68kOpcode.MoveQ, 0, d22),
                new M68kInstruction(M68kOpcode.Jmp)
                {
                    TargetLabel = "for$body0$end"
                },
                new M68kInstruction(M68kOpcode.Label)
                {
                    Label = "for$body0$8"
                },
                new M68kInstruction(M68kOpcode.Jmp)
                {
                    TargetLabel = "for$body0$end"
                },
                new M68kInstruction(M68kOpcode.Label)
                {
                    Label = "for$body0$end"
                },
                new M68kInstruction(M68kOpcode.MoveQ, d21, d23),
                new M68kInstruction(M68kOpcode.Sub, d22, d23),
                new M68kInstruction(M68kOpcode.Move, a7, a15),
                new M68kInstruction(M68kOpcode.Adda, d23, a15),
                new M68kInstruction(M68kOpcode.Move, a15, d24),
                new M68kInstruction(M68kOpcode.Move, a8, a16),

                new M68kInstruction(M68kOpcode.Adda, d22, a16),
                new M68kInstruction(M68kOpcode.Move, d24, a16),
                new M68kInstruction(M68kOpcode.Move, d22, d25),
                new M68kInstruction(M68kOpcode.Adda, 1, d25),
                new M68kInstruction(M68kOpcode.Cmp, d20, d25),
                new M68kInstruction(M68kOpcode.Beq)
                {
                    TargetLabel = "for$end$loopexit0"
                },
                new M68kInstruction(M68kOpcode.Move, d25, d22),
                new M68kInstruction(M68kOpcode.Jmp)
                {
                    TargetLabel = "for$body0$8"
                },
                new M68kInstruction(M68kOpcode.Label)
                {
                    Label = "for$end$loopexit0"
                },
            };

            var la = new LivenessAnalysis(instructions);

            var gr = InterferenceGraphGenerator.MakeGraph(la.Nodes, RegType.Data, new List <string>());

            Assert.IsTrue(gr.IsEdgeBetween("D21", "D20"));
            Assert.IsTrue(gr.IsEdgeBetween("D21", "D22"));
            Assert.IsTrue(gr.IsEdgeBetween("D21", "D23"));
            Assert.IsTrue(gr.IsEdgeBetween("D21", "D24"));
            Assert.IsTrue(gr.IsEdgeBetween("D21", "D25"));

            Assert.IsFalse(gr.IsEdgeBetween("D23", "D24"));
            Assert.IsFalse(gr.IsEdgeBetween("D23", "D25"));
            Assert.IsFalse(gr.IsEdgeBetween("D24", "D25"));

            Assert.IsTrue(gr.IsEdgeBetween("D22", "D20"));
            Assert.IsTrue(gr.IsEdgeBetween("D22", "D23"));
            Assert.IsTrue(gr.IsEdgeBetween("D22", "D24"));
            Assert.IsFalse(gr.IsEdgeBetween("D22", "D25"));

            /*
             *  add.l #1,D25_
             *  cmp.l D20_,D25_
             *  beq for$end$loopexit0
             *  move.l D25_,D22_
             *  jmp for$body0$8
             * for$end$loopexit0:
             */
        }
        public void PredSuccWithBranch()
        {
            var instructions = new[]
            {
                new M68kInstruction(M68kOpcode.Move, 4, d0),                    // 0
                new M68kInstruction(M68kOpcode.Bgt)
                {
                    TargetLabel = "end"
                },                                                              // 1
                new M68kInstruction(M68kOpcode.Label)
                {
                    Label = "foo"
                },                                                              // 2
                new M68kInstruction(M68kOpcode.Move, 1, d0),                    // 3
                new M68kInstruction(M68kOpcode.Label)
                {
                    Label = "end"
                },                                                              // 4
                new M68kInstruction(M68kOpcode.Move, 3, d0),                    // 5
                //new M68kInstruction(M68kOpcode.Rts) // This would introduce D2-D7
                new M68kInstruction(M68kOpcode.Move)                            // 6
                {
                    AddressingMode1 = M68kAddressingMode.Register,
                    Register1       = d0,
                    AddressingMode2 = M68kAddressingMode.Address,
                    FinalRegister2  = M68kRegister.SP
                },
                new M68kInstruction(M68kOpcode.Jmp)
                {
                    TargetLabel = "foo"
                },                                                              // 7
                new M68kInstruction(M68kOpcode.Move, 3, d0),                    // 8
            };

            //TODO: Conditional branches have 2 successors!!!

            var la = new LivenessAnalysis(instructions);

            CollectionAssert.AreEquivalent(la.Nodes[0].Pred, new CfgNode[] { });
            CollectionAssert.AreEquivalent(la.Nodes[0].Succ, new[] { la.Nodes[1] });

            CollectionAssert.AreEquivalent(la.Nodes[1].Pred, new[] { la.Nodes[0] });
            CollectionAssert.AreEquivalent(la.Nodes[1].Succ, new[] { la.Nodes[2], la.Nodes[4] });

            CollectionAssert.AreEquivalent(la.Nodes[2].Pred, new[] { la.Nodes[1], la.Nodes[7] });
            CollectionAssert.AreEquivalent(la.Nodes[2].Succ, new[] { la.Nodes[3] });

            CollectionAssert.AreEquivalent(la.Nodes[3].Pred, new[] { la.Nodes[2] });
            CollectionAssert.AreEquivalent(la.Nodes[3].Succ, new[] { la.Nodes[4] });

            CollectionAssert.AreEquivalent(la.Nodes[4].Pred, new[] { la.Nodes[1], la.Nodes[3] });
            CollectionAssert.AreEquivalent(la.Nodes[4].Succ, new[] { la.Nodes[5] });

            CollectionAssert.AreEquivalent(la.Nodes[5].Pred, new[] { la.Nodes[4] });
            CollectionAssert.AreEquivalent(la.Nodes[5].Succ, new[] { la.Nodes[6] });

            CollectionAssert.AreEquivalent(la.Nodes[6].Pred, new[] { la.Nodes[5] });
            CollectionAssert.AreEquivalent(la.Nodes[6].Succ, new[] { la.Nodes[7] });

            CollectionAssert.AreEquivalent(la.Nodes[7].Pred, new[] { la.Nodes[6] });
            CollectionAssert.AreEquivalent(la.Nodes[7].Succ, new[] { la.Nodes[2] });

            CollectionAssert.AreEquivalent(la.Nodes[8].Pred, new CfgNode[] { });
            CollectionAssert.AreEquivalent(la.Nodes[8].Succ, new CfgNode[] { });
        }
        public void Test2()
        {
            var b = d11;
            var c = d12;
            var d = d13;
            var e = d14;
            var f = d15;
            var g = d16;
            var h = d17;
            var j = d19;
            var k = d20;
            var m = d21;

            /*
             * g := mem[j+12]
             * h := k - 1
             * f := g * h
             * e := mem[j+8]
             * m := mem[j+16]
             * b := mem[f]
             * c := e + 8
             * d := c
             * k := m + 4
             * j := b*/

            var instructions = new[]
            {
                M68kInstruction.LoadFromMemory(j, g),

                new M68kInstruction(M68kOpcode.Move, k, d0),
                new M68kInstruction(M68kOpcode.Sub, 1, d0),
                new M68kInstruction(M68kOpcode.Move, d0, h),

                new M68kInstruction(M68kOpcode.Move, g, d0),
                new M68kInstruction(M68kOpcode.Add, h, d0),
                new M68kInstruction(M68kOpcode.Move, d0, f),

                M68kInstruction.LoadFromMemory(j, e),
                M68kInstruction.LoadFromMemory(j, m),
                M68kInstruction.LoadFromMemory(f, b),

                new M68kInstruction(M68kOpcode.Move, e, d0),
                new M68kInstruction(M68kOpcode.Add, 8, d0),
                new M68kInstruction(M68kOpcode.Move, d0, c),

                new M68kInstruction(M68kOpcode.Move, c, d),

                new M68kInstruction(M68kOpcode.Move, m, d0),
                new M68kInstruction(M68kOpcode.Add, 4, d0),
                new M68kInstruction(M68kOpcode.Move, d0, k),

                new M68kInstruction(M68kOpcode.Move, b, j),

                // Cause Live out: d k j

                M68kInstruction.StoreToMemory(d, j),
                M68kInstruction.StoreToMemory(k, j),
                M68kInstruction.StoreToMemory(j, j),

                //new M68kInstruction(M68kOpcode.Rts)
            };

            var la = new LivenessAnalysis(instructions);

            var gr = InterferenceGraphGenerator.MakeGraph(la.Nodes, RegType.Data, "D0,D1,D2,D3,D4,D5,D6,D7".Split(',').ToList());

            AssertEdge(gr, j, f);
            AssertEdge(gr, j, e);
            AssertEdge(gr, j, k);
            AssertEdge(gr, j, h);
            AssertEdge(gr, j, g);

            AssertEdge(gr, f, e);
            AssertEdge(gr, f, m);
            AssertEdge(gr, f, m);

            AssertEdge(gr, k, b);
            AssertEdge(gr, k, d);
            AssertEdge(gr, k, g);

            AssertEdge(gr, h, g);

            AssertEdge(gr, b, m);
            AssertEdge(gr, b, c);
            AssertEdge(gr, b, d);

            AssertNoEdge(gr, j, b);
            AssertNoEdge(gr, d, c);
        }