using external functions from llvm

Is there documentation somewhere on how to call external functions from llvm? The only guide I found was this: http://www.gearleaf.com/blog/post/44, and it doesn’t seem to be working for me.

I have a function:

llvm::GenericValue lle_X_create_number_object(llvm::FunctionType* ft, const std::vectorllvm::GenericValue& args)
{
llvm_object_structure* result = new llvm_object_structure;
result->typeIdx = TypeSystem::number;
result->data = reinterpret_cast<unsigned char*>(new double(args[0].DoubleVal));
llvm::GenericValue gv;
gv.PointerVal = reinterpret_cast<void*>(result);
return gv;
}

defined in an extern “C” block. I add it as a symbol with:

llvm::sys::DynamicLibrary::AddSymbol(“lle_X_create_number_object”,(void*)lle_X_create_number_object);

yet when attempting to call it I still get: “LLVM ERROR: Program used external function ‘create_number_object’ which could not be resolved!”

You are adding the symbol as “lle_X_create_number_object” yet your error message implies you have tried to lookup and use “create_number_object”. Can you provide the code for the lookup?

The blog post I linked to implied that adding a symbol in the form lle_X_FUNCTIONNAME would allow you to call a function called FUNCTIONNAME. Is this not the case?

Ok, so calling lle_X_FUNCTIONNAME instead of FUNCTIONNAME works (is there any reason the post used the lle_X_ prefix other than convention? was it once possible to call external functions as I was originally trying, or, why did the blog post think it was possible?)

I’m now running into trouble when trying to access arguments however. printing args.size() from the function yields 12105250188025543488. The generated call to it looks like:

%object_tmp = call %object_structure* @lle_X_create_number_object(double 5.000000e+00) ; <%object_structure*> [#uses=1]

Alec Benzer <alecbenzer@gmail.com> writes:

Ok, so calling lle_X_FUNCTIONNAME instead of FUNCTIONNAME works (is there
any reason the post used the lle_X_ prefix other than convention? was it
once possible to call external functions as I was originally trying, or, why
did the blog post think it was possible?)

AFAIK you can name the function as you please (with some reasonable
restrictions on the character set, etc)

I'm now running into trouble when trying to access arguments however.
printing args.size() from the function yields 12105250188025543488. The
generated call to it looks like:

%object_tmp = call %object_structure* @lle_X_create_number_object(double
5.000000e+00) ; <%object_structure*> [#uses=1]

You are calling a function that takes a single argument of type
`double'. But on a previous post you showed the function with this
signature:

llvm::GenericValue
lle_X_create_number_object(llvm::FunctionType* ft,
                           const std::vector<llvm::GenericValue>& args)

so as the execution enters the function above from your call, the stack
can be considered corrupt. Also, the return type of the `call' might not
be right (it depends on the ABI of your platform.)

It is strange to generate GenericValue's from JITted code. Are you doing
some kind of meta-interpreter? I'm afraid that you might be utterly
confused about how to use LLVM.

I’m afraid that you might be utterly confused about how to use LLVM.

Er, I don’t think so? I think I was mostly just confused about interfacing with external functions, since whoever wrote that blog post (http://www.gearleaf.com/blog/post/44) didn’t seem to know what he was talking about (or he was doing stuff that once worked but now doesn’t? I don’t know). If you glance at that post I think you’ll understand why I was doing what I was doing.

anyway, I think I get it now, what I was trying to do seems to be working how I expect it to.

I’m afraid that you might be utterly confused about how to use LLVM.

Er, I don’t think so? I think I was mostly just confused about interfacing with external functions, since whoever wrote that blog post (http://www.gearleaf.com/blog/post/44) didn’t seem to know what he was talking about (or he was doing stuff that once worked but now doesn’t? I don’t know). If you glance at that post I think you’ll understand why I was doing what I was doing.

The blog appears to leave out a lot of context and as such is confusing. lle_X appears to be a special prefix which is used by the interpreter and not the JIT from what I can gather from a quick look at https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_27/lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp but I didn’t bother to look to much into the detail.

Alec Benzer <alecbenzer@gmail.com> writes:

I'm afraid that you might be utterly confused about how to use LLVM.

Er, I don't think so? I think I was mostly just confused about interfacing
with external functions, since whoever wrote that blog post (
http://www.gearleaf.com/blog/post/44) didn't seem to know what he was
talking about (or he was doing stuff that once worked but now doesn't? I
don't know). If you glance at that post I think you'll understand why I was
doing what I was doing.

anyway, I think I get it now, what I was trying to do seems to be working
how I expect it to.

I've just looked at the blog post.

That is over-complicated. There is no need for a wrapping function for
calling external functions. It seems to me that the example on that blog
post is badly broken on several ways.

Instead of sys::DynamicLibrary::AddSymbol use
Module::getOrInsertFunction and then ExecutionEngine::addGlobalMapping
passing to it a pointer to your function. No wrappers needed. Be sure
that the FunctionType matches the signature of your function. Try first
with the simplest case (a function that takes 0 args and returs void)
then with an integer argument, etc. Things become really messy when you
reach C structs (let's forget about C++ classes.)

Finally, follow the standard requirements for setting up the JIT, like
calling InitializaNativeTarget at the beginning of `main'.

My advice is to forget about the example on that blog post and use as an
skeleton some of the examples that comes with LLVM, like HowToUseJIT or
Fibonacci.

Alec Benzer wrote:

The blog post I linked to implied that adding a symbol in the form
lle_X_FUNCTIONNAME would allow you to call a function called
FUNCTIONNAME. Is this not the case?

It is not. I haven't read the blog post, but I recognize the lle_X_ format as part of the internals of the llvm interpreter. If you were modifying the internals of the interpreter, then this might work.

If you want to JIT (or even use the interpreter with libffi) and call functions declared in your program, you write your function *normally*. No renaming, certainly no GenericValue cruft. Please see the tutorial at llvm.org/docs/tutorial/, in particular chapter 4 where they demo doing exactly this.

Nick