getelementptr中第一个opperand的目的

aks*_*kst 1 c llvm clang

我正在使用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;
}
Run Code Online (Sandbox Code Playgroud)

如果我用它编译它的位置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
}
Run Code Online (Sandbox Code Playgroud)

我的问题是第一个operrand在线路调用上的目的是什么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
                                                      ^^^^^
Run Code Online (Sandbox Code Playgroud)

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

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

但排放的LLVM不符合.我想这可能是getelementptr指令也可能适应指针指针,显然它不是.

从阅读本文来看,很明显我对LLVM(和C)的了解并不是最好的,但这对我来说已经足够了.所以如果你的答案考虑到这一点,我会很感激,所以像我这样的业余爱好者可以理解:)

Chr*_*oph 10

有关于此的FAQ条目.

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

my_point->x
Run Code Online (Sandbox Code Playgroud)

是相同的

(*my_point).x
Run Code Online (Sandbox Code Playgroud)

反过来又是一样的

my_point[0].x
Run Code Online (Sandbox Code Playgroud)

那就是你正在寻找的零.

至于你的上一个例子,getelementptr是地址计算,但没有内存查找,所以它不能处理迭代指针.正确的输入值将是常规数组

struct point my_point[42];
Run Code Online (Sandbox Code Playgroud)

C表达式

float *p = &my_point[7].y;
Run Code Online (Sandbox Code Playgroud)

然后将对应于LLVM IR

%1 = getelementptr %struct.point* %my_point, i32 7, i32 1
Run Code Online (Sandbox Code Playgroud)