Commit 3521ba8b by Alan Modra

PowerPC64 ELFv2 support

PowerPC64 ELFv2 support
	* src/powerpc/ffitarget.h: Import from upstream.
	* src/powerpc/ffi.c: Likewise.
	* src/powerpc/linux64.S: Likewise.
	* src/powerpc/linux64_closure.S: Likewise.
	* doc/libffi.texi: Likewise.
	* testsuite/libffi.call/cls_double_va.c: Likewise.
	* testsuite/libffi.call/cls_longdouble_va.c: Likewise.

From-SVN: r204917
parent abe6cd5d
2013-11-18 Alan Modra <amodra@gmail.com>
* src/powerpc/ffitarget.h: Import from upstream.
* src/powerpc/ffi.c: Likewise.
* src/powerpc/linux64.S: Likewise.
* src/powerpc/linux64_closure.S: Likewise.
* doc/libffi.texi: Likewise.
* testsuite/libffi.call/cls_double_va.c: Likewise.
* testsuite/libffi.call/cls_longdouble_va.c: Likewise.
2013-09-20 Alan Modra <amodra@gmail.com>
* configure: Regenerate.
......
......@@ -184,11 +184,11 @@ This calls the function @var{fn} according to the description given in
@var{rvalue} is a pointer to a chunk of memory that will hold the
result of the function call. This must be large enough to hold the
result and must be suitably aligned; it is the caller's responsibility
result, no smaller than the system register size (generally 32 or 64
bits), and must be suitably aligned; it is the caller's responsibility
to ensure this. If @var{cif} declares that the function returns
@code{void} (using @code{ffi_type_void}), then @var{rvalue} is
ignored. If @var{rvalue} is @samp{NULL}, then the return value is
discarded.
ignored.
@var{avalues} is a vector of @code{void *} pointers that point to the
memory locations holding the argument values for a call. If @var{cif}
......@@ -214,7 +214,7 @@ int main()
ffi_type *args[1];
void *values[1];
char *s;
int rc;
ffi_arg rc;
/* Initialize the argument info vectors */
args[0] = &ffi_type_pointer;
......@@ -222,7 +222,7 @@ int main()
/* Initialize the cif */
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ffi_type_uint, args) == FFI_OK)
&ffi_type_sint, args) == FFI_OK)
@{
s = "Hello World!";
ffi_call(&cif, puts, &rc, values);
......@@ -360,7 +360,7 @@ You must first describe the structure to @samp{libffi} by creating a
new @code{ffi_type} object for it.
@tindex ffi_type
@deftp ffi_type
@deftp {Data type} ffi_type
The @code{ffi_type} has the following members:
@table @code
@item size_t size
......@@ -414,6 +414,7 @@ Here is the corresponding code to describe this struct to
int i;
tm_type.size = tm_type.alignment = 0;
tm_type.type = FFI_TYPE_STRUCT;
tm_type.elements = &tm_type_elements;
for (i = 0; i < 9; i++)
......@@ -540,19 +541,21 @@ A trivial example that creates a new @code{puts} by binding
#include <ffi.h>
/* Acts like puts with the file given at time of enclosure. */
void puts_binding(ffi_cif *cif, unsigned int *ret, void* args[],
FILE *stream)
void puts_binding(ffi_cif *cif, void *ret, void* args[],
void *stream)
@{
*ret = fputs(*(char **)args[0], stream);
*(ffi_arg *)ret = fputs(*(char **)args[0], (FILE *)stream);
@}
typedef int (*puts_t)(char *);
int main()
@{
ffi_cif cif;
ffi_type *args[1];
ffi_closure *closure;
int (*bound_puts)(char *);
void *bound_puts;
int rc;
/* Allocate closure and bound_puts */
......@@ -565,13 +568,13 @@ int main()
/* Initialize the cif */
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
&ffi_type_uint, args) == FFI_OK)
&ffi_type_sint, args) == FFI_OK)
@{
/* Initialize the closure, setting stream to stdout */
if (ffi_prep_closure_loc(closure, &cif, puts_binding,
stdout, bound_puts) == FFI_OK)
@{
rc = bound_puts("Hello World!");
rc = ((puts_t)bound_puts)("Hello World!");
/* rc now holds the result of the call to fputs */
@}
@}
......
......@@ -106,6 +106,10 @@ typedef enum ffi_abi {
#define FFI_CLOSURES 1
#define FFI_NATIVE_RAW_API 0
#if defined (POWERPC) || defined (POWERPC_FREEBSD)
# define FFI_TARGET_SPECIFIC_VARIADIC 1
# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs
#endif
/* For additional types like the below, take care about the order in
ppc_closures.S. They must follow after the FFI_TYPE_LAST. */
......@@ -118,14 +122,23 @@ typedef enum ffi_abi {
defined in ffi.c, to determine the exact return type and its size. */
#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2)
#if defined(POWERPC64) || defined(POWERPC_AIX)
/* Used by ELFv2 for homogenous structure returns. */
#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_TYPE_LAST + 1)
#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_TYPE_LAST + 2)
#define FFI_V2_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 3)
#if _CALL_ELF == 2
# define FFI_TRAMPOLINE_SIZE 32
#else
# if defined(POWERPC64) || defined(POWERPC_AIX)
# if defined(POWERPC_DARWIN64)
# define FFI_TRAMPOLINE_SIZE 48
# else
# define FFI_TRAMPOLINE_SIZE 24
# endif
#else /* POWERPC || POWERPC_AIX */
# else /* POWERPC || POWERPC_AIX */
# define FFI_TRAMPOLINE_SIZE 40
# endif
#endif
#ifndef LIBFFI_ASM
......
......@@ -32,15 +32,22 @@
#ifdef __powerpc64__
.hidden ffi_call_LINUX64
.globl ffi_call_LINUX64
# if _CALL_ELF == 2
.text
ffi_call_LINUX64:
addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_call_LINUX64@l
.localentry ffi_call_LINUX64, . - ffi_call_LINUX64
# else
.section ".opd","aw"
.align 3
ffi_call_LINUX64:
#ifdef _CALL_LINUX
# ifdef _CALL_LINUX
.quad .L.ffi_call_LINUX64,.TOC.@tocbase,0
.type ffi_call_LINUX64,@function
.text
.L.ffi_call_LINUX64:
#else
# else
.hidden .ffi_call_LINUX64
.globl .ffi_call_LINUX64
.quad .ffi_call_LINUX64,.TOC.@tocbase,0
......@@ -48,7 +55,8 @@ ffi_call_LINUX64:
.type .ffi_call_LINUX64,@function
.text
.ffi_call_LINUX64:
#endif
# endif
# endif
.LFB1:
mflr %r0
std %r28, -32(%r1)
......@@ -63,26 +71,35 @@ ffi_call_LINUX64:
mr %r31, %r5 /* flags, */
mr %r30, %r6 /* rvalue, */
mr %r29, %r7 /* function address. */
/* Save toc pointer, not for the ffi_prep_args64 call, but for the later
bctrl function call. */
# if _CALL_ELF == 2
std %r2, 24(%r1)
# else
std %r2, 40(%r1)
# endif
/* Call ffi_prep_args64. */
mr %r4, %r1
#ifdef _CALL_LINUX
# if defined _CALL_LINUX || _CALL_ELF == 2
bl ffi_prep_args64
#else
# else
bl .ffi_prep_args64
#endif
# endif
ld %r0, 0(%r29)
# if _CALL_ELF == 2
mr %r12, %r29
# else
ld %r12, 0(%r29)
ld %r2, 8(%r29)
ld %r11, 16(%r29)
# endif
/* Now do the call. */
/* Set up cr1 with bits 4-7 of the flags. */
mtcrf 0x40, %r31
/* Get the address to call into CTR. */
mtctr %r0
mtctr %r12
/* Load all those argument registers. */
ld %r3, -32-(8*8)(%r28)
ld %r4, -32-(7*8)(%r28)
......@@ -117,12 +134,17 @@ ffi_call_LINUX64:
/* This must follow the call immediately, the unwinder
uses this to find out if r2 has been saved or not. */
# if _CALL_ELF == 2
ld %r2, 24(%r1)
# else
ld %r2, 40(%r1)
# endif
/* Now, deal with the return value. */
mtcrf 0x01, %r31
bt- 30, .Ldone_return_value
bt- 29, .Lfp_return_value
bt 31, .Lstruct_return_value
bt 30, .Ldone_return_value
bt 29, .Lfp_return_value
std %r3, 0(%r30)
/* Fall through... */
......@@ -130,7 +152,7 @@ ffi_call_LINUX64:
/* Restore the registers we used and return. */
mr %r1, %r28
ld %r0, 16(%r28)
ld %r28, -32(%r1)
ld %r28, -32(%r28)
mtlr %r0
ld %r29, -24(%r1)
ld %r30, -16(%r1)
......@@ -147,14 +169,48 @@ ffi_call_LINUX64:
.Lfloat_return_value:
stfs %f1, 0(%r30)
b .Ldone_return_value
.Lstruct_return_value:
bf 29, .Lsmall_struct
bf 28, .Lfloat_homog_return_value
stfd %f1, 0(%r30)
stfd %f2, 8(%r30)
stfd %f3, 16(%r30)
stfd %f4, 24(%r30)
stfd %f5, 32(%r30)
stfd %f6, 40(%r30)
stfd %f7, 48(%r30)
stfd %f8, 56(%r30)
b .Ldone_return_value
.Lfloat_homog_return_value:
stfs %f1, 0(%r30)
stfs %f2, 4(%r30)
stfs %f3, 8(%r30)
stfs %f4, 12(%r30)
stfs %f5, 16(%r30)
stfs %f6, 20(%r30)
stfs %f7, 24(%r30)
stfs %f8, 28(%r30)
b .Ldone_return_value
.Lsmall_struct:
std %r3, 0(%r30)
std %r4, 8(%r30)
b .Ldone_return_value
.LFE1:
.long 0
.byte 0,12,0,1,128,4,0,0
#ifdef _CALL_LINUX
# if _CALL_ELF == 2
.size ffi_call_LINUX64,.-ffi_call_LINUX64
# else
# ifdef _CALL_LINUX
.size ffi_call_LINUX64,.-.L.ffi_call_LINUX64
#else
# else
.size .ffi_call_LINUX64,.-.ffi_call_LINUX64
#endif
# endif
# endif
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
......@@ -197,8 +253,8 @@ ffi_call_LINUX64:
.uleb128 0x4
.align 3
.LEFDE1:
#endif
#if defined __ELF__ && defined __linux__
# if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2
.section .note.GNU-stack,"",@progbits
# endif
#endif
......@@ -33,15 +33,22 @@
#ifdef __powerpc64__
FFI_HIDDEN (ffi_closure_LINUX64)
.globl ffi_closure_LINUX64
# if _CALL_ELF == 2
.text
ffi_closure_LINUX64:
addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha
addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l
.localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64
# else
.section ".opd","aw"
.align 3
ffi_closure_LINUX64:
#ifdef _CALL_LINUX
# ifdef _CALL_LINUX
.quad .L.ffi_closure_LINUX64,.TOC.@tocbase,0
.type ffi_closure_LINUX64,@function
.text
.L.ffi_closure_LINUX64:
#else
# else
FFI_HIDDEN (.ffi_closure_LINUX64)
.globl .ffi_closure_LINUX64
.quad .ffi_closure_LINUX64,.TOC.@tocbase,0
......@@ -49,61 +56,103 @@ ffi_closure_LINUX64:
.type .ffi_closure_LINUX64,@function
.text
.ffi_closure_LINUX64:
#endif
# endif
# endif
# if _CALL_ELF == 2
# 32 byte special reg save area + 64 byte parm save area and retval
# + 13*8 fpr save area + round to 16
# define STACKFRAME 208
# define PARMSAVE 32
# No parameter save area is needed for the call to ffi_closure_helper_LINUX64,
# so return value can start there.
# define RETVAL PARMSAVE
# else
# 48 bytes special reg save area + 64 bytes parm save area
# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
# define STACKFRAME 240
# define PARMSAVE 48
# define RETVAL PARMSAVE+64
# endif
.LFB1:
# save general regs into parm save area
std %r3, 48(%r1)
std %r4, 56(%r1)
std %r5, 64(%r1)
std %r6, 72(%r1)
# if _CALL_ELF == 2
ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif
mflr %r0
lwz %r12, 28(%r12) # cif->flags
mtcrf 0x40, %r12
addi %r12, %r1, PARMSAVE
bt 7, .Lparmsave
# Our caller has not allocated a parameter save area.
# We need to allocate one here and use it to pass gprs to
# ffi_closure_helper_LINUX64. The return value area will do.
addi %r12, %r1, -STACKFRAME+RETVAL
.Lparmsave:
std %r0, 16(%r1)
# Save general regs into parm save area
std %r3, 0(%r12)
std %r4, 8(%r12)
std %r5, 16(%r12)
std %r6, 24(%r12)
std %r7, 32(%r12)
std %r8, 40(%r12)
std %r9, 48(%r12)
std %r10, 56(%r12)
# load up the pointer to the parm save area
mr %r5, %r12
# else
mflr %r0
# Save general regs into parm save area
# This is the parameter save area set up by our caller.
std %r3, PARMSAVE+0(%r1)
std %r4, PARMSAVE+8(%r1)
std %r5, PARMSAVE+16(%r1)
std %r6, PARMSAVE+24(%r1)
std %r7, PARMSAVE+32(%r1)
std %r8, PARMSAVE+40(%r1)
std %r9, PARMSAVE+48(%r1)
std %r10, PARMSAVE+56(%r1)
std %r7, 80(%r1)
std %r8, 88(%r1)
std %r9, 96(%r1)
std %r10, 104(%r1)
std %r0, 16(%r1)
# mandatory 48 bytes special reg save area + 64 bytes parm save area
# + 16 bytes retval area + 13*8 bytes fpr save area + round to 16
stdu %r1, -240(%r1)
.LCFI0:
# load up the pointer to the parm save area
addi %r5, %r1, PARMSAVE
# endif
# next save fpr 1 to fpr 13
stfd %f1, 128+(0*8)(%r1)
stfd %f2, 128+(1*8)(%r1)
stfd %f3, 128+(2*8)(%r1)
stfd %f4, 128+(3*8)(%r1)
stfd %f5, 128+(4*8)(%r1)
stfd %f6, 128+(5*8)(%r1)
stfd %f7, 128+(6*8)(%r1)
stfd %f8, 128+(7*8)(%r1)
stfd %f9, 128+(8*8)(%r1)
stfd %f10, 128+(9*8)(%r1)
stfd %f11, 128+(10*8)(%r1)
stfd %f12, 128+(11*8)(%r1)
stfd %f13, 128+(12*8)(%r1)
stfd %f1, -104+(0*8)(%r1)
stfd %f2, -104+(1*8)(%r1)
stfd %f3, -104+(2*8)(%r1)
stfd %f4, -104+(3*8)(%r1)
stfd %f5, -104+(4*8)(%r1)
stfd %f6, -104+(5*8)(%r1)
stfd %f7, -104+(6*8)(%r1)
stfd %f8, -104+(7*8)(%r1)
stfd %f9, -104+(8*8)(%r1)
stfd %f10, -104+(9*8)(%r1)
stfd %f11, -104+(10*8)(%r1)
stfd %f12, -104+(11*8)(%r1)
stfd %f13, -104+(12*8)(%r1)
# set up registers for the routine that actually does the work
# get the context pointer from the trampoline
mr %r3, %r11
# load up the pointer to the saved fpr registers */
addi %r6, %r1, -104
# now load up the pointer to the result storage
addi %r4, %r1, 112
# load up the pointer to the result storage
addi %r4, %r1, -STACKFRAME+RETVAL
# now load up the pointer to the parameter save area
# in the previous frame
addi %r5, %r1, 240 + 48
stdu %r1, -STACKFRAME(%r1)
.LCFI0:
# now load up the pointer to the saved fpr registers */
addi %r6, %r1, 128
# get the context pointer from the trampoline
mr %r3, %r11
# make the call
#ifdef _CALL_LINUX
# if defined _CALL_LINUX || _CALL_ELF == 2
bl ffi_closure_helper_LINUX64
#else
# else
bl .ffi_closure_helper_LINUX64
#endif
# endif
.Lret:
# now r3 contains the return type
......@@ -112,10 +161,12 @@ ffi_closure_LINUX64:
# look up the proper starting point in table
# by using return type as offset
ld %r0, STACKFRAME+16(%r1)
cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT
bge .Lsmall
mflr %r4 # move address of .Lret to r4
sldi %r3, %r3, 4 # now multiply return type by 16
addi %r4, %r4, .Lret_type0 - .Lret
ld %r0, 240+16(%r1)
add %r3, %r3, %r4 # add contents of table to table address
mtctr %r3
bctr # jump to it
......@@ -128,117 +179,175 @@ ffi_closure_LINUX64:
.Lret_type0:
# case FFI_TYPE_VOID
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
nop
# case FFI_TYPE_INT
#ifdef __LITTLE_ENDIAN__
lwa %r3, 112+0(%r1)
#else
lwa %r3, 112+4(%r1)
#endif
# ifdef __LITTLE_ENDIAN__
lwa %r3, RETVAL+0(%r1)
# else
lwa %r3, RETVAL+4(%r1)
# endif
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_FLOAT
lfs %f1, 112+0(%r1)
lfs %f1, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_DOUBLE
lfd %f1, 112+0(%r1)
lfd %f1, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_LONGDOUBLE
lfd %f1, 112+0(%r1)
lfd %f1, RETVAL+0(%r1)
mtlr %r0
lfd %f2, 112+8(%r1)
lfd %f2, RETVAL+8(%r1)
b .Lfinish
# case FFI_TYPE_UINT8
#ifdef __LITTLE_ENDIAN__
lbz %r3, 112+0(%r1)
#else
lbz %r3, 112+7(%r1)
#endif
# ifdef __LITTLE_ENDIAN__
lbz %r3, RETVAL+0(%r1)
# else
lbz %r3, RETVAL+7(%r1)
# endif
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_SINT8
#ifdef __LITTLE_ENDIAN__
lbz %r3, 112+0(%r1)
#else
lbz %r3, 112+7(%r1)
#endif
# ifdef __LITTLE_ENDIAN__
lbz %r3, RETVAL+0(%r1)
# else
lbz %r3, RETVAL+7(%r1)
# endif
extsb %r3,%r3
mtlr %r0
b .Lfinish
# case FFI_TYPE_UINT16
#ifdef __LITTLE_ENDIAN__
lhz %r3, 112+0(%r1)
#else
lhz %r3, 112+6(%r1)
#endif
# ifdef __LITTLE_ENDIAN__
lhz %r3, RETVAL+0(%r1)
# else
lhz %r3, RETVAL+6(%r1)
# endif
mtlr %r0
.Lfinish:
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_SINT16
#ifdef __LITTLE_ENDIAN__
lha %r3, 112+0(%r1)
#else
lha %r3, 112+6(%r1)
#endif
# ifdef __LITTLE_ENDIAN__
lha %r3, RETVAL+0(%r1)
# else
lha %r3, RETVAL+6(%r1)
# endif
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_UINT32
#ifdef __LITTLE_ENDIAN__
lwz %r3, 112+0(%r1)
#else
lwz %r3, 112+4(%r1)
#endif
# ifdef __LITTLE_ENDIAN__
lwz %r3, RETVAL+0(%r1)
# else
lwz %r3, RETVAL+4(%r1)
# endif
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_SINT32
#ifdef __LITTLE_ENDIAN__
lwa %r3, 112+0(%r1)
#else
lwa %r3, 112+4(%r1)
#endif
# ifdef __LITTLE_ENDIAN__
lwa %r3, RETVAL+0(%r1)
# else
lwa %r3, RETVAL+4(%r1)
# endif
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_UINT64
ld %r3, 112+0(%r1)
ld %r3, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_SINT64
ld %r3, 112+0(%r1)
ld %r3, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# case FFI_TYPE_STRUCT
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
nop
# case FFI_TYPE_POINTER
ld %r3, 112+0(%r1)
ld %r3, RETVAL+0(%r1)
mtlr %r0
addi %r1, %r1, 240
addi %r1, %r1, STACKFRAME
blr
# esac
# case FFI_V2_TYPE_FLOAT_HOMOG
lfs %f1, RETVAL+0(%r1)
lfs %f2, RETVAL+4(%r1)
lfs %f3, RETVAL+8(%r1)
b .Lmorefloat
# case FFI_V2_TYPE_DOUBLE_HOMOG
lfd %f1, RETVAL+0(%r1)
lfd %f2, RETVAL+8(%r1)
lfd %f3, RETVAL+16(%r1)
lfd %f4, RETVAL+24(%r1)
mtlr %r0
lfd %f5, RETVAL+32(%r1)
lfd %f6, RETVAL+40(%r1)
lfd %f7, RETVAL+48(%r1)
lfd %f8, RETVAL+56(%r1)
addi %r1, %r1, STACKFRAME
blr
.Lmorefloat:
lfs %f4, RETVAL+12(%r1)
mtlr %r0
lfs %f5, RETVAL+16(%r1)
lfs %f6, RETVAL+20(%r1)
lfs %f7, RETVAL+24(%r1)
lfs %f8, RETVAL+28(%r1)
addi %r1, %r1, STACKFRAME
blr
.Lsmall:
# ifdef __LITTLE_ENDIAN__
ld %r3,RETVAL+0(%r1)
mtlr %r0
ld %r4,RETVAL+8(%r1)
addi %r1, %r1, STACKFRAME
blr
# else
# A struct smaller than a dword is returned in the low bits of r3
# ie. right justified. Larger structs are passed left justified
# in r3 and r4. The return value area on the stack will have
# the structs as they are usually stored in memory.
cmpldi %r3, FFI_V2_TYPE_SMALL_STRUCT + 7 # size 8 bytes?
neg %r5, %r3
ld %r3,RETVAL+0(%r1)
blt .Lsmalldown
mtlr %r0
ld %r4,RETVAL+8(%r1)
addi %r1, %r1, STACKFRAME
blr
.Lsmalldown:
addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7
mtlr %r0
sldi %r5, %r5, 3
addi %r1, %r1, STACKFRAME
srd %r3, %r3, %r5
blr
# endif
.LFE1:
.long 0
.byte 0,12,0,1,128,0,0,0
#ifdef _CALL_LINUX
# if _CALL_ELF == 2
.size ffi_closure_LINUX64,.-ffi_closure_LINUX64
# else
# ifdef _CALL_LINUX
.size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64
#else
# else
.size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64
#endif
# endif
# endif
.section .eh_frame,EH_FRAME_FLAGS,@progbits
.Lframe1:
......@@ -267,14 +376,14 @@ ffi_closure_LINUX64:
.byte 0x2 # DW_CFA_advance_loc1
.byte .LCFI0-.LFB1
.byte 0xe # DW_CFA_def_cfa_offset
.uleb128 240
.uleb128 STACKFRAME
.byte 0x11 # DW_CFA_offset_extended_sf
.uleb128 0x41
.sleb128 -2
.align 3
.LEFDE1:
#endif
#if defined __ELF__ && defined __linux__
# if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits
# endif
#endif
......@@ -45,19 +45,17 @@ int main (void)
args[2] = NULL;
ffi_call(&cif, FFI_FN(printf), &res, args);
// { dg-output "7.0" }
/* { dg-output "7.0" } */
printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" }
/* { dg-output "\nres: 4" } */
/* The call to cls_double_va_fn is static, so have to use a normal prep_cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint, arg_types) == FFI_OK);
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL,
code) == FFI_OK);
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_double_va_fn, NULL, code) == FFI_OK);
res = ((int(*)(char*, double))(code))(format, doubleArg);
// { dg-output "\n7.0" }
res = ((int(*)(char*, ...))(code))(format, doubleArg);
/* { dg-output "\n7.0" } */
printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" }
/* { dg-output "\nres: 4" } */
exit(0);
}
......@@ -45,20 +45,17 @@ int main (void)
args[2] = NULL;
ffi_call(&cif, FFI_FN(printf), &res, args);
// { dg-output "7.0" }
/* { dg-output "7.0" } */
printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" }
/* { dg-output "\nres: 4" } */
/* The call to cls_longdouble_va_fn is static, so have to use a normal prep_cif */
CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &ffi_type_sint,
arg_types) == FFI_OK);
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL, code) == FFI_OK);
CHECK(ffi_prep_closure_loc(pcl, &cif, cls_longdouble_va_fn, NULL,
code) == FFI_OK);
res = ((int(*)(char*, long double))(code))(format, ldArg);
// { dg-output "\n7.0" }
res = ((int(*)(char*, ...))(code))(format, ldArg);
/* { dg-output "\n7.0" } */
printf("res: %d\n", (int) res);
// { dg-output "\nres: 4" }
/* { dg-output "\nres: 4" } */
exit(0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment