I have a situation where global ctors in LLVM IR being sent to ORC JIT for compilation can’t be found by the JIT (on a lookup
). The specific use case I have here is to save the object to a file (to be linked and executed later). Output with some debug info as well is below:
Looking up { (__mlir_load_ctor_1_kernel, RequiredSymbol) } in [ ("main", MatchAllSymbols) ] (required state: Ready)
Could not compile __mlir_load_ctor_1_kernel:
Symbols not found: [ __mlir_load_ctor_1_kernel ]
Program aborted due to an unhandled Error:
Symbols not found: [ __mlir_load_ctor_1_kernel ]
This is what the LLVM IR looks like:
@llvm.global_ctors = appending global [3 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 0, void ()* @__mlir_load_ctor_1_kernel, i8* null }, ...]
define internal void @__mlir_load_ctor_1_kernel() !dbg !3 {
%1 = call i8* ...
...
ret void
}
...
I have no symbol lookup issues without the use of global ctors. Is it possible that the global ctor was somehow optimized away? I couldn’t immediately find a way to dump the IR right before the final code generation to confirm this, but any pointers to verify that or to ensure that the compilation succeeds will be appreciated. Note that I’m not trying to execute the IR yet and, thus, not expecting the initializers to be called on an invocation. I’m just looking up the list of functions in the module to dump the object for offline linking and execution. The same IR compiles, links, and executes fine if I use this route.
opt -O3 | llc -O3 --relocation-model=pic | as - -o aot.o
# Link aot.o and it succeeds; execute and the global ctor is correctly called.
...
UPDATE: After I had typed out the message above, I realized ORC JIT handles/replaces LLVM global ctors/dtors to generate a single “init” function: llvm-project/LLJIT.cpp at e4dd1d033063c8a669c7e77d9d7f88c1d3058e88 · llvm/llvm-project · GitHub
Not looking those up and dumping the compiled object:
$ nm orc.o | grep orc
00000000000009a0 T __orc_init_func.LLVMDialectModule
However, when I try to link and use the above object, I don’t see the initializer executing. Reading this elf, I find no init/ctors section:
$ readelf -SW orc.o | grep init
However, the one generated via AOT:
$ readelf -SW aot.o | grep init
[ 6] .init_array.0 INIT_ARRAY 0000000000000000 004050 000018 08 WA 0 0 8
[ 7] .rela.init_array.0 RELA 0000000000000000 004de0 000048 18 I 20 6 8
Is there a way one can get the ORC compiled object correctly have the static initializer?
Other relevant code:
CC: @lhames