在LLVM IR中,当我想从数组中获取值时,似乎有三种方法可以做到这一点:使用extractvalue,使用extractelement,并使用getelementptr然后加载。
但是,从语言参考来看,我不清楚在哪种情况下你应该使用哪一个。除了差异之外(extractvalue也可以访问来自结构元素不能的结构的成员,语法有点不同,GEP只会解决计算,其中extractvalue和extractelement似乎也进行内存取消引用),在这种情况下,每个指令都是使用
例如,在以下c代码中
int arr[2];
// do some stuff with arr
int i = arr[0];
第三行可以用IR写成:
%0 = extractvalue [2 x i32] @arr, i32 0
%0 = extractelement [2 x i32] @arr, i32 0
%0 = load i32* getelementptr inbounds ([2 x i32]* @arr, i32 0, i32 0)
如果我没有弄错,这三条红外线完全相同。 我编译为IR的另一个C程序包含行
printf(" %d", a[i]);
当我用clang编译它时,相应的IR看起来像这样:
%25 = load i32, i32* %i14, align 4
%26 = load i32*, i32** %a, align 4
%arrayidx18 = getelementptr inbounds i32, i32* %26, i32 %25
%27 = load i32, i32* %arrayidx18, align 4
%call20 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0), i32 %27)
那么为什么getelementptr在这里使用而不是extractelement? 何时使用其他说明?
答案 0 :(得分:2)
在LLVM 4.0文档中:
extractelement
表明它特定于向量并在提供的索引处返回标量值。 (如果索引超出界限,则未定义)
extractvalue
表明它对于结构和数组(聚合类型)是通用的,并返回索引所寻址的结构字段的值at。它支持多个索引,可用于以类似于getelementptr
中使用的索引的方式访问嵌套元素。
getelementptr
(顾名思义)返回指向某个位置的指针,而上述其他操作返回一个值。因此load
指令要求获取值(或store
如果写入。)
我正在编写一个发出LLVM的编译器,我使用getelementptr
概括了大多数向量和聚合访问(读取和写入),以简化发出代码。然而;其他编译器可以进行更深入的分析并生成特定于类型的LLVM操作。
答案 1 :(得分:2)
使用LLVM IR,与C不同,数组是存储在虚拟寄存器中的值类型,因此您可以将GEP添加到值数组的元素。如果将该数组存储在内存中的某个位置并且具有指向该数组的指针,则表示您使用GEP然后使用加载或存储的时间。