Next: TC-7 Given Code, Previous: TC-7 Goals, Up: TC-7 [Contents][Index]
The goal of TC-7 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, TC-9.
let var answer := 42 in answer := 51 end
$ tc --inst-display the-answer.tig # == Final assembler ouput. == # # Routine: _main tc_main: # Allocate frame move $x11, $ra move $x3, $s0 move $x4, $s1 move $x5, $s2 move $x6, $s3 move $x7, $s4 move $x8, $s5 move $x9, $s6 move $x10, $s7 l0: li $x1, 42 sw $x1, ($fp) li $x2, 51 sw $x2, ($fp) l1: move $s0, $x3 move $s1, $x4 move $s2, $x5 move $s3, $x6 move $s4, $x7 move $s5, $x8 move $s6, $x9 move $s7, $x10 move $ra, $x11 # Deallocate frame jr $ra
At this stage the compiler cannot know what registers are used; that’s
why in the previous output it saves "uselessly" all the callee-save
registers on main
entry. For the same reason, the frame is not
allocated.
While Nolimips accepts the lack of register allocation, it does require the frame to be allocated. That is the purpose of --nolimips-display:
$ tc --nolimips-display the-answer.tig # == Final assembler ouput. == # # Routine: _main tc_main: sw $fp, -4 ($sp) move $fp, $sp sub $sp, $sp, 8 move $x11, $ra move $x3, $s0 move $x4, $s1 move $x5, $s2 move $x6, $s3 move $x7, $s4 move $x8, $s5 move $x9, $s6 move $x10, $s7 l0: li $x1, 42 sw $x1, ($fp) li $x2, 51 sw $x2, ($fp) l1: move $s0, $x3 move $s1, $x4 move $s2, $x5 move $s3, $x6 move $s4, $x7 move $s5, $x8 move $s6, $x9 move $s7, $x10 move $ra, $x11 move $sp, $fp lw $fp, -4 ($fp) jr $ra
The final stage, register allocation, addresses both issues. For your information, it results in:
$ tc -sI the-answer.tig # == Final assembler ouput. == # # Routine: _main tc_main: sw $fp, -4 ($sp) move $fp, $sp sub $sp, $sp, 8 l0: li $t0, 42 sw $t0, ($fp) li $t0, 51 sw $t0, ($fp) l1: move $sp, $fp lw $fp, -4 ($fp) jr $ra
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
$ tc -e --inst-display add.tig # == Final assembler ouput. == # # Routine: add tc_l0: # Allocate frame move $x15, $ra sw $a0, ($fp) move $x0, $a1 move $x1, $a2 move $x7, $s0 move $x8, $s1 move $x9, $s2 move $x10, $s3 move $x11, $s4 move $x12, $s5 move $x13, $s6 move $x14, $s7 l2: add $x6, $x0, $x1 move $v0, $x6 l3: move $s0, $x7 move $s1, $x8 move $s2, $x9 move $s3, $x10 move $s4, $x11 move $s5, $x12 move $s6, $x13 move $s7, $x14 move $ra, $x15 # Deallocate frame jr $ra .data l1: .word 1 .asciiz "\n" .text # Routine: _main tc_main: # Allocate frame move $x28, $ra move $x20, $s0 move $x21, $s1 move $x22, $s2 move $x23, $s3 move $x24, $s4 move $x25, $s5 move $x26, $s6 move $x27, $s7 l4: move $a0, $fp li $x16, 2 move $a1, $x16 li $x17, 3 move $a2, $x17 jal tc_l0 move $x4, $v0 move $a0, $fp li $x18, 1 move $a1, $x18 move $a2, $x4 jal tc_l0 move $x5, $v0 move $a0, $x5 jal tc_print_int la $x19, l1 move $a0, $x19 jal tc_print l5: move $s0, $x20 move $s1, $x21 move $s2, $x22 move $s3, $x23 move $s4, $x24 move $s5, $x25 move $s6, $x26 move $s7, $x27 move $ra, $x28 # Deallocate frame jr $ra
Once your function calls work properly, you can start using Nolimips (using options --nop-after-branch --unlimited-registers --execute) to check the behavior of your compiler.
$ tc -eR --nolimips-display add.tig >add.nolimips
$ nolimips -l nolimips -Nue add.nolimips 6
You must also complete the runtime. No difference must be observable between a run with HAVM and another with Nolimips:
substring("", 1, 1)
$ tc -e --nolimips-display substring-0-1-1.tig # == Final assembler ouput. == # .data l0: .word 0 .asciiz "" .text # Routine: _main tc_main: # Allocate frame move $x12, $ra move $x4, $s0 move $x5, $s1 move $x6, $s2 move $x7, $s3 move $x8, $s4 move $x9, $s5 move $x10, $s6 move $x11, $s7 l1: la $x1, l0 move $a0, $x1 li $x2, 1 move $a1, $x2 li $x3, 1 move $a2, $x3 jal tc_substring l2: move $s0, $x4 move $s1, $x5 move $s2, $x6 move $s3, $x7 move $s4, $x8 move $s5, $x9 move $s6, $x10 move $s7, $x11 move $ra, $x12 # Deallocate frame jr $ra
$ tc -eR --nolimips-display substring-0-1-1.tig >substring-0-1-1.nolimips
$ nolimips -l nolimips -Nue substring-0-1-1.nolimips error→substring: arguments out of bounds ⇒120
Next: TC-7 Given Code, Previous: TC-7 Goals, Up: TC-7 [Contents][Index]