Hello!
I recently started making a JIT compiler for my own language and I have just gotten to the point of conditional statements. My code produces the following IR when putting a return statement inside the conditional block:
define double @fib(double %i) {
entry:
%x = alloca double, align 8
%i1 = alloca double, align 8
store double %i, double* %i1, align 8
store double 0.000000e+00, double* %x, align 8
%0 = load double, double* %i1, align 8
%1 = fcmp ult double %0, 2.000000e+00
%2 = uitofp i1 %1 to double
%3 = fcmp one double %2, 0.000000e+00
br i1 %3, label %then, label %else
then: ; preds = %entry
%4 = load double, double* %i1, align 8
store double %4, double* %x, align 8
%5 = load double, double* %x, align 8 ; These two lines seem
ret double %5** ; to be the problem
br label %continue
else: ; preds = %entry
%6 = load double, double* %i1, align 8
%7 = fsub double %6, 1.000000e+00
%8 = call double @fib(double %7)
%9 = load double, double* %i1, align 8
%10 = fsub double %9, 2.000000e+00
%11 = call double @fib(double %10)
%12 = fadd double %8, %11
ret double %12
br label %continue
continue: ; preds = %else, %then
%13 = load double, double* %x, align 8
ret double %13
}
define double @entry() {
entry:
%0 = call double @fib(double 1.700000e+01)
ret double %0
}
These two lines in the then BasicBlock seem to be the problem:
%5 = load double, double* %x, align 8
ret double %5**
If I just set the value of %x
and return it afterwards the code runs as expected.
When calling the lookup of the “entry” on the LLJIT I get an error like this:
EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
The debugger tracks this down to some machine code, that from what I can see is my compiled program:
vmovsd %xmm0, (%rsp)
movq $0x0, 0x8(%rsp)
vmovsd 0xfe6(%rip), %xmm1 ; xmm1 = mem[0],zero
vcmpnlesd %xmm0, %xmm1, %xmm0
vmovsd 0xfe1(%rip), %xmm1 ; xmm1 = mem[0],zero
vandpd %xmm1, %xmm0, %xmm0
vxorpd %xmm1, %xmm1, %xmm1
vucomisd %xmm1, %xmm0
je 0x103f35043
vmovsd (%rsp), %xmm0 ; xmm0 = mem[0],zero
vmovsd %xmm0, 0x8(%rsp)
retq ; The error occurs here
jmp 0x103f35078
vmovsd (%rsp), %xmm0 ; xmm0 = mem[0],zero
vaddsd 0xfc0(%rip), %xmm0, %xmm0
callq 0x103f35000
vmovsd %xmm0, 0x10(%rsp)
vmovsd (%rsp), %xmm0 ; xmm0 = mem[0],zero
vaddsd 0xfb0(%rip), %xmm0, %xmm0
callq 0x103f35000
vaddsd 0x10(%rsp), %xmm0, %xmm0
addq $0x18, %rsp
retq
vmovsd 0x8(%rsp), %xmm0 ; xmm0 = mem[0],zero
addq $0x18, %rsp
retq
nopw %cs:(%rax,%rax)
pushq %rax
vmovsd 0xf87(%rip), %xmm0 ; xmm0 = mem[0],zero
callq 0x103f35000
popq %rax
retq
Specifically to the first retq
instruction.
When setting a variable and returning it after the block the problem doesn’t seem to happen.
Can someone explain why the above IR is incorrect and how I can fix the problem?
Any help is enormously appreciated!
Tom