Proper way to use "host application" function from JIT code

Hi,
I found myself doing very similar things to what’s discussed in http://lists.cs.uiuc.edu/pipermail/cfe-dev/2010-July/009836.html.

More precisely, I’ve modified the clang-interpreter example so that I can specify a .cpp source file at runtime which is JIT-compiled and some functions inside it get called by the interpreter executable itself.
In this context, “host-application” is actually the clang-interpreter executable, while the external .cpp file is what I refer to as the “plugin.cpp”.

Proceeding with my experiments, I wanted to try to “export” a function from the “host-application” to be called by the “plugin” and following the discussion at the above linked address, it seems like I should have to go through the

llvm::Function *KnownFunction = cast<llvm::Function>(Mod->getOrInsertFunction(...)

route, but it turns out I was able to simply define a function in the host-application, and then extern declare it in my plugin.cpp and then be able to call it from one of the functions inside the plugin itself.

In other words, I didn’t have to do any “manual” function instantiation in the jitted code.
Has something changed (that wasn’t possible at the time of the referenced discussion), or am I doing something that’s working by chance but conceptually wrong?

On a side note, I found out that in this case of a host-application exported function I don’t even have to declare it as extern “C”, as the reference in the plugin is correctly mangled, although the host-application is compiled with gcc and so I think this works almost by chance.

On the other side, all functions defined in the plugin that I’m calling from the host-application seem to have to be declared extern “C”, otherwise all calls to llvm::Module::getFunction fail.
Is this the only way to do that or is there some supported way to find mangled function names in the plugin, other than dumping its contents and discovering what’s the real name in the IR?

Thanks,
Andrea.

Hi Andrea,

As I understand it, when the JIT emitter encounters a function call, it attempts to get a pointer to the function from the JIT engine by calling the JIT::getPointerToFunction() method. If the JIT engine isn’t able to associate the function with an existing known function and can’t JIT it, it will attempt to lookup the function by name. One of the ways it attempts to do so is by calling sys::DynamicLibrary::SearchForAddressOfSymbol() which will return the address of the function in the current process if such an address is available.

I believe that this basic functionality has be in place for quite some time. It has, however, been changed recently so that the implementation of this external symbol resolution is now handled in the JITMemoryManager, rather than in the JIT engine itself. The practical implication of this is that you can provide your own implementation of the JIT memory manager to extend external symbol resolution if you like. In any event, calling functions in the current process should work just as you’ve seen it.

-Andy

Thanks Andrew,
that makes sense actually.

Just one thing, about the last point in my original email: all functions defined in the plugin will instead have to be explicitly declared extern "C" or I have to, somehow, obtain the mangled name (and what's the best/safest way to do that) if I want llvm::Module::getFunction to succeed?

Andrea.

I’m not particularly familiar with how the module value lookup works. Maybe someone else can comment?

-Andy