I'm struggling to figure out how to assign an array element using the LLVM c++ API. consider this C code:
int main()
{
int aa[68];
aa[56] = 7;
return 0;
}
using
clang -S -emit-llvm main.c
I get the following IR (attributes and other things are skipped for simplicity):
define dso_local i32 @main() #0 {
%1 = alloca i32, align 4
%2 = alloca [68 x i32], align 16
store i32 0, i32* %1, align 4
%3 = getelementptr inbounds [68 x i32], [68 x i32]* %2, i64 0, i64 56
store i32 7, i32* %3, align 16
ret i32 0
}
I already know how to create an inbounds GEP, but when storing a value (7) to the array the type is a pointer to i32.
my language is very similar to C, that's why I'm using C as an example (so far it's just C but with a different syntax). generated IR for my language is:
define i32 @main() {
%0 = alloca [2 x i32], align 4
%1 = getelementptr [2 x i32], [2 x i32]* %0, i32 1
store i32 1, [2 x i32]* %1, align 4
ret i32 0
}
how can I possibly turn [2 x i32]* into i32* when creating a store? this is how I create the store:
llvm::AllocaInst *stored = symbol_table[arr_name];
llvm::Value *result = ir_builder->CreateGEP(stored->getAllocatedType(), stored, idx_vals);
// idx_vals contains the index
ir_builder->CreateStore(val, result); // here val is a value stored in a symbol table
// and it's type is llvm::Value *
how can I possibly turn [2 x i32]* into i32* when creating a store?
This is exactly what the "get element pointer" instruction does. You have a pointer to an object like a struct or an array, and you want a pointer to one element.
%1 = getelementptr [2 x i32], [2 x i32]* %0, i32 1
This isn't quite what you want. Picture a C string in memory, you don't have a [*number* x i8]*
you just have an i8*
. If you had a pointer to [*number* x i8]*
you'd be stepping into that array and getting a pointer to one of its elements, but with a C string you have a pointer to a single i8
element and you step over it, advancing your pointer by sizeof the pointee.
What your %1
is doing is stepping over one whole [2 x i32]
and pointing to another full [2 x i32]
after it. You don't want to step over at all, so your first index should be i32 0
. Then you want to step into it and select the second i32
in your 2 x i32
? Use i32 1
as your second index.
%1 = getelementptr [2 x i32], [2 x i32]* %0, i32, 0, i32 1
produces an i32*
.
See the LLVM GEP FAQ: https://www.llvm.org/docs/GetElementPtr.html