jak-project/doc/emitter.md
2020-08-30 20:39:39 -04:00

24 lines
2.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Emitter
x86-64 has a lot of instructions. They are described in Volume 2 of the 5 Volume "Intel® 64 and IA-32 Architectures Software Developers Manual". Just this volume alone is over 2000 pages, which would take forever to fully implement. As a result, we will use only a subset of these instructions. This the rough plan:
- Most instructions like `add` will only be implemented with `r64 r64` versions.
- To accomplish something like `add rax, 1`, we will use a temporary register `X`
- `mov X, 1`
- `add rax, X`
- The constant propagation system will be able to provide enough information that we could eventually use `add r64 immX` and similar if needed.
- Register allocation should handle the case `(set! x (+ 3 y))` as:
- `mov x, 3`
- `add x, y`
- but `(set! x (+ y 3))`, in cases where `y` is needed after and `x` can't take its place, will become the inefficient
- `mov x, y`
- `mov rtemp, 3`
- `add x, rtemp`
- Loading constants into registers will be done efficiently, using the same strategy used by modern versions of `gcc` and `clang`.
- Memory access will be done in the form `mov rdest, [roff + raddr]` where `roff` is the offset register. Doing memory access in this form was found to be much faster in simple benchmark test.
- Memory access to the stack will have an extra `sub` and more complicated dereference. GOAL code seems to avoid using the stack in most places, and I suspect the programmers attempted to avoid stack spills.
- `mov rdest, rsp` : coloring move for upcoming subtract
- `sub rdest, roff` : convert real pointer to GOAL pointer
- `mov rdest, [rdest + roff + variable_offset]` : access memory through normal GOAL deref.
- Note - we should check that the register allocator gets this right always, and eliminates moves and avoid using a temporary register.
- Again, the constant propagation should give use enough information, if we ever want/need to implement a more efficient `mov rdest, [rsp + varaible_offset]` type instructions.
- Memory access to static data should use `rip` addressing, like `mov rdest, [rip + offset]`. And creating pointers to static data could be `lea rdest, [rip - roff + offset]`