LLVM:如何给数组元素赋值?

5

我正在努力想出如何使用LLVM C++ API分配数组元素。考虑以下C代码:

int main()
{
    int aa[68];
    aa[56] = 7;

    return 0;
}

使用

clang -S -emit-llvm main.c

我得到了以下IR(为简化起见,属性和其他内容被略去):

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
}

我已经知道如何创建一个入站的GEP,但是当将一个值(7)存储到数组中时,类型是指向 i32 的指针。

我的语言非常类似于C,这就是为什么我使用C作为示例(到目前为止它只是具有不同语法的C)。 生成的IR代码如下:

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
}

我如何将 [2 x i32]* 转换为 i32* 在创建存储时?这是我创建存储的方式:
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 *

为了补充我的答案,这里有一个你没有问到的相关问题的答案:如何通过单个存储指令将[2 x i32]存储到[2 x i32]*中。使用%A = insertvalue [2 x i32] undef, i32 7, 0%B = insertvalue [2 x i32] %A, i32 8, 1构建一个[2 x i32]。您可以在任何值或类型上调用thing->dump()以查看它是什么(对于值,它包括类型)。您应该能够看到您的%1是一个[2 x i32]*而不是i32*,并且我示例中的%B是一个[2 x i32]数组。 - Nick Lewycky
1个回答

1
当创建一个存储器时,如何将[2 x i32] *转换为i32 *?
这正是“获取元素指针”指令的作用。您有一个指向对象(如结构体或数组)的指针,并且想要指向一个元素的指针。
%1 = getelementptr [2 x i32], [2 x i32]* %0, i32 1

这并不是你想要的。想象一下内存中的C字符串,你没有一个[*number* x i8]*,而只有一个i8*。如果你有一个指向[*number* x i8]*的指针,你将进入该数组并获得其元素之一的指针,但对于C字符串,你只有一个指向单个i8元素的指针,并且你通过跨越它来推进指针,其大小为指针所指的对象的sizeof

你的%1正在跨越整个[2 x i32],并在其后指向另一个完整的[2 x i32]。你不想跨越任何东西,因此你的第一个索引应该是i32 0。然后你想进入它并选择你的2 x i32中的第二个i32?使用i32 1作为你的第二个索引。

%1 = getelementptr [2 x i32], [2 x i32]* %0, i32, 0, i32 1

生成一个 i32*

请参阅LLVM GEP FAQ:https://www.llvm.org/docs/GetElementPtr.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接