引数が関数へ渡される方法や関数から値が返される方法について規則を規定する多くの呼び出し規約があります。
次の表は、Windows* でサポートされている呼び出し規約をまとめたものです。
呼び出し規約 |
コンパイラー・オプション |
説明 |
---|---|---|
__cdecl |
/Gd |
C/C++/DPC++ プログラムのデフォルトの呼び出し規約。変数引数を使用する関数で指定できます。 |
__stdcall |
/Gz |
Win32 API 関数に使用される標準呼び出し規約です。 これは C++ 固有のコンテンツです。DPC++ には適用されません。 |
__fastcall |
/Gr |
引数がスタックではなく、レジスターで渡されるように指定する高速な呼び出し規約です。 これは C++ 固有のコンテンツです。DPC++ には適用されません。 |
__regcall |
/Qregcall は、宣言で別の呼び出し規約が指定されない限り、コンパイル時に __regcall が関数のデフォルトの呼び出し規約であることを指定します。 |
インテル® oneAPI DPC++/C++ コンパイラーの呼び出し規約で、レジスターでできる限り多くの引数を渡せるように指定します。同様に、__regcall は値を返す際、可能な限りレジスターを使用します。この呼び出し規約は、変数引数を使用する関数で指定された場合は無視されます。 インテル互換のベクトル関数 ABI の詳細については、「Vector Function Application Binary Interface」 (英語、PDF) を参照してください。 GCC ベクトル関数 ABI の詳細については、sourceware.org (英語) の GLIBC wiki にある Libmvec - vector math library ドキュメントを参照してください。 |
__thiscall |
なし |
変数引数を使用しない C++ メンバー関数により使用されるデフォルトの呼び出し規約です。 |
__vectorcall |
/Gv |
ベクトル引数を渡す関数がベクトルレジスターを使用するように指定する呼び出し規約です。 |
次の表は、Linux* でサポートされている呼び出し規約をまとめたものです。
呼び出し規約 |
コンパイラー・オプション |
説明 |
---|---|---|
__attribute((cdecl)) |
なし |
C/C++/DPC++ プログラムのデフォルトの呼び出し規約。変数引数を使用する関数で指定できます。 |
__attribute((stdcall)) |
なし |
引数がスタックで渡されるように指定する呼び出し規約です。変数引数を使用する関数では指定できません。 |
__attribute((regparm (number))) |
なし |
IA-32 アーキテクチャー・ベースのシステムでは regparm 属性により、コンパイラーは最大 number で指定される個数の引数をスタックではなく、EAX、 EDX、 ECX レジスターで渡します。可変長引数をとる関数は、引き続きスタック上ですべての引数を渡します。 |
__attribute__((regcall)) |
-regcall は、宣言で別の呼び出し規約が指定されない限り、コンパイル時に __regcall が関数のデフォルトの呼び出し規約であることを指定します。 |
インテル® oneAPI DPC++/C++ コンパイラーの呼び出し規約で、レジスターでできる限り多くの引数を渡せるように指定します。同様に、__regcall は値を返す際、可能な限りレジスターを使用します。この呼び出し規約は、変数引数を使用する関数で指定された場合は無視されます。 |
__attribute__((vectorcall)) |
なし |
ベクトル引数を渡す関数がベクトルレジスターを使用するように指定する呼び出し規約です。 |
__regcall 呼び出し規約はインテル® oneAPI DPC++/C++ コンパイラー特有のものです。次の点に注意してください。
__regcall を使用するには、関数の宣言の前にキーワードを配置してください。次に例を示します。
例 |
---|
__regcall int foo (int i, int j); |
// Linux* __attribute__((regcall)) foo (int I, int j); |
__regcall のすべてのレジスターは、コンパイラーにより予約されているレジスターを除き、引数の引き渡し/値の返しに使用できます。次の表は、コンパイルのデフォルト ABI に応じた各レジスタークラスで利用可能なレジスターです。レジスターは表にリストされた順番で使用されます。
これは C++ 固有のコンテンツです。DPC++ には適用されません。
レジスタークラス/アーキテクチャー |
Linux* IA-32 |
Windows* IA-32 |
Linux* インテル® 64 |
Windows* インテル® 64 |
---|---|---|---|---|
GPR |
EAX、ECX、EDX、EDI、ESI |
ECX、EDX、EDI、ESI |
RAX、RCX、RDX、RDI、RSI、R8、R9、R10、R11、R12、R14、R15 |
RAX、RCX、RDX、RDI、RSI、R8、R9、R11、R12、R14、R15 |
FP |
ST0 |
ST0 |
ST0 |
ST0 |
MMX |
なし |
なし |
なし |
なし |
XMM |
XMM0 - XMM7 |
XMM0 - XMM7 |
XMM0 - XMM15 |
XMM0 - XMM15 |
YMM |
YMM0 - YMM7 |
YMM0 - YMM7 |
YMM0 - YMM15 |
YMM0 - YMM15 |
ZMM |
ZMM0 - ZMM7 |
ZMM0 - ZMM7 |
ZMM0 - YMM15 |
ZMM0 - YMM15 |
これは DPC++ 固有のコンテンツです。
レジスタークラス/アーキテクチャー |
Linux* インテル® 64 |
Windows* インテル® 64 |
---|---|---|
GPR |
RAX、RCX、RDX、RDI、RSI、R8、R9、R10、R11、R12、R14、R15 |
RAX、RCX、RDX、RDI、RSI、R8、R9、R11、R12、R14、R15 |
FP |
ST0 |
ST0 |
MMX |
なし |
なし |
XMM |
XMM0 - XMM15 |
XMM0 - XMM15 |
YMM |
YMM0 - YMM15 |
YMM0 - YMM15 |
ZMM |
ZMM0 - YMM15 |
ZMM0 - YMM15 |
__regcall の引数や戻り値はデータ型に基づいて分類され、次の表にあるように、そのクラスのレジスターで渡されます。
これは C++ 固有のコンテンツです。DPC++ には適用されません。
型 (符号なし/符号付きの両方の型) |
IA-32 アーキテクチャー |
インテル® 64 アーキテクチャー |
---|---|---|
bool、char、int、enum、_Decimal32、long、pointer |
GPR |
GPR |
short、__mmask{8,16,32,64} |
GPR |
GPR |
long long、__int64 |
「構造体の分類規則」を参照してください。 |
GPR |
_Decimal64 |
XMM |
GPR |
long double |
FP |
FP |
float、double、float128、_Decimal128 |
XMM |
XMM |
__m128、__m128i、__m128d |
XMM |
XMM |
__m256、__m256i、__m256d |
YMM |
YMM |
__m512、__m512i、__m512d |
ZMM |
ZMM |
complex type、struct、union |
「構造体の分類規則」を参照してください。 |
「構造体の分類規則」を参照してください。 |
注構造体には、GPR クラスの分類が使用されます。 |
||
注IA-32 アーキテクチャー・ベースのシステムでは、これらの 64 ビット整数型 (long long, __int64) は、2 つの 32 ビット整数フィールドから成る構造体として実装されているかのように、GPR クラスに分類され、2 個のレジスターで渡されます。 |
これは DPC++ 固有のコンテンツです。
型 (符号なし/符号付きの両方の型) |
インテル® 64 アーキテクチャー |
---|---|
bool、char、int、enum、_Decimal32、long、pointer |
GPR |
short、__mmask{8,16,32,64} |
GPR |
long long、__int64 |
GPR |
_Decimal64 |
GPR |
long double |
FP |
float、double、float128、_Decimal128 |
XMM |
__m128、__m128i、__m128d |
XMM |
__m256、__m256i、__m256d |
YMM |
__m512、__m512i、__m512d |
ZMM |
complex type、struct、union |
「構造体の分類規則」を参照してください。 |
注構造体には、GPR クラスの分類が使用されます。 |
関連クラスのレジスターよりもレジスターのサイズが小さい型は、下位のレジスターで渡されます。例えば、float は XMM レジスターの下位 4 バイトで渡されます。
構造体/共用体および複素数型は、次の例外を除いて x86_64 ABI と同じように分類されます。
構造体の全体のサイズの制限はありません。
基本型のレジスタークラスは「データ型の分類」を参照してください。
IA-32 アーキテクチャー・ベースのシステムの場合、4 バイトで分類されます。その他のアーキテクチャー・ベースのシステムの場合、8 バイトで分類されます。
8 バイトで分類されます。
「データ型の分類」と「構造体の分類規則」で説明されている分類の後、__regcall 引数と戻り値は利用可能なレジスターで指定されたレジスターに配置されるか、または次の説明に従ってメモリーに配置されます。
データ型の値の各チャンクにレジスタークラスが割り当てられます。各チャンクは、インテル® 64 アーキテクチャー・ベースのシステムの場合は 8 バイト、IA-32 アーキテクチャー・ベースのシステムの場合は 4 バイトです (IA-32 は C++ のみ)。利用可能なレジスターからレジスターを十分利用できる場合には、値全体がレジスターに渡されます。そうでない場合は、値はスタックを使用して渡されます。
1 つまたは複数のレジスタークラスが使用される場合、利用可能なレジスターの表のこれらのクラスのレジスターが表の順番のとおりに使用されます。
必要なレジスタークラスのいずれかで利用可能なレジスターがない場合は、値全体がスタックに配置されます。
次のレジスターは、引数渡しや値の戻しで使用されない限り、__regcall 呼び出し間でその値を保持します。
これは C++ 固有のコンテンツです。DPC++ には適用されません。
レジスタークラス/ABI |
IA-32 アーキテクチャー |
Linux* インテル® 64 |
Windows* インテル® 64 |
---|---|---|---|
GPR |
ESI、EDI、EBX、EBP、ESP |
R12 - R15、RBX、RBP、RSP |
R12 - R15、RBX、RBP、RSP |
FP |
なし |
なし |
なし |
MMX |
なし |
なし |
なし |
XMM |
XMM4 - XMM7 |
XMM8 - XMM15 |
XMM8 - XMM15 |
YMM |
XMM4 - XMM7 |
XMM8 - XMM15 |
XMM8 - XMM15 |
ZMM |
XMM4 - XMM7 |
XMM8 - XMM15 |
XMM8 - XMM15 |
これは DPC++ 固有のコンテンツです。
レジスタークラス/ABI |
Linux* インテル® 64 |
Windows* インテル® 64 |
---|---|---|
GPR |
R12 - R15、RBX、RBP、RSP |
R12 - R15、RBX、RBP、RSP |
FP |
なし |
なし |
MMX |
なし |
なし |
XMM |
XMM8 - XMM15 |
XMM8 - XMM15 |
YMM |
XMM8 - XMM15 |
XMM8 - XMM15 |
ZMM |
XMM8 - XMM15 |
XMM8 - XMM15 |
その他のレジスターでは、この呼び出しで値は保持されません。