@@ -102,6 +102,15 @@ void ffi_prep_args(char *stack, extended_cif *ecif)
102102 FFI_ASSERT (0 );
103103 }
104104 }
105+ #ifdef _WIN64
106+ else if (z > 8 )
107+ {
108+ /* On Win64, if a single argument takes more than 8 bytes,
109+ then it is always passed by reference. */
110+ * (void * * )argp = * p_argv ;
111+ z = 8 ;
112+ }
113+ #endif
105114 else
106115 {
107116 memcpy (argp , * p_argv , z );
@@ -124,14 +133,25 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
124133 switch (cif -> rtype -> type )
125134 {
126135 case FFI_TYPE_VOID :
127- case FFI_TYPE_STRUCT :
128136 case FFI_TYPE_SINT64 :
129137 case FFI_TYPE_FLOAT :
130138 case FFI_TYPE_DOUBLE :
131139 case FFI_TYPE_LONGDOUBLE :
132140 cif -> flags = (unsigned ) cif -> rtype -> type ;
133141 break ;
134142
143+ case FFI_TYPE_STRUCT :
144+ /* MSVC returns small structures in registers. Put in cif->flags
145+ the value FFI_TYPE_STRUCT only if the structure is big enough;
146+ otherwise, put the 4- or 8-bytes integer type. */
147+ if (cif -> rtype -> size <= 4 )
148+ cif -> flags = FFI_TYPE_INT ;
149+ else if (cif -> rtype -> size <= 8 )
150+ cif -> flags = FFI_TYPE_SINT64 ;
151+ else
152+ cif -> flags = FFI_TYPE_STRUCT ;
153+ break ;
154+
135155 case FFI_TYPE_UINT64 :
136156#ifdef _WIN64
137157 case FFI_TYPE_POINTER :
@@ -201,8 +221,7 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
201221#else
202222 case FFI_SYSV :
203223 /*@-usedef@*/
204- /* Function call needs at least 40 bytes stack size, on win64 AMD64 */
205- return ffi_call_AMD64 (ffi_prep_args , & ecif , cif -> bytes ? cif -> bytes : 40 ,
224+ return ffi_call_AMD64 (ffi_prep_args , & ecif , cif -> bytes ,
206225 cif -> flags , ecif .rvalue , fn );
207226 /*@=usedef@*/
208227 break ;
@@ -227,7 +246,7 @@ void *
227246#else
228247static void __fastcall
229248#endif
230- ffi_closure_SYSV (ffi_closure * closure , int * argp )
249+ ffi_closure_SYSV (ffi_closure * closure , char * argp )
231250{
232251 // this is our return value storage
233252 long double res ;
@@ -237,7 +256,7 @@ ffi_closure_SYSV (ffi_closure *closure, int *argp)
237256 void * * arg_area ;
238257 unsigned short rtype ;
239258 void * resp = (void * )& res ;
240- void * args = & argp [ 1 ] ;
259+ void * args = argp + sizeof ( void * ) ;
241260
242261 cif = closure -> cif ;
243262 arg_area = (void * * ) alloca (cif -> nargs * sizeof (void * ));
0 commit comments