LLVM: доступ к параметру массива в функции - PullRequest
2 голосов
/ 14 февраля 2020

Я пытаюсь написать компилятор, используя LLVM C ++ API, и пытаюсь получить доступ к параметру массива в функции.

Насколько я могу судить по генерации IR в Clang, эти два кода имеют разные LLVM ИК-коды:

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

Если при передаче массива в качестве параметра мне сначала нужно использовать builder.CreateStore(), а затем llvm::GetElementPtrInst::CreateInBounds(), чтобы получить указатель на индекс.

Однако при написании компилятора я использую шаблон посетителя и вижу такие коды, как a[0] = 1 как assign expression. При посещении узла дерева assign_expression мне нужно определить, нужен ли load.

Есть ли способ определить, является ли массив локальной переменной или параметром?

Обновление 1: , например, в C, если функция определена следующим образом:

void test(int a[]) {
  a[0] = 1;
}

соответствующий код LLVM C ++ для a[0] = 1 имеет вид:

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);

Однако, когда массив определен локально, код auto loaded_tmp = builder.CreateLoad(param); не требуется. Поэтому мой вопрос: как мне узнать, нужно ли мне CreateLoad?

Обновление 2 : LLVM IR, сгенерированный clang для следующего C кода:

int h(int a[]) {
    a[0] = 1;
    a[1] = 2;
}

- это

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
}

с инструкцией load перед каждым store

1 Ответ

1 голос
/ 14 февраля 2020

Есть ли способ определить, является ли массив локальной переменной или параметром?

Method1:

Использовать isa<Argument> вот так:

Analysis/BasicAliasAnalysis.cpp

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

Метод 2:

Используйте комбинацию LLVMGetFirstParam LLVMGetLastParam и LLVMGetNextParam, чтобы определить, является ли значение параметром.

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

...