JIT interaction with linkonce_odr global variables


I recently hit an issue when JIT’ing my generated IR using llvm::orc::LLJIT. My IR contains the following definition of a global variable:

$_ZZ23TestStaticVarInFunctionbE1x = comdat any
@_ZZ23TestStaticVarInFunctionbE1x = linkonce_odr dso_local global i32 123, comdat, align 4

And in my host process, there exists the same symbol. I would expect LLJIT to resolve the global variable above to the address inside the host process, since it has linkage ‘linkonce_odr’. However, it turns out that LLJIT resolved it as if it were a conventional global variable definition and gave it its own address (I have added ‘GetForCurrentProcess’ generator for symbol resolution of course).

I can workaround this issue by making the symbol a declaration (drop the initializer, comdat and make the linkage external), but I’m wondering if it is expected behavior that LLJIT does not respect linkonce_odr specifier, since the documentation says LLJIT’s symbol resolution should work as if I were running a normal linker.


Hi Haoran

Hi Haoran, Stefan,

This case is poorly supported at the moment. I think your workaround (changing it to a decl) is good for now. You could also use a JITLink plugin to replace the duplicate definition with an absolute symbol at link time, but it’s probably better to drop the definition before adding and save yourself some compile time.

Eventually I would like to improve weak symbol handling by adding a new WeakSymbolManager abstraction. This would be attached to the ExecutionSession and would be called for each MaterializationUnit before it is added. It would enable proper resolution of weak symbols across JITDylib boundaries (also currently unsupported) and could scan the process symbols first. It’s on my todo list, but I have to get some JITLink work and the removable dylibs feature done first. If anyone wants to tackle this as a project I’d be happy to help with pointers. :slight_smile: