Merge a newer version of libffi_osx, based on the
version of libffi in OSX 10.6.1. This fixes issue6918
This commit is contained in:
parent
9f20d9d0ee
commit
16766d7cd6
|
@ -1,7 +1,7 @@
|
|||
#if defined(__ppc__) || defined(__ppc64__)
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin.S - Copyright (c) 2000 John Hornkvist
|
||||
ppc-darwin.S - Copyright (c) 2000 John Hornkvist
|
||||
Copyright (c) 2004 Free Software Foundation, Inc.
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
@ -294,7 +294,7 @@ LSCIE1:
|
|||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0x10 ; FDE Encoding (pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
|
@ -308,7 +308,7 @@ LSFDE1:
|
|||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB0$non_lazy_ptr-. ; FDE initial location
|
||||
.g_long LFB0-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB0
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
|
@ -338,10 +338,6 @@ LASFDE1:
|
|||
.byte 0x1c ; uleb128 0x1c
|
||||
.align LOG2_GPR_BYTES
|
||||
LEFDE1:
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB0$non_lazy_ptr:
|
||||
.g_long LFB0
|
||||
|
||||
#if defined(__ppc64__)
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#define L(x) x
|
||||
|
||||
#define SF_ARG9 MODE_CHOICE(56,112)
|
||||
|
@ -57,7 +56,6 @@
|
|||
((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\
|
||||
(x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT)
|
||||
|
||||
|
||||
#if !defined(LIBFFI_ASM)
|
||||
|
||||
enum {
|
||||
|
@ -75,20 +73,6 @@ enum {
|
|||
FLAG_RETVAL_REFERENCE = 1 << (31 - 4)
|
||||
};
|
||||
|
||||
|
||||
void ffi_prep_args(extended_cif* inEcif, unsigned *const stack);
|
||||
|
||||
typedef union
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
} ffi_dblfl;
|
||||
|
||||
int ffi_closure_helper_DARWIN( ffi_closure* closure,
|
||||
void* rvalue, unsigned long* pgr,
|
||||
ffi_dblfl* pfr);
|
||||
|
||||
|
||||
#if defined(__ppc64__)
|
||||
void ffi64_struct_to_ram_form(const ffi_type*, const char*, unsigned int*,
|
||||
const char*, unsigned int*, unsigned int*, char*, unsigned int*);
|
||||
|
@ -96,11 +80,6 @@ void ffi64_struct_to_reg_form(const ffi_type*, const char*, unsigned int*,
|
|||
unsigned int*, char*, unsigned int*, char*, unsigned int*);
|
||||
bool ffi64_stret_needs_ptr(const ffi_type* inType,
|
||||
unsigned short*, unsigned short*);
|
||||
bool ffi64_struct_contains_fp(const ffi_type* inType);
|
||||
unsigned int ffi64_data_size(const ffi_type* inType);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // !defined(LIBFFI_ASM)
|
||||
#endif // !defined(LIBFFI_ASM)
|
|
@ -1,7 +1,7 @@
|
|||
#if defined(__ppc__)
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc. based on ppc_closure.S
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
@ -43,8 +43,8 @@
|
|||
|
||||
_ffi_closure_ASM:
|
||||
LFB1:
|
||||
mflr r0 /* extract return address */
|
||||
stg r0,MODE_CHOICE(8,16)(r1) /* save return address */
|
||||
mflr r0 // Save return address
|
||||
stg r0,SF_RETURN(r1)
|
||||
|
||||
LCFI0:
|
||||
/* 24/48 bytes (Linkage Area)
|
||||
|
@ -54,7 +54,7 @@ LCFI0:
|
|||
176/232 total bytes */
|
||||
|
||||
/* skip over caller save area and keep stack aligned to 16/32. */
|
||||
stgu r1,-SF_ROUND(MODE_CHOICE(176,248))(r1)
|
||||
stgu r1,-SF_ROUND(176)(r1)
|
||||
|
||||
LCFI1:
|
||||
/* We want to build up an area for the parameters passed
|
||||
|
@ -67,58 +67,44 @@ LCFI1:
|
|||
|
||||
/* Save GPRs 3 - 10 (aligned to 4/8)
|
||||
in the parents outgoing area. */
|
||||
stg r3,MODE_CHOICE(200,304)(r1)
|
||||
stg r4,MODE_CHOICE(204,312)(r1)
|
||||
stg r5,MODE_CHOICE(208,320)(r1)
|
||||
stg r6,MODE_CHOICE(212,328)(r1)
|
||||
stg r7,MODE_CHOICE(216,336)(r1)
|
||||
stg r8,MODE_CHOICE(220,344)(r1)
|
||||
stg r9,MODE_CHOICE(224,352)(r1)
|
||||
stg r10,MODE_CHOICE(228,360)(r1)
|
||||
stg r3,200(r1)
|
||||
stg r4,204(r1)
|
||||
stg r5,208(r1)
|
||||
stg r6,212(r1)
|
||||
stg r7,216(r1)
|
||||
stg r8,220(r1)
|
||||
stg r9,224(r1)
|
||||
stg r10,228(r1)
|
||||
|
||||
/* Save FPRs 1 - 13. (aligned to 8) */
|
||||
stfd f1,MODE_CHOICE(56,112)(r1)
|
||||
stfd f2,MODE_CHOICE(64,120)(r1)
|
||||
stfd f3,MODE_CHOICE(72,128)(r1)
|
||||
stfd f4,MODE_CHOICE(80,136)(r1)
|
||||
stfd f5,MODE_CHOICE(88,144)(r1)
|
||||
stfd f6,MODE_CHOICE(96,152)(r1)
|
||||
stfd f7,MODE_CHOICE(104,160)(r1)
|
||||
stfd f8,MODE_CHOICE(112,168)(r1)
|
||||
stfd f9,MODE_CHOICE(120,176)(r1)
|
||||
stfd f10,MODE_CHOICE(128,184)(r1)
|
||||
stfd f11,MODE_CHOICE(136,192)(r1)
|
||||
stfd f12,MODE_CHOICE(144,200)(r1)
|
||||
stfd f13,MODE_CHOICE(152,208)(r1)
|
||||
stfd f1,56(r1)
|
||||
stfd f2,64(r1)
|
||||
stfd f3,72(r1)
|
||||
stfd f4,80(r1)
|
||||
stfd f5,88(r1)
|
||||
stfd f6,96(r1)
|
||||
stfd f7,104(r1)
|
||||
stfd f8,112(r1)
|
||||
stfd f9,120(r1)
|
||||
stfd f10,128(r1)
|
||||
stfd f11,136(r1)
|
||||
stfd f12,144(r1)
|
||||
stfd f13,152(r1)
|
||||
|
||||
/* Set up registers for the routine that actually does the work.
|
||||
Get the context pointer from the trampoline. */
|
||||
mr r3,r11
|
||||
|
||||
/* Load the pointer to the result storage. */
|
||||
/* current stack frame size - ((4/8 * 4) + saved registers) */
|
||||
addi r4,r1,MODE_CHOICE(160,216)
|
||||
|
||||
/* Load the pointer to the saved gpr registers. */
|
||||
addi r5,r1,MODE_CHOICE(200,304)
|
||||
|
||||
/* Load the pointer to the saved fpr registers. */
|
||||
addi r6,r1,MODE_CHOICE(56,112)
|
||||
|
||||
/* Make the call. */
|
||||
// Set up registers for the routine that actually does the work.
|
||||
mr r3,r11 // context pointer from the trampoline
|
||||
addi r4,r1,160 // result storage
|
||||
addi r5,r1,200 // saved GPRs
|
||||
addi r6,r1,56 // saved FPRs
|
||||
bl Lffi_closure_helper_DARWIN$stub
|
||||
|
||||
/* Now r3 contains the return type
|
||||
so use it to look up in a table
|
||||
/* Now r3 contains the return type. Use it to look up in a table
|
||||
so we know how to deal with each type. */
|
||||
|
||||
/* Look the proper starting point in table
|
||||
by using return type as offset. */
|
||||
addi r5,r1,MODE_CHOICE(160,216) // Get pointer to results area.
|
||||
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
|
||||
mflr r4 // Move to r4.
|
||||
slwi r3,r3,4 // Now multiply return type by 16.
|
||||
add r3,r3,r4 // Add contents of table to table address.
|
||||
addi r5,r1,160 // Copy result storage pointer.
|
||||
bl Lget_ret_type0_addr // Get pointer to Lret_type0 into LR.
|
||||
mflr r4 // Move to r4.
|
||||
slwi r3,r3,4 // Multiply return type by 16.
|
||||
add r3,r3,r4 // Add contents of table to table address.
|
||||
mtctr r3
|
||||
bctr
|
||||
|
||||
|
@ -143,7 +129,7 @@ Lret_type0:
|
|||
|
||||
/* case FFI_TYPE_INT */
|
||||
Lret_type1:
|
||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
@ -171,42 +157,42 @@ Lret_type4:
|
|||
|
||||
/* case FFI_TYPE_UINT8 */
|
||||
Lret_type5:
|
||||
lbz r3,MODE_CHOICE(3,7)(r5)
|
||||
lbz r3,3(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT8 */
|
||||
Lret_type6:
|
||||
lbz r3,MODE_CHOICE(3,7)(r5)
|
||||
lbz r3,3(r5)
|
||||
extsb r3,r3
|
||||
b Lfinish
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT16 */
|
||||
Lret_type7:
|
||||
lhz r3,MODE_CHOICE(2,6)(r5)
|
||||
lhz r3,2(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT16 */
|
||||
Lret_type8:
|
||||
lha r3,MODE_CHOICE(2,6)(r5)
|
||||
lha r3,2(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_UINT32 */
|
||||
Lret_type9: // same as Lret_type1
|
||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
||||
/* case FFI_TYPE_SINT32 */
|
||||
Lret_type10: // same as Lret_type1
|
||||
lwz r3,MODE_CHOICE(0,4)(r5)
|
||||
lwz r3,0(r5)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
|
@ -227,7 +213,7 @@ Lret_type12: // same as Lret_type11
|
|||
|
||||
/* case FFI_TYPE_STRUCT */
|
||||
Lret_type13:
|
||||
b MODE_CHOICE(Lfinish,Lret_struct)
|
||||
b Lfinish
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
@ -239,12 +225,13 @@ Lret_type13:
|
|||
// padded to 16 bytes.
|
||||
Lret_type14:
|
||||
lg r3,0(r5)
|
||||
// fall through
|
||||
|
||||
/* case done */
|
||||
Lfinish:
|
||||
addi r1,r1,SF_ROUND(MODE_CHOICE(176,248)) // Restore stack pointer.
|
||||
lg r0,MODE_CHOICE(8,16)(r1) /* Get return address. */
|
||||
mtlr r0 /* Reset link register. */
|
||||
addi r1,r1,SF_ROUND(176) // Restore stack pointer.
|
||||
lg r0,SF_RETURN(r1) // Restore return address.
|
||||
mtlr r0 // Restore link register.
|
||||
blr
|
||||
|
||||
/* END(ffi_closure_ASM) */
|
||||
|
@ -261,7 +248,7 @@ LSCIE1:
|
|||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0x10 ; FDE Encoding (pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
|
@ -275,7 +262,7 @@ LSFDE1:
|
|||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
||||
.g_long LFB1-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB1
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
|
@ -317,9 +304,5 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
|
|||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
.g_long dyld_stub_binding_helper
|
||||
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long LFB1
|
||||
|
||||
#endif // __ppc__
|
||||
|
|
|
@ -28,13 +28,13 @@
|
|||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
#include "ffi.h"
|
||||
#include "ffi_common.h"
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ppc-darwin.h"
|
||||
#include <ppc-darwin.h>
|
||||
#include <architecture/ppc/mode_independent_asm.h>
|
||||
|
||||
#if 0
|
||||
|
@ -42,17 +42,14 @@
|
|||
#include <libkern/OSCacheControl.h> // for sys_icache_invalidate()
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* Explicit prototype instead of including a header to allow compilation
|
||||
* on Tiger systems.
|
||||
*/
|
||||
#else
|
||||
|
||||
#pragma weak sys_icache_invalidate
|
||||
extern void sys_icache_invalidate(void *start, size_t len);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
extern void ffi_closure_ASM(void);
|
||||
|
||||
// The layout of a function descriptor. A C function pointer really
|
||||
|
@ -760,9 +757,7 @@ ffi_prep_closure(
|
|||
|
||||
// Flush the icache. Only necessary on Darwin.
|
||||
#if defined(POWERPC_DARWIN)
|
||||
if (sys_icache_invalidate) {
|
||||
sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE);
|
||||
}
|
||||
sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE);
|
||||
#else
|
||||
flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE);
|
||||
#endif
|
||||
|
@ -804,6 +799,12 @@ ffi_prep_closure(
|
|||
} ldu;
|
||||
#endif
|
||||
|
||||
typedef union
|
||||
{
|
||||
float f;
|
||||
double d;
|
||||
} ffi_dblfl;
|
||||
|
||||
/* The trampoline invokes ffi_closure_ASM, and on entry, r11 holds the
|
||||
address of the closure. After storing the registers that could possibly
|
||||
contain parameters to be passed into the stack frame and setting up space
|
||||
|
@ -829,7 +830,7 @@ ffi_closure_helper_DARWIN(
|
|||
unsigned int nf = 0; /* number of FPRs already used. */
|
||||
unsigned int ng = 0; /* number of GPRs already used. */
|
||||
ffi_cif* cif = closure->cif;
|
||||
unsigned int avn = cif->nargs;
|
||||
long avn = cif->nargs;
|
||||
void** avalue = alloca(cif->nargs * sizeof(void*));
|
||||
ffi_type** arg_types = cif->arg_types;
|
||||
|
||||
|
@ -906,9 +907,9 @@ ffi_closure_helper_DARWIN(
|
|||
size_al = ALIGN(arg_types[i]->size, 8);
|
||||
|
||||
if (size_al < 3)
|
||||
avalue[i] = (char*)pgr + MODE_CHOICE(4,8) - size_al;
|
||||
avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al;
|
||||
else
|
||||
avalue[i] = (char*)pgr;
|
||||
avalue[i] = (void*)pgr;
|
||||
|
||||
ng += (size_al + 3) / sizeof(long);
|
||||
pgr += (size_al + 3) / sizeof(long);
|
||||
|
@ -988,8 +989,8 @@ ffi_closure_helper_DARWIN(
|
|||
We use a union to pass the long double to avalue[i]. */
|
||||
else if (nf == NUM_FPR_ARG_REGISTERS - 1)
|
||||
{
|
||||
memcpy (&temp_ld.lb[0], pfr, sizeof(ldbits));
|
||||
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(ldbits));
|
||||
memcpy (&temp_ld.lb[0], pfr, sizeof(temp_ld.lb[0]));
|
||||
memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1]));
|
||||
avalue[i] = &temp_ld.ld;
|
||||
}
|
||||
#else
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#if defined(__ppc64__)
|
||||
|
||||
/* -----------------------------------------------------------------------
|
||||
darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation,
|
||||
Inc. based on ppc_closure.S
|
||||
|
||||
PowerPC Assembly glue.
|
||||
|
@ -297,8 +297,8 @@ Lret_struct:
|
|||
|
||||
// case done
|
||||
Lfinish:
|
||||
lg r1,0(r1) // Restore stack pointer.
|
||||
ld r31,-8(r1) // Restore registers we used.
|
||||
lg r1,0(r1) // Restore stack pointer.
|
||||
ld r31,-8(r1) // Restore registers we used.
|
||||
ld r30,-16(r1)
|
||||
lg r0,SF_RETURN(r1) // Get return address.
|
||||
mtlr r0 // Reset link register.
|
||||
|
@ -318,7 +318,7 @@ LSCIE1:
|
|||
.byte 0x7c ; sleb128 -4; CIE Data Alignment Factor
|
||||
.byte 0x41 ; CIE RA Column
|
||||
.byte 0x1 ; uleb128 0x1; Augmentation size
|
||||
.byte 0x90 ; FDE Encoding (indirect pcrel)
|
||||
.byte 0x10 ; FDE Encoding (pcrel)
|
||||
.byte 0xc ; DW_CFA_def_cfa
|
||||
.byte 0x1 ; uleb128 0x1
|
||||
.byte 0x0 ; uleb128 0x0
|
||||
|
@ -332,7 +332,7 @@ LSFDE1:
|
|||
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1 ; FDE CIE offset
|
||||
.g_long LLFB1$non_lazy_ptr-. ; FDE initial location
|
||||
.g_long LFB1-. ; FDE initial location
|
||||
.set L$set$3,LFE1-LFB1
|
||||
.g_long L$set$3 ; FDE address range
|
||||
.byte 0x0 ; uleb128 0x0; Augmentation size
|
||||
|
@ -374,11 +374,6 @@ L_ffi_closure_helper_DARWIN$lazy_ptr:
|
|||
.indirect_symbol _ffi_closure_helper_DARWIN
|
||||
.g_long dyld_stub_binding_helper
|
||||
|
||||
.data
|
||||
.align LOG2_GPR_BYTES
|
||||
LLFB1$non_lazy_ptr:
|
||||
.g_long LFB1
|
||||
|
||||
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
|
||||
.align LOG2_GPR_BYTES
|
||||
|
||||
|
|
|
@ -46,23 +46,20 @@
|
|||
|
||||
.globl _ffi_prep_args
|
||||
|
||||
.align 4
|
||||
.align 4
|
||||
.globl _ffi_call_SYSV
|
||||
|
||||
_ffi_call_SYSV:
|
||||
.LFB1:
|
||||
LFB1:
|
||||
pushl %ebp
|
||||
.LCFI0:
|
||||
LCFI0:
|
||||
movl %esp,%ebp
|
||||
subl $8,%esp
|
||||
ASSERT_STACK_ALIGNED
|
||||
.LCFI1:
|
||||
LCFI1:
|
||||
subl $8,%esp
|
||||
/* Make room for all of the new args. */
|
||||
movl 16(%ebp),%ecx
|
||||
subl %ecx,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
movl %esp,%eax
|
||||
|
||||
/* Place all of the ffi_prep_args in position */
|
||||
|
@ -71,170 +68,349 @@ _ffi_call_SYSV:
|
|||
pushl %eax
|
||||
call *8(%ebp)
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
/* Return stack to previous state and call the function */
|
||||
addl $16,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
addl $16,%esp
|
||||
|
||||
call *28(%ebp)
|
||||
|
||||
/* XXX: return returns return with 'ret $4', that upsets the stack! */
|
||||
|
||||
/* Remove the space we pushed for the args */
|
||||
movl 16(%ebp),%ecx
|
||||
addl %ecx,%esp
|
||||
|
||||
|
||||
/* Load %ecx with the return type code */
|
||||
movl 20(%ebp),%ecx
|
||||
|
||||
|
||||
/* If the return value pointer is NULL, assume no return value. */
|
||||
cmpl $0,24(%ebp)
|
||||
jne retint
|
||||
jne Lretint
|
||||
|
||||
/* Even if there is no space for the return value, we are
|
||||
obliged to handle floating-point values. */
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne noretval
|
||||
jne Lnoretval
|
||||
fstp %st(0)
|
||||
|
||||
jmp epilogue
|
||||
jmp Lepilogue
|
||||
|
||||
retint:
|
||||
Lretint:
|
||||
cmpl $FFI_TYPE_INT,%ecx
|
||||
jne retfloat
|
||||
jne Lretfloat
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
jmp epilogue
|
||||
jmp Lepilogue
|
||||
|
||||
retfloat:
|
||||
Lretfloat:
|
||||
cmpl $FFI_TYPE_FLOAT,%ecx
|
||||
jne retdouble
|
||||
jne Lretdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstps (%ecx)
|
||||
jmp epilogue
|
||||
jmp Lepilogue
|
||||
|
||||
retdouble:
|
||||
Lretdouble:
|
||||
cmpl $FFI_TYPE_DOUBLE,%ecx
|
||||
jne retlongdouble
|
||||
jne Lretlongdouble
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstpl (%ecx)
|
||||
jmp epilogue
|
||||
jmp Lepilogue
|
||||
|
||||
retlongdouble:
|
||||
Lretlongdouble:
|
||||
cmpl $FFI_TYPE_LONGDOUBLE,%ecx
|
||||
jne retint64
|
||||
jne Lretint64
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
fstpt (%ecx)
|
||||
jmp epilogue
|
||||
jmp Lepilogue
|
||||
|
||||
retint64:
|
||||
Lretint64:
|
||||
cmpl $FFI_TYPE_SINT64,%ecx
|
||||
jne retstruct1b
|
||||
jne Lretstruct1b
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movl %eax,0(%ecx)
|
||||
movl %edx,4(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retstruct1b:
|
||||
cmpl $FFI_TYPE_SINT8,%ecx
|
||||
jne retstruct2b
|
||||
movl 24(%ebp),%ecx
|
||||
movb %al,0(%ecx)
|
||||
jmp epilogue
|
||||
|
||||
retstruct2b:
|
||||
cmpl $FFI_TYPE_SINT16,%ecx
|
||||
jne retstruct
|
||||
movl 24(%ebp),%ecx
|
||||
movw %ax,0(%ecx)
|
||||
jmp epilogue
|
||||
jmp Lepilogue
|
||||
|
||||
retstruct:
|
||||
cmpl $FFI_TYPE_STRUCT,%ecx
|
||||
jne noretval
|
||||
Lretstruct1b:
|
||||
cmpl $FFI_TYPE_SINT8,%ecx
|
||||
jne Lretstruct2b
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movb %al,0(%ecx)
|
||||
jmp Lepilogue
|
||||
|
||||
Lretstruct2b:
|
||||
cmpl $FFI_TYPE_SINT16,%ecx
|
||||
jne Lretstruct
|
||||
/* Load %ecx with the pointer to storage for the return value */
|
||||
movl 24(%ebp),%ecx
|
||||
movw %ax,0(%ecx)
|
||||
jmp Lepilogue
|
||||
|
||||
Lretstruct:
|
||||
cmpl $FFI_TYPE_STRUCT,%ecx
|
||||
jne Lnoretval
|
||||
/* Nothing to do! */
|
||||
addl $4,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
subl $4,%esp
|
||||
|
||||
ASSERT_STACK_ALIGNED
|
||||
|
||||
addl $8,%esp
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
noretval:
|
||||
epilogue:
|
||||
ASSERT_STACK_ALIGNED
|
||||
addl $8, %esp
|
||||
|
||||
|
||||
Lnoretval:
|
||||
Lepilogue:
|
||||
addl $8,%esp
|
||||
movl %ebp,%esp
|
||||
popl %ebp
|
||||
ret
|
||||
LFE1:
|
||||
.ffi_call_SYSV_end:
|
||||
#if 0
|
||||
.size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV
|
||||
|
||||
.align 4
|
||||
FFI_HIDDEN (ffi_closure_SYSV)
|
||||
.globl _ffi_closure_SYSV
|
||||
|
||||
_ffi_closure_SYSV:
|
||||
LFB2:
|
||||
pushl %ebp
|
||||
LCFI2:
|
||||
movl %esp, %ebp
|
||||
LCFI3:
|
||||
subl $56, %esp
|
||||
leal -40(%ebp), %edx
|
||||
movl %edx, -12(%ebp) /* resp */
|
||||
leal 8(%ebp), %edx
|
||||
movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */
|
||||
leal -12(%ebp), %edx
|
||||
movl %edx, (%esp) /* &resp */
|
||||
movl %ebx, 8(%esp)
|
||||
LCFI7:
|
||||
call L_ffi_closure_SYSV_inner$stub
|
||||
movl 8(%esp), %ebx
|
||||
movl -12(%ebp), %ecx
|
||||
cmpl $FFI_TYPE_INT, %eax
|
||||
je Lcls_retint
|
||||
cmpl $FFI_TYPE_FLOAT, %eax
|
||||
je Lcls_retfloat
|
||||
cmpl $FFI_TYPE_DOUBLE, %eax
|
||||
je Lcls_retdouble
|
||||
cmpl $FFI_TYPE_LONGDOUBLE, %eax
|
||||
je Lcls_retldouble
|
||||
cmpl $FFI_TYPE_SINT64, %eax
|
||||
je Lcls_retllong
|
||||
cmpl $FFI_TYPE_SINT8, %eax
|
||||
je Lcls_retstruct1
|
||||
cmpl $FFI_TYPE_SINT16, %eax
|
||||
je Lcls_retstruct2
|
||||
cmpl $FFI_TYPE_STRUCT, %eax
|
||||
je Lcls_retstruct
|
||||
Lcls_epilogue:
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
Lcls_retint:
|
||||
movl (%ecx), %eax
|
||||
jmp Lcls_epilogue
|
||||
Lcls_retfloat:
|
||||
flds (%ecx)
|
||||
jmp Lcls_epilogue
|
||||
Lcls_retdouble:
|
||||
fldl (%ecx)
|
||||
jmp Lcls_epilogue
|
||||
Lcls_retldouble:
|
||||
fldt (%ecx)
|
||||
jmp Lcls_epilogue
|
||||
Lcls_retllong:
|
||||
movl (%ecx), %eax
|
||||
movl 4(%ecx), %edx
|
||||
jmp Lcls_epilogue
|
||||
Lcls_retstruct1:
|
||||
movsbl (%ecx), %eax
|
||||
jmp Lcls_epilogue
|
||||
Lcls_retstruct2:
|
||||
movswl (%ecx), %eax
|
||||
jmp Lcls_epilogue
|
||||
Lcls_retstruct:
|
||||
lea -8(%ebp),%esp
|
||||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret $4
|
||||
LFE2:
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3)
|
||||
#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4)
|
||||
#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4)
|
||||
#define CIF_FLAGS_OFFSET 20
|
||||
|
||||
.align 4
|
||||
FFI_HIDDEN (ffi_closure_raw_SYSV)
|
||||
.globl _ffi_closure_raw_SYSV
|
||||
|
||||
_ffi_closure_raw_SYSV:
|
||||
LFB3:
|
||||
pushl %ebp
|
||||
LCFI4:
|
||||
movl %esp, %ebp
|
||||
LCFI5:
|
||||
pushl %esi
|
||||
LCFI6:
|
||||
subl $36, %esp
|
||||
movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */
|
||||
movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */
|
||||
movl %edx, 12(%esp) /* user_data */
|
||||
leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */
|
||||
movl %edx, 8(%esp) /* raw_args */
|
||||
leal -24(%ebp), %edx
|
||||
movl %edx, 4(%esp) /* &res */
|
||||
movl %esi, (%esp) /* cif */
|
||||
call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */
|
||||
movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */
|
||||
cmpl $FFI_TYPE_INT, %eax
|
||||
je Lrcls_retint
|
||||
cmpl $FFI_TYPE_FLOAT, %eax
|
||||
je Lrcls_retfloat
|
||||
cmpl $FFI_TYPE_DOUBLE, %eax
|
||||
je Lrcls_retdouble
|
||||
cmpl $FFI_TYPE_LONGDOUBLE, %eax
|
||||
je Lrcls_retldouble
|
||||
cmpl $FFI_TYPE_SINT64, %eax
|
||||
je Lrcls_retllong
|
||||
Lrcls_epilogue:
|
||||
addl $36, %esp
|
||||
popl %esi
|
||||
popl %ebp
|
||||
ret
|
||||
Lrcls_retint:
|
||||
movl -24(%ebp), %eax
|
||||
jmp Lrcls_epilogue
|
||||
Lrcls_retfloat:
|
||||
flds -24(%ebp)
|
||||
jmp Lrcls_epilogue
|
||||
Lrcls_retdouble:
|
||||
fldl -24(%ebp)
|
||||
jmp Lrcls_epilogue
|
||||
Lrcls_retldouble:
|
||||
fldt -24(%ebp)
|
||||
jmp Lrcls_epilogue
|
||||
Lrcls_retllong:
|
||||
movl -24(%ebp), %eax
|
||||
movl -20(%ebp), %edx
|
||||
jmp Lrcls_epilogue
|
||||
LFE3:
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
.section .eh_frame,EH_FRAME_FLAGS,@progbits
|
||||
.Lframe1:
|
||||
.long .LECIE1-.LSCIE1 /* Length of Common Information Entry */
|
||||
.LSCIE1:
|
||||
.long 0x0 /* CIE Identifier Tag */
|
||||
.byte 0x1 /* CIE Version */
|
||||
#ifdef __PIC__
|
||||
.ascii "zR\0" /* CIE Augmentation */
|
||||
#else
|
||||
.ascii "\0" /* CIE Augmentation */
|
||||
#endif
|
||||
.byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */
|
||||
.byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */
|
||||
.byte 0x8 /* CIE RA Column */
|
||||
#ifdef __PIC__
|
||||
.byte 0x1 /* .uleb128 0x1; Augmentation size */
|
||||
.byte 0x1b /* FDE Encoding (pcrel sdata4) */
|
||||
#endif
|
||||
.byte 0xc /* DW_CFA_def_cfa */
|
||||
.byte 0x4 /* .uleb128 0x4 */
|
||||
.byte 0x4 /* .uleb128 0x4 */
|
||||
.byte 0x88 /* DW_CFA_offset, column 0x8 */
|
||||
.byte 0x1 /* .uleb128 0x1 */
|
||||
.align 4
|
||||
.LECIE1:
|
||||
.LSFDE1:
|
||||
.long .LEFDE1-.LASFDE1 /* FDE Length */
|
||||
.LASFDE1:
|
||||
.long .LASFDE1-.Lframe1 /* FDE CIE offset */
|
||||
#ifdef __PIC__
|
||||
.long .LFB1-. /* FDE initial location */
|
||||
#else
|
||||
.long .LFB1 /* FDE initial location */
|
||||
#endif
|
||||
.long .ffi_call_SYSV_end-.LFB1 /* FDE address range */
|
||||
#ifdef __PIC__
|
||||
.byte 0x0 /* .uleb128 0x0; Augmentation size */
|
||||
#endif
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI0-.LFB1
|
||||
.byte 0xe /* DW_CFA_def_cfa_offset */
|
||||
.byte 0x8 /* .uleb128 0x8 */
|
||||
.byte 0x85 /* DW_CFA_offset, column 0x5 */
|
||||
.byte 0x2 /* .uleb128 0x2 */
|
||||
.byte 0x4 /* DW_CFA_advance_loc4 */
|
||||
.long .LCFI1-.LCFI0
|
||||
.byte 0xd /* DW_CFA_def_cfa_register */
|
||||
.byte 0x5 /* .uleb128 0x5 */
|
||||
.align 4
|
||||
.LEFDE1:
|
||||
.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
|
||||
L_ffi_closure_SYSV_inner$stub:
|
||||
.indirect_symbol _ffi_closure_SYSV_inner
|
||||
hlt ; hlt ; hlt ; hlt ; hlt
|
||||
|
||||
|
||||
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
|
||||
EH_frame1:
|
||||
.set L$set$0,LECIE1-LSCIE1
|
||||
.long L$set$0
|
||||
LSCIE1:
|
||||
.long 0x0
|
||||
.byte 0x1
|
||||
.ascii "zR\0"
|
||||
.byte 0x1
|
||||
.byte 0x7c
|
||||
.byte 0x8
|
||||
.byte 0x1
|
||||
.byte 0x10
|
||||
.byte 0xc
|
||||
.byte 0x5
|
||||
.byte 0x4
|
||||
.byte 0x88
|
||||
.byte 0x1
|
||||
.align 2
|
||||
LECIE1:
|
||||
.globl _ffi_call_SYSV.eh
|
||||
_ffi_call_SYSV.eh:
|
||||
LSFDE1:
|
||||
.set L$set$1,LEFDE1-LASFDE1
|
||||
.long L$set$1
|
||||
LASFDE1:
|
||||
.long LASFDE1-EH_frame1
|
||||
.long LFB1-.
|
||||
.set L$set$2,LFE1-LFB1
|
||||
.long L$set$2
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$3,LCFI0-LFB1
|
||||
.long L$set$3
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x84
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$4,LCFI1-LCFI0
|
||||
.long L$set$4
|
||||
.byte 0xd
|
||||
.byte 0x4
|
||||
.align 2
|
||||
LEFDE1:
|
||||
.globl _ffi_closure_SYSV.eh
|
||||
_ffi_closure_SYSV.eh:
|
||||
LSFDE2:
|
||||
.set L$set$5,LEFDE2-LASFDE2
|
||||
.long L$set$5
|
||||
LASFDE2:
|
||||
.long LASFDE2-EH_frame1
|
||||
.long LFB2-.
|
||||
.set L$set$6,LFE2-LFB2
|
||||
.long L$set$6
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$7,LCFI2-LFB2
|
||||
.long L$set$7
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x84
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$8,LCFI3-LCFI2
|
||||
.long L$set$8
|
||||
.byte 0xd
|
||||
.byte 0x4
|
||||
.align 2
|
||||
LEFDE2:
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
.globl _ffi_closure_raw_SYSV.eh
|
||||
_ffi_closure_raw_SYSV.eh:
|
||||
LSFDE3:
|
||||
.set L$set$10,LEFDE3-LASFDE3
|
||||
.long L$set$10
|
||||
LASFDE3:
|
||||
.long LASFDE3-EH_frame1
|
||||
.long LFB3-.
|
||||
.set L$set$11,LFE3-LFB3
|
||||
.long L$set$11
|
||||
.byte 0x0
|
||||
.byte 0x4
|
||||
.set L$set$12,LCFI4-LFB3
|
||||
.long L$set$12
|
||||
.byte 0xe
|
||||
.byte 0x8
|
||||
.byte 0x84
|
||||
.byte 0x2
|
||||
.byte 0x4
|
||||
.set L$set$13,LCFI5-LCFI4
|
||||
.long L$set$13
|
||||
.byte 0xd
|
||||
.byte 0x4
|
||||
.byte 0x4
|
||||
.set L$set$14,LCFI6-LCFI5
|
||||
.long L$set$14
|
||||
.byte 0x85
|
||||
.byte 0x3
|
||||
.align 2
|
||||
LEFDE3:
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ifndef __x86_64__ */
|
||||
|
|
|
@ -55,7 +55,7 @@ ffi_call_unix64(
|
|||
/* Register class used for passing given 64bit part of the argument.
|
||||
These represent classes as documented by the PS ABI, with the exception
|
||||
of SSESF, SSEDF classes, that are basically SSE class, just gcc will
|
||||
use SF or DFmode move instead of DImode to avoid reformatting penalties.
|
||||
use SF or DFmode move instead of DImode to avoid reformating penalties.
|
||||
|
||||
Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves
|
||||
whenever possible (upper half does contain padding). */
|
||||
|
@ -621,4 +621,4 @@ ffi_closure_unix64_inner(
|
|||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
#endif /* __x86_64__ */
|
|
@ -27,543 +27,410 @@
|
|||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
----------------------------------------------------------------------- */
|
||||
|
||||
//#ifndef __x86_64__
|
||||
|
||||
#include <ffi.h>
|
||||
#include <ffi_common.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
//void ffi_prep_args(char *stack, extended_cif *ecif);
|
||||
|
||||
static inline int
|
||||
retval_on_stack(
|
||||
ffi_type* tp)
|
||||
{
|
||||
if (tp->type == FFI_TYPE_STRUCT)
|
||||
{
|
||||
// int size = tp->size;
|
||||
|
||||
if (tp->size > 8)
|
||||
return 1;
|
||||
|
||||
switch (tp->size)
|
||||
{
|
||||
case 1: case 2: case 4: case 8:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ffi_prep_args is called by the assembly routine once stack space
|
||||
has been allocated for the function's arguments */
|
||||
/*@-exportheader@*/
|
||||
extern void ffi_prep_args(char*, extended_cif*);
|
||||
void
|
||||
ffi_prep_args(
|
||||
char* stack,
|
||||
extended_cif* ecif)
|
||||
/*@=exportheader@*/
|
||||
has been allocated for the function's arguments */
|
||||
|
||||
void ffi_prep_args(char *stack, extended_cif *ecif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void** p_argv = ecif->avalue;
|
||||
register char* argp = stack;
|
||||
register ffi_type** p_arg;
|
||||
|
||||
if (retval_on_stack(ecif->cif->rtype))
|
||||
{
|
||||
*(void**)argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_arg = ecif->cif->arg_types;
|
||||
|
||||
for (i = ecif->cif->nargs; i > 0; i--, p_arg++, p_argv++)
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if (ecif->cif->flags == FFI_TYPE_STRUCT)
|
||||
{
|
||||
size_t z = (*p_arg)->size;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned)argp)
|
||||
argp = (char*)ALIGN(argp, sizeof(int));
|
||||
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
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;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(signed int*)argp = (signed int)*(SINT32*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int*)argp = (unsigned int)*(UINT32*)(*p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
memcpy(argp, *p_argv, z);
|
||||
|
||||
argp += z;
|
||||
}
|
||||
*(void **) argp = ecif->rvalue;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = ecif->avalue;
|
||||
|
||||
for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types;
|
||||
i != 0;
|
||||
i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned) argp)
|
||||
argp = (char *) ALIGN(argp, sizeof(int));
|
||||
|
||||
z = (*p_arg)->size;
|
||||
if (z < sizeof(int))
|
||||
{
|
||||
z = sizeof(int);
|
||||
switch ((*p_arg)->type)
|
||||
{
|
||||
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;
|
||||
|
||||
case FFI_TYPE_SINT32:
|
||||
*(signed int *) argp = (signed int)*(SINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT32:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
case FFI_TYPE_STRUCT:
|
||||
*(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv);
|
||||
break;
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(argp, *p_argv, z);
|
||||
}
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Perform machine dependent cif processing */
|
||||
ffi_status
|
||||
ffi_prep_cif_machdep(
|
||||
ffi_cif* cif)
|
||||
ffi_status ffi_prep_cif_machdep(ffi_cif *cif)
|
||||
{
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
#if !defined(X86_WIN32) && !defined(X86_DARWIN)
|
||||
case FFI_TYPE_STRUCT:
|
||||
/* Set the return type flag */
|
||||
switch (cif->rtype->type)
|
||||
{
|
||||
case FFI_TYPE_VOID:
|
||||
#ifdef X86
|
||||
case FFI_TYPE_STRUCT:
|
||||
case FFI_TYPE_UINT8:
|
||||
case FFI_TYPE_UINT16:
|
||||
case FFI_TYPE_SINT8:
|
||||
case FFI_TYPE_SINT16:
|
||||
#endif
|
||||
case FFI_TYPE_VOID:
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
cif->flags = (unsigned)cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
||||
case FFI_TYPE_STRUCT:
|
||||
switch (cif->rtype->size)
|
||||
{
|
||||
case 1:
|
||||
cif->flags = FFI_TYPE_SINT8;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
cif->flags = FFI_TYPE_SINT16;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FFI_TYPE_SINT64:
|
||||
case FFI_TYPE_FLOAT:
|
||||
case FFI_TYPE_DOUBLE:
|
||||
case FFI_TYPE_LONGDOUBLE:
|
||||
cif->flags = (unsigned) cif->rtype->type;
|
||||
break;
|
||||
|
||||
case FFI_TYPE_UINT64:
|
||||
cif->flags = FFI_TYPE_SINT64;
|
||||
break;
|
||||
|
||||
#ifndef X86
|
||||
case FFI_TYPE_STRUCT:
|
||||
if (cif->rtype->size == 1)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT8; /* same as char size */
|
||||
}
|
||||
else if (cif->rtype->size == 2)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT16; /* same as short size */
|
||||
}
|
||||
else if (cif->rtype->size == 4)
|
||||
{
|
||||
cif->flags = FFI_TYPE_INT; /* same as int type */
|
||||
}
|
||||
else if (cif->rtype->size == 8)
|
||||
{
|
||||
cif->flags = FFI_TYPE_SINT64; /* same as int64 type */
|
||||
}
|
||||
else
|
||||
{
|
||||
cif->flags = FFI_TYPE_STRUCT;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Darwin: The stack needs to be aligned to a multiple of 16 bytes */
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
|
||||
return FFI_OK;
|
||||
|
||||
default:
|
||||
cif->flags = FFI_TYPE_INT;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef X86_DARWIN
|
||||
cif->bytes = (cif->bytes + 15) & ~0xF;
|
||||
#endif
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void
|
||||
ffi_call_SYSV(
|
||||
void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif* ,
|
||||
unsigned ,
|
||||
unsigned ,
|
||||
/*@out@*/ unsigned* ,
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)());
|
||||
|
||||
#ifdef X86_WIN32
|
||||
/*@-declundef@*/
|
||||
/*@-exportheader@*/
|
||||
extern void
|
||||
ffi_call_STDCALL(
|
||||
void (char *, extended_cif *),
|
||||
/*@out@*/ extended_cif* ,
|
||||
unsigned ,
|
||||
unsigned ,
|
||||
/*@out@*/ unsigned* ,
|
||||
void (*fn)(void));
|
||||
/*@=declundef@*/
|
||||
/*@=exportheader@*/
|
||||
extern void ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *,
|
||||
unsigned, unsigned, unsigned *, void (*fn)());
|
||||
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
void
|
||||
ffi_call(
|
||||
/*@dependent@*/ ffi_cif* cif,
|
||||
void (*fn)(void),
|
||||
/*@out@*/ void* rvalue,
|
||||
/*@dependent@*/ void** avalue)
|
||||
void ffi_call(ffi_cif *cif, void (*fn)(), 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) && retval_on_stack(cif->rtype))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
/* To avoid changing the assembly code make sure the size of the argument
|
||||
block is a multiple of 16. Then add 8 to compensate for local variables
|
||||
in ffi_call_SYSV. */
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
|
||||
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->flags == FFI_TYPE_STRUCT))
|
||||
{
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, cif->flags, ecif.rvalue,
|
||||
fn);
|
||||
break;
|
||||
#ifdef X86_WIN32
|
||||
case FFI_STDCALL:
|
||||
/*@-usedef@*/
|
||||
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
case FFI_STDCALL:
|
||||
ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** private members **/
|
||||
|
||||
static void
|
||||
ffi_closure_SYSV(
|
||||
ffi_closure* closure) __attribute__((regparm(1)));
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
static void
|
||||
ffi_closure_raw_SYSV(
|
||||
ffi_raw_closure* closure) __attribute__((regparm(1)));
|
||||
#endif
|
||||
|
||||
/*@-exportheader@*/
|
||||
static inline
|
||||
void
|
||||
ffi_prep_incoming_args_SYSV(
|
||||
char* stack,
|
||||
void** rvalue,
|
||||
void** avalue,
|
||||
ffi_cif* cif)
|
||||
/*@=exportheader@*/
|
||||
{
|
||||
register unsigned int i;
|
||||
register void** p_argv = avalue;
|
||||
register char* argp = stack;
|
||||
register ffi_type** p_arg;
|
||||
|
||||
if (retval_on_stack(cif->rtype))
|
||||
{
|
||||
*rvalue = *(void**)argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; i > 0; i--, p_arg++, p_argv++)
|
||||
{
|
||||
// size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned)argp)
|
||||
argp = (char*)ALIGN(argp, sizeof(int));
|
||||
|
||||
// z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
*p_argv = (void*)argp;
|
||||
|
||||
argp += (*p_arg)->size;
|
||||
}
|
||||
}
|
||||
static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
|
||||
void** args, ffi_cif* cif);
|
||||
void FFI_HIDDEN ffi_closure_SYSV (ffi_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
unsigned int FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *, void **, void *)
|
||||
__attribute__ ((regparm(1)));
|
||||
void FFI_HIDDEN ffi_closure_raw_SYSV (ffi_raw_closure *)
|
||||
__attribute__ ((regparm(1)));
|
||||
|
||||
/* This function is jumped to by the trampoline */
|
||||
__attribute__((regparm(1)))
|
||||
static void
|
||||
ffi_closure_SYSV(
|
||||
ffi_closure* closure)
|
||||
|
||||
unsigned int FFI_HIDDEN
|
||||
ffi_closure_SYSV_inner (closure, respp, args)
|
||||
ffi_closure *closure;
|
||||
void **respp;
|
||||
void *args;
|
||||
{
|
||||
long double res;
|
||||
ffi_cif* cif = closure->cif;
|
||||
void** arg_area = (void**)alloca(cif->nargs * sizeof(void*));
|
||||
void* resp = (void*)&res;
|
||||
void* args = __builtin_dwarf_cfa();
|
||||
|
||||
/* This call will initialize ARG_AREA, such that each
|
||||
element in that array points to the corresponding
|
||||
value on the stack; and if the function returns
|
||||
a structure, it will reset RESP to point to the
|
||||
structure return address. */
|
||||
ffi_prep_incoming_args_SYSV(args, (void**)&resp, arg_area, cif);
|
||||
|
||||
(closure->fun)(cif, resp, arg_area, closure->user_data);
|
||||
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (cif->flags == FFI_TYPE_INT)
|
||||
asm("movl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
else if (cif->flags == FFI_TYPE_FLOAT)
|
||||
asm("flds (%0)"
|
||||
: : "r" (resp) : "st");
|
||||
else if (cif->flags == FFI_TYPE_DOUBLE)
|
||||
asm("fldl (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (cif->flags == FFI_TYPE_LONGDOUBLE)
|
||||
asm("fldt (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (cif->flags == FFI_TYPE_SINT64)
|
||||
asm("movl 0(%0),%%eax;"
|
||||
"movl 4(%0),%%edx"
|
||||
: : "r" (resp)
|
||||
: "eax", "edx");
|
||||
|
||||
#if defined(X86_WIN32) || defined(X86_DARWIN)
|
||||
else if (cif->flags == FFI_TYPE_SINT8) /* 1-byte struct */
|
||||
asm("movsbl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
else if (cif->flags == FFI_TYPE_SINT16) /* 2-bytes struct */
|
||||
asm("movswl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
#endif
|
||||
|
||||
else if (cif->flags == FFI_TYPE_STRUCT)
|
||||
asm("lea -8(%ebp),%esp;"
|
||||
"pop %esi;"
|
||||
"pop %edi;"
|
||||
"pop %ebp;"
|
||||
"ret $4");
|
||||
// our various things...
|
||||
ffi_cif *cif;
|
||||
void **arg_area;
|
||||
|
||||
cif = closure->cif;
|
||||
arg_area = (void**) alloca (cif->nargs * sizeof (void*));
|
||||
|
||||
/* this call will initialize ARG_AREA, such that each
|
||||
* element in that array points to the corresponding
|
||||
* value on the stack; and if the function returns
|
||||
* a structure, it will re-set RESP to point to the
|
||||
* structure return address. */
|
||||
|
||||
ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif);
|
||||
|
||||
(closure->fun) (cif, *respp, arg_area, closure->user_data);
|
||||
|
||||
return cif->flags;
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
|
||||
ffi_cif *cif)
|
||||
{
|
||||
register unsigned int i;
|
||||
register void **p_argv;
|
||||
register char *argp;
|
||||
register ffi_type **p_arg;
|
||||
|
||||
argp = stack;
|
||||
|
||||
if ( cif->flags == FFI_TYPE_STRUCT ) {
|
||||
*rvalue = *(void **) argp;
|
||||
argp += 4;
|
||||
}
|
||||
|
||||
p_argv = avalue;
|
||||
|
||||
for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++)
|
||||
{
|
||||
size_t z;
|
||||
|
||||
/* Align if necessary */
|
||||
if ((sizeof(int) - 1) & (unsigned) argp) {
|
||||
argp = (char *) ALIGN(argp, sizeof(int));
|
||||
}
|
||||
|
||||
z = (*p_arg)->size;
|
||||
|
||||
/* because we're little endian, this is what it turns into. */
|
||||
|
||||
*p_argv = (void*) argp;
|
||||
|
||||
p_argv++;
|
||||
argp += z;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* How to make a trampoline. Derived from gcc/config/i386/i386.c. */
|
||||
#define FFI_INIT_TRAMPOLINE(TRAMP, FUN, CTX) \
|
||||
({ \
|
||||
unsigned char* __tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - ((unsigned int)__tramp + FFI_TRAMPOLINE_SIZE); \
|
||||
*(unsigned char*)&__tramp[0] = 0xb8; \
|
||||
*(unsigned int*)&__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char*)&__tramp[5] = 0xe9; \
|
||||
*(unsigned int*)&__tramp[6] = __dis; /* jmp __fun */ \
|
||||
})
|
||||
|
||||
#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \
|
||||
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
|
||||
unsigned int __fun = (unsigned int)(FUN); \
|
||||
unsigned int __ctx = (unsigned int)(CTX); \
|
||||
unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
|
||||
*(unsigned char*) &__tramp[0] = 0xb8; \
|
||||
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
|
||||
*(unsigned char *) &__tramp[5] = 0xe9; \
|
||||
*(unsigned int*) &__tramp[6] = __dis; /* jmp __fun */ \
|
||||
})
|
||||
|
||||
|
||||
/* the cif must already be prep'ed */
|
||||
ffi_status
|
||||
ffi_prep_closure(
|
||||
ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void* user_data)
|
||||
ffi_prep_closure (ffi_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,void**,void*),
|
||||
void *user_data)
|
||||
{
|
||||
// FFI_ASSERT(cif->abi == FFI_SYSV);
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_SYSV, (void*)closure);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
|
||||
&ffi_closure_SYSV, \
|
||||
(void*)closure);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
/* ------- Native raw API support -------------------------------- */
|
||||
|
||||
#if !FFI_NO_RAW_API
|
||||
|
||||
__attribute__((regparm(1)))
|
||||
static void
|
||||
ffi_closure_raw_SYSV(
|
||||
ffi_raw_closure* closure)
|
||||
{
|
||||
long double res;
|
||||
ffi_raw* raw_args = (ffi_raw*)__builtin_dwarf_cfa();
|
||||
ffi_cif* cif = closure->cif;
|
||||
unsigned short rtype = cif->flags;
|
||||
void* resp = (void*)&res;
|
||||
|
||||
(closure->fun)(cif, resp, raw_args, closure->user_data);
|
||||
|
||||
/* now, do a generic return based on the value of rtype */
|
||||
if (rtype == FFI_TYPE_INT)
|
||||
asm("movl (%0),%%eax"
|
||||
: : "r" (resp) : "eax");
|
||||
else if (rtype == FFI_TYPE_FLOAT)
|
||||
asm("flds (%0)"
|
||||
: : "r" (resp) : "st");
|
||||
else if (rtype == FFI_TYPE_DOUBLE)
|
||||
asm("fldl (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (rtype == FFI_TYPE_LONGDOUBLE)
|
||||
asm("fldt (%0)"
|
||||
: : "r" (resp) : "st", "st(1)");
|
||||
else if (rtype == FFI_TYPE_SINT64)
|
||||
asm("movl 0(%0),%%eax;"
|
||||
"movl 4(%0),%%edx"
|
||||
: : "r" (resp) : "eax", "edx");
|
||||
}
|
||||
|
||||
ffi_status
|
||||
ffi_prep_raw_closure(
|
||||
ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void* user_data)
|
||||
ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
|
||||
ffi_cif* cif,
|
||||
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
|
||||
void *user_data,
|
||||
void *codeloc)
|
||||
{
|
||||
// FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
if (cif->abi != FFI_SYSV)
|
||||
return FFI_BAD_ABI;
|
||||
|
||||
int i;
|
||||
|
||||
/* We currently don't support certain kinds of arguments for raw
|
||||
closures. This should be implemented by a separate assembly language
|
||||
routine, since it would require argument processing, something we
|
||||
don't do now for performance. */
|
||||
for (i = cif->nargs - 1; i >= 0; i--)
|
||||
{
|
||||
FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||
FFI_ASSERT(cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
FFI_INIT_TRAMPOLINE(closure->tramp, &ffi_closure_raw_SYSV, (void*)closure);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
int i;
|
||||
|
||||
FFI_ASSERT (cif->abi == FFI_SYSV);
|
||||
|
||||
// we currently don't support certain kinds of arguments for raw
|
||||
// closures. This should be implemented by a separate assembly language
|
||||
// routine, since it would require argument processing, something we
|
||||
// don't do now for performance.
|
||||
|
||||
for (i = cif->nargs-1; i >= 0; i--)
|
||||
{
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT);
|
||||
FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE);
|
||||
}
|
||||
|
||||
|
||||
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
|
||||
codeloc);
|
||||
|
||||
closure->cif = cif;
|
||||
closure->user_data = user_data;
|
||||
closure->fun = fun;
|
||||
|
||||
return FFI_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ffi_prep_args_raw(
|
||||
char* stack,
|
||||
extended_cif* ecif)
|
||||
ffi_prep_args_raw(char *stack, extended_cif *ecif)
|
||||
{
|
||||
memcpy(stack, ecif->avalue, ecif->cif->bytes);
|
||||
memcpy (stack, ecif->avalue, ecif->cif->bytes);
|
||||
}
|
||||
|
||||
/* We borrow this routine from libffi (it must be changed, though, to
|
||||
actually call the function passed in the first argument. as of
|
||||
libffi-1.20, this is not the case.) */
|
||||
//extern void
|
||||
//ffi_call_SYSV(
|
||||
// void (*)(char *, extended_cif *),
|
||||
///*@out@*/ extended_cif* ,
|
||||
// unsigned ,
|
||||
// unsigned ,
|
||||
//*@out@*/ unsigned* ,
|
||||
// void (*fn)());
|
||||
/* we borrow this routine from libffi (it must be changed, though, to
|
||||
* actually call the function passed in the first argument. as of
|
||||
* libffi-1.20, this is not the case.)
|
||||
*/
|
||||
|
||||
extern void
|
||||
ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)());
|
||||
|
||||
#ifdef X86_WIN32
|
||||
extern void
|
||||
ffi_call_STDCALL(
|
||||
void (*)(char *, extended_cif *),
|
||||
/*@out@*/ extended_cif* ,
|
||||
unsigned ,
|
||||
unsigned ,
|
||||
/*@out@*/ unsigned* ,
|
||||
void (*fn)());
|
||||
#endif // X86_WIN32
|
||||
ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned,
|
||||
unsigned, unsigned *, void (*fn)());
|
||||
#endif /* X86_WIN32 */
|
||||
|
||||
void
|
||||
ffi_raw_call(
|
||||
/*@dependent@*/ ffi_cif* cif,
|
||||
void (*fn)(),
|
||||
/*@out@*/ void* rvalue,
|
||||
/*@dependent@*/ ffi_raw* fake_avalue)
|
||||
ffi_raw_call(ffi_cif *cif, void (*fn)(), void *rvalue, ffi_raw *fake_avalue)
|
||||
{
|
||||
extended_cif ecif;
|
||||
void **avalue = (void **)fake_avalue;
|
||||
|
||||
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) && retval_on_stack(cif->rtype))
|
||||
{
|
||||
/*@-sysunrecog@*/
|
||||
ecif.rvalue = alloca(cif->rtype->size);
|
||||
/*@=sysunrecog@*/
|
||||
}
|
||||
else
|
||||
ecif.rvalue = rvalue;
|
||||
|
||||
switch (cif->abi)
|
||||
{
|
||||
case FFI_SYSV:
|
||||
/*@-usedef@*/
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
extended_cif ecif;
|
||||
void **avalue = (void **)fake_avalue;
|
||||
|
||||
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_SYSV:
|
||||
ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#ifdef X86_WIN32
|
||||
case FFI_STDCALL:
|
||||
/*@-usedef@*/
|
||||
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes,
|
||||
cif->flags, ecif.rvalue, fn);
|
||||
/*@=usedef@*/
|
||||
break;
|
||||
case FFI_STDCALL:
|
||||
ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags,
|
||||
ecif.rvalue, fn);
|
||||
break;
|
||||
#endif /* X86_WIN32 */
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
default:
|
||||
FFI_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !FFI_NO_RAW_API
|
||||
//#endif // !__x86_64__
|
||||
#endif // __i386__
|
||||
#endif
|
||||
#endif // __i386__
|
Loading…
Reference in New Issue