When using LLVM 8, I could add the following module to JIT:
define i64 @f1()
ret i64 4
and after that the following module:
define i64 @f1()
ret i64 5
And the new function
f1 would effectively shadow the old function, so calling
f1 would return 5 now.
When I upgraded the JIT to LLVM 9/10, I now get an error when adding the second module: “Duplicate definition of symbol ‘f1’”.
Question: Going forward, is that the new design of LLVM, that functions have to have unique names in JIT across all LLVM modules that ever get added to it?
This means I have to update my compiler/interpreter (that allows shadowing) to ensure the symbols that get passed to LLVM are always unique, even if the first and second
f1 function are defined later in the interactive prompt (and thus end up in separate LLVM modules).
Going forward, is that the new design of LLVM, that functions have to have unique names in JIT across all LLVM modules that ever get added to it?
Yes. The newer OrcV2 JIT APIs are trying to stay very close to the static and dynamic linker rules, including rejecting duplicate symbols. Requiring symbol names to be unique allows us to support concurrent compilation for symbols using the (unique) symbol names as keys for tracking.
If you want to leave both definitions of f1 in the JIT’d process then the standard solution would be to number them: f1.1, f1.2, …, f1.N, and always use the most recent f1.N when f1 is referenced.
If you want to replace definitions (e.g. because f1 will be an anonymous REPL expression) then LLVM 12 should allow you to remove the old definition, then add a new definition with the same name. Two caveats to this: (1) The code removal feature is currently under development*. It’s looking good, but I can’t be 100% certain yet that it will land in LLVM 12. (2) Code removal only takes care of freeing resources – You will be responsible for ensuring that you either remove or rebind any users of the old definition (e.g. by updating stub pointers).
Thanks a lot for the answer @lhames. Everything is clear now.
I think the best solution for us is to rework our compiler to always emit unique symbols to LLVM (for example using the
f1.2, … scheme that you suggested), and then everything will work. There are other things that broke in the update, so I will first make the change with the old JIT, ensure things work, and then upgrade JIT to the newer one.
The feature to remove old functions that you work on is interesting. Although once the compiler emits unique names, I think there is no harm in keeping the old function around.
Thanks again for clarifying this, it is now clear what we need to do.