Oracle Solaris Studio 12.4 Man Pages

印刷ビューの終了

更新: January 2015
 
 

filename.il(4)

名前

inline , filename.il - アセンブリ言語インラインテンプレートファイル

説明

アセンブリ言語の呼び出し命令は、インラインテンプレート (*.il) ファイルから取得した対応する関数本体のコピーによって置き換えられます。

インラインテンプレートファイルは、次の例のように接尾辞 .il を持ちます。

% CC foo.il hello.c

インライン化はコンパイラのコードジェネレータにより行われます。

使用法

inlinefile には、次の形式の 1 つまたは複数のラベル付きアセンブリ言語テンプレートが含まれています。

 
inline-directive
instructions
...
.end

ここで、instructions は、指定されたルーチンのインライン展開です。inline-directive は次の形式のコマンドです。

.inline   identifier, argsize

これは、identifier で指定したルーチンのコードのブロックを宣言し、ルーチンの引数の合計サイズ (バイト単位) として argsize を指定します。argsize の値は無視されます。

指定されたルーチンの呼び出しは、インラインテンプレート内のコードで置き換えられます。

注意: argsize の値は無視されますが、従来のコンパイラバージョンとの互換性を保つために含まれています。

複数のテンプレートが含まれていてもかまいません。一致するテンプレートのうち、最初のもの以外は無視されます。

コンパイラで本体を変更すれば、インラインテンプレートを最適化できます。テンプレートファイル内に命令 .volatile を含めると、このような最適化は禁止されます。

コーディング規則

インラインテンプレートは、C 互換の手続き呼び出しを展開した形式でコーディングする必要があります。ただし、呼び出し命令が実行されることはないので、戻りアドレスが予期された場所にないこともあります。

インラインテンプレートは、あとで詳しく述べるように、Oracle Solaris Studio の標準のパラメータの渡し方およびレジスタ使用法の規則に従う必要があります。このような慣習に違反したルーチンは呼び出さないでください。たとえば、setjmp(3c) などのアセンブリ言語のルーチンを呼び出すと、問題が発生する可能性があります。

下記のレジスタ以外のレジスタは、使用および設定してはいけません。

インラインテンプレート内の分岐命令は、インラインテンプレート内に定義した数値ラベル (1f2b など) にのみ制御を移すことができます。それ以外に制御を移すことは許可されません。

テンプレートには戻り命令は必要ないため、含めないようにしてください。

Oracle Solaris Studio コンパイラで生成したオペレーションコードおよびアドレッシングモードのみが、動作を保証されています。命令のバイナリエンコーディングは許可されていますが、生成されるコードの正確性は、残りのインラインテンプレートの正確性に依存します。バイナリエンコーディングでも、コンパイラによるテンプレートの最適化が禁止されています。

SPARC システムのコーディング規則

SPARC では、C 関数への引数は、パラメータ配列の場合と同様に渡されます。配列の要素は「スロット」と呼ばれます。スロットには 0 で始まる番号が割り当てられます。32 ビットコードでは、配列に 32 ビットの要素 (スロット) が含まれます。64 ビットコードでは、配列に 64 ビットの要素 (スロット) が含まれます。ルーチンへの後続のパラメータは、パラメータ配列の後続のスロットで渡されます。

32 ビットコードでは、パラメータ配列は %fp+68 で開始し、スタックポインタとフレームポインタは 64 ビット (8 バイト) 境界に整列されます。64 ビットコードでは、パラメータ配列は %fp+BIAS+128 で開始し、スタックポインタとフレームポインタは 128 ビット (16 バイト) 境界に整列されます。レジスタで渡されるパラメータには、それらのスロットに対応する (未使用の) メモリー位置も含まれます。

