IUCompilerCourse / public-student-support-code

Public helper code for p423/p523 students (Racket)
MIT License
155 stars 74 forks source link

Chapter 7 and TailJmp replacement #16

Open funnydog opened 2 years ago

funnydog commented 2 years ago

Hi,

I'm at the end of Chapter 7 and I implemented the last pass, prelude-and-conclusion.

Unfortunately when I try to run the tests I get the following error:

lookup: didn't find rbp in (rax rdi r9 r15)

By looking at the debug output I was able to track down the problem with the way the interpreter applies the functions, in the call-function public method:

         ;; interpret the body of the function in the new-env
         (define result-env
           (parameterize ([get-basic-blocks blocks])
             ((interp-x86-block new-env)
              (dict-ref blocks (symbol-append f 'start)))))

Instead of calling the function, the evaluation begins at the start basic block, skipping the prelude.

While I understand that the reason it was done this way was to bypass the need of the function's entry/exit points while implementing the previous passes, unfortunately when the interpreter skips the prelude and the conclusion it misses a bunch of instructions like pushes (and pops).

When the TailJmp fake instruction is replaced with real instructions meant to pop the current frame (in the last pass), the interpreter doesn't know that %rbp (and possiby other registers) were pushed on the stack.

As a hack I changed the interpreter to add to the env the %rbp register but of course then it halts on unmatched popq.

I also tried unsuccessfully to fake the push and the pops, but then realized that what I really needed was the interpreter to execute the code in the prelude: it's there for a reason and faking its behavior wasn't going to cut it.

Is there a way to have the interpreter call the actual preludes and conclusions?

The produced code works correctly when compiled, and here I found another issue: the (compiler-tests) function matches only X86Program and not ProgramDefs, while interp-x86-4 doesn't like the X86Program AST node.

For now I'm only testing the last pass with the compilation step and comment out the pass when I need the interpreter. Is this the way it was supposed to work from the start?

I'd like to close this lengthy post by thanking you for the great source of knowledge this book / course is, I think I'm not only going to code my first compiler but also know every detail about it. It's mind opening and I'm really enjoying the journey with every incremental improvement.

Thank you,

funnydog