'Confused about LLVM Arrays

I'm kind of confused on what are the steps to create, store and get values from LLVM arrays, so far I'm creating it with:

auto type = llvm::ArrayType::get(<TYPE>, <SOME_UINT>);
auto array = builder.CreateAlloca(type);

With that, I tried to get llvm::InBoundGEP to each element and store llvm::Value's to them, but that didn't worked...

Is there some guide for doing this?



Solution 1:[1]

Well, today I discovered the llc -march=cpp tool and actually helped me a lot, so I will answer here what I did in the end:

create the array (for that we need the type first):

auto arrayType = llvm::ArrayType::get(llvm::IntegerType::get(context, 32), size);
auto arrayPtr = new llvm::AllocaInst(arrayType, "", block);

now we will store some values to the array, for that we need to integers (read the GetElementPtr manual to know that each of them do), the second integer will tell the index (as in array[index]):

auto zero = llvm::ConstantInt::get(context, llvm::APInt(64, 0, true));
auto index = llvm::ConstantInt::get(context, llvm::APInt(32, INDEX, true));

now we can point to the element in the array and store something to it, (we will store the same index as in array[index] = index):

auto ptr = llvm::GetElementPtrInst::Create(arrayPtr, { zero, index }, "", block);
auto store = new llvm::StoreInst(index, ptr, false, block);

Do that for each element of the array.

Now to load, assuming you have a llvm::Value as the index (which was my case, and ExtractElementInst didn't handle that, as far as I know at least...):

first get a ptr to the element (just like before):

ptr = llvm::GetElementPtrInst::Create(arrayPtr, { zero, index }, "", block);

And load the value to some variable:

auto value = builder.CreateLoad(ptr);

There's a thing I learnt, you cannot easily create variable-length arrays, you will have to use some stack tricks I don't actually know how to use just yet, but if you wanna know, here are the instructions to use: http://llvm.org/docs/LangRef.html#llvm-stacksave-intrinsic

Try compiling this simple code:

int n = 5; int array[n];

with clang -S -llvm-emit your-file.c

And you will see those instructions.

Solution 2:[2]

following #Shello 's code i've been using it also for GlobalVariable arrays:

Value *index_pointer(GlobalVariable *array, Value *index) {
  return Builder.CreateGEP(
    array, {ConstantInt::get(Context, APInt(64, 0, true)), index}, "tmp");

}

Solution 3:[3]

Here's what worked for me, inspired by @Shelo's answer:

// The values we want to create an array of
int integers[] = { 1, 2, 3, 4, 5 };

// Create llvm constants
std::vector<llvm::Value *> values;
for (int i : integers) {
    Value * value = ConstantInt::get(context, llvm::APInt(32, i, true));
    values.push_back(value);
}

// Get type of element and create array-type
Type * type = values[0]->getType();
auto arrayType = llvm::ArrayType::get(type, values.size());

// Create the alloca and zero index
AllocaInst *alloca = Builder.CreateAlloca(arrayType);
auto zero = ConstantInt::get(context, llvm::APInt(32, 0, true));

// Foreach value, create the corresponding index as a Value, create a GEP and store.
for (int i = 0; i < values.size(); i++) {
    auto index = ConstantInt::get(context, llvm::APInt(32, i, true));
    auto ptr = Builder.CreateGEP(alloca, { zero, index });
    Builder.CreateStore(values[i], ptr);
}
// Do something with alloca

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Shelo
Solution 2 roberto
Solution 3 Jeppe