我正在使用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
}
我的问题是第一个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
^^^^^
我猜第二个操作数是类型%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;
}
但是发出的LLVM
没有匹配。我认为可能是getelementptr
指令也可能适应指针指针,显然它不是。
从阅读本文来看,我对LLVM
(和C
)的了解并不是最好的,但这对我来说已经足够了。所以如果你的答案考虑到这一点我会很感激,所以像我这样的业余爱好者可以理解:)
答案 0 :(得分:10)
有一个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