c - getelementptr 中第一个操作数的目的

标签 c clang llvm

我使用的是 LLVM 版本 3.4.2,我的问题是关于 getelementptr 指令的。假设我有这段 C 代码,我只是在其中分配结构的属性。

struct point {
  float x;
  float y;
  float z;
};

int main(void) {
  struct point my_point;

  my_point.x = 0;
  my_point.y = 0;
  my_point.z = 0;
}

如果我在哪里使用 clang my_example.c -S -emit-llvm 编译它,这是发出的以下 llvm。

%struct.point = type { float, float, float }

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %my_point = alloca %struct.point, align 4
  %1 = getelementptr inbounds %struct.point* %my_point, i32 0, i32 0
  store float 0.000000e+00, float* %1, align 4
  %2 = getelementptr inbounds %struct.point* %my_point, i32 0, i32 1
  store float 0.000000e+00, float* %2, align 4
  %3 = getelementptr inbounds %struct.point* %my_point, i32 0, i32 2
  store float 0.000000e+00, float* %3, align 4
  ret i32 0
}

我的问题是调用 getelementptr 的行中第一个操作数的目的是什么,例如

%1 = getelementptr inbounds %struct.point* %my_point, i32 0, i32 0
%2 = getelementptr inbounds %struct.point* %my_point, i32 0, i32 1
%3 = getelementptr inbounds %struct.point* %my_point, i32 0, i32 2
                                                      ^^^^^

我猜第二个操作数是 %struct.point 类型中的属性索引。但是第一个索引让我感到困惑。我认为它可能类似于下面的内容,其中第一个操作数充当指针指针中的索引。

int main(void) {
  struct point** my_point;

  my_point = alloca(sizeof(struct point**));
  my_point[0] = alloca(sizeof(struct point*));
  my_point[0]->x = 0;
  my_point[0]->y = 0;
  my_point[0]->z = 0;
}

但是发出的 LLVM 不匹配。我认为 getelementptr 指令可能也适用于指针指针,显然不是。

通过阅读本文,我可能会变得非常明显,我对 LLVM(和 C)的了解不是最好的,但它足以让我过得去。因此,如果您的回答考虑到这一点,我将不胜感激,以便像我这样的业余爱好者能够理解:)

最佳答案

有一个 FAQ entry关于那个。

getelementptr 将指针作为第一个参数,需要取消引用。在 C 代码方面,考虑这些等价的表达式:

my_point->x

相同
(*my_point).x

这又是一样的

my_point[0].x

这就是您要查找的零。

关于你的最后一个例子,getelementptr 做地址计算,但没有内存查找,所以它不能处理迭代指针。正确的输入值应该是一个像

这样的常规数组
struct point my_point[42];

C 表达式

float *p = &my_point[7].y;

然后将对应于 LLVM IR

%1 = getelementptr %struct.point* %my_point, i32 7, i32 1

关于c - getelementptr 中第一个操作数的目的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25820628/

相关文章:

c - 访问时未分配字符串

c - 如何fork最年轻的进程

c - 函数指针是否强制清除指令流水线?

c++ - 在 llvm 中用 Undef 值替换对删除指令的所有使用?

llvm - 通过 llvm 的死代码消除过程删除指令

c - 与没有版本的共享库链接

android - 使用 Android NDK 使用 clang++ 编译 C++ 代码时未定义对 `_Unwind_Resume' 的引用

c++ - 模板类实例化的多重继承以及对成员函数的访问

llvm - llvm 中的自动矢量化

c++ - LLVM传递计数 vector 类型指令