シンボルの可視属性オプション

シンボル・プリエンプションまたは位置に依存しないコードが不要なアプリケーションは、汎用の ABI 可視属性を利用してパフォーマンスを向上させることができます。

可視性オプションは IA-32 コンパイラと Itanium® コンパイラの両方でサポートされますが、現在のところ、最適化によりパフォーマンスを向上できるのは Itanium ベース・システムのみです。

グローバル・シンボルと可視属性

グローバル・シンボルは、宣言されたコンパイル単位 (単一ソースファイルとそのインクルード・ファイル) の外部で見えるシンボルです。コンパイル単位中の各グローバル・シンボル定義や参照には、それらが定義されたコンポーネントの外部からどのように参照されるかを制御する可視属性があります。次の表に、可視属性の値の定義を示します。

EXTERN

コンパイラはシンボルを別のコンポーネントで定義されたものとして扱います。これは別のコンポーネントにある同じ名前の定義によってシンボルが無効にされる (プリエンプトされる) とコンパイラが仮定することを意味します。(「シンボル・プリエンプション」 を参照)。関数シンボルの可視属性が extern の場合、コンパイラはそのシンボルが間接的に呼び出され、間接呼び出しスタブをインライン展開できることを認識しています。

DEFAULT

他のコンポーネントはシンボルを参照することができます。シンボル定義は別のコンポーネントにある同じ名前の定義によって無効に (プリエンプト) されます。

PROTECTED

他のコンポーネントはシンボルを参照することができますが、別のコンポーネントにある同じ名前の定義によってプリエンプトすることはできません。

HIDDEN

他のコンポーネントはシンボルを直接参照することはできません。しかし、そのアドレスは間接的に (例えば、別のコンポーネントの関数への呼び出し引数として、または別のコンポーネントの関数でデータ項目参照にそのアドレスを格納して) 他のコンポーネントに渡すことができます。

INTERNAL

シンボルは、シンボルが定義されたコンポーネントの外部から直接的にも間接的にも参照することはできません。


可視性は参照と定義の両方に適用されます。シンボル参照の可視属性は、対応する定義にその可視属性が適用されるというアサーションです。

シンボル・プリエンプションと最適化

共有可能なオブジェクトの関数やデータ項目を使用するときに、それらの代わりに独自に定義したものを使用することができます。例えば、アプリケーションが標準のランタイム・ライブラリの共有可能なオブジェクト libc.so を使用するときに、独自のヒープ管理ルーチン malloc および free の定義を使用することができます。この場合、libc.so 内での malloc および free への呼び出しが、libc.so にある定義ではなく独自のルーチンの定義を呼び出すことが重要です。独自の定義は、共有可能なオブジェクト内の定義を無効に (プリエンプト) します。

このように共有オブジェクトの項目を再定義する機能は、シンボル・プリエンプションと呼ばれます。ランタイム・ローダがコンポーネントをロードするとき、コンポーネント内の default 可視属性のシンボルはすべて、既にロードされているコンポーネント内の同じ名前のシンボルによるプリエンプションに従います。ただし、メイン・プログラムのイメージは常に最初にロードされるので、メイン・プログラムが定義するシンボルがプリエンプト (つまり再定義) されることはありません。

default 可視属性のシンボルは実行時までメモリアドレスにバインドされないため、シンボル・プリエンプションが発生する可能性により多くのコンパイラの最適化は禁止されます。例えば、default 可視属性のルーチンへの呼び出しは、コンパイル単位が共有可能なオブジェクトにリンクされた場合にプリエンプトされるため、インライン展開することができません。プリエンプト可能なデータシンボルは、名前が異なるコンポーネント中のシンボルにバインドされるため、GP 相対アドレス指定を使用してアクセスすることはできません。GP 相対アドレスはコンパイル時にはわかりません。

シンボル・プリエンプションは、コンパイラの最適化と全く逆の効果であるため、ほとんど使用されていない機能です。この理由のため、コンパイラはすべてのグローバル・シンボル定義をデフォルトでプリエンプト可能ではない (つまり、protected 可視属性) として扱います 。別のコンパイル単位で定義されているシンボルへのグローバル参照は、デフォルトでプリエンプト可能である (つまり、default 可視属性) として仮定されます。すべてのグローバル定義や参照をプリエンプト可能にする場合は、-fpic オプションを指定してこのデフォルトを無視してください。

シンボルの可視属性の明示的な指定

