在LLVM IR中,当我想从数组中获取一个值时,似乎有三种方法可以做到这一点:使用extractvalue、使用extractelement和使用getelementptr后跟一个load。
然而,从语言参考中并不清楚应该在哪种情况下使用哪种方法。除了差异(extractvalue还可以访问结构体的成员,而extractelement无法访问,语法略有不同,GEP仅进行地址计算,而extractvalue和extractelement似乎也进行内存解引用),在每种情况下应该使用哪些指令?
例如,在以下C代码中:
第三行可以用IR写成:
如果我没记错的话,这三个IR行代码实际上是做同样的事情。 我编译成IR的另一个C程序中包含了这一行代码。
当我使用clang编译时,相应的IR如下所示:
那么为什么在这里使用getelementptr而不是例如extractelement?其他指令在什么情况下使用?
然而,从语言参考中并不清楚应该在哪种情况下使用哪种方法。除了差异(extractvalue还可以访问结构体的成员,而extractelement无法访问,语法略有不同,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行代码实际上是做同样的事情。 我编译成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?其他指令在什么情况下使用?