LLVM:如何分配数组元素?

kam*_*ow1 5 c++ llvm llvm-c++-api

我正在努力弄清楚如何使用 LLVM c++ API 分配数组元素。考虑这个 C 代码:

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

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用

clang -S -emit-llvm main.c
Run Code Online (Sandbox Code Playgroud)

我得到以下 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
}
Run Code Online (Sandbox Code Playgroud)

我已经知道如何创建入站 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
}
Run Code Online (Sandbox Code Playgroud)

创建商店时如何将 [2 x i32]* 转换为 i32* ?这就是我创建商店的方式:

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
}
Run Code Online (Sandbox Code Playgroud)

小智 1

创建商店时如何将 [2 x i32]* 转换为 i32* ?

这正是“获取元素指针”指令的作用。您有一个指向结构体或数组等对象的指针,并且您需要一个指向一个元素的指针。

%1 = getelementptr [2 x i32], [2 x i32]* %0, i32 1
Run Code Online (Sandbox Code Playgroud)

这不完全是你想要的。想象一下内存中的一个 C 字符串,你没有一个,[*number* x i8]*只有一个i8*. 如果你有一个指向[*number* x i8]*该数组的指针,那么你将单步进入该数组并获取指向其元素之一的指针,但是对于 C 字符串,你有一个指向单个元素的指针i8,你可以跨过它,将你的指针向前移动指针的大小

%1所做的就是跨过一个整体[2 x i32]并指向[2 x i32]它后面的另一个整体。你根本不想跨过去,所以你的第一个索引应该是i32 0. 然后你想进入它并选择i32你的2 x i32?中的第二个。用作i32 1您的第二个索引。

%1 = getelementptr [2 x i32], [2 x i32]* %0, i32, 0, i32 1
Run Code Online (Sandbox Code Playgroud)

产生一个i32*.

请参阅 LLVM GEP 常见问题解答:https://www.llvm.org/docs/GetElementPtr.html