x86-64 Backend
This section documents the different constraints, assumptions and limitations of the current x86-64 backend. It also documents the specific implementation quirks of the backend.
φ Elimination
φ elimination (also known as SSA destruction) is performed in the naive "translate into copies" method, but this has
known limitations (see lost copy problem). It is assumed that the split-crit-edges
pass has been run over the SIR module before codegen begins, if this is not done
incorrect code can be emitted.
Type Representation
bool
bool
is represented the same way as an i8
(i.e. in byte
-sized partial registers), with false
being zero
and true
being 1
.
condbr
and icmp
/fcmp
Interactions
Currently, the backend has two states for implementing condbr
:
- The comparison is the instruction directly before the
condbr
- The comparison is not directly before the
condbr
This is a bit of a hack, but it's to ensure that CPU flags are maintained correctly. The two states are implemented like so:
Directly Before
This is how you'd want it to be emitted, a cmp
-like instruction followed by
a jump that models the condition in the comparison. You get code like this emitted:
cmp rax, rdx
jl .TRUE
jmp .FALSE
In this case, the icmp
/fcmp
does not have a constrained register, and is
only emitted to manipulate CPU flags.
Not Directly Before
This is the case that needs to be optimized better, but for now this is what it does. The condbr
places a register constraint on the comparison instruction, and it emits instructions to jump to the
true branch if that register is 1, and jump to the false branch otherwise. It effectively
generates this code:
test R, R
jnz .TRUE
jmp .FALSE
When the comparison is emitted, it is expected to also emit a set*
instruction to copy the condition
to a register, so that the test
previously emitted will work. The end result should look like this:
cmp rax, rdx
xor R, R
setle R
...
test R, R
jnz .TRUE
jmp .FALSE