x86: Add support for Go closures
This commit is contained in:
@@ -218,25 +218,28 @@ struct call_frame
|
|||||||
struct abi_params
|
struct abi_params
|
||||||
{
|
{
|
||||||
int dir; /* parameter growth direction */
|
int dir; /* parameter growth direction */
|
||||||
|
int static_chain; /* the static chain register used by gcc */
|
||||||
int nregs; /* number of register parameters */
|
int nregs; /* number of register parameters */
|
||||||
int regs[3];
|
int regs[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct abi_params abi_params[FFI_LAST_ABI] = {
|
static const struct abi_params abi_params[FFI_LAST_ABI] = {
|
||||||
[FFI_SYSV] = { 1, 0 },
|
[FFI_SYSV] = { 1, R_ECX, 0 },
|
||||||
[FFI_THISCALL] = { 1, 1, { R_ECX } },
|
[FFI_THISCALL] = { 1, R_EAX, 1, { R_ECX } },
|
||||||
[FFI_FASTCALL] = { 1, 2, { R_ECX, R_EDX } },
|
[FFI_FASTCALL] = { 1, R_EAX, 2, { R_ECX, R_EDX } },
|
||||||
[FFI_STDCALL] = { 1, 0 },
|
[FFI_STDCALL] = { 1, R_ECX, 0 },
|
||||||
[FFI_PASCAL] = { -1, 0 },
|
[FFI_PASCAL] = { -1, R_ECX, 0 },
|
||||||
[FFI_REGISTER] = { -1, 3, { R_EAX, R_EDX, R_ECX } },
|
/* ??? No defined static chain; gcc does not support REGISTER. */
|
||||||
[FFI_MS_CDECL] = { 1, 0 }
|
[FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } },
|
||||||
|
[FFI_MS_CDECL] = { 1, R_ECX, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void ffi_call_i386(struct call_frame *, char *)
|
extern void ffi_call_i386(struct call_frame *, char *)
|
||||||
FFI_HIDDEN __declspec(fastcall);
|
FFI_HIDDEN __declspec(fastcall);
|
||||||
|
|
||||||
void
|
static void
|
||||||
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
|
void **avalue, void *closure)
|
||||||
{
|
{
|
||||||
size_t rsize, bytes;
|
size_t rsize, bytes;
|
||||||
struct call_frame *frame;
|
struct call_frame *frame;
|
||||||
@@ -281,6 +284,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
frame->fn = fn;
|
frame->fn = fn;
|
||||||
frame->flags = flags;
|
frame->flags = flags;
|
||||||
frame->rvalue = rvalue;
|
frame->rvalue = rvalue;
|
||||||
|
frame->regs[pabi->static_chain] = (unsigned)closure;
|
||||||
|
|
||||||
narg_reg = 0;
|
narg_reg = 0;
|
||||||
switch (flags)
|
switch (flags)
|
||||||
@@ -345,6 +349,18 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|||||||
ffi_call_i386 (frame, stack);
|
ffi_call_i386 (frame, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
||||||
|
{
|
||||||
|
ffi_call_int (cif, fn, rvalue, avalue, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue,
|
||||||
|
void **avalue, void *closure)
|
||||||
|
{
|
||||||
|
ffi_call_int (cif, fn, rvalue, avalue, closure);
|
||||||
|
}
|
||||||
|
|
||||||
/** private members **/
|
/** private members **/
|
||||||
|
|
||||||
@@ -493,6 +509,42 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|||||||
return FFI_OK;
|
return FFI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FFI_HIDDEN ffi_go_closure_EAX(void);
|
||||||
|
void FFI_HIDDEN ffi_go_closure_ECX(void);
|
||||||
|
void FFI_HIDDEN ffi_go_closure_STDCALL(void);
|
||||||
|
|
||||||
|
ffi_status
|
||||||
|
ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif,
|
||||||
|
void (*fun)(ffi_cif*,void*,void**,void*))
|
||||||
|
{
|
||||||
|
void (*dest)(void);
|
||||||
|
|
||||||
|
switch (cif->abi)
|
||||||
|
{
|
||||||
|
case FFI_SYSV:
|
||||||
|
case FFI_MS_CDECL:
|
||||||
|
dest = ffi_go_closure_ECX;
|
||||||
|
break;
|
||||||
|
case FFI_THISCALL:
|
||||||
|
case FFI_FASTCALL:
|
||||||
|
dest = ffi_go_closure_ECX;
|
||||||
|
break;
|
||||||
|
case FFI_STDCALL:
|
||||||
|
case FFI_PASCAL:
|
||||||
|
dest = ffi_go_closure_STDCALL;
|
||||||
|
break;
|
||||||
|
case FFI_REGISTER:
|
||||||
|
default:
|
||||||
|
return FFI_BAD_ABI;
|
||||||
|
}
|
||||||
|
|
||||||
|
closure->tramp = dest;
|
||||||
|
closure->cif = cif;
|
||||||
|
closure->fun = fun;
|
||||||
|
|
||||||
|
return FFI_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------- Native raw API support -------------------------------- */
|
/* ------- Native raw API support -------------------------------- */
|
||||||
|
|
||||||
#if !FFI_NO_RAW_API
|
#if !FFI_NO_RAW_API
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ typedef enum ffi_abi {
|
|||||||
/* ---- Definitions for closures ----------------------------------------- */
|
/* ---- Definitions for closures ----------------------------------------- */
|
||||||
|
|
||||||
#define FFI_CLOSURES 1
|
#define FFI_CLOSURES 1
|
||||||
|
#define FFI_GO_CLOSURES 1
|
||||||
|
|
||||||
#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
|
#define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1)
|
||||||
#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
|
#define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2)
|
||||||
@@ -127,7 +128,6 @@ typedef enum ffi_abi {
|
|||||||
|| (defined (__x86_64__) && defined (X86_DARWIN))
|
|| (defined (__x86_64__) && defined (X86_DARWIN))
|
||||||
# define FFI_TRAMPOLINE_SIZE 24
|
# define FFI_TRAMPOLINE_SIZE 24
|
||||||
# define FFI_NATIVE_RAW_API 0
|
# define FFI_NATIVE_RAW_API 0
|
||||||
# define FFI_GO_CLOSURES 1
|
|
||||||
#else
|
#else
|
||||||
# define FFI_TRAMPOLINE_SIZE 12
|
# define FFI_TRAMPOLINE_SIZE 12
|
||||||
# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */
|
||||||
|
|||||||
@@ -228,6 +228,28 @@ ENDF(C(ffi_call_i386))
|
|||||||
jmp *%eax
|
jmp *%eax
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
|
.macro FFI_GO_CLOSURE suffix, chain, t1, t2
|
||||||
|
.align 16
|
||||||
|
.globl C(ffi_go_closure_\suffix)
|
||||||
|
FFI_HIDDEN(C(ffi_go_closure_\suffix))
|
||||||
|
C(ffi_go_closure_\suffix):
|
||||||
|
cfi_startproc
|
||||||
|
subl $closure_FS, %esp
|
||||||
|
cfi_adjust_cfa_offset(closure_FS)
|
||||||
|
FFI_CLOSURE_SAVE_REGS
|
||||||
|
movl 4(\chain), \t1 /* copy cif */
|
||||||
|
movl 8(\chain), \t2 /* copy fun */
|
||||||
|
movl \t1, 28(%esp)
|
||||||
|
movl \t2, 32(%esp)
|
||||||
|
movl \chain, 36(%esp) /* closure is user_data */
|
||||||
|
jmp 88f
|
||||||
|
cfi_endproc
|
||||||
|
ENDF(C(ffi_go_closure_\suffix))
|
||||||
|
.endm
|
||||||
|
|
||||||
|
FFI_GO_CLOSURE EAX, %eax, %edx, %ecx
|
||||||
|
FFI_GO_CLOSURE ECX, %ecx, %edx, %eax
|
||||||
|
|
||||||
/* The closure entry points are reached from the ffi_closure trampoline.
|
/* The closure entry points are reached from the ffi_closure trampoline.
|
||||||
On entry, %eax contains the address of the ffi_closure. */
|
On entry, %eax contains the address of the ffi_closure. */
|
||||||
|
|
||||||
@@ -242,6 +264,9 @@ C(ffi_closure_i386):
|
|||||||
|
|
||||||
FFI_CLOSURE_SAVE_REGS
|
FFI_CLOSURE_SAVE_REGS
|
||||||
FFI_CLOSURE_COPY_TRAMP_DATA
|
FFI_CLOSURE_COPY_TRAMP_DATA
|
||||||
|
|
||||||
|
88: /* Entry point from preceeding Go closures. */
|
||||||
|
|
||||||
FFI_CLOSURE_CALL_INNER
|
FFI_CLOSURE_CALL_INNER
|
||||||
FFI_CLOSURE_MASK_AND_JUMP
|
FFI_CLOSURE_MASK_AND_JUMP
|
||||||
|
|
||||||
@@ -303,6 +328,8 @@ E(X86_RET_UNUSED15)
|
|||||||
cfi_endproc
|
cfi_endproc
|
||||||
ENDF(C(ffi_closure_i386))
|
ENDF(C(ffi_closure_i386))
|
||||||
|
|
||||||
|
FFI_GO_CLOSURE STDCALL, %ecx, %edx, %eax
|
||||||
|
|
||||||
/* For REGISTER, we have no available parameter registers, and so we
|
/* For REGISTER, we have no available parameter registers, and so we
|
||||||
enter here having pushed the closure onto the stack. */
|
enter here having pushed the closure onto the stack. */
|
||||||
|
|
||||||
@@ -339,8 +366,13 @@ C(ffi_closure_STDCALL):
|
|||||||
cfi_adjust_cfa_offset(closure_FS)
|
cfi_adjust_cfa_offset(closure_FS)
|
||||||
|
|
||||||
FFI_CLOSURE_SAVE_REGS
|
FFI_CLOSURE_SAVE_REGS
|
||||||
0:
|
|
||||||
|
0: /* Entry point from ffi_closure_REGISTER. */
|
||||||
|
|
||||||
FFI_CLOSURE_COPY_TRAMP_DATA
|
FFI_CLOSURE_COPY_TRAMP_DATA
|
||||||
|
|
||||||
|
88: /* Entry point from preceeding Go closure. */
|
||||||
|
|
||||||
FFI_CLOSURE_CALL_INNER
|
FFI_CLOSURE_CALL_INNER
|
||||||
|
|
||||||
movl %eax, %ecx
|
movl %eax, %ecx
|
||||||
|
|||||||
Reference in New Issue
Block a user