[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64
From: |
Paulo César Pereira de Andrade |
Subject: |
Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64 |
Date: |
Fri, 30 Aug 2019 13:18:53 -0400 |
Hi Paul,
Em qua, 28 de ago de 2019 às 20:41, Paul Cercueil <address@hidden> escreveu:
[...]
> I tried, but I could not succeed to make a test case that shows the
> issue... All I tried have been working just fine.
>
> The actual code that triggers the issue is this one:
> https://gist.github.com/pcercuei/8db789b415f6ced73abb01a6504b64c7
> As it's generated, it's not the easiest to understand, sorry...
>
> The thing to see, is that line 26 I write register 0 (rax), which is
> then untouched until line 58 or 71.
>
> This is what Lightning generates:
> https://gist.github.com/pcercuei/6b4afef692682b139a46449665454681
>
> As you can see, line 30 %rax is written to, and %eax is written back to
> memory on lines 69 or 84.
> But also, line 49 %rax is unconditionally overwritten.
The problem is that after the code does JIT_R0 = JIT_V1 + JIT_V2, that
is %rax = %r13 + %r14 -- lea 0x0(%r13,%r14,1),%rax -- there is a function
call. %rax is not callee save, you need to save it to memory, and restore
once the function returns. The called function is free to change %rax.
this is normal for all JIT_Rx. Only JIT_Vx registers are not modified.
If you are 100% sure the called function does not change JIT_R0, you could
add jit_live(JIT_R0) after the jit_callr(JIT_V0), but that would not work
because it would normally choose %rax as a function pointer (this is a long
TODO to generate %rip displacement calls), or, you could cause it to choose
another register as the function pointer, by creating a jump over the
function call or some other construct, but that also would not work if
calling a varargs function, because the abi requires adding the number of
FPR register/arguments in %rax.
Basically, if there is a function call, jit_jmpi to unknown location (not
to a jit_label_t) or a jit_jmpr, all non callee save registers are
considered dead in the next instruction. It does this also for jit_jmpi
(to unknown location) and jit_jmpr because otherwise the register allocator
would run out of registers, as it cannot follow where the jump will land,
and what will happen there.
The closest/minimal reproducer for the issue does not even need the
qdivr, because once jit_qdivr is called, %rax is already considered dead, is:
"""
.data 32
fmt:
.c "%d\n"
.code
jmpi main
func:
prolog
//reti 2
epilog
main:
prolog
movi %v1 2
movi %v2 3
addr %r0 %v1 %v2
movi %v(3) func
callr %v(3)
//movi %r0 5
//qdivr %v1 %v2 %v2 %v1
prepare
pushargi fmt
ellipsis
pushargr %r0
finishi @printf
ret
epilog
"""
If you uncomment the 'reti 2' it will print 5, otherwise it will print 2.
BTW, I see you found another way to workaround the issues with %rax
described above by manually using callr. So, even if no code touchs %rax,
it will be considered dead in jit_qdivr and it will not save/restore it.
If you uncomment only the qdivr above, %rax will be 1, and if you also
uncomment the 'movi %r0 5' (to simulate quickly a reload from memory)
you will notice that the qdvir will not clobber %rax, because then it
understands it is live.
> Cheers,
> -Paul
Thanks,
Paulo
- [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paul Cercueil, 2019/08/18
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paul Cercueil, 2019/08/21
- Message not available
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paul Cercueil, 2019/08/22
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paulo César Pereira de Andrade, 2019/08/28
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paul Cercueil, 2019/08/28
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paulo César Pereira de Andrade, 2019/08/28
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paul Cercueil, 2019/08/28
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64,
Paulo César Pereira de Andrade <=
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paul Cercueil, 2019/08/30
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paulo César Pereira de Andrade, 2019/08/30
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paul Cercueil, 2019/08/31
- Re: [Lightning] jit_qdivr_u trashes JIT_R0 on x86_64, Paulo César Pereira de Andrade, 2019/08/31