C语言 如何访问数组在llvm ir?



我对llvm如何访问数组感到困惑。

对于二维数组,如

int a[5][5];
int func1(){
return a[1][2];
}

翻译的llvm-ir是

@a = global [5 x [5 x i32]] zeroinitializer, align 16
define i32 @func1() #0 {
entry:
%0 = load i32, i32* getelementptr inbounds ([5 x [5 x i32]], [5 x [5 x i32]]* @a, i64 0, i64 1, i64 2), align 4
ret i32 %0
}

我认为应该首先使用索引1来获取内部维度';[5 x i32] ';然后使用索引2来获取&;i32&;

但是当一个二维数组作为函数参数(或数组指针)时,事情就变得奇怪了

int func2(int a[][5]){
return a[2][3];
}
define i32 @func2([5 x i32]* %a) #0 {
entry:
%a.addr = alloca [5 x i32]*, align 8
store [5 x i32]* %a, [5 x i32]** %a.addr, align 8
%0 = load [5 x i32]*, [5 x i32]** %a.addr, align 8
%arrayidx = getelementptr inbounds [5 x i32], [5 x i32]* %0, i64 2
%arrayidx1 = getelementptr inbounds [5 x i32], [5 x i32]* %arrayidx, i64 0, i64 3
%1 = load i32, i32* %arrayidx1, align 4
ret i32 %1
}

我不知道我的理解是否正确。

似乎"a"已加载到%0,且当前%0的类型为"[5 x i32]*">

%0 = load [5 x i32]*, [5 x i32]** %a.addr, align 8

然后使用"%0"访问外部维度的"a",但现在"%0"被认为是"[5 x i32]"one_answers"%arrayidx"将会有"i32"

%arrayidx = getelementptr inbounds [5 x i32], [5 x i32]* %0, i64 2

然后就更奇怪了,"%arrayidx"仍然被认为是"[5 x i32]",但它实际上是"i32">

%arrayidx1 = getelementptr inbounds [5 x i32], [5 x i32]* %arrayidx, i64 0, i64 3

怎么解释?如何使用像Builder.CreateInBoundsGEP(type, array, Idxs);这样的API来生成它?这似乎不可能,因为我试过了

// type is "[5 x i32]" and array also has a type of "[5 x i32]", inorder to generate the same ir 
// as %arrayidx = getelementptr inbounds [5 x i32], [5 x i32]* %0, i64 2
auto arrayidx = Builder.CreateInBoundsGEP(type, array, Idxs)
// but now arrayidx is "i32" and now type and the type of arrayidx is not match
auto arrayidx1 = Builder.CreateInBoundsGEP(type, arrayidx, Idxs)
%arrayidx = getelementptr inbounds [5 x i32], [5 x i32]* %0, i64 2

%0%arrayidx都是[5 x i32]*

B = getelementptr <type>, <type>* A, i64 idx0类似于B = &A[idx0]

%arrayidx1 = getelementptr inbounds [5 x i32], [5 x i32]* %arrayidx, i64 0, i64 3

%arrayidx1i32*

C = getelementptr <type>, <type>* B, i64 idx0, i64 idx1类似于C = &B[idx0][idx1]

最新更新