Once uncompressed (for instance with tar zxvf ltl-java.tar.gz), you get the following Java files:
LTL.java | LTL Language (Location Transfer Language) |
LTLinterp.java | LTL Interpreter (to make tests) |
X86_64.java | x86-64 Assembly |
These classes are complete and documented here. Take some time to read and understand all this.
As usual, we strongly advise to proceed step by step, with systematic testing.
class Arcs { Set<Register> prefs = new HashSet<>(); Set<Register> intfs = new HashSet<>(); } class Interference { Map<Register, Arcs> graph; }Build such as graph from the liveness analysis, that is,
Interference(Liveness lg) { ... }Hints:
To debug, you can print the interference graph with the following method:
void print() { System.out.println("interference:"); for (Register r: graph.keySet()) { Arcs a = graph.get(r); System.out.println(" " + r + " pref=" + a.prefs + " intf=" + a.intfs); } }With a C program such as
int main() { return 42; }you should obtain something like
interference: #3 pref=[%r12] intf=[%rbx, %rax, #1, #2] %rbx pref=[#2] intf=[#3, %rax, %r12] %rax pref=[#1] intf=[#3, %rbx, %r12, #2] %r12 pref=[#3] intf=[%rbx, %rax, #2] #1 pref=[%rax] intf=[#3, #2] #2 pref=[%rbx] intf=[#3, %rax, %r12, #1]
class Coloring { Map<Register, Operand> colors = new HashMap<>(); int nlocals = 0; // number of stack slots ... }The starting point is the interference graph, that is
Coloring(Interference ig) { ... }
You do not have to implement George-Appel's algorithm presented in the lecture. You can go for something simpler, as follows:
When selecting a register to color, you can favor
To debug, one can print the coloring with the following method:
void print() { System.out.println("coloring output:"); for (Register r: colors.keySet()) { Operand o = colors.get(r); System.out.println(" " + r + " --> " + o); } }With a C program such as
int main() { return 42; }you should obtain something like
coloring output: #3 --> %r12 #1 --> %rax #2 --> %rbx
class ToLTL implements ERTLVisitor { private Coloring coloring; // coloring for the current function int size_locals; // size for the spilled registers LTLgraph graph; // graph under construction ... }
You can print the result with method print from class LTLfile. With a C program such as
int main() { return 42; }you should obtain something like
=== LTL ================================================== main() entry : L5 L5: goto L4 L4: goto L3 L3: goto L2 L2: mov $42 %rax --> L1 L1: goto L10 L10: goto L9 L9: goto L8 L8: goto L7 L7: goto L6 L6: return
Then you can test as follows:
> ./run -i "mon/chemin/vers/mini-c --interp-ltl" Test de mon/chemin/vers/mini-c --interp-ltl Interprétation Execution normale ----------------- ........................................................... Execution conduisant à un échec ------------------------------- ... Compilation: Compilation : 62/62 : 100% Comportement du code : 62/62 : 100%
class Lin implements LTLVisitor { private LTLgraph cfg; // graph under translation private X86_64 asm; // assembly code under de construction private HashSet<Label> visited; // instructions already translated ...The assembly code under construction is stored in asm. The table visited stores the instructions already translated. You can use the following method:
private void lin(Label l) { if (visited.contains(l)) { asm.needLabel(l); asm.jmp(l.name); } else { visited.add(l); asm.label(l); cfg.graph.get(l).accept(this); } }It produces code from a given label, if not already done, and a jump to that label otherwise. This code is mutually recursive with the various visit methods from class Lin that translate the various LTL instructions.
We translate a LTL function f as follows:
cfg = f.body; asm.label(f.name); lin(f.entry);
With a C program such as
int main() { return 42; }you should obtain something like
.text .globl main main: movq $42, %rax ret .data
> ./run -3 mon/chemin/vers/mini-c Test de mon/chemin/vers/mini-c Partie 3 Execution normale ----------------- ........................................................... Execution conduisant à un échec ------------------------------- ../run: line 266: 12739 Segmentation fault ./a.out > out ../run: line 266: 12751 Floating point exception./a.out > out ../run: line 266: 12763 Floating point exception./a.out > out Compilation: Compilation : 62/62 : 100% Code produit : 62/62 : 100% Comportement du code : 62/62 : 100%