【问题标题】:In which cases is the C compiler allowed to ignore the calling conventions?在哪些情况下允许 C 编译器忽略调用约定?
【发布时间】:2013-05-14 10:52:31
【问题描述】:

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

编译器如何以及何时可以确定给定函数是否适用?

  • 静态函数仅对同一编译单元中的其他函数可见,因此非常适合此类破坏 ABI 的优化。但是指向静态函数的函数指针仍然可以传递给其他模块。编译器是否尝试确定函数指针是否在代码中的任何位置传递?

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

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

【问题讨论】:

    标签: linker shared-libraries calling-convention abi


    【解决方案1】:

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

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

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

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

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

    没什么大不了的——它必须有效。

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

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

    除非您的库仅由一个翻译单元组成,否则您会期望几乎所有功能都需要在外部可见。 “外部但仅在我的库中”和“对所有人都外部”之间在 C 中没有有意义的区别。但是,理论上,你可以试试这个。但是,我怀疑您是否会获得很大的加速,这对于一个不平凡的代码库来说将是一个很大的努力。

    【讨论】:

    • 在某些 ARM 系统上,期望浮点值以与其他参数相同的方式或在 FP 寄存器中传递的代码之间可能存在兼容性困难。如果不是函数指针,我认为可以通过让编译器生成使用 FPU 的代码的编译器生成一个使用 FPU 寄存器的名称混乱的函数版本和一个“弱链接”包装器来解决这个问题一个未修改的名称,将普通参数复制到 FPU 寄存器并调用修改后的版本。
    • 使用 FPU 并想要调用 FPU 寄存器版本的编译器自豪代码将产生对重命名版本的调用,以及将 FPU 寄存器复制到普通参数的弱链接包装器并调用未损坏的版本。这应该允许调用者和被调用代码 FPU 使用的任何组合之间的“通用”行为。至于函数指针,我认为可以通过说除非“特别”声明它们总是指向使用最基本 ABI 的方法来回避 ABI 差异的问题。这看起来可行吗?
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2020-01-02
      • 2010-10-12
      • 2017-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多