summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnthony Green <green@moxielogic.com>2022-09-05 12:19:57 -0400
committerAnthony Green <green@moxielogic.com>2022-09-05 12:19:57 -0400
commite4c5d46b0abaa8a12e97f0e0673e3efdda59fab8 (patch)
treef8eef7225c44565f5f8e8db2e22367df9fe3ec64 /src
parent4b79267be359b42e7a4cbf95068abe805aae0061 (diff)
downloadlibffi-e4c5d46b0abaa8a12e97f0e0673e3efdda59fab8.tar.gz
Pass large structs by value
Diffstat (limited to 'src')
-rw-r--r--src/sparc/ffi64.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/sparc/ffi64.c b/src/sparc/ffi64.c
index 9e04061..5ae43e8 100644
--- a/src/sparc/ffi64.c
+++ b/src/sparc/ffi64.c
@@ -421,12 +421,28 @@ ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue,
void **avalue, void *closure)
{
size_t bytes = cif->bytes;
+ size_t i, nargs = cif->nargs;
+ ffi_type **arg_types = cif->arg_types;
FFI_ASSERT (cif->abi == FFI_V9);
if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM))
bytes += FFI_ALIGN (cif->rtype->size, 16);
+ /* If we have any large structure arguments, make a copy so we are passing
+ by value. */
+ for (i = 0; i < nargs; i++)
+ {
+ ffi_type *at = arg_types[i];
+ int size = at->size;
+ if (at->type == FFI_TYPE_STRUCT && size > 4)
+ {
+ char *argcopy = alloca (size);
+ memcpy (argcopy, avalue[i], size);
+ avalue[i] = argcopy;
+ }
+ }
+
ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure);
}