在哪些情况下C编译器允许忽略调用约定?

时间:2013-05-14 10:52:31

标签: linker shared-libraries calling-convention abi

由于显而易见的原因,C编译器必须编译其他共享库外部可见的所有函数,以便它们符合平台的调用约定和其他ABI要求。但是,我已经了解到,对于可以保证永远不会从外部模块调用的函数,它不一定需要这样做。

编译器如何以及何时确定对于给定函数是否成立?

  • 静态函数只对同一编译单元中的其他函数可见,因此对于这种ABI破坏优化是一个很好的选择。但是静态函数的函数指针仍然可以传递给其他模块。编译器是否尝试确定函数指针是否在代码中的任何位置传递?

  • gcc编译器具有some extensions,允许将符号声明为默认符号,隐藏符号甚至是内部符号,文档特别提到此信息可用于执行某些不可能从外部执行的优化可见的功能。如果将函数指针传递给注释为内部函数的外部代码会发生什么?

什么是帮助编译器尽可能多地执行优化的最佳方法,同时仍然保证与其他库的互操作性?我应该只使用编译器选项将所有函数定义为内部函数,并使用所有需要外部可见的函数的属性覆盖它吗?

2 个答案:

答案 0 :(得分:1)

C标准要求在所有情况下,指向同一函数的两个指针比较相等。

如果您将符号声明为外部并且指针永远不会传递给外部代码,则编译器只能执行ABI破解技巧。

  

编译器是否尝试确定是否传递了函数指针   代码中的任何地方?

是的,如果它想要执行此优化,它确实如此。编译器可以简单地知道哪些函数对它们执行了函数指针衰减,因此知道你是否已经获取函数的地址并不是什么大问题。保守地说,编译器可以假设所有函数指针都传递给外部代码,或者他们可能会尝试更高级的东西。

  

如果函数指针传递给外部代码会发生什么   对于注释为内部的函数?

没有什么值得关注的 - 它必须有效。

内部/外部可见性主要与可见性有关。编译器只能在相对较少的情况下将其转换为许可证以打破ABI。

  

我应该只使用编译器选项将所有函数定义为   内部,并使用所有函数的属性覆盖它   需要外部可见吗?

除非您的图书馆仅由一个翻译单元组成,否则您可能希望几乎所有功能都需要在外部可见。 “外部但仅限于我的库”和“外部所有”之间的C没有任何有意义的差异。但是,从理论上讲,你可以试试这个。但是,我怀疑你是否会获得更多的加速,这对于一个非平凡的代码库来说将是一个很大的努力。

答案 1 :(得分:0)

  

静态函数仅对同一编译单元中的其他函数可见,因此是进行此类ABI优化的理想选择。但是静态函数的函数指针仍然可以传递给其他模块。编译器是否尝试确定函数指针是否在代码中的任何位置传递?

是的,编译器会进行“转义分析”以查看给定的函数是否实际上仅在内部使用,或者它是否通过其指针转义。

  

gcc编译器有一些扩展,允许将符号声明为默认符号,隐藏符号甚至是内部符号,文档特别提到这些信息可用于执行某些类型的优化,这些优化对于外部可见的函数是不可能的。如果将函数指针传递给注释为内部函数的外部代码会发生什么?

请参阅我对第一点的回答。