Newbie question: Getting info about JIT-compiled function

Andrew Haley wrote:

Jeff Kuskin wrote:
> Apologies if this is a FAQ.
>
> I am using the LLVM JIT facility on an x86_64 platform. I generate
> IR for a single function using IRBuilder(), use the
> FunctionPassManager to do some optimization passes, and then call
> ExecutionEngine::getPointerToFunction() to get a native-code version
> of the function. Everything works fine so far.
>
> Two questions:
>
> Question (1): How can I get the size of the native function? I see
> that the information is stored in the __jitSymbolTable structure in
> JITEmitter.cpp, but I don't see any interface to query this symbol
> table. I see AddFunctionToSymbolTable() and
> RemoveFunctionFromSymbolTable(), but not any equivalent of
> GetFunctionFromSymbolTable(). Is there a supported way to get at
> the JitSymbolEntry for a function? If not, is there an alternate
> way to determine the size (in bytes) of the native function?

The answer seems to be "create your own memory manager and define
endFunctionBody()". If you have a look at class MyJITMemoryManager in
http://icedtea.classpath.org/hg/icedtea6/file/0507a324ec22/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp

you'll see how I did it.

I took a look and it makes sense (though it does seem a bit heavyweight).
I'll give it a try.

> Question (2): Does LLVM have any routines for printing the
> disassembly of a native code function? I see that lli can do this,
> but I would much prefer an LLVM library routine that I can call from
> my own code rather than having to write the bitcode to a file and
> then invoke lli. Suggestions?

This keeps changing, but on x86 with 4.2 you do this to enable
assembly dumps:

std::vector<const char*> Args;
Args.push_back(""); // program name
Args.push_back("-debug-only=" "x86-emitter");
cl::ParseCommandLineOptions(Args.size()-1, (char**)&Args[0]);

I must be missing something here. I added this code and it is executed
before any function is compiled. But I still don't see the x86 asm
printed. I build the function, run the FunctionPassManager,
and then call getPointerToFunction(). All works fine. But I don't
see any printing when the FunctionPassManager runs, and even if I
call f->print() (f being the Function*) after the FunctionPassManager
runs, I still see only the LLVM asm but not x86 asm.

What am I doing wrong?

Thanks!

-- Jeff

Andrew Haley wrote:

Jeff Kuskin wrote:

Apologies if this is a FAQ.

I am using the LLVM JIT facility on an x86_64 platform. I generate
IR for a single function using IRBuilder(), use the
FunctionPassManager to do some optimization passes, and then call
ExecutionEngine::getPointerToFunction() to get a native-code version
of the function. Everything works fine so far.

Two questions:

Question (1): How can I get the size of the native function? I see
that the information is stored in the __jitSymbolTable structure in
JITEmitter.cpp, but I don't see any interface to query this symbol
table. I see AddFunctionToSymbolTable() and
RemoveFunctionFromSymbolTable(), but not any equivalent of
GetFunctionFromSymbolTable(). Is there a supported way to get at
the JitSymbolEntry for a function? If not, is there an alternate
way to determine the size (in bytes) of the native function?

The answer seems to be "create your own memory manager and define
endFunctionBody()". If you have a look at class MyJITMemoryManager in
http://icedtea.classpath.org/hg/icedtea6/file/0507a324ec22/ports/hotspot/src/share/vm/shark/sharkBuilder.hpp

you'll see how I did it.

I took a look and it makes sense (though it does seem a bit heavyweight).
I'll give it a try.

Question (2): Does LLVM have any routines for printing the
disassembly of a native code function? I see that lli can do this,
but I would much prefer an LLVM library routine that I can call from
my own code rather than having to write the bitcode to a file and
then invoke lli. Suggestions?

This keeps changing, but on x86 with 4.2 you do this to enable
assembly dumps:

std::vector<const char*> Args;
Args.push_back(""); // program name
Args.push_back("-debug-only=" "x86-emitter");
cl::ParseCommandLineOptions(Args.size()-1, (char**)&Args[0]);

I must be missing something here. I added this code and it is executed
before any function is compiled. But I still don't see the x86 asm
printed. I build the function, run the FunctionPassManager,
and then call getPointerToFunction(). All works fine. But I don't
see any printing when the FunctionPassManager runs, and even if I
call f->print() (f being the Function*) after the FunctionPassManager
runs, I still see only the LLVM asm but not x86 asm.

Instead of "x86-emitter", try "jit".

Evan