One uncompressed (for instance with tar zxvf rtl-ocaml.tar.gz), you get a directory mini-c/ with the following OCaml modules :
Pp | Pretty-printing library |
Ops | x86-64 operations to be used in instruction selection |
Label | Labels |
Register | Registers (x86-64 and pseudo-registers) |
Rtltree | Register Transfer Language (RTL) |
Rtlinterp | RTL interpreter (to make tests) |
These modules are complete. Click on a module name to access its documentation. Take some time to understand what is provided.
This new minic.ml adds a command line option --interp-rtl to execute the RTL code (using function Rtlinterp.program). Beside, the new main file outputs the RTL code (with function Rtltree.print_file) when the command line option --debug is used.
We strongly advise to proceed step by step, with systematic testing.
let graph = ref Label.M.emptyIt is useful to declare a function to add a new instruction to the graph, at a fresh label that is returned:
let generate i = let l = Label.fresh () in graph := Label.M.add l i !graph; l
To translate expressions, introduce a recursive function as follows,
let rec expr e destr destl = ...where e is the expression to translate, destr is the destination pseudo-register, and destl is the destination label.
To translate statements, introduce a recursive function as follows,
let rec stmt s destl retr exitl = ...where s is the statement to translate and destl is the destination label. When the statement is return, the returned value must be stored in retr and the control must be transferred to label exitl (function exit).
Introduce a function deffun to translate a mini-C function to a value of type Rtltree.deffun. To do so, create a fresh pseudo-register for the function result and a fresh label for the function exit, and call function stmt above on the function body.
Finally, implement a function that translates a mini-C program to the type Rtltree.file, by translating each mini-C function independently.
Test with the following mini-C program:
int main() { return 42; }You must get something like this:
=== RTL ================================================== #1 main() entry : L2 exit : L1 locals: L2: mov $42 #1 --> L1
The new RTL instructions to be used are: Emunop, Embinop.
Test with programs such as
int main() { return 40 - (-2); }
Test with programs such as
int main() { int x, y; y = 40; x = 2; return y + x; }
To translate statements if and while, it is useful to introduce a function
let rec condition e truel false = ...that translates an expression e to RTL and transfers control to label truel if the value is not zero and to label falsel otherwise.
Add support for C constructions && and ||, with the expected lazy semantics.
New RTL instructions to be used are: Emubranch, Embbranch, Egoto.
Test with programs such as
int main() { if (1 <= 2) return 3; else return 4; }
The new RTL instructions to be used are: Ecall.
Test with programs such as
int fact(int n) { if (n <= 1) return 1; return n * fact(n-1); } int main() { return fact(42); }
The new RTL instructions to be used are: Eload, Estore.
Test with programs such as
struct S { int a; int b; }; int main() { struct S *p; p = malloc(sizeof(struct S)); p->a = 40; p->b = 2; return p->a + p->b; }
> ./run -i "mon/chemin/vers/mini-c --interp-rtl" Test de mon/chemin/vers/mini-c --interp-rtl Interprétation Execution normale ----------------- ........................................................... Execution conduisant à un échec ------------------------------- ... Compilation: Compilation : 62/62 : 100% Comportement du code : 62/62 : 100%