bbn
bbn

Reputation: 21

LLVM: access array parameter in a function

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

Upvotes: 2

Views: 1296

Answers (1)

A. K.
A. K.

Reputation: 38272

Is there a way to determine whether the array is a local defined variable or a parameter?

Method1:

Use isa<Argument> like this:

Analysis/BasicAliasAnalysis.cpp

 167   if (isa<Argument>(V))
 168     return true;

Method2:

Use a combination of LLVMGetFirstParam LLVMGetLastParam and LLVMGetNextParam to find if a value is a parameter.

See: https://github.com/llvm/llvm-project/blob/master/llvm/lib/IR/Core.cpp#L2456

Upvotes: 1

Related Questions