__vectorcall__vectorcall

Microsoft 固有の仕様Microsoft Specific

_ _Vectorcall呼び出し規約は、関数の引数には、可能であればレジスタで渡されることを指定します。The __vectorcall calling convention specifies that arguments to functions are to be passed in registers, when possible. _ _vectorcallの引数よりも多くレジスタを使用して_ _fastcallまたは既定x64 呼び出し規則を使用します。__vectorcall uses more registers for arguments than __fastcall or the default x64 calling convention use. _ _Vectorcall呼び出し規約がストリーミング SIMD 拡張命令 2 (SSE2) を含む x86 および x64 プロセッサ上のネイティブ コードでサポートされているだけです。The __vectorcall calling convention is only supported in native code on x86 and x64 processors that include Streaming SIMD Extensions 2 (SSE2) and above. 使用 _ _vectorcallレジスタに読み込まれる関数を渡す複数の浮動小数点または SIMD ベクターの引数を高速化し、引数を利用する操作を実行します。Use __vectorcall to speed functions that pass several floating-point or SIMD vector arguments and perform operations that take advantage of the arguments loaded in registers. 次の一覧の x86 と x64 の実装に共通する機能を示しています。 _ _vectorcallします。The following list shows the features that are common to the x86 and x64 implementations of __vectorcall. 相違点については、このトピックで後ほど説明します。The differences are explained later in this article.

要素Element 実装Implementation
C の名前装飾規約C name-decoration convention 「アット」2 つの関数名が付加されたもの (@@) 後に (10 進数) のパラメーター リスト内のバイト数。Function names are suffixed with two "at" signs (@@) followed by the number of bytes (in decimal) in the parameter list.
大文字と小文字の変換規約Case-translation convention 大文字小文字は変換されません。No case translation is performed.

使用して、 /Gvコンパイラ オプションでは、各関数を原因としてコンパイルするモジュールで _ _vectorcall関数は、メンバー関数でない限り、競合する呼び出し規約の属性で宣言されて、使用vararg可変個引数リストでは、名前またはmainします。Using the /Gv compiler option causes each function in the module to compile as __vectorcall unless the function is a member function, is declared with a conflicting calling convention attribute, uses a vararg variable argument list, or has the name main.

レジスタによって 3 種類の引数を渡すことができます _ _vectorcall関数:整数型値、ベクター型値、および同種のベクター集計(HVA) の値。You can pass three kinds of arguments by register in __vectorcall functions: integer type values, vector type values, and homogeneous vector aggregate (HVA) values.

整数型は、2 つの条件を満たしています。まずプロセッサのネイティブなレジスタ サイズ (たとえば、x86 コンピューターでは 4 バイト、x64 コンピューターでは 8 バイト) に収まります。また、そのビット表現を変更せずにレジスタ長の整数値に変換し、再度元に戻すことができます。An integer type satisfies two requirements: it fits in the native register size of the processor—for example, 4 bytes on an x86 machine or 8 bytes on an x64 machine—and it’s convertible to an integer of register length and back again without changing its bit representation. 昇格できる任意の種類などint x86 (long x64)-など、 charまたは短い— にキャストできるかint (long x64) と含まない変更は、整数型は、元の型にバックアップします。For example, any type that can be promoted to int on x86 (long long on x64)—for example, a char or short—or that can be cast to int (long long on x64) and back to its original type without change is an integer type. 整数型は、ポインター、参照、および構造体または共用体(x64 では 8 バイト) の 4 バイトの種類またはそれ以下。Integer types include pointer, reference, and struct or union types of 4 bytes (8 bytes on x64) or less. X64 プラットフォームより大きな構造体共用体型は、呼び出し元によっては、x86 上で割り当てられたメモリへの参照によって渡されるプラットフォームでは、渡される値によって、スタックにします。On x64 platforms, larger struct and union types are passed by reference to memory allocated by the caller; on x86 platforms, they are passed by value on the stack.

ベクター型は、いずれかの浮動小数点型-など、 floatまたは二重: または SIMD ベクター型-たとえば、 _ _m128または __m256.A vector type is either a floating-point type—for example, a float or double—or an SIMD vector type—for example, __m128 or __m256.

HVA 型は、同一のベクター型を持つ最大 4 個のデータ メンバーから成る複合型です。An HVA type is a composite type of up to four data members that have identical vector types. HVA 型のアラインメント要件は、そのメンバーのベクター型のアラインメント要件と同じになります。An HVA type has the same alignment requirement as the vector type of its members. これは、HVA の例構造体の定義を 32 バイト アラインメントを持つ 3 つの同一のベクター型が含まれています。This is an example of an HVA struct definition that contains three identical vector types and has 32-byte alignment:

typedef struct {
   __m256 x;
   __m256 y;
   __m256 z;
} hva3;    // 3 element HVA type on __m256

関数を使用して明示的に宣言、 _ _vectorcall個別にヘッダー ファイル内のキーワードがエラーなしでリンクするためのコードをコンパイルします。Declare your functions explicitly with the __vectorcall keyword in header files to allow separately compiled code to link without errors. 関数を使用するようにプロトタイプ宣言する必要があります _ _vectorcallと使用できない、vararg可変長引数リスト。Functions must be prototyped to use __vectorcall, and can’t use a vararg variable length argument list.

使用してメンバー関数を宣言すること、 _ _vectorcall指定子。A member function may be declared by using the __vectorcall specifier. 非表示このポインターは、最初の整数型引数としてレジスタで渡されます。The hidden this pointer is passed by register as the first integer type argument.

ARM マシンで _ _vectorcallが受け入れられるし、コンパイラによって無視されます。On ARM machines, __vectorcall is accepted and ignored by the compiler.

静的でないクラスのメンバー関数が行外で宣言されている場合、行外の宣言で呼び出し規則の修飾子を指定する必要はありません。For non-static class member functions, if the function is defined out-of-line, the calling convention modifier does not have to be specified on the out-of-line definition. つまり、クラスの非静的なメンバーの場合は、宣言時に指定された呼び出し規則が定義の時点で仮定されます。That is, for class non-static members, the calling convention specified during declaration is assumed at the point of definition. 次のクラス定義があるとします。Given this class definition:

struct MyClass {
   void __vectorcall mymethod();
};

ここで、this:

void MyClass::mymethod() { return; }

は次の記述と同じです。is equivalent to this:

void __vectorcall MyClass::mymethod() { return; }

_ _Vectorcall呼び出し規約を指定するくださいとへのポインターを _ _vectorcall関数が作成されます。The __vectorcall calling convention modifier must be specified when a pointer to a __vectorcall function is created. 次の例では、作成、 typedefへのポインターの _ _vectorcall関数を受け取る 4 つ二重引数を返す、 __m256値。The next example creates a typedef for a pointer to a __vectorcall function that takes four double arguments and returns an __m256 value:

typedef __m256 (__vectorcall * vcfnptr)(double, double, double, double);

以前のバージョンとの互換性のため _vectorcallのシノニムです _ _vectorcallしない限り、コンパイラ オプション/Za(言語拡張機能を無効にする)を指定します。For compatibility with previous versions, _vectorcall is a synonym for __vectorcall unless compiler option /Za (Disable language extensions) is specified.

x64 での __vectorcall 規約__vectorcall convention on x64

_ _Vectorcall x64 呼び出し規則、標準の x64 呼び出し規則の追加のレジスタを利用するを拡張します。The __vectorcall calling convention on x64 extends the standard x64 calling convention to take advantage of additional registers. 整数型引数とベクター型引数の両方が、引数リスト内の位置に基づいてレジスタにマップされます。Both integer type arguments and vector type arguments are mapped to registers based on position in the argument list. HVA 引数は、未使用のベクター レジスタに割り当てられます。HVA arguments are allocated to unused vector registers.

