diff options
Diffstat (limited to 'src/moxie')
-rw-r--r-- | src/moxie/ffi.c | 53 |
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. */ |