Skip to content

Commit 0d0ab67

Browse files
committed
Add basic __vectorcall support
This is a fake implementation, which piggy-backs on the x64 standard calling convention and __fastcall, for x86_64 and x86 respectively, without any modifications. It won't work for some vector type parameters and for any HVA types. Since SIMD vector types and HVA are not supported by ext/ffi anyway, only float/double parameters would be a real issue.
1 parent 380f31f commit 0d0ab67

File tree

3 files changed

+13
-3
lines changed

3 files changed

+13
-3
lines changed

src/x86/ffi.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
7474
case FFI_MS_CDECL:
7575
case FFI_PASCAL:
7676
case FFI_REGISTER:
77+
case FFI_VECTORCALL_PARTIAL:
7778
break;
7879
default:
7980
return FFI_BAD_ABI;
@@ -136,6 +137,7 @@ ffi_prep_cif_machdep(ffi_cif *cif)
136137
case FFI_FASTCALL:
137138
case FFI_STDCALL:
138139
case FFI_MS_CDECL:
140+
case FFI_VECTORCALL_PARTIAL:
139141
flags = X86_RET_STRUCTARG;
140142
break;
141143
default:
@@ -240,6 +242,7 @@ static const struct abi_params abi_params[FFI_LAST_ABI] = {
240242
[FFI_PASCAL] = { -1, R_ECX, 0 },
241243
/* ??? No defined static chain; gcc does not support REGISTER. */
242244
[FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } },
245+
[FFI_VECTORCALL_PARTIAL] = { 1, R_EAX, 2, { R_ECX, R_EDX } },
243246
[FFI_MS_CDECL] = { 1, R_ECX, 0 }
244247
};
245248

@@ -355,7 +358,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
355358
/* Issue 434: For thiscall and fastcall, if the paramter passed
356359
as 64-bit integer or struct, all following integer paramters
357360
will be passed on stack. */
358-
if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
361+
if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL || cabi == FFI_VECTORCALL_PARTIAL)
359362
&& (t == FFI_TYPE_SINT64
360363
|| t == FFI_TYPE_UINT64
361364
|| t == FFI_TYPE_STRUCT))
@@ -494,7 +497,7 @@ ffi_closure_inner (struct closure_frame *frame, char *stack)
494497
/* Issue 434: For thiscall and fastcall, if the paramter passed
495498
as 64-bit integer or struct, all following integer paramters
496499
will be passed on stack. */
497-
if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL)
500+
if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL || cabi == FFI_VECTORCALL_PARTIAL)
498501
&& (t == FFI_TYPE_SINT64
499502
|| t == FFI_TYPE_UINT64
500503
|| t == FFI_TYPE_STRUCT))
@@ -543,6 +546,7 @@ ffi_prep_closure_loc (ffi_closure* closure,
543546
case FFI_THISCALL:
544547
case FFI_FASTCALL:
545548
case FFI_MS_CDECL:
549+
case FFI_VECTORCALL_PARTIAL:
546550
dest = ffi_closure_i386;
547551
break;
548552
case FFI_STDCALL:
@@ -590,6 +594,7 @@ ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
590594
break;
591595
case FFI_THISCALL:
592596
case FFI_FASTCALL:
597+
case FFI_VECTORCALL_PARTIAL:
593598
dest = ffi_go_closure_EAX;
594599
break;
595600
case FFI_STDCALL:

src/x86/ffitarget.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ typedef enum ffi_abi {
8282
FFI_FIRST_ABI = 0,
8383
FFI_WIN64, /* sizeof(long double) == 8 - microsoft compilers */
8484
FFI_GNUW64, /* sizeof(long double) == 16 - GNU compilers */
85+
FFI_VECTORCALL_PARTIAL,
8586
FFI_LAST_ABI,
8687
#ifdef __GNUC__
8788
FFI_DEFAULT_ABI = FFI_GNUW64
@@ -107,6 +108,7 @@ typedef enum ffi_abi {
107108
FFI_MS_CDECL = 5,
108109
FFI_PASCAL = 6,
109110
FFI_REGISTER = 7,
111+
FFI_VECTORCALL_PARTIAL = 8,
110112
FFI_LAST_ABI,
111113
FFI_DEFAULT_ABI = FFI_MS_CDECL
112114
#else

src/x86/ffiw64.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ EFI64(ffi_prep_cif_machdep)(ffi_cif *cif)
5757
switch (cif->abi)
5858
{
5959
case FFI_WIN64:
60+
case FFI_VECTORCALL_PARTIAL:
6061
case FFI_GNUW64:
6162
break;
6263
default:
@@ -116,7 +117,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
116117
size_t rsize;
117118
struct win64_call_frame *frame;
118119

119-
FFI_ASSERT(cif->abi == FFI_GNUW64 || cif->abi == FFI_WIN64);
120+
FFI_ASSERT(cif->abi == FFI_GNUW64 || cif->abi == FFI_WIN64 || cif->abi == FFI_VECTORCALL_PARTIAL);
120121

121122
flags = cif->flags;
122123
rsize = 0;
@@ -209,6 +210,7 @@ EFI64(ffi_prep_closure_loc)(ffi_closure* closure,
209210
switch (cif->abi)
210211
{
211212
case FFI_WIN64:
213+
case FFI_VECTORCALL_PARTIAL:
212214
case FFI_GNUW64:
213215
break;
214216
default:
@@ -232,6 +234,7 @@ EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif,
232234
switch (cif->abi)
233235
{
234236
case FFI_WIN64:
237+
case FFI_VECTORCALL_PARTIAL:
235238
case FFI_GNUW64:
236239
break;
237240
default:

0 commit comments

Comments
 (0)