The goal of T7 is straightforward: starting from LIR, generate the
MIPS instructions, except that you don't have actual registers: we
still heavily use Temp
s. Register allocation will be done in a
later stage, T9.
1 + 2 * 3
File 118: seven.tig
$ tc --inst-display seven.tig # == Final assembler ouput. == # # Routine: Main t_main: move t5, $s0 move t6, $s1 move t7, $s2 move t8, $s3 move t9, $s4 move t10, $s5 move t11, $s6 move t12, $s7 l0: li t3, 2 mul t2, t3, 3 li t4, 1 add t1, t4, t2 l1: move $s0, t5 move $s1, t6 move $s2, t7 move $s3, t8 move $s4, t9 move $s5, t10 move $s6, t11 move $s7, t12 Example 119: tc --inst-display seven.tig
Please, note that at this stage, the control flow analysis and the
liveness analysis are not performed yet, therefore the compiler cannot
know what registers are really to be saved. That's why in the previous
output it saves "uselessly" all the callee-save registers on main
entry. The next stage, which combines control flow analysis, liveness
analysis, and register allocation, will make it useless. For your
information, it results in:
$ tc -sI seven.tig # == Final assembler ouput. == # # Routine: Main t_main: sw $fp, ($sp) move $fp, $sp sub $sp, $sp, 8 sw $ra, -4 ($fp) l0: li $t0, 2 mul $t1, $t0, 3 li $t0, 1 add $t0, $t0, $t1 l1: lw $ra, -4 ($fp) move $sp, $fp lw $fp, ($fp) jr $ra Example 120: tc -sI seven.tig
A delicate part of this exercise is handling the function calls:
let function add (x: int, y: int) : int = x + y
in
print_int (add (1, (add (2, 3)))); print ("\n")
end
File 121: add.tig
$ tc -e --mipsy-display add.tig # == Final assembler ouput. == # # Routine: add l0: sw $fp, -4 ($sp) move $fp, $sp sub $sp, $sp, 12 sw $ra, -8 ($fp) sw $a0, ($fp) move t0, $a1 move t1, $a2 move t7, $s0 move t8, $s1 move t9, $s2 move t10, $s3 move t11, $s4 move t12, $s5 move t13, $s6 move t14, $s7 l2: add t6, t0, t1 move $v0, t6 l3: move $s0, t7 move $s1, t8 move $s2, t9 move $s3, t10 move $s4, t11 move $s5, t12 move $s6, t13 move $s7, t14 lw $ra, -8 ($fp) move $sp, $fp lw $fp, -4 ($fp) jr $ra .data l1: .word 1 .asciiz "\n" .text # Routine: Main t_main: sw $fp, ($sp) move $fp, $sp sub $sp, $sp, 8 sw $ra, -4 ($fp) move t19, $s0 move t20, $s1 move t21, $s2 move t22, $s3 move t23, $s4 move t24, $s5 move t25, $s6 move t26, $s7 l4: move $a0, $fp li t15, 2 move $a1, t15 li t16, 3 move $a2, t16 jal l0 move t4, $v0 move $a0, $fp li t17, 1 move $a1, t17 move $a2, t4 jal l0 move t5, $v0 move $a0, t5 jal print_int la t18, l1 move $a0, t18 jal print l5: move $s0, t19 move $s1, t20 move $s2, t21 move $s3, t22 move $s4, t23 move $s5, t24 move $s6, t25 move $s7, t26 lw $ra, -4 ($fp) move $sp, $fp lw $fp, ($fp) jr $ra Example 122: tc -e --mipsy-display add.tig
Once your function calls work properly, you can start using mipsy to check the behavior of your compiler.
$ tc -eH add.tig >add.hir Example 123: tc -eH add.tig >add.hir
$ havm add.hir 6 Example 124: havm add.hir
Unfortunately, you need to adjust the output of tc, using
t123
, to mipsy conventions: $x123.
$ tc -eR --mipsy-display add.tig >add.instr Example 125: tc -eR --mipsy-display add.tig >add.instr
$ sed -e's/\([^$a-z]\)t\([0-9][0-9]*\)/\1$x\2/g' add.instr >add.mipsy Example 126: sed -e's/\([^$a-z]\)t\([0-9][0-9]*\)/\1$x\2/g' add.instr >add.mipsy
$ mipsy --unlimited-regs --execute add.mipsy 6 Example 127: mipsy --unlimited-regs --execute add.mipsy
You must also complete the runtime. No difference must be observable between a run with havm and another with mipsy:
substring ("", 1, 1)
File 128: substring-0-1-1.tig
$ tc -eH substring-0-1-1.tig >substring-0-1-1.hir Example 129: tc -eH substring-0-1-1.tig >substring-0-1-1.hir
$ havm substring-0-1-1.hir substring: arguments out of bounds =>120 Example 130: havm substring-0-1-1.hir
$ tc -e --mipsy-display substring-0-1-1.tig # == Final assembler ouput. == # .data l0: .word 0 .asciiz "" .text # Routine: Main t_main: sw $fp, ($sp) move $fp, $sp sub $sp, $sp, 8 sw $ra, -4 ($fp) move t4, $s0 move t5, $s1 move t6, $s2 move t7, $s3 move t8, $s4 move t9, $s5 move t10, $s6 move t11, $s7 l1: la t1, l0 move $a0, t1 li t2, 1 move $a1, t2 li t3, 1 move $a2, t3 jal substring l2: move $s0, t4 move $s1, t5 move $s2, t6 move $s3, t7 move $s4, t8 move $s5, t9 move $s6, t10 move $s7, t11 lw $ra, -4 ($fp) move $sp, $fp lw $fp, ($fp) jr $ra Example 131: tc -e --mipsy-display substring-0-1-1.tig
$ tc -eR --mipsy-display substring-0-1-1.tig >substring-0-1-1.instr Example 132: tc -eR --mipsy-display substring-0-1-1.tig >substring-0-1-1.instr
$ sed -e's/\([^$a-z]\)t\([0-9][0-9]*\)/\1$x\2/g' substring-0-1-1.instr >substring-0-1-1.mipsy Example 133: sed -e's/\([^$a-z]\)t\([0-9][0-9]*\)/\1$x\2/g' substring-0-1-1.instr >substring-0-1-1.mipsy
$ mipsy --unlimited-regs --execute substring-0-1-1.mipsy substring: arguments out of bounds =>120 Example 134: mipsy --unlimited-regs --execute substring-0-1-1.mipsy