如何访问LLVM IR的阵列?

发布于 2025-01-27 04:55:58 字数 1947 浏览 2 评论 0原文

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

对于一个2维数组,就像

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”。

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

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]”,“%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

如何解释它?以及如何使用api喜欢builder.createinboundsgep(type,array,idxs);生成它?似乎不可能,因为我尝试了

// 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)

I am confused about how llvm visits an array.

For a 2-dimension array, like

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

The translated llvm-ir is

@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
}

I think what had been done is to first use index 1 to fetch the inner dimension "[5 x i32]" and then use index 2 to fetch "i32".

But when a 2-dimension array as a function parameter(or array pointer), then things go weird

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
}

I don't know if my understanding is correct.

It seems that the location of "a" is loaded to %0 and currently %0 has type "[5 x i32]*"

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

Then use "%0" to visit the outer dimension of "a", but now "%0" is considered to be "[5 x i32]", and "%arrayidx" will have type "i32".

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

Then it is more strange, "%arrayidx" is still considered as "[5 x i32]", but it is actually "i32"

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

How to explain it? And how to use API like Builder.CreateInBoundsGEP(type, array, Idxs); to generate it? It seems impossible because I tried

// 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦过后 2025-02-03 04:55:58
%arrayidx = getelementptr inbounds [5 x i32], [5 x i32]* %0, i64 2

%0%arrayIdx[5 x i32]*

b = getElementPtr< type>,type>* a,i64 idx0 typ 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 or类似于c =& b [idx0] [idx1] [idx1]

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

Both %0and %arrayidx are [5 x i32]*.

B = getelementptr <type>, <type>* A, i64 idx0 is something like B = &A[idx0].

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

%arrayidx1 is i32*.

C = getelementptr <type>, <type>* B, i64 idx0, i64 idx1 is something like C = &B[idx0][idx1]

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文