LLVM IR GetElementPtr指令简介
23 Oct 2024getelementptr是LLVM IR里的一个用于计算指针偏移量的指令,非常常见但是又非常容易引起误解。
内容参考——GetElementPtr,LLVM IR tutorial
getelementptr指令只是计算偏移量,不对指针做解引用。
语法:
<result> = getelementptr <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr inbounds <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr nusw <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr nuw <ty>, ptr <ptrval>{, <ty> <idx>}*
<result> = getelementptr inrange(S,E) <ty>, ptr <ptrval>{, <ty> <idx>}*<result> = getelementptr <ty>, <N x ptr> <ptrval>, <vector index type> <idx>
太复杂,先只考虑最简单的情况
<result> = getelementptr <ty>, ptr <ptrval>{, <ty> <idx>}*
第一个参数<ty> 代表要用什么样的类型解读第二个参数<ptrval>,这个类型为聚合类型,即结构体、数组或者向量。
第二个参数<ptrval>是一个value,是一个指针,作为指针偏移量计算的起始点。
{, <ty> <idx>}*是正则表达式的记号,表示<ty> <idx>这个结构可出现0次或多次,其中<ty>为整形,idx为具体的索引值。
考虑以下样例:
struct complicate{
int x;
long y;
struct insideComplicate{
int x;
long y;
} z;
char a[10];
};
char accessA(struct complicate* c){
c->z.y = 3;
c->a[3] = 'c';
return c->a[5];
}
采用clang file.c -O2 -o file -c -emit-llvm编译(-O2用以生产更简洁的IR),得到以下IR:
%struct.complicate = type { i32, i64, %struct.insideComplicate, [10 x i8] }
%struct.insideComplicate = type { i32, i64 }
define dso_local signext i8 @accessA(ptr nocapture noundef %0) local_unnamed_addr #2 {
%2 = getelementptr inbounds %struct.complicate, ptr %0, i64 0, i32 2, i32 1
store i64 3, ptr %2, align 8, !tbaa !13
%3 = getelementptr inbounds %struct.complicate, ptr %0, i64 0, i32 3, i64 3
store i8 99, ptr %3, align 1, !tbaa !17
%4 = getelementptr inbounds %struct.complicate, ptr %0, i64 0, i32 3, i64 5
%5 = load i8, ptr %4, align 1, !tbaa !17
ret i8 %5
}
c->z.y 被解析成
getelementptr inbounds %struct.complicate, ptr %0, i64 0, i32 2, i32 1
其中%0为c, 第一组i64 0可看作由%struct.complicate组成的数组里取第一个元素;第二组i32 2表示在%struct.complicate这个结构体类型里取第三个元素,注意——这里的第三个元素仅仅就是第三个元素,与每个元素的字节数无关。
在%struct.complicate中,第一个元素为i32,第二个元素为i64,第三个元素为%struct.insideComplicate,因此第二组i32 2取到%struct.insideComplicate;第三组i32 1对类型%struct.insideComplicate取第二个元素i64,于是完成c->z.y的取地址工作。
剩下两条getelementptr指令与源码的对应关系留给读者。