[LLVMdev] Module management questions

Larry Gritz lg at larrygritz.com
Tue Aug 17 17:04:47 PDT 2010

On Aug 17, 2010, at 10:11 AM, Owen Anderson wrote:

> In principle this ought to work, if you're careful.  Are you sure you're not generating code that calls into functions that got totally inlined away?

How would I know?

>  Are you running the Verifier pass at regular intervals?

Yes, both before and after the set of optimization passes.

So let me clarify what I'm doing:  I have a whole bunch of C++ functions (including some inline and templated functions) that the dynamically-compiled user code may need, so I precompile that into bitcode with llvm-g++, and seed the Module with that bitcode, then add the user code (translated by our app from a custom programming language into LLVM IR) and then optimize.  But I need to do this several times, for several user programs, which can come along irregularly during the execution of our app, and I never want to throw away the JITed machine code, though once I JIT I should not need the IR I generated for the user program.

Also, an update: I've found that I'm totally safe if I create (and seed) a new Module and ExecutionEngine every time I need to JIT user code.  But that's very slow and also a pig on memory use since I never free the Module or EE.

I also found by experimentation that I seem to be able to keep a single Module and merely make a new EE for each new bit of user code -- but that is only safe if I move certain routines (that the user code may call) from the llvm-g++-ified code into a module statically compiled by g++.  That is, if those few routines are just function calls to LLVM and not attempted to be inlined, all seems well as long as I don't reuse the EE's.  This approach seems stable for now and saves most of the memory, but still smells like I'm working around an LLVM bug.

So far I've had a hard time actually reproducing a crash in anything other than our full app, but if somebody wants to work with me on tracking the underlying bug, I can try to narrow it down to a simple example.

In the mean time, perhaps somebody can answer these questions for me:  who owns the machine code that is returned by ExecutionEngine::getPointerToFunction?  Is that "static" once JITed?  Owned by the EE?  If I delete the Module and/or EE after JITing, can I still call the JITed code?  If not, may I suggest as a future feature either the ability for the client app to take complete ownership of the JIT code, or else to ask the Module/EE to release as many resources and memory as possible except the callable JIT code?

Larry Gritz
lg at larrygritz.com

More information about the llvm-dev mailing list