Problem with x86_64 JIT from a .so on Linux (LLVM 2.4)

Hi again,

From a .so, I'm doing the following:

* I create an empty Module, declare some functions (from the main
executable) and add a global mapping for them.
* Then I create a jitted function that calls those global functions
* and I call it.

The JITted function segfaults because x86_64 JIT creates a call with
32bit relative address to rip, while the called function is outside
reach.
See the backtrace:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 47056050356368 (LWP 22307)]
0x00002acc00464d10 in ?? ()
(gdb) bt
#0 0x00002acc00464d10 in ?? ()
#1 0x00002acc1869f026 in ?? ()
#2 0x000000000074eb10 in ?? ()
#3 0x000000000074eb10 in ?? ()
#4 0x0000000000000000 in ?? ()

This is the jitted function: the last call refers 0x2acc00464d10,
while the correct address is 0x464d10
(gdb) disass 0x00002acc1869f010 0x00002acc1869f026
Dump of assembler code from 0x2acc1869f010 to 0x2acc1869f026:
0x00002acc1869f010: push %r14
0x00002acc1869f012: push %rbx
0x00002acc1869f013: sub $0x8,%rsp
0x00002acc1869f017: mov $0x7f0ed0,%edi
0x00002acc1869f01c: callq 0x2acc173ecca0 <perl_trace>
0x00002acc1869f021: callq 0x2acc00464d10
End of assembler dump.
(gdb) disass 0x464d10
Dump of assembler code for function Perl_pp_gvsv:
0x0000000000464d10 <Perl_pp_gvsv+0>: push %rbp

We have two problems here.
Code generation pass should select a different opcode to do the 64bit
absolute call when 32 bits of displacement are not enough.
Even if the correct opcode was generated, it will be suboptimal (the
correct sequence requires loading the address into a register and then
performing the call; the optimal would be to allocate the function at
a lower address, and use the 32 bit call).
Any plan to provide a way to choose where to allocate the jitted
functions when in 64 bit address space?

Corrado

Hi again,

From a .so, I'm doing the following:

* I create an empty Module, declare some functions (from the main
executable) and add a global mapping for them.
* Then I create a jitted function that calls those global functions
* and I call it.

The JITted function segfaults because x86_64 JIT creates a call with
32bit relative address to rip, while the called function is outside
reach.
See the backtrace:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 47056050356368 (LWP 22307)]
0x00002acc00464d10 in ?? ()
(gdb) bt
#0 0x00002acc00464d10 in ?? ()
#1 0x00002acc1869f026 in ?? ()
#2 0x000000000074eb10 in ?? ()
#3 0x000000000074eb10 in ?? ()
#4 0x0000000000000000 in ?? ()

This is the jitted function: the last call refers 0x2acc00464d10,
while the correct address is 0x464d10
(gdb) disass 0x00002acc1869f010 0x00002acc1869f026
Dump of assembler code from 0x2acc1869f010 to 0x2acc1869f026:
0x00002acc1869f010: push %r14
0x00002acc1869f012: push %rbx
0x00002acc1869f013: sub $0x8,%rsp
0x00002acc1869f017: mov $0x7f0ed0,%edi
0x00002acc1869f01c: callq 0x2acc173ecca0 <perl_trace>
0x00002acc1869f021: callq 0x2acc00464d10
End of assembler dump.
(gdb) disass 0x464d10
Dump of assembler code for function Perl_pp_gvsv:
0x0000000000464d10 <Perl_pp_gvsv+0>: push %rbp

We have two problems here.
Code generation pass should select a different opcode to do the 64bit
absolute call when 32 bits of displacement are not enough.
Even if the correct opcode was generated, it will be suboptimal (the
correct sequence requires loading the address into a register and then
performing the call; the optimal would be to allocate the function at
a lower address, and use the 32 bit call).
Any plan to provide a way to choose where to allocate the jitted
functions when in 64 bit address space?

See comments in X86TargetMachine::addCodeEmitter.

X86 backend is defaulting to large code model for non-Darwin x86-64 targets. This *should* work, but there might be bugs. You should be able to look at the code generated with llc -relocation-model=pic -code-model=large.

Evan