Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 防止clang扩展聚合类型的参数?_C++_C_Clang_Llvm - Fatal编程技术网

C++ 防止clang扩展聚合类型的参数?

C++ 防止clang扩展聚合类型的参数?,c++,c,clang,llvm,C++,C,Clang,Llvm,我正在使用clang为一些C代码吐出优化的LLVM IR,我遇到了一个障碍。我假设,如果我一次只向clang传递一个函数(声明了必要的依赖项),那么生成的LLVM例程的函数签名将与我传递的函数一致(即,相同类型的相同数量的参数)。这在大多数情况下都有效,聚合类型除外。例如: 下面是C代码 struct A { double x; int y; }; int f(struct A a) { return a.y; } 结果如下所示 ; Function Attrs: n

我正在使用clang为一些C代码吐出优化的LLVM IR,我遇到了一个障碍。我假设,如果我一次只向clang传递一个函数(声明了必要的依赖项),那么生成的LLVM例程的函数签名将与我传递的函数一致(即,相同类型的相同数量的参数)。这在大多数情况下都有效,聚合类型除外。例如:

下面是C代码

struct A {
    double x;
    int y;
};

int f(struct A a) {
    return a.y;
}
结果如下所示

; Function Attrs: nounwind readnone uwtable
define i32 @f(double %a.coerce0, i32 %a.coerce1) #0 {
entry:
  ret i32 %a.coerce1
}
结构已扩展为连续参数,因此函数现在似乎接受两个参数,而不是一个参数。有没有办法阻止这种扩张?即使这是一种向前声明结构的方式,这样clang就不会为了扩展它而知道它的组成字段了


谢谢你的帮助

此行为由(x86 64位体系结构的应用程序二进制接口)指定。它在ABI中指定,以便不同编译器编译的函数可以互操作。出于同样的原因,在不违反ABI的情况下不能更改它,这意味着函数的所有客户端都需要知道如何调用它

ABI要求在以下情况下以这种方式拆分聚合对象:

  • 聚合对象的大小不超过16字节,并且

  • < > > C++中,聚合对象是“POD”(普通旧数据)。

否则,参数将按地址传递(尽管仍需要制作副本)


因此,您可以通过使类型变大来克服聚合类型的反聚合,但这必须对使用该类型的每个翻译单元可见。

您还可以通过void*传递内容,并将内存强制转换为所需的结构,但是一个更好的问题是,为什么您试图避免让前端执行它需要执行的一些基于类型的降低(上面的ABI答案)。FWIW我们也可以在后端执行此操作,但它需要前端类型信息才能正确执行下降操作,这对于llvm和clang来说是一个很大的变化。

这很有趣!谢谢你的回答。大多数32位体系结构的规范也类似吗?或者我可以切换到x86以完全避免这个问题吗?@Hoyt:32位ABI基于寄存器数量少得多的体系结构,因此它在优化调用时不会太费力。IIRC,在32位模式下,虽然小的聚合可以在单个寄存器中传递,但聚合永远不会取消聚合。有关更多信息,请参阅。注意:不要被AMD的使用所迷惑;64位模式下的英特尔x86也使用了同样的ABI。@霍伊特:故意使用32位模式似乎与希望发出优化代码的愿望相矛盾,正如在OP中所说的。我只是说。是的,我会第一个承认,我不得不以上市时间的名义剥夺了很多优化潜力(例如,通过拆分成函数编译单元来消除任何全局优化的可能性)。为32位arch编译并不是世界末日,尽管我希望尽可能避免这种情况,这是x86_64的一个非常聪明的技巧…@hoyt:您的另一个选择是强制按引用传递(即传递指针)并在被叫人的前奏中复制结构。我对你的项目了解不够,无法提出其他建议。祝你好运。