Update missing changes for 3.0.9r4.
This commit is contained in:
@@ -145,13 +145,35 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
|
||||
case FFI_TYPE_UINT64:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_POINTER:
|
||||
if (byte_offset + type->size <= 4)
|
||||
classes[0] = X86_64_INTEGERSI_CLASS;
|
||||
else
|
||||
classes[0] = X86_64_INTEGER_CLASS;
|
||||
return 1;
|
||||
{
|
||||
int size = byte_offset + type->size;
|
||||
|
||||
if (size <= 4)
|
||||
{
|
||||
classes[0] = X86_64_INTEGERSI_CLASS;
|
||||
return 1;
|
||||
}
|
||||
else if (size <= 8)
|
||||
{
|
||||
classes[0] = X86_64_INTEGER_CLASS;
|
||||
return 1;
|
||||
}
|
||||
else if (size <= 12)
|
||||
{
|
||||
classes[0] = X86_64_INTEGER_CLASS;
|
||||
classes[1] = X86_64_INTEGERSI_CLASS;
|
||||
return 2;
|
||||
}
|
||||
else if (size <= 16)
|
||||
{
|
||||
classes[0] = classes[1] = X86_64_INTEGERSI_CLASS;
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
FFI_ASSERT (0);
|
||||
}
|
||||
case FFI_TYPE_FLOAT:
|
||||
if (byte_offset == 0)
|
||||
if (!(byte_offset % 8))
|
||||
classes[0] = X86_64_SSESF_CLASS;
|
||||
else
|
||||
classes[0] = X86_64_SSE_CLASS;
|
||||
@@ -171,13 +193,21 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
|
||||
int i;
|
||||
enum x86_64_reg_class subclasses[MAX_CLASSES];
|
||||
|
||||
/* If the struct is larger than 16 bytes, pass it on the stack. */
|
||||
if (type->size > 16)
|
||||
/* If the struct is larger than 32 bytes, pass it on the stack. */
|
||||
if (type->size > 32)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < words; i++)
|
||||
classes[i] = X86_64_NO_CLASS;
|
||||
|
||||
/* Zero sized arrays or structures are NO_CLASS. We return 0 to
|
||||
signalize memory class, so handle it as special case. */
|
||||
if (!words)
|
||||
{
|
||||
classes[0] = X86_64_NO_CLASS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Merge the fields of structure. */
|
||||
for (ptr = type->elements; *ptr != NULL; ptr++)
|
||||
{
|
||||
@@ -198,6 +228,20 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
|
||||
byte_offset += (*ptr)->size;
|
||||
}
|
||||
|
||||
if (words > 2)
|
||||
{
|
||||
/* When size > 16 bytes, if the first one isn't
|
||||
X86_64_SSE_CLASS or any other ones aren't
|
||||
X86_64_SSEUP_CLASS, everything should be passed in
|
||||
memory. */
|
||||
if (classes[0] != X86_64_SSE_CLASS)
|
||||
return 0;
|
||||
|
||||
for (i = 1; i < words; i++)
|
||||
if (classes[i] != X86_64_SSEUP_CLASS)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Final merger cleanup. */
|
||||
for (i = 0; i < words; i++)
|
||||
{
|
||||
@@ -207,15 +251,25 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[],
|
||||
return 0;
|
||||
|
||||
/* The X86_64_SSEUP_CLASS should be always preceded by
|
||||
X86_64_SSE_CLASS. */
|
||||
X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */
|
||||
if (classes[i] == X86_64_SSEUP_CLASS
|
||||
&& (i == 0 || classes[i - 1] != X86_64_SSE_CLASS))
|
||||
classes[i] = X86_64_SSE_CLASS;
|
||||
&& classes[i - 1] != X86_64_SSE_CLASS
|
||||
&& classes[i - 1] != X86_64_SSEUP_CLASS)
|
||||
{
|
||||
/* The first one should never be X86_64_SSEUP_CLASS. */
|
||||
FFI_ASSERT (i != 0);
|
||||
classes[i] = X86_64_SSE_CLASS;
|
||||
}
|
||||
|
||||
/* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */
|
||||
/* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS,
|
||||
everything should be passed in memory. */
|
||||
if (classes[i] == X86_64_X87UP_CLASS
|
||||
&& (i == 0 || classes[i - 1] != X86_64_X87_CLASS))
|
||||
classes[i] = X86_64_SSE_CLASS;
|
||||
&& (classes[i - 1] != X86_64_X87_CLASS))
|
||||
{
|
||||
/* The first one should never be X86_64_X87UP_CLASS. */
|
||||
FFI_ASSERT (i != 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return words;
|
||||
}
|
||||
@@ -528,10 +582,10 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue,
|
||||
argp += arg_types[i]->size;
|
||||
}
|
||||
/* If the argument is in a single register, or two consecutive
|
||||
registers, then we can use that address directly. */
|
||||
integer registers, then we can use that address directly. */
|
||||
else if (n == 1
|
||||
|| (n == 2
|
||||
&& SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1])))
|
||||
|| (n == 2 && !(SSE_CLASS_P (classes[0])
|
||||
|| SSE_CLASS_P (classes[1]))))
|
||||
{
|
||||
/* The argument is in a single register. */
|
||||
if (SSE_CLASS_P (classes[0]))
|
||||
|
||||
Reference in New Issue
Block a user