我有这样的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 represatation中,这看起来像:
%struct.str3 = type { i32, double}
...
call void @someVoidFunc(i32 0)
call void @someStrFunc(%struct.str3* sret %tmp, i32 0)
...
所以,我不明白,为什么llvm会改变签名,我怎么能理解哪种类型真的返回功能呢?
答案 0 :(得分:2)
按值传递给函数并按值返回的结构是棘手。它们很棘手,因为它们需要关于编译器如何将它们转换为汇编(平台ABI)的非常具体的规则。虽然LLVM试图保持与平台无关,但C在这方面非常依赖于平台,因此Clang通过值和值返回的结构进行特定于ABI的结构降低,以便随后的LLVM IR - >本机代码降低正常工作。
TL; DR:你选择了一个非常讨厌的角落去探索。如果你真的关心这样的函数签名,那么首先看看通过寄存器传递结构的规则的AMD64 ABI(或ARM ABI)。如果您并不真正关心这些特定用例,那么可以找一些更简单的例子来使用。
答案 1 :(得分:-1)
那么,怎么说@Collin这是RVO。 我们可以理解llvm何时通过属性sret将签名更改为函数。 在代码中,我们可以使用方法hasStructRetAttr
检测到这一点