0

我有这样的C代码:

typedef struct {
  int a1;
  double a2;
} str3;
...
extern void someVoidFunc(int a);
extern str3 someStrFunc(int b);
int main() {
  someVoidFunc(0);
  someStrFunc(0);
  return 0;
}

在 llvm 表示中,这看起来像:

%struct.str3 = type { i32, double}
...
call void @someVoidFunc(i32 0)
call void @someStrFunc(%struct.str3* sret %tmp, i32 0)
...

所以,我不明白,为什么 llvm 更改签名,以及我如何理解哪种类型真正返回函数?

4

2 回答 2

3

按值传递给函数并按值返回的结构很棘手。它们很棘手,因为它们需要关于编译器如何将它们转换为程序集(平台 ABI)的非常具体的规则。虽然 LLVM 试图保持平台独立,但 C 在这方面非常依赖于平台,因此 Clang 对按值传递的结构和按值返回的结构进行特定于 ABI 的降低,以便随后的 LLVM IR --> 本机代码降低只是工作

TL;DR:你选择了一个非常讨厌的角落来探索。如果您真的关心此类函数签名,那么首先通过 AMD64 ABI(或 ARM ABI)查看通过寄存器传递结构的规则。如果您并不真正关心这些特定的用例,那么可以找一些更简单的例子来玩。

于 2013-04-24T20:24:21.687 回答
-2

那么,@Collin 怎么说这是 RVO。我们可以理解 llvm 何时通过属性sret将签名更改为功能。在代码中,我们可以使用hasStructRetAttr方法检测到这一点

于 2013-04-25T08:39:16.513 回答