Working through ‘WACC’ – chapter 4 Logical and relational operators

Because I like the cover here it is again

The big step here is that we add jumps, conditional and unconditional, because && and || can cause us to skip executing some code .

Ignoring Nora is a bad idea

This is where we start generating labels for jumps. The book says generate meaningful label names so that you can understand what’s going on when you see them later. My reaction “aint nobody got time for that”

(I am writing these blogs after I reached chapter 8, so I have some hindsight)

Anyway I just finished retro fitting intelligent names to labels.

More sample TACKY code

To get a feel for what things look like now here is one of the test programs (note how return is the only way that the programs under test can communicate with the test harness).

int main(void) {
    return 0 || 0>1 && (1 / 0);
}

and here is the TACKY (I decided to capitalize this because calling things tacky is not nice) code

Function: main
      JumpIfNotZero Int(0) "_or_true_0"
      Binary GreaterThan Int(0) Int(1) Variable("temp.2")
      JumpIfZero Variable("temp.2") "_and_false_3"
      Binary Divide Int(1) Int(0) Variable("temp.5")
      JumpIfZero Variable("temp.5") "_and_false_3"
      Copy Int(1) Variable("temp.6")
      Jump "_and_end_4"
  Label "_and_false_3"
      Copy Int(0) Variable("temp.6")
  Label "_and_end_4"
      JumpIfNotZero Variable("temp.6") "_or_true_0"
      Copy Int(0) Variable("temp.7")
      Jump "_or_end_1"
  Label "_or_true_0"
      Copy Int(1) Variable("temp.7")
  Label "_or_end_1"
      Return Variable("temp.7")
      Return Int(0)

you will note how very inefficient this is, for example the first line says

JumpIfNotZero Int(0) "_or_true_0"

This is jump never going to be executed, “if 0 is not 0”! I assume we will improve this in part III of the book ‘Optimizations’. That adventure awaits me.

Notice how the TACKY code is self contained, it could be written to a file and processed by a separate program. In later chapters I wondered (and still do) about writing a TACKY interpreter. That would make debugging the front end a lot easier. It would be a fun project.

MASM differences

This is when we need to start worrying about the operand size differences. The setxx instructions (page 83) in gcc speak are easy since the target is always a byte. In MASM speak you have to tell it the size, up till now everything was 4 bytes so it was easy, not so much now. Here is that start of the code generated for the above TACKY

        push rbp
        mov rbp, rsp
        sub rsp, 16
        mov r11d, 0
        cmp r11d, 0
        jne _or_true_0
        mov r11d, 0
        cmp r11d, 1
        mov DWORD PTR[rbp-4], 0
        setg BYTE PTR[rbp-4]
        cmp DWORD PTR[rbp-4], 0
        je _and_false_3

Till now I was blindly emitting DWORD PTR now I have to know the size and emit the correct PTR prefix


When I finish a chapter I keep saying to myself, “now create a Hack CPU backend”. It will be much easier to do it when I am at a primitive stage, like where I am now. But no, I keep saying, “just one more chapter…”

Anyway on to, woohoo, local variables


Comments

Leave a comment