最初の 4 個の引数がすべて整数型引数の場合、それらの引数は左から順にその位置に対応するレジスタ (RCX、RDX、R8、R9) に渡されます。When any of the first four arguments in order from left to right are integer type arguments, they are passed in the register that corresponds to that position—RCX, RDX, R8, or R9. 非表示このポインターは、最初の整数型引数として扱われます。A hidden this pointer is treated as the first integer type argument. 最初の 4 個の引数のうちの 1 個が HVA 引数であって、使用可能なレジスタに渡すことができない場合は、その代わりに、呼び出し元が割り当てたメモリへの参照が、その引数に対応する整数型のレジスタに渡されます。When an HVA argument in one of the first four arguments can’t be passed in the available registers, a reference to caller-allocated memory is passed in the corresponding integer type register instead. 5 番目以降のパラメーター位置にある整数型引数は、スタックに渡されます。Integer type arguments after the fourth parameter position are passed on the stack.

最初の 6 個の引数がすべてベクター型引数の場合、それらの引数はその位置に従って、左から順に SSE ベクター レジスタの 0 ~ 5 に値で渡されます。When any of the first six arguments in order from left to right are vector type arguments, they are passed by value in SSE vector registers 0 to 5 according to argument position. 浮動小数点と _ _m128型は渡される XMM レジスタと __m256型は YMM で渡されるを登録します。Floating-point and __m128 types are passed in XMM registers, and __m256 types are passed in YMM registers. この点は標準の x64 呼び出し規約と異なり、ベクター型が参照渡しではなく値渡しされ、追加のレジスタが使用されます。This differs from the standard x64 calling convention, because the vector types are passed by value instead of by reference, and additional registers are used. ベクター型引数に割り当てられるシャドウ スタック領域は 8 バイトに固定と/homeparamsオプションは適用されません。The shadow stack space allocated for vector type arguments is fixed at 8 bytes, and the /homeparams option does not apply. 7 番目以降のパラメーター位置にあるベクター型引数は、呼び出し元が割り当てられたメモリへの参照によってスタックに渡されます。Vector type arguments in the seventh and later parameter positions are passed on the stack by reference to memory allocated by the caller.

未使用のベクター レジスタの XMM0 ~ XMM5 の昇順で HVA 引数のデータ メンバーを割り当てられたベクター引数にレジスタが割り当てられた後、(または YMM0 ~ YMM5 の __m256型)、十分なレジスタがある限り、HVA 全体を使用できます。After registers are allocated for vector arguments, the data members of HVA arguments are allocated, in ascending order, to unused vector registers XMM0 to XMM5 (or YMM0 to YMM5, for __m256 types), as long as there are enough registers available for the entire HVA. 十分なレジスタが使用できない場合、HVA 引数は、呼び出し元が割り当てたメモリへの参照によって渡されます。If not enough registers are available, the HVA argument is passed by reference to memory allocated by the caller. HVA 引数用のスタック シャドウ領域は 8 バイトに固定され、内容は未定義です。The stack shadow space for an HVA argument is fixed at 8 bytes with undefined content. HVA の引数は、パラメーター リストの左から順にレジスタに割り当てられますが、任意の位置に割り当てることもできます。HVA arguments are assigned to registers in order from left to right in the parameter list, and may be in any position. 最初の 4 個の引数位置のいずれかに、ベクター レジスタに割り当てられていない HVA 引数がある場合、その位置に対応する整数レジスタに参照によって渡されます。HVA arguments in one of the first four argument positions that are not assigned to vector registers are passed by reference in the integer register that corresponds to that position. 5 番目以降のパラメーター位置にあり、参照によって渡された HVA 引数はスタックにプッシュされます。HVA arguments passed by reference after the fourth parameter position are pushed on the stack.

結果の _ _vectorcall可能であればレジスタの値によって関数が返されます。Results of __vectorcall functions are returned by value in registers when possible. 8 バイト以下の構造体や共用体を含む整数型の結果は、値によって RAX に返されます。Results of integer type, including structs or unions of 8 bytes or less, are returned by value in RAX. ベクター型の結果は、サイズに応じて XMM0 または YMM0 に値によって返されます。Vector type results are returned by value in XMM0 or YMM0, depending on size. HVA の結果は、要素のサイズに応じて、各データ要素がレジスタ XMM0:XMM3 またはレジスタ YMM0:YMM3 に値によって返されます。HVA results have each data element returned by value in registers XMM0:XMM3 or YMM0:YMM3, depending on element size. 対応するレジスタに収まらない結果の型は、呼び出し元が割り当てたメモリへの参照によって返されます。Result types that don't fit in the corresponding registers are returned by reference to memory allocated by the caller.

