Я пытаюсь написать компилятор, используя 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