#include <stdlib.h>
extern void ffi_closure_ASM (void);
+extern void ffi_go_closure_ASM (void);
enum {
/* The assembly depends on these exact flags.
extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *,
void (*fn)(void), void (*fn2)(void));
+extern void ffi_call_go_AIX(extended_cif *, long, unsigned, unsigned *,
+ void (*fn)(void), void (*fn2)(void), void *closure);
+
extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *,
void (*fn)(void), void (*fn2)(void), ffi_type*);
}
}
+void
+ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue,
+ void *closure)
+{
+ 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) &&
+ (cif->rtype->type == FFI_TYPE_STRUCT))
+ {
+ ecif.rvalue = alloca (cif->rtype->size);
+ }
+ else
+ ecif.rvalue = rvalue;
+
+ switch (cif->abi)
+ {
+ case FFI_AIX:
+ ffi_call_go_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
+ FFI_FN(ffi_prep_args), closure);
+ break;
+ default:
+ FFI_ASSERT(0);
+ break;
+ }
+}
+
static void flush_icache(char *);
static void flush_range(char *, int);
return FFI_OK;
}
+ffi_status
+ffi_prep_go_closure (ffi_go_closure* closure,
+ ffi_cif* cif,
+ void (*fun)(ffi_cif*, void*, void**, void*))
+{
+ switch (cif->abi)
+ {
+ case FFI_AIX:
+
+ FFI_ASSERT (cif->abi == FFI_AIX);
+
+ closure->tramp = (void *)ffi_go_closure_ASM;
+ closure->cif = cif;
+ closure->fun = fun;
+ return FFI_OK;
+
+ // For now, ffi_prep_go_closure is only implemented for AIX, not for Darwin
+ default:
+ return FFI_BAD_ABI;
+ break;
+ }
+ return FFI_OK;
+}
+
static void
flush_icache(char *addr)
{
ffi_closure_helper_DARWIN (ffi_closure *, void *,
unsigned long *, ffi_dblfl *);
+ffi_type *
+ffi_go_closure_helper_DARWIN (ffi_go_closure*, void *,
+ unsigned long *, ffi_dblfl *);
+
/* Basically the trampoline invokes ffi_closure_ASM, and on
entry, r11 holds the address of the closure.
After storing the registers that could possibly contain
up space for a return value, ffi_closure_ASM invokes the
following helper function to do most of the work. */
-ffi_type *
-ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
+static ffi_type *
+ffi_closure_helper_common (ffi_cif* cif,
+ void (*fun)(ffi_cif*, void*, void**, void*),
+ void *user_data, void *rvalue,
unsigned long *pgr, ffi_dblfl *pfr)
{
/* rvalue is the pointer to space for return value in closure assembly
void ** avalue;
ffi_type ** arg_types;
long i, avn;
- ffi_cif * cif;
ffi_dblfl * end_pfr = pfr + NUM_FPR_ARG_REGISTERS;
unsigned size_al;
#if defined(POWERPC_DARWIN64)
unsigned fpsused = 0;
#endif
- cif = closure->cif;
avalue = alloca (cif->nargs * sizeof(void *));
if (cif->rtype->type == FFI_TYPE_STRUCT)
i++;
}
- (closure->fun) (cif, rvalue, avalue, closure->user_data);
+ (fun) (cif, rvalue, avalue, user_data);
/* Tell ffi_closure_ASM to perform return type promotions. */
return cif->rtype;
}
+
+ffi_type *
+ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
+ unsigned long *pgr, ffi_dblfl *pfr)
+{
+ return ffi_closure_helper_common (closure->cif, closure->fun,
+ closure->user_data, rvalue, pgr, pfr);
+}
+
+ffi_type *
+ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue,
+ unsigned long *pgr, ffi_dblfl *pfr)
+{
+ return ffi_closure_helper_common (closure->cif, closure->fun,
+ closure, rvalue, pgr, pfr);
+}
+