スタックは、x64、呼び出し元によって保持の実装 _ _vectorcallします。The stack is maintained by the caller in the x64 implementation of __vectorcall. 呼び出された関数のためのスタックは、呼び出し元のプロローグ コードとエピローグ コードによって割り当てられ、クリアされます。The caller prolog and epilog code allocates and clears the stack for the called function. 引数はスタックで右から左へプッシュされます。レジスタに渡された引数には、シャドウ スタック領域が割り当てられます。Arguments are pushed on the stack from right to left, and shadow stack space is allocated for arguments passed in registers.

次に例を示します。 Examples:

// crt_vc64.c
// Build for amd64 with: cl /arch:AVX /W3 /FAs crt_vc64.c
// This example creates an annotated assembly listing in
// crt_vc64.asm.

#include <intrin.h>
#include <xmmintrin.h>

typedef struct {
   __m128 array[2];
} hva2;    // 2 element HVA type on __m128

typedef struct {
   __m256 array[4];
} hva4;    // 4 element HVA type on __m256

// Example 1: All vectors
// Passes a in XMM0, b in XMM1, c in YMM2, d in XMM3, e in YMM4.
// Return value in XMM0.
__m128 __vectorcall
example1(__m128 a, __m128 b, __m256 c, __m128 d, __m256 e) {
   return d;
}

// Example 2: Mixed int, float and vector parameters
// Passes a in RCX, b in XMM1, c in R8, d in XMM3, e in YMM4,
// f in XMM5, g pushed on stack.
// Return value in YMM0.
__m256 __vectorcall
example2(int a, __m128 b, int c, __m128 d, __m256 e, float f, int g) {
   return e;
}

// Example 3: Mixed int and HVA parameters
// Passes a in RCX, c in R8, d in R9, and e pushed on stack.
// Passes b by element in [XMM0:XMM1];
// b's stack shadow area is 8-bytes of undefined value.
// Return value in XMM0.
__m128 __vectorcall example3(int a, hva2 b, int c, int d, int e) {
   return b.array[0];
}

// Example 4: Discontiguous HVA
// Passes a in RCX, b in XMM1, d in XMM3, and e is pushed on stack.
// Passes c by element in [YMM0,YMM2,YMM4,YMM5], discontiguous because
// vector arguments b and d were allocated first.
// Shadow area for c is an 8-byte undefined value.
// Return value in XMM0.
float __vectorcall example4(int a, float b, hva4 c, __m128 d, int e) {
   return b;
}

// Example 5: Multiple HVA arguments
// Passes a in RCX, c in R8, e pushed on stack.
// Passes b in [XMM0:XMM1], d in [YMM2:YMM5], each with
// stack shadow areas of an 8-byte undefined value.
// Return value in RAX.
int __vectorcall example5(int a, hva2 b, int c, hva4 d, int e) {
   return c + e;
}

// Example 6: HVA argument passed by reference, returned by register
// Passes a in [XMM0:XMM1], b passed by reference in RDX, c in YMM2,
// d in [XMM3:XMM4].
// Register space was insufficient for b, but not for d.
// Return value in [YMM0:YMM3].
hva4 __vectorcall example6(hva2 a, hva4 b, __m256 c, hva2 d) {
   return b;
}

int __cdecl main( void )
{
   hva4 h4;
   hva2 h2;
   int i;
   float f;
   __m128 a, b, d;
   __m256 c, e;

   a = b = d = _mm_set1_ps(3.0f);
   c = e = _mm256_set1_ps(5.0f);
   h2.array[0] = _mm_set1_ps(6.0f);
   h4.array[0] = _mm256_set1_ps(7.0f);

   b = example1(a, b, c, d, e);
   e = example2(1, b, 3, d, e, 6.0f, 7);
   d = example3(1, h2, 3, 4, 5);
   f = example4(1, 2.0f, h4, d, 5);
   i = example5(1, h2, 3, h4, 5);
   h4 = example6(h2, h4, c, h2);
}

x86 での __vectorcall 規約__vectorcall convention on x86

_ _Vectorcall呼び出し規約次のように、 _ _fastcallの 32 ビット整数型の引数とベクター型と HVA 引数に対して SSE ベクター レジスタを利用規則。The __vectorcall calling convention follows the __fastcall convention for 32-bit integer type arguments, and takes advantage of the SSE vector registers for vector type and HVA arguments.

パラメーター リストの最初の 2 個の整数型引数は、左から順にそれぞれ ECX と EDX に配置されます。The first two integer type arguments found in the parameter list from left to right are placed in ECX and EDX, respectively. 非表示このポインターは、最初の整数型引数として扱われ、ECX に渡されます。A hidden this pointer is treated as the first integer type argument, and is passed in ECX. 最初の 6 個のベクター型引数は、SSE ベクター レジスタ 0 ~ 5 を介し、引数のサイズに応じて YMM または XMM レジスタに値によって渡されます。The first six vector type arguments are passed by value through SSE vector registers 0 to 5, in the XMM or YMM registers, depending on argument size.

最初の 6 個のベクター型引数は、左から順に SSE ベクター レジスタの 0 ~ 5 に値で渡されます。The first six vector type arguments in order from left to right are passed by value in SSE vector registers 0 to 5. 浮動小数点と _ _m128型は渡される XMM レジスタと __m256型は YMM で渡されるを登録します。Floating-point and __m128 types are passed in XMM registers, and __m256 types are passed in YMM registers. シャドウ スタック領域は、レジスタで渡されるベクター型引数に対して割り当てられます。No shadow stack space is allocated for vector type arguments passed by register. 7 番目以降のベクター型引数は、呼び出し元が割り当てられたメモリへの参照によってスタックに渡されます。The seventh and subsequent vector type arguments are passed on the stack by reference to memory allocated by the caller. コンパイラ エラーの制限C2719これらの引数には適用されません。The limitation of compiler error C2719 does not apply to these arguments.

レジスタの XMM0 ~ XMM5 を HVA 引数のメンバーが未使用のベクターの昇順で割り当てられているデータ ベクター引数にレジスタが割り当てられた後、(または YMM0 ~ YMM5 の __m256型)、十分なレジスタがある限り、HVA 全体を使用できます。After registers are allocated for vector arguments, the data members of HVA arguments are allocated in ascending order to unused vector registers XMM0 to XMM5 (or YMM0 to YMM5, for __m256 types), as long as there are enough registers available for the entire HVA. 十分なレジスタが使用できない場合、HVA 引数は、呼び出し元が割り当てたメモリへの参照によってスタックに渡されます。If not enough registers are available, the HVA argument is passed on the stack by reference to memory allocated by the caller. HVA 引数には、スタック シャドウ領域は割り当てられません。No stack shadow space for an HVA argument is allocated. HVA の引数は、パラメーター リストの左から順にレジスタに割り当てられますが、任意の位置に割り当てることもできます。HVA arguments are assigned to registers in order from left to right in the parameter list, and may be in any position.

結果の _ _vectorcall可能であればレジスタの値によって関数が返されます。Results of __vectorcall functions are returned by value in registers when possible. 4 バイト以下の構造体や共用体を含む整数型の結果は、値によって EAX に返されます。Results of integer type, including structs or unions of 4 bytes or less, are returned by value in EAX. 8 バイト以下の整数型の構造体や共用体は、値によって EDX:EAX に返されます。Integer type structs or unions of 8 bytes or less are returned by value in EDX:EAX. ベクター型の結果は、サイズに応じて XMM0 または YMM0 に値によって返されます。Vector type results are returned by value in XMM0 or YMM0, depending on size. HVA の結果は、要素のサイズに応じて、各データ要素がレジスタ XMM0:XMM3 またはレジスタ YMM0:YMM3 に値によって返されます。HVA results have each data element returned by value in registers XMM0:XMM3 or YMM0:YMM3, depending on element size. 他の結果の型は、呼び出し元が割り当てたメモリへの参照によって返されます。Other result types are returned by reference to memory allocated by the caller.

X86 の実装 _ _vectorcall次のように、呼び出し元と、呼び出された関数で、右から左にスタックにプッシュする引数の規約スタックを消去戻る直前。The x86 implementation of __vectorcall follows the convention of arguments pushed on the stack from right to left by the caller, and the called function clears the stack just before it returns. スタックには、レジスタに配置されていない引数のみがプッシュされます。Only arguments that are not placed in registers are pushed on the stack.

次に例を示します。 Examples:

// crt_vc86.c
// Build for x86 with: cl /arch:AVX /W3 /FAs crt_vc86.c
// This example creates an annotated assembly listing in
// crt_vc86.asm.

#include <intrin.h>
#include <xmmintrin.h>

typedef struct {
   __m128 array[2];
} hva2;    // 2 element HVA type on __m128

typedef struct {
   __m256 array[4];
} hva4;    // 4 element HVA type on __m256

// Example 1: All vectors
// Passes a in XMM0, b in XMM1, c in YMM2, d in XMM3, e in YMM4.
// Return value in XMM0.
__m128 __vectorcall
example1(__m128 a, __m128 b, __m256 c, __m128 d, __m256 e) {
   return d;
}

// Example 2: Mixed int, float and vector parameters
// Passes a in ECX, b in XMM0, c in EDX, d in XMM1, e in YMM2,
// f in XMM3, g pushed on stack.
// Return value in YMM0.
__m256 __vectorcall
example2(int a, __m128 b, int c, __m128 d, __m256 e, float f, int g) {
   return e;
}

// Example 3: Mixed int and HVA parameters
// Passes a in ECX, c in EDX, d and e pushed on stack.
// Passes b by element in [XMM0:XMM1].
// Return value in XMM0.
__m128 __vectorcall example3(int a, hva2 b, int c, int d, int e) {
   return b.array[0];
}

// Example 4: HVA assigned after vector types
// Passes a in ECX, b in XMM0, d in XMM1, and e in EDX.
// Passes c by element in [YMM2:YMM5].
// Return value in XMM0.
float __vectorcall example4(int a, float b, hva4 c, __m128 d, int e) {
   return b;
}

// Example 5: Multiple HVA arguments
// Passes a in ECX, c in EDX, e pushed on stack.
// Passes b in [XMM0:XMM1], d in [YMM2:YMM5].
// Return value in EAX.
int __vectorcall example5(int a, hva2 b, int c, hva4 d, int e) {
   return c + e;
}

// Example 6: HVA argument passed by reference, returned by register
// Passes a in [XMM1:XMM2], b passed by reference in ECX, c in YMM0,
// d in [XMM3:XMM4].
// Register space was insufficient for b, but not for d.
// Return value in [YMM0:YMM3].
hva4 __vectorcall example6(hva2 a, hva4 b, __m256 c, hva2 d) {
   return b;
}

int __cdecl main( void )
{
   hva4 h4;
   hva2 h2;
   int i;
   float f;
   __m128 a, b, d;
   __m256 c, e;

   a = b = d = _mm_set1_ps(3.0f);
   c = e = _mm256_set1_ps(5.0f);
   h2.array[0] = _mm_set1_ps(6.0f);
   h4.array[0] = _mm256_set1_ps(7.0f);

   b = example1(a, b, c, d, e);
   e = example2(1, b, 3, d, e, 6.0f, 7);
   d = example3(1, h2, 3, 4, 5);
   f = example4(1, 2.0f, h4, d, 5);
   i = example5(1, h2, 3, h4, 5);
   h4 = example6(h2, h4, c, h2);
}

END Microsoft 固有の仕様End Microsoft Specific

関連項目See also

引数の渡し規則と名前付け規則Argument Passing and Naming Conventions
キーワードKeywords