open Printf
open Print
open ASM
let reg () r =
sprintf "$%s" (MIPS.print r)
let lab () l =
l
let print_instruction () = function
| IComment (break, c) ->
sprintf "%s# %s" (if break then "\n" else "") c
| INop ->
sprintf "nop"
| IConst (r, i) ->
sprintf "li %a, %ld" reg r i
| IUnOp (op, r1, r2) ->
PrintOps.unop reg () (op, r1, r2)
| IBinOp (op, r, r1, r2) ->
sprintf "%s %a, %a, %a" (PrintOps.binop op) reg r reg r1 reg r2
| ICall l ->
sprintf "jal %s" l
| ILoad (r1, r2, o) ->
sprintf "lw %a, %ld(%a)" reg r1 o reg r2
| IStore (r1, o, r2) ->
sprintf "sw %a, %ld(%a)" reg r2 o reg r1
| IGoto l ->
sprintf "j %s" l
| IUnBranch (cond, r, l) ->
sprintf "%a, %a" (PrintOps.uncon reg) (cond, r) lab l
| IBinBranch (cond, r1, r2, l) ->
sprintf "%s %a, %a, %s" (PrintOps.bincon cond) reg r1 reg r2 l
| IReturn ->
sprintf "jr $ra"
| ILabel l ->
sprintf "%s:" l
let print_program () p =
let globals =
sprintf "\
.data \n\
globals: \n\
.space %ld \n\
" p.globals
in
let start =
sprintf "\
.text \n\
main: \n\
la $gp, globals \n\
j %s \n\
" p.entry
in
let support =
"\
write: \n\
li $v0, 1 \n\
syscall \n\
j $ra \n\
.data \n\
nl: \n\
.asciiz \"\\n\" \n\
.align 2 \n\
.text \n\
writeln: \n\
li $v0, 1 \n\
syscall \n\
la $a0, nl \n\
li $v0, 4 \n\
syscall \n\
j $ra \n\
readln: \n\
li $v0, 5 \n\
syscall \n\
j $ra \n\
alloc: \n\
li $v0, 9 \n\
syscall \n\
j $ra \n\
"
in
let bulk =
sprintf "%a" (termlist nl print_instruction) p.code
in
globals ^ start ^ support ^ bulk