スロットサイズよりも大きいデータ型は、複数のスロットで渡されます。32 ビットコードでは、double および long long は 2 つのスロットで渡されます。境界整列は行われませんが、前のパラメータスロットの隣にパックされます。64 ビットコードでは、double および long long は 1 つのスロットしか占有しませんが、long double および double complex は 2 つのスロットを占有します。これらのスロットは境界整列され (slot # % 2 == 0)、境界整列で必要な場合はスロットをスキップします。

パラメータ配列の最初の 6 つのスロットは、レジスタで渡されます。32 ビットコードでは、これらのスロットは常にレジスタ %o0 - %o5 の下位 32 ビットに格納されます。

64 ビットコードでは、これらの 6 つのスロットは、整数型であればレジスタ %o0 - %o5 の 64 ビット全体に格納されます。float、double、long double の各型は、スロット 0 - 5 に対応する倍精度レジスタ %d0 - %d10 で渡されます。float complex、double complex、および long double complex の各型は、基底型のパラメータが 2 つしか存在しない場合と同様に渡されます。imaginary 型は、通常の float 型と同様に渡されます。64 ビットコードでは、スロット 6 - 31 の float、double、および long double はレジスタ %d12 - %d62 で渡されます。値によって渡される構造体および共用体は複雑になるため、インラインテンプレートで使用することはお勧めしません。

整数値を返す関数は、%o0 または %o0%o1 で値を返します。32 ビットコードでは、long long は %o0 の上位 32 ビットと %o1 の下位 32 ビットを使用して返されます。

浮動小数点数または複素数の値を返す関数は、%f0%f1%d0%d2%d4、および %d6 の一部のサブセットで値を返します。

レジスタ %o0-%o5 および %f0-%f31 は一時レジスタとして使用できます。

整数型および単精度浮動小数点型の引数は、32 ビットで整列されています。

倍精度浮動小数点型引数は、オフセットが 8 の倍数である場合、64 ビットで整列されていることが保証されています。

各制御移管命令 (分岐および呼び出し) は、直後に nop が必要です。

呼び出し命令は、パラメータを渡すのに使用するレジスタ数を、呼び出されたルーチンに示すための付加 (最終) 引数を持つ必要があります。

SPARC システムの場合は、展開された「呼び出し」のあとに続く命令は、削除されるので注意してください。

s86/x64 プラットフォームに関する注意

-xarchssesse2、sse2a、または sse3 以上に設定してコンパイルされたプログラムは、それらの拡張機能が備わったプラットフォームでのみ実行する必要があります。

この警告は、.il インラインアセンブリ言語の関数を採用しているプログラムや、拡張機能を使用している __asm() アセンブラコードにも当てはまります。

コンパイルとリンクを別々に行う場合は、必ずコンパイラを使ってリンクし、同じ -xarch 設定で正しい起動ルーチンがリンクされるようにしてください。

32 ビット x86 システムのコーディング規則

引数はスタックに積んで渡されます。呼び出し命令は実行されていないので、最初の引数は (%esp) の位置、2 つ目の引数は 4 (%esp) の位置、のように配置されます。32 ビット以下の整数型の結果は %eax で返され、64 ビットの整数型の結果は %edx:%eax で返されます。浮動小数点の結果は、%st(0) に格納して返されます。

コードでは、レジスタ %eax%ecx、および %edx を使用できます。その他のレジスタの値はすべて、保持する必要があります。浮動小数点スタックは、インライン展開テンプレートの先頭では空になっています。また、終わりでは空になっている必要があります (浮動小数点値の戻り値を除く)。

x64 プラットフォームのコーディング規則

引数は、その分類に従って渡されます。分類としては、整数型、sse 型、メモリー型引数などがあります。

符号付きか符号なしかを問わず、_Bool、char、short、int、long、long long、およびポインタ型の引数は、整数型の引数です。サイズが 16 バイト以下で、_Bool、char、short、int、long、long long、またはポインタ型の整列されたメンバーからなる集合体 (構造体、共用体、配列) 型の引数も整数型になります。

float および double 型の引数は、sse 型の引数です。サイズが 16 バイト以下で、float または double 型の整列されたメンバーからなる集合体型の引数も sse 型になります。

long double 型および、サイズが 16 バイトを超えるか、整列されていないメンバーからなる集合体型の引数は、メモリー型の引数です。

整数型引数は、%rdi、%rsi、%rdx、%rcx、%r8、%r9 の順序で整数レジスタで渡されます。集合体型の整数型引数は、1 つで整数レジスタを 2 つまで保持できます。整数型引数の個数が 6 個より多い場合、7 つ目以降の整数型引数はメモリー型引数と見なされます。

sse 型引数は、%xmm0 から %xmm7 の順序で sse レジスタで渡されます。集合体型の sse 型引数は、1 つで sse レジスタを 2 つまで保持でき、1 つの sse レジスタは最大 8 バイトの引数を保持できます。たとえば、double complex 型の引数は連続する 2 つの sse レジスタで渡され、float complex 型の引数は 1 つの sse レジスタで渡されます。sse 型引数の個数が 8 個より多い場合、9 つ目以降の sse 型引数はメモリー型引数と見なされます。

整数型および sse 型引数には、個別に番号が割り当てられます。

メモリー型引数は、関数引数リストで見て右から左の順に、スタックに積んで渡されます。スタック上の各引数は、そのサイズに従って、サイズが 8 以下の場合は 8、それ以外の場合は 16 で整列されます。インライン展開テンプレートの先頭ではスタックは 16 で整列されます。

呼び出し命令は実行されていないので、最初のメモリー型引数は (%rsp) の位置に配置され、2 つ目の引数は、最初のメモリー型引数のサイズと 2 つ目のメモリー引数型の境界整列などに従って、8(%rsp) または 16(%rsp) の位置に配置されます。

戻り値は、引数と同様に分類されます。

8 バイト以下の整数型の結果は %rax で返され、9 - 16 バイトの整数型の結果は %rdx:%rax で返されます。

sse 型の結果もまた、そのサイズに従って %xmm0 または %xmm1:%xmm0 で返されます。

long double 型の結果は %st(0) で返されます。

戻り値が long double complex 型の場合、値の実部は %st0、虚部は %st1 で返されます。

メモリー型の結果の場合、呼び出し元は戻り値用のストレージ領域を提供し、関数の最初の引数であるかのように、このストレージ領域のアドレスを %rdi で渡します。実質的に、このアドレスは隠れた最初の引数になります。復帰時、%rax には、呼び出し元によって %rdi で渡されたアドレスが含まれます。

コードでレジスタ %rbp を変更してはいけません。浮動小数点スタックは、インライン展開テンプレートの先頭では空になっています。また、終わりでは空になっている必要があります (浮動小数点値の戻り値を除く)。

%rbp に加えて、レジスタ %rbx および %r12 - %r15 の値も、インライン化されたコード全体で維持される必要があります。

例については、libm.il または vis.il を参照してください。コンパイラの lib/ ディレクトリの下に、サポートされた各アーキテクチャーに固有のこれらのライブラリのバージョンが見つかります。

関連項目

Darryl Gove 著『Solaris Application Programming』(Prentice-Hall 2008 ISBN: 0138134553)

SPARC International Inc. (http://www.sparc.org/specificationsDocuments.html) から提供されている『The SPARC Architecture Manual Version 9』