Next: , Previous: , Up: TC-7   [Contents][Index]


4.16.2 TC-7 Samples

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 Temps. Register allocation will be done in a later stage, TC-9.

let
  var answer := 42
in
  answer := 51
end

File 4.69: the-answer.tig

$ 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

Example 4.110: tc --inst-display the-answer.tig

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

Example 4.111: tc --nolimips-display the-answer.tig

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

Example 4.112: tc -sI the-answer.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 4.70: add.tig

$ 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

Example 4.113: tc -e --inst-display add.tig


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

Example 4.114: tc -eR --nolimips-display add.tig >add.nolimips

$ nolimips -l nolimips -Nue add.nolimips
6

Example 4.115: nolimips -l nolimips -Nue add.nolimips


You must also complete the runtime. No difference must be observable between a run with HAVM and another with Nolimips:

substring("", 1, 1)

File 4.71: substring-0-1-1.tig

$ 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

Example 4.116: tc -e --nolimips-display substring-0-1-1.tig

$ tc -eR --nolimips-display substring-0-1-1.tig >substring-0-1-1.nolimips

Example 4.117: 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

Example 4.118: nolimips -l nolimips -Nue substring-0-1-1.nolimips


Next: , Previous: , Up: TC-7   [Contents][Index]