Fix struct arg passing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
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. */