let generate_code source_fname procs =
let ret = ref (
"\t.file\t\"" ^ source_fname ^ "\"\n" ^
"\t.section\t.rodata\n.WI:\n\t.string\t\"%d\\n\"\n" ^
"\t.text\n"
)
in
let code_of_proc p =
let code_of_var v =
match v.var_def.vd_value with
| Some(Integer i) -> "", "$" ^ (string_of_int i)
| _ ->
(
match v.var_reg with
| Some 0 -> "", "%eax"
| Some 1 -> "", "%ebx"
| Some 2 -> "", "%ecx"
| Some 3 -> "", "%edx"
| Some 4 -> "", "%eax"
| Some n -> "", "%reg" ^ (string_of_int n)
| None -> "", "%fuck"
)
in
let code_of_instr = function
| Addi(v1, v2, v3) ->
let i1, r1 = code_of_var v1 in
let i2, r2 = code_of_var v2 in
let i3, r3 = code_of_var v3 in
"\taddl\t" ^ r3 ^ ", " ^ r2 ^ "\n" ^
"\tmovl\t" ^ r2 ^ ", " ^ r1 ^ "\n"
| Movi(v1, v2) ->
let i1, r1 = code_of_var v1 in
let i2, r2 = code_of_var v2 in
"\tmovl\t" ^ r2 ^ ", " ^ r1 ^ "\n"
| ExtCall(n, l) ->
(
match n with
| "writeInt" ->
let i1, r1 = code_of_var (List.hd l) in
"\tmov\t" ^ r1 ^ ", 4(%esp)\n" ^ "\tmovl\t$.WI, (%esp)\n" ^ "\tcall\tprintf\n"
| _ -> "\tcall " ^ n ^ "\n"
)
| Nop -> "\tnop\n"
in
ret := !ret ^
".globl " ^ p.proc_name ^ "\n" ^
"\t.type\t" ^ p.proc_name ^ ", @function\n" ^ p.proc_name ^ ":\n" ^
"\tpushl\t%ebp\n" ^ "\tmovl\t%esp, %ebp\n";
ret := !ret ^
"\tsubl\t$24, %esp\n";
ret := !ret ^ List.fold_left (fun s i -> s ^ code_of_instr i) "" p.proc_value.bb_block ^
"\tmov\t$0, %eax\n" ^
"\tleave\n\tret\n"
in
List.iter (fun p -> code_of_proc p) procs; !ret ^ "\t.size\tmain, .-main\n" ^ "\t.section\t.note.GNU-stack,\"\",@progbits\n" ^ "\t.ident\t\"Bifton 0.1.0\"\n"