summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnthony Green <green@moxielogic.com>2021-07-29 16:58:32 -0400
committerAnthony Green <green@moxielogic.com>2021-07-29 16:58:32 -0400
commit86d5ecc5e84fbbc79fcff6a307310630d9d68549 (patch)
treef693228a86570c4e7d7e75884e7134dcc462acca /src
parent03596285ed36b94bb3e1d8bdebfe58590e2766df (diff)
downloadlibffi-86d5ecc5e84fbbc79fcff6a307310630d9d68549.tar.gz
Fix struct arg passing
Diffstat (limited to 'src')
-rw-r--r--src/moxie/ffi.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/src/moxie/ffi.c b/src/moxie/ffi.c
index 16d2bb3..696581a 100644
--- a/src/moxie/ffi.c
+++ b/src/moxie/ffi.c
@@ -1,7 +1,7 @@
/* -----------------------------------------------------------------------
- ffi.c - Copyright (C) 2012, 2013, 2018 Anthony Green
-
- Moxie Foreign Function Interface
+ ffi.c - Copyright (C) 2012, 2013, 2018, 2021 Anthony Green
+
+ Moxie Foreign Function Interface
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -54,14 +54,14 @@ void *ffi_prep_args(char *stack, extended_cif *ecif)
i--, p_arg++)
{
size_t z;
-
+
z = (*p_arg)->size;
if ((*p_arg)->type == FFI_TYPE_STRUCT)
{
z = sizeof(void*);
*(void **) argp = *p_argv;
- }
+ }
else if (z < sizeof(int))
{
z = sizeof(int);
@@ -70,19 +70,19 @@ void *ffi_prep_args(char *stack, extended_cif *ecif)
case FFI_TYPE_SINT8:
*(signed int *) argp = (signed int)*(SINT8 *)(* p_argv);
break;
-
+
case FFI_TYPE_UINT8:
*(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv);
break;
-
+
case FFI_TYPE_SINT16:
*(signed int *) argp = (signed int)*(SINT16 *)(* p_argv);
break;
-
+
case FFI_TYPE_UINT16:
*(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv);
break;
-
+
default:
FFI_ASSERT(0);
}
@@ -116,26 +116,26 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
return FFI_OK;
}
-extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
- extended_cif *,
- unsigned, unsigned,
- unsigned *,
+extern void ffi_call_EABI(void *(*)(char *, extended_cif *),
+ extended_cif *,
+ unsigned, unsigned,
+ unsigned *,
void (*fn)(void));
-void ffi_call(ffi_cif *cif,
- void (*fn)(void),
- void *rvalue,
+void ffi_call(ffi_cif *cif,
+ void (*fn)(void),
+ void *rvalue,
void **avalue)
{
extended_cif ecif;
ecif.cif = cif;
ecif.avalue = avalue;
-
+
/* If the return value is a struct and we don't have a return */
/* value address then we need to make one */
- if ((rvalue == NULL) &&
+ if ((rvalue == NULL) &&
(cif->rtype->type == FFI_TYPE_STRUCT))
{
ecif.rvalue = alloca(cif->rtype->size);
@@ -143,10 +143,10 @@ void ffi_call(ffi_cif *cif,
else
ecif.rvalue = rvalue;
- switch (cif->abi)
+ switch (cif->abi)
{
case FFI_EABI:
- ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
+ ffi_call_EABI(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);
break;
default:
@@ -172,7 +172,7 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
void *struct_rvalue = (void *) arg1;
/* 6 words reserved for register args + 3 words from jsr */
- char *stack_args = frame_pointer + 9*4;
+ char *stack_args = frame_pointer + 9*4;
/* Lay the register arguments down in a continuous chunk of memory. */
unsigned register_args[6] =
@@ -211,7 +211,16 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
avalue[i] = ptr;
break;
case FFI_TYPE_STRUCT:
- avalue[i] = *(void**)ptr;
+ {
+ if (arg_types[i]->type->size > 4)
+ {
+ void *copy = alloca(arg_types[i]->type->size);
+ memcpy(copy, *(void**)ptr, arg_types[i]->type->size);
+ avalue[i] = copy;
+ }
+ else
+ avalue[i] = *(void**)ptr;
+ }
break;
default:
/* This is an 8-byte value. */