I'm looking for information on how programs that span multiple LLVM
modules work at runtime, especially wrt. symbol handling when running
in a JIT setting. To give some background, I'm developing a language
that targets LLVM as a backend, and I'd like my translation units to
map to LLVM modules as closely as possible.
What I'm looking for here is something similar to how Java or Python
handles intra-module depencies at runtime, where they load modules (or
classes, in the Java case) as necessary, and where different modules
can cooperate during different runs of the same program depending on
the code path that is taken.
Is it possibly to get a hook call when a JITed module encounters a
symbol reference it can't resolve locally? My current solution is
based upon pessimizations that force the loading of all dependent
modules, but that's wasteful in many cases when only some of those
dependencies are actually required for execution.
That said, I would also like to examine the possibility to recompile
modules in the running system on the fly from source, so that it is
possible to update modules as longs as their interfaces stay
compatible. Can LLVM freeze the JIT in a safe place and unload
I'm also curious to find out how the external symbols referenced from
the C frontend are resolved (such as printf or other functions in
libc). I assume there is a dlsym() call somewhere depending on the
libs listed in the module, is this correct? Does this happen at module
load time or at some later point while executing?
Finally, is the LLVM linked really required for a system like this? I
know the JIT is happy executing my bytecode modules as long as they
are self-contained, but on-demand loading is a requirement for this
(test) project. Currently all I'm getting is a hard error from the
runtime complaining that a referenced symbol is undefined.
Any information (or pointers to information) on the above would be
very helpful to me.