@@ -152,12 +152,42 @@ classify_argument(
152152 case FFI_TYPE_UINT64 :
153153 case FFI_TYPE_SINT64 :
154154 case FFI_TYPE_POINTER :
155+ #if 0
155156 if (byte_offset + type -> size <= 4 )
156157 classes [0 ] = X86_64_INTEGERSI_CLASS ;
157158 else
158159 classes [0 ] = X86_64_INTEGER_CLASS ;
159160
160161 return 1 ;
162+ #else
163+ {
164+ int size = byte_offset + type -> size ;
165+
166+ if (size <= 4 )
167+ {
168+ classes [0 ] = X86_64_INTEGERSI_CLASS ;
169+ return 1 ;
170+ }
171+ else if (size <= 8 )
172+ {
173+ classes [0 ] = X86_64_INTEGER_CLASS ;
174+ return 1 ;
175+ }
176+ else if (size <= 12 )
177+ {
178+ classes [0 ] = X86_64_INTEGER_CLASS ;
179+ classes [1 ] = X86_64_INTEGERSI_CLASS ;
180+ return 2 ;
181+ }
182+ else if (size <= 16 )
183+ {
184+ classes [0 ] = classes [1 ] = X86_64_INTEGERSI_CLASS ;
185+ return 2 ;
186+ }
187+ else
188+ FFI_ASSERT (0 );
189+ }
190+ #endif
161191
162192 case FFI_TYPE_FLOAT :
163193 if (byte_offset == 0 )
@@ -213,6 +243,21 @@ classify_argument(
213243 byte_offset += (* ptr )-> size ;
214244 }
215245
246+ if (words > 2 )
247+ {
248+ /* When size > 16 bytes, if the first one isn't
249+ X86_64_SSE_CLASS or any other ones aren't
250+ X86_64_SSEUP_CLASS, everything should be passed in
251+ memory. */
252+ if (classes [0 ] != X86_64_SSE_CLASS )
253+ return 0 ;
254+
255+ for (i = 1 ; i < words ; i ++ )
256+ if (classes [i ] != X86_64_SSEUP_CLASS )
257+ return 0 ;
258+ }
259+
260+
216261 /* Final merger cleanup. */
217262 for (i = 0 ; i < words ; i ++ )
218263 {
@@ -224,13 +269,20 @@ classify_argument(
224269 /* The X86_64_SSEUP_CLASS should be always preceded by
225270 X86_64_SSE_CLASS. */
226271 if (classes [i ] == X86_64_SSEUP_CLASS
227- && (i == 0 || classes [i - 1 ] != X86_64_SSE_CLASS ))
272+ && classes [i - 1 ] != X86_64_SSE_CLASS
273+ && classes [i - 1 ] != X86_64_SSEUP_CLASS )
274+ {
275+ FFI_ASSERT (i != 0 );
228276 classes [i ] = X86_64_SSE_CLASS ;
277+ }
229278
230279 /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
231280 if (classes [i ] == X86_64_X87UP_CLASS
232- && (i == 0 || classes [i - 1 ] != X86_64_X87_CLASS ))
281+ && classes [i - 1 ] != X86_64_X87_CLASS )
282+ {
283+ FFI_ASSERT (i != 0 );
233284 classes [i ] = X86_64_SSE_CLASS ;
285+ }
234286 }
235287
236288 return words ;
@@ -369,6 +421,7 @@ ffi_prep_cif_machdep(
369421
370422 cif -> flags = flags ;
371423 cif -> bytes = bytes ;
424+ cif -> bytes = ALIGN (bytes ,8 );
372425
373426 return FFI_OK ;
374427}
@@ -449,7 +502,61 @@ ffi_call(
449502 case X86_64_INTEGER_CLASS :
450503 case X86_64_INTEGERSI_CLASS :
451504 reg_args -> gpr [gprcount ] = 0 ;
452- memcpy (& reg_args -> gpr [gprcount ], a , size < 8 ? size : 8 );
505+ switch (arg_types [i ]-> type ) {
506+ case FFI_TYPE_SINT8 :
507+ {
508+ int8_t shortval = * (int8_t * )a ;
509+ int64_t actval = (int64_t )shortval ;
510+ reg_args -> gpr [gprcount ] = actval ;
511+ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
512+ break ;
513+ }
514+
515+ case FFI_TYPE_SINT16 :
516+ {
517+ int16_t shortval = * (int16_t * )a ;
518+ int64_t actval = (int64_t )shortval ;
519+ memcpy (& reg_args -> gpr [gprcount ], & actval , 8 );
520+ break ;
521+ }
522+
523+ case FFI_TYPE_SINT32 :
524+ {
525+ int32_t shortval = * (int32_t * )a ;
526+ int64_t actval = (int64_t )shortval ;
527+ memcpy (& reg_args -> gpr [gprcount ], & actval , 8 );
528+ break ;
529+ }
530+
531+ case FFI_TYPE_UINT8 :
532+ {
533+ u_int8_t shortval = * (u_int8_t * )a ;
534+ u_int64_t actval = (u_int64_t )shortval ;
535+ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/
536+ reg_args -> gpr [gprcount ] = actval ;
537+ break ;
538+ }
539+
540+ case FFI_TYPE_UINT16 :
541+ {
542+ u_int16_t shortval = * (u_int16_t * )a ;
543+ u_int64_t actval = (u_int64_t )shortval ;
544+ memcpy (& reg_args -> gpr [gprcount ], & actval , 8 );
545+ break ;
546+ }
547+
548+ case FFI_TYPE_UINT32 :
549+ {
550+ u_int32_t shortval = * (u_int32_t * )a ;
551+ u_int64_t actval = (u_int64_t )shortval ;
552+ memcpy (& reg_args -> gpr [gprcount ], & actval , 8 );
553+ break ;
554+ }
555+
556+ default :
557+ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8);
558+ reg_args -> gpr [gprcount ] = * (int64_t * )a ;
559+ }
453560 gprcount ++ ;
454561 break ;
455562
@@ -505,12 +612,15 @@ ffi_prep_closure(
505612 return FFI_OK ;
506613}
507614
615+ #pragma clang diagnostic push
616+ #pragma clang diagnostic ignored "-Wmissing-prototypes"
508617int
509618ffi_closure_unix64_inner (
510619 ffi_closure * closure ,
511620 void * rvalue ,
512621 RegisterArgs * reg_args ,
513622 char * argp )
623+ #pragma clang diagnostic pop
514624{
515625 ffi_cif * cif = closure -> cif ;
516626 void * * avalue = alloca (cif -> nargs * sizeof (void * ));
@@ -621,4 +731,4 @@ ffi_closure_unix64_inner(
621731 return ret ;
622732}
623733
624- #endif /* __x86_64__ */
734+ #endif /* __x86_64__ */
0 commit comments