インテル® Fortran コンパイラには可視属性オプションが備わっており、可視属性のコマンドライン制御、およびこれら属性の完全な範囲を設定するソース構文が提供されます。これらオプションにより、ヘッダファイルの変更に依存せずに、機能に直接アクセスできるようになります。可視オプションによって指定された可視属性が、すべてのグローバル・シンボルに適用されます。シンボルの可視属性を明示的に指定するには、次の 2 つのオプションを使用できます:

-fvisibility=keyword
-fvisibility-keyword=
file

最初の形式は、グローバル・シンボルのデフォルトの可視属性を指定します。2 番目の形式は、1 つのファイル内にあるシンボルの可視属性を指定します (この形式は最初の形式を上書きします)。

file は、可視属性を設定するシンボルの一覧が含まれたファイルのパス名を指定します。各シンボルは余白 (ブランク、タブ、または改行) で区切ります。

どちらのオプションとも keyword には externdefaultprotectedhidden、または internal を指定します。各キーワードについては上記の定義を参照してください。


可視属性を明示的に指定する際はどちらか 1 つの方法のみを使用してください。可視属性は宣言で使用するか、あるいは file 内のシンボル名を指定するかのどちらかにします。両方を同時に使用することはできません。

-fvisibility-keyword=file オプションでは、keyword に対する 5 つのコマンドライン・オプションのうちいずれかを使用して、複数のシンボルに同じ可視性を指定します:

-fvisibility-extern=file
-fvisibility-default=
file
-fvisibility-protected=
file
-fvisibility-hidden=
file
-fvisibility-internal=
file

file は、可視属性を設定するシンボル名のリストを含むファイルのパス名です。file ファイル中のシンボル名は、ブランク、タブ、または改行で区切ります 。例えば、次のコマンドライン・オプションを使用する場合の例を示します:

-fvisibility-protected=prot.txt

ここでは prot.txt というファイルに abcde というシンボルが含まれており、これら各シンボルに protected の可視属性が設定されます。 これは、各シンボルの宣言で visibility=protected という属性を指定した場合と同じです。

シンボルファイルを使用しない可視属性の設定 (-fvisibility=keyword)

このオプションは、可視属性リストファイルで指定がなく、宣言に visibilty 属性のないシンボルの可視属性を設定します。シンボル・ファイル・オプションが特に指定されない場合、指定した属性がすべてのシンボルに設定されます。コマンドラインの入力例を次に示します:

ifort -fvisibility=protected a.f

次のコマンドライン・オプションの 1 つを使用してシンボルのデフォルトの可視属性を設定することができます:

-fvisibility=extern
-fvisibility=default
-fvisibility=protected
-fvisibility=hidden  
-fvisibility=internal

上記のオプションは優先度順に記載されています。したがって、属性構文またはコマンドライン・オプションのどちらかを使用して可視属性を明示的に extern に設定した場合、defaultprotectedhidden、または internal の各設定を上書きします。また、可視属性を明示的に default に設定した場合には、protectedhidden、または internal の各設定を上書きします。

default の可視属性では、コンパイラがデフォルトのシンボル可視属性を変更して、デフォルトの設定を必要とする関数や変数のデフォルト属性を設定することが可能です。internal はプロセッサ固有の属性なので、この属性に一般的なオプションを使用することは好ましくありません。

次に、コマンドライン・オプションを 2 つ併用した例について検討します。

-fvisibility=protected -fvisibility-default=prot.txt

ここでは prot.txt というファイル (上記を参照) により、abcde を除くすべてのグローバル・シンボルに protected の可視属性が設定されます。しかし、これらの 5 つのシンボルの可視属性は default に設定されプリエンプト可能になります。

可視属性に関連するオプション

-fminshared

コンパイル単位をメイン・プログラムのコンポーネントとして処理し、共有可能オブジェクトの一部としてリンクしないように指示します。

メイン・プログラムで定義されたシンボルはプリエンプトできないため、これによりコンパイラは default 可視属性で宣言されたシンボルを protected 可視属性であるかのように扱います。つまり、-fminshared-fvisibility=protected を意味します。コンパイラは位置に依存しないコードをメイン・プログラム用に生成する必要はありません。グローバル・オフセット・テーブル (GOT) のサイズを減らしてメモリのトラフィックを減らす、絶対アドレス指定を使用することができます。

-fpic

完全なシンボル・プリエンプションを指定します。グローバル・シンボル定義は、明示的に他の方法で指定されなければ、グローバル・シンボル参照と同様に default 可視属性 (つまり、プリエンプト可能) になります。位置に依存しないコードを生成します。Itanium® ベース・システムでは、共有オブジェクトをビルドする必要があります。