I am trying to write a compiler using LLVM C++ API, and I am trying to access array parameter in a function.
As far as I can tell from clang's IR generation, those two codes has different LLVM IR codes:
void foo(void) {
int a[2];
a[0] = 1;
// %1 = getelementptr inbounds [2 x i32], [2 x i32]* %0, i32 0, i32 0
// store i32 1, i32* %1
void bar(int a[]) {
a[0] = 1;
// store i32* %0, i32** %3, align 8
// %4 = load i32*, i32** %3, align 8
// %5 = getelementptr inbounds i32, i32* %4, i64 0
// store i32 1, i32* %5, align 4
If passing an array as a parameter, I need to use builder.CreateStore() first, then use llvm::GetElementPtrInst::CreateInBounds() to get the pointer to the index.
However, when writing the compiler, I am using the visitor pattern and see codes like a[0] = 1 as assign expression. When visiting the tree node assign_expression, I need to determine whether the load is needed.
Is there a way to determine whether the array is a local defined variable or a parameter?
Update 1: for example, in C, if a function is defined like this:
void test(int a[]) {
a[0] = 1;
}
the corresponding LLVM C++ code for a[0] = 1 is like:
for(auto arg = theFunction->arg_begin(); arg != theFunction->arg_end(); arg ++) {
auto param = builder.CreateAlloca(llvm::Type::getInt32Ty(context)->getPointerTo());
builder.CreateStore(arg, param);
}
// a[0] = 1
auto loaded_tmp = builder.CreateLoad(param);
auto value = llvm::GetElementPtrInst::CreateInBounds(tmp, {Const(0), Const(0)}, "", the_basic_block);
However, when the array is defined local, the code auto loaded_tmp = builder.CreateLoad(param); is not needed. So my question is: how do I get to know if I need the CreateLoad?
Update 2: The LLVM IR generated by clang for the following C code :
int h(int a[]) {
a[0] = 1;
a[1] = 2;
}
is
define dso_local i32 @h(i32*) #0 {
%2 = alloca i32, align 4
%3 = alloca i32*, align 8
store i32* %0, i32** %3, align 8
%4 = load i32*, i32** %3, align 8
%5 = getelementptr inbounds i32, i32* %4, i64 0
store i32 1, i32* %5, align 4
%6 = load i32*, i32** %3, align 8
%7 = getelementptr inbounds i32, i32* %6, i64 1
store i32 2, i32* %7, align 4
%8 = load i32, i32* %2, align 4
ret i32 %8
}
which has a load instruction before each store
if(isa<Argument>(value)){…but I have a feeling that you're doing something bad. Perhaps my intuition is you shouldn't need to load sometimes, it should be always or neither. Anyway, isa is what you want now. Have fun.storebeforegetelementptr. However, in the function where the array is locally defined, there is nostore. So I think it is required to check if the array in the codea[0] = 1expression is locally defined or passed as a parameter. Thanks for your reply, I will tryisato see if it works.