由于显而易见的原因,C 编译器必须编译其他共享库外部可见的所有函数,以便它们符合平台的调用约定和其他 ABI 要求。但是,我了解到,对于可以保证永远不会从外部模块调用的函数,不一定需要这样做。
编译器如何以及何时可以确定对于给定函数来说这是否成立?
静态函数仅对同一编译单元中的其他函数可见,因此是此类破坏 ABI 优化的良好候选者。但是指向静态函数的函数指针仍然可以传递给其他模块。编译器是否尝试确定函数指针是否在代码中的任何位置传递?
gcc 编译器有 some extensions允许将符号声明为默认、隐藏甚至内部符号,并且文档特别提到该信息可用于执行外部可见函数不可能实现的某些优化。如果将函数指针传递给注释为内部函数的外部代码,会发生什么?
帮助编译器执行尽可能多的优化,同时仍然保证与其他库的互操作性的最佳方法是什么?我是否应该使用编译器选项将所有函数定义为内部函数,并使用所有需要外部可见的函数的属性覆盖它?
最佳答案
C 标准要求在所有情况下,指向同一函数的两个指针比较相等。
如果您将符号声明为外部并且指针永远不会传递给外部代码,则编译器只能执行破坏 ABI 的技巧。
Does the compiler try to determine if function pointers are passed anywhere in the code?
是的,如果它想执行此优化,它会执行此优化。编译器可以轻松地知道哪些函数对其执行了函数指针衰减,因此知道是否获取了函数的地址并不是什么大问题。保守地说,编译器可以假设所有函数指针都传递给外部代码,或者它们可能会尝试更高级的东西。
What would happen if a function pointer was passed to external code for a function annotated as being internal?
没有什么太大的兴趣 - 它必须有效。
内部/外部可见性主要是关于可见性。编译器只有在相对少数的情况下才能将其转换为破解 ABI 的许可证。
Should I just use the compiler option to define all functions as internal, and override that with an attribute for all functions that need to be externally visible?
除非您的库仅由单个翻译单元组成,否则您会期望几乎所有函数都需要外部可见。在 C 中,“外部但仅在我的库内”和“外部到所有人”之间没有任何有意义的区别。然而,理论上,你可以尝试这个。然而,我怀疑您是否会实现很大的加速,并且对于一个不平凡的代码库来说这将是大量的工作。
关于linker - 在什么情况下 C 编译器可以忽略调用约定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16541275/