I am trying to get started with LLVM in order to add just-in-time compilation for my code, but finding it very difficult find references on how to do the things I want in LLVM, despite having checked through the Kaleidoscope tutorial, the language reference manual, the programmer's manual and the doxygen documentation. Are there more references to LLVM's C++ API than these?
Now for the concrete question. I have allocated an array object with two elements (which I assume corresponds to double[2]
in C++):
const llvm::Type* double_t = llvm::Type::getDoubleTy(llvm::getGlobalContext());
const llvm::Type* array_t = llvm::ArrayType::get(double_t,2)
Later in the code, I create a function, where this array is one of the arguments. Then, in my function I extract the first element in the array and return it to the user:
llvm::Function::arg_iterator AI = jit_function_->arg_begin();
llvm::Value *x = AI;
llvm::Value *x0 = Builder.CreateExtractValue(x,0);
Builder.CreateRet(x0);
The code jits fine, but when I try to run it, it doesn't work. For example:
typedef double (*GenType)(double[2]);
GenType FP = GenType(intptr_t(TheExecutionEngine->getPointerToFunction(jit_function_)));
double y[2] = {10,20};
double r = FP(y);
printf("r = %g\n", r);
The return value is just nonsense and I can't see what I'm doing wrong. If I pass the values in the array (10 and 20) as scalar arguments to the function, it works fine.
I think I am able to answer my own question. For the first part of the question, a good reference to LLVM (in addition to the ones mentioned above) is to write what you want in plain C and compile it with Clang and look at the LLVM output: clang -S -emit-llvm test.c -o -
.
For the concrete question, my problem was that I assumed that I was passing an array of two doubles to the jitted function, while in fact I was passing a pointer to an array with two values. So the solution is to change:
const llvm::Type* array_t = llvm::ArrayType::get(double_t,2);
to
const llvm::Type* array_t = llvm::PointerType::getUnqual(llvm::ArrayType::get(double_t,2));
And to add an additional dereferencing by changing
llvm::Value *x0 = Builder.CreateExtractValue(x,0);
to
llvm::Value *x0 = Builder.CreateExtractValue(Builder.CreateLoad(x),0);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With