Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing elements in LLVM arrays

Tags:

llvm

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.

like image 801
Joel Avatar asked Feb 02 '23 07:02

Joel


1 Answers

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);
like image 153
Joel Avatar answered Mar 05 '23 18:03

Joel