3

明らかな理由から、C コンパイラは、他の共有ライブラリから外部的に見えるすべての関数をコンパイルして、プラットフォームの呼び出し規則やその他の ABI 要件に準拠する必要があります。ただし、外部モジュールから呼び出されないことが保証されている関数については、必ずしもそうする必要はないことを学びました。

コンパイラは、それが特定の関数に当てはまるかどうかをいつどのように判断できますか?

  • 静的関数は、同じコンパイル ユニット内の他の関数からしか見えないため、このような ABI を破る最適化に適しています。ただし、静的関数への関数ポインターは、他のモジュールに引き続き渡すことができます。コンパイラは、関数ポインタがコードのどこかに渡されているかどうかを判断しようとしますか?

  • gcc コンパイラには、シンボルをデフォルト、非表示、または内部として宣言できる拡張機能がいくつかあります。ドキュメントでは、この情報を使用して、外部から見える関数では不可能なある種の最適化を実行できると具体的に述べています。内部として注釈が付けられた関数の外部コードに関数ポインタが渡されるとどうなるでしょうか?

他のライブラリとの相互運用性を保証しながら、コンパイラが可能な限り多くの最適化を実行できるようにする最善の方法は何でしょうか? コンパイラ オプションを使用してすべての関数を内部として定義し、それを外部から見えるようにする必要があるすべての関数の属性でオーバーライドする必要がありますか?

4

2 に答える 2

1

C 標準で、すべての場合において、同じ関数への 2 つのポインターが等しいことが要求されます。

コンパイラは、シンボルを外部として宣言し、ポインターが外部コードに渡されない場合にのみ、ABI を破るトリックを実行できます。

コンパイラは、関数ポインタがコードのどこかに渡されているかどうかを判断しようとしますか?

はい、この最適化を実行したい場合は実行します。コンパイラーは、関数ポインターの減衰が実行された関数を簡単に知ることができるため、関数のアドレスを取得したかどうかを知ることは大したことではありません。保守的に言えば、コンパイラはすべての関数ポインタが外部コードに渡されていると想定するか、より高度なものを試みる可能性があります。

内部として注釈が付けられた関数の外部コードに関数ポインタが渡されるとどうなるでしょうか?

あまり興味深いものはありません-うまくいくはずです。

内部/外部の可視性は、主にその可視性に関するものです。コンパイラは、比較的まれなケースでのみ、ABI を破るためのライセンスに変えることができます。

コンパイラ オプションを使用してすべての関数を内部として定義し、それを外部から見えるようにする必要があるすべての関数の属性でオーバーライドする必要がありますか?

ライブラリが 1 つの翻訳単位のみで構成されている場合を除き、事実上すべての関数を外部から見えるようにする必要があると考えられます。C では、"External but only within my library" と "External to all" の間に意味のある違いはありません。ただし、理論的には、これを試すことができます。ただし、大幅な高速化を達成できるとは思えません。これは、重要なコードベースにとっては多大な労力になるでしょう。

于 2013-12-04T10:11:08.250 に答える
0

静的関数は、同じコンパイル ユニット内の他の関数からしか見えないため、このような ABI を破る最適化に適しています。ただし、静的関数への関数ポインターは、他のモジュールに引き続き渡すことができます。コンパイラは、関数ポインタがコードのどこかに渡されているかどうかを判断しようとしますか?

はい、コンパイラは「エスケープ分析」を行って、指定された関数が実際に内部でのみ使用されているのか、それともポインターを介してエスケープされているのかを確認します。

gcc コンパイラには、シンボルをデフォルト、非表示、または内部として宣言できる拡張機能がいくつかあります。ドキュメントでは、この情報を使用して、外部から見える関数では不可能なある種の最適化を実行できると具体的に述べています。内部として注釈が付けられた関数の外部コードに関数ポインタが渡されるとどうなるでしょうか?

あなたの最初のポイントに対する私の答えを見てください。

于 2013-12-04T10:10:44.240 に答える