ffi 1.0.11 → 1.0.12.pre
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ffi might be problematic. Click here for more details.
- data/Rakefile +1 -1
- data/ext/ffi_c/AbstractMemory.c +9 -0
- data/ext/ffi_c/AbstractMemory.h +4 -0
- data/ext/ffi_c/Buffer.c +8 -0
- data/ext/ffi_c/Call.c +8 -0
- data/ext/ffi_c/ClosurePool.c +12 -0
- data/ext/ffi_c/DynamicLibrary.c +7 -1
- data/ext/ffi_c/Function.c +11 -1
- data/ext/ffi_c/Function.h +6 -0
- data/ext/ffi_c/FunctionInfo.c +8 -0
- data/ext/ffi_c/LastError.c +8 -0
- data/ext/ffi_c/MemoryPointer.c +8 -0
- data/ext/ffi_c/MemoryPointer.h +6 -0
- data/ext/ffi_c/MethodHandle.c +8 -0
- data/ext/ffi_c/Platform.c +8 -0
- data/ext/ffi_c/Pointer.c +8 -0
- data/ext/ffi_c/Pointer.h +6 -0
- data/ext/ffi_c/Struct.c +6 -0
- data/ext/ffi_c/StructByReference.c +8 -0
- data/ext/ffi_c/StructByValue.c +8 -0
- data/ext/ffi_c/StructLayout.c +6 -0
- data/ext/ffi_c/Thread.c +7 -0
- data/ext/ffi_c/Thread.h +6 -0
- data/ext/ffi_c/Type.c +3 -0
- data/ext/ffi_c/Types.h +4 -0
- data/ext/ffi_c/Variadic.c +8 -0
- data/ext/ffi_c/endian.h +3 -0
- data/ext/ffi_c/extconf.rb +6 -1
- data/ext/ffi_c/libffi.vc.mk +26 -0
- data/ext/ffi_c/libffi.vc64.mk +26 -0
- data/ext/ffi_c/libffi/ChangeLog +541 -0
- data/ext/ffi_c/libffi/ChangeLog.libffi +13 -87
- data/ext/ffi_c/libffi/LICENSE +3 -3
- data/ext/ffi_c/libffi/Makefile.am +41 -32
- data/ext/ffi_c/libffi/Makefile.in +95 -66
- data/ext/ffi_c/libffi/Makefile.vc +141 -0
- data/ext/ffi_c/libffi/Makefile.vc64 +141 -0
- data/ext/ffi_c/libffi/README +40 -4
- data/ext/ffi_c/libffi/aclocal.m4 +729 -7854
- data/ext/ffi_c/libffi/build-ios.sh +67 -0
- data/ext/ffi_c/libffi/compile +11 -10
- data/ext/ffi_c/libffi/config.guess +4 -1
- data/ext/ffi_c/libffi/config.sub +6 -3
- data/ext/ffi_c/libffi/configure +6264 -6354
- data/ext/ffi_c/libffi/configure.ac +155 -63
- data/ext/ffi_c/libffi/depcomp +81 -35
- data/ext/ffi_c/libffi/doc/libffi.info +78 -18
- data/ext/ffi_c/libffi/doc/libffi.texi +64 -5
- data/ext/ffi_c/libffi/doc/stamp-vti +4 -4
- data/ext/ffi_c/libffi/doc/version.texi +4 -4
- data/ext/ffi_c/libffi/fficonfig.h.in +18 -0
- data/ext/ffi_c/libffi/fficonfig.hw +57 -0
- data/ext/ffi_c/libffi/include/Makefile.in +21 -3
- data/ext/ffi_c/libffi/include/ffi.h.in +42 -14
- data/ext/ffi_c/libffi/include/ffi.h.vc +427 -0
- data/ext/ffi_c/libffi/include/ffi.h.vc64 +427 -0
- data/ext/ffi_c/libffi/include/ffi_common.h +9 -5
- data/ext/ffi_c/libffi/install-sh +364 -167
- data/ext/ffi_c/libffi/ltmain.sh +2599 -1369
- data/ext/ffi_c/libffi/m4/ax_cc_maxopt.m4 +176 -0
- data/ext/ffi_c/libffi/m4/ax_cflags_warn_all.m4 +195 -0
- data/ext/ffi_c/libffi/m4/ax_check_compiler_flags.m4 +76 -0
- data/ext/ffi_c/libffi/m4/ax_compiler_vendor.m4 +63 -0
- data/ext/ffi_c/libffi/m4/ax_configure_args.m4 +70 -0
- data/ext/ffi_c/libffi/m4/ax_enable_builddir.m4 +300 -0
- data/ext/ffi_c/libffi/m4/ax_gcc_archflag.m4 +215 -0
- data/ext/ffi_c/libffi/m4/ax_gcc_x86_cpuid.m4 +79 -0
- data/ext/ffi_c/libffi/m4/libtool.m4 +1239 -768
- data/ext/ffi_c/libffi/m4/ltoptions.m4 +7 -6
- data/ext/ffi_c/libffi/m4/ltversion.m4 +6 -6
- data/ext/ffi_c/libffi/m4/lt~obsolete.m4 +9 -3
- data/ext/ffi_c/libffi/man/Makefile.in +21 -3
- data/ext/ffi_c/libffi/mdate-sh +0 -0
- data/ext/ffi_c/libffi/missing +60 -44
- data/ext/ffi_c/libffi/msvcc.sh +197 -0
- data/ext/ffi_c/libffi/src/alpha/osf.S +39 -18
- data/ext/ffi_c/libffi/src/arm/ffi.c +443 -24
- data/ext/ffi_c/libffi/src/arm/ffitarget.h +17 -1
- data/ext/ffi_c/libffi/src/arm/gentramp.sh +118 -0
- data/ext/ffi_c/libffi/src/arm/sysv.S +206 -15
- data/ext/ffi_c/libffi/src/arm/trampoline.S +4450 -0
- data/ext/ffi_c/libffi/src/avr32/ffi.c +4 -2
- data/ext/ffi_c/libffi/src/avr32/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/closures.c +17 -35
- data/ext/ffi_c/libffi/src/cris/ffi.c +1 -1
- data/ext/ffi_c/libffi/src/cris/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/dlmalloc.c +66 -4
- data/ext/ffi_c/libffi/src/frv/ffitarget.h +2 -6
- data/ext/ffi_c/libffi/src/ia64/ffi.c +7 -5
- data/ext/ffi_c/libffi/src/ia64/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/java_raw_api.c +1 -1
- data/ext/ffi_c/libffi/src/m32r/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/m68k/ffi.c +10 -0
- data/ext/ffi_c/libffi/src/m68k/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/m68k/sysv.S +36 -0
- data/ext/ffi_c/libffi/src/mips/ffi.c +12 -5
- data/ext/ffi_c/libffi/src/mips/ffitarget.h +18 -11
- data/ext/ffi_c/libffi/src/mips/n32.S +4 -4
- data/ext/ffi_c/libffi/src/moxie/eabi.S +128 -0
- data/ext/ffi_c/libffi/src/moxie/ffi.c +276 -0
- data/ext/ffi_c/libffi/src/pa/ffi.c +7 -4
- data/ext/ffi_c/libffi/src/pa/ffitarget.h +6 -5
- data/ext/ffi_c/libffi/src/powerpc/aix.S +5 -1
- data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +2 -0
- data/ext/ffi_c/libffi/src/powerpc/asm.h +1 -1
- data/ext/ffi_c/libffi/src/powerpc/darwin.S +215 -77
- data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +358 -100
- data/ext/ffi_c/libffi/src/powerpc/ffi.c +11 -5
- data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +603 -172
- data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +17 -4
- data/ext/ffi_c/libffi/src/prep_cif.c +16 -13
- data/ext/ffi_c/libffi/src/s390/ffitarget.h +4 -2
- data/ext/ffi_c/libffi/src/sh/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/sh64/ffitarget.h +2 -2
- data/ext/ffi_c/libffi/src/sparc/ffi.c +55 -11
- data/ext/ffi_c/libffi/src/sparc/ffitarget.h +5 -3
- data/ext/ffi_c/libffi/src/x86/ffi.c +54 -92
- data/ext/ffi_c/libffi/src/x86/ffi64.c +17 -8
- data/ext/ffi_c/libffi/src/x86/ffitarget.h +15 -14
- data/ext/ffi_c/libffi/src/x86/sysv.S +40 -26
- data/ext/ffi_c/libffi/src/x86/unix64.S +4 -0
- data/ext/ffi_c/libffi/src/x86/win32.S +379 -191
- data/ext/ffi_c/libffi/src/x86/win64.S +15 -7
- data/ext/ffi_c/libffi/testsuite/Makefile.am +1 -1
- data/ext/ffi_c/libffi/testsuite/Makefile.in +22 -4
- data/ext/ffi_c/libffi/testsuite/lib/libffi.exp +350 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +1 -5
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double_va.c +3 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble.c +2 -2
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_longdouble_va.c +3 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_pointer_stack.c +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_abi.c +2 -3
- data/ext/ffi_c/libffi/testsuite/libffi.call/err_bad_typedef.c +2 -1
- data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +36 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/huge_struct.c +17 -17
- data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.call/stret_medium2.c +1 -0
- data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +1 -1
- data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +1 -3
- data/ext/ffi_c/win32/stdint.h +199 -0
- data/gen/Rakefile +18 -2
- data/lib/ffi/platform/arm-linux/types.conf +102 -0
- data/lib/ffi/platform/i486-gnu/types.conf +107 -0
- data/lib/ffi/platform/ia64-linux/types.conf +102 -0
- data/lib/ffi/platform/mips-linux/types.conf +102 -0
- data/lib/ffi/platform/mipsel-linux/types.conf +102 -0
- data/lib/ffi/platform/powerpc-linux/types.conf +100 -0
- data/lib/ffi/platform/s390-linux/types.conf +102 -0
- data/lib/ffi/platform/s390x-linux/types.conf +102 -0
- data/lib/ffi/platform/sparc-linux/types.conf +102 -0
- data/lib/ffi/tools/types_generator.rb +8 -1
- data/lib/ffi_c.bundle +0 -0
- metadata +72 -42
@@ -1,7 +1,8 @@
|
|
1
1
|
/* -----------------------------------------------------------------------
|
2
|
-
ffi.c - Copyright (
|
3
|
-
|
4
|
-
|
2
|
+
ffi.c - Copyright (C) 2011 Anthony Green
|
3
|
+
Copyright (C) 2008 Red Hat, Inc
|
4
|
+
Copyright (C) 2007, 2008 Free Software Foundation, Inc
|
5
|
+
Copyright (c) 1998 Geoffrey Keating
|
5
6
|
|
6
7
|
PowerPC Foreign Function Interface
|
7
8
|
|
@@ -949,14 +950,19 @@ ffi_prep_closure_loc (ffi_closure *closure,
|
|
949
950
|
#ifdef POWERPC64
|
950
951
|
void **tramp = (void **) &closure->tramp[0];
|
951
952
|
|
952
|
-
|
953
|
+
if (cif->abi != FFI_LINUX64)
|
954
|
+
return FFI_BAD_ABI;
|
953
955
|
/* Copy function address and TOC from ffi_closure_LINUX64. */
|
954
956
|
memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
|
955
957
|
tramp[2] = codeloc;
|
956
958
|
#else
|
957
959
|
unsigned int *tramp;
|
958
960
|
|
959
|
-
|
961
|
+
if (! (cif->abi == FFI_GCC_SYSV
|
962
|
+
|| cif->abi == FFI_SYSV
|
963
|
+
|| cif->abi == FFI_LINUX
|
964
|
+
|| cif->abi == FFI_LINUX_SOFT_FLOAT))
|
965
|
+
return FFI_BAD_ABI;
|
960
966
|
|
961
967
|
tramp = (unsigned int *) &closure->tramp[0];
|
962
968
|
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Copyright (C) 1998 Geoffrey Keating
|
5
5
|
Copyright (C) 2001 John Hornkvist
|
6
|
-
Copyright (C) 2002, 2006, 2007, 2009 Free Software Foundation, Inc.
|
6
|
+
Copyright (C) 2002, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
|
7
7
|
|
8
8
|
FFI support for Darwin and AIX.
|
9
9
|
|
@@ -35,11 +35,17 @@
|
|
35
35
|
extern void ffi_closure_ASM (void);
|
36
36
|
|
37
37
|
enum {
|
38
|
-
/* The assembly depends on these exact flags.
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
/* The assembly depends on these exact flags.
|
39
|
+
For Darwin64 (when FLAG_RETURNS_STRUCT is set):
|
40
|
+
FLAG_RETURNS_FP indicates that the structure embeds FP data.
|
41
|
+
FLAG_RETURNS_128BITS signals a special struct size that is not
|
42
|
+
expanded for float content. */
|
43
|
+
FLAG_RETURNS_128BITS = 1 << (31-31), /* These go in cr7 */
|
44
|
+
FLAG_RETURNS_NOTHING = 1 << (31-30),
|
45
|
+
FLAG_RETURNS_FP = 1 << (31-29),
|
46
|
+
FLAG_RETURNS_64BITS = 1 << (31-28),
|
47
|
+
|
48
|
+
FLAG_RETURNS_STRUCT = 1 << (31-27), /* This goes in cr6 */
|
43
49
|
|
44
50
|
FLAG_ARG_NEEDS_COPY = 1 << (31- 7),
|
45
51
|
FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */
|
@@ -50,43 +56,61 @@ enum {
|
|
50
56
|
/* About the DARWIN ABI. */
|
51
57
|
enum {
|
52
58
|
NUM_GPR_ARG_REGISTERS = 8,
|
53
|
-
NUM_FPR_ARG_REGISTERS = 13
|
59
|
+
NUM_FPR_ARG_REGISTERS = 13,
|
60
|
+
LINKAGE_AREA_GPRS = 6
|
54
61
|
};
|
55
|
-
|
62
|
+
|
63
|
+
enum { ASM_NEEDS_REGISTERS = 4 }; /* r28-r31 */
|
56
64
|
|
57
65
|
/* ffi_prep_args is called by the assembly routine once stack space
|
58
66
|
has been allocated for the function's arguments.
|
67
|
+
|
68
|
+
m32/m64
|
59
69
|
|
60
70
|
The stack layout we want looks like this:
|
61
71
|
|
62
72
|
| Return address from ffi_call_DARWIN | higher addresses
|
63
73
|
|--------------------------------------------|
|
64
|
-
| Previous backchain pointer 4 | stack pointer here
|
74
|
+
| Previous backchain pointer 4/8 | stack pointer here
|
65
75
|
|--------------------------------------------|<+ <<< on entry to
|
66
|
-
|
|
76
|
+
| ASM_NEEDS_REGISTERS=r28-r31 4*(4/8) | | ffi_call_DARWIN
|
67
77
|
|--------------------------------------------| |
|
68
|
-
|
|
78
|
+
| When we have any FP activity... the | |
|
79
|
+
| FPRs occupy NUM_FPR_ARG_REGISTERS slots | |
|
80
|
+
| here fp13 .. fp1 from high to low addr. | |
|
81
|
+
~ ~ ~
|
82
|
+
| Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS
|
69
83
|
|--------------------------------------------| |
|
70
|
-
|
|
84
|
+
| TOC=R2 (AIX) Reserved (Darwin) 4/8 | |
|
71
85
|
|--------------------------------------------| | stack |
|
72
|
-
| Reserved 2*4
|
86
|
+
| Reserved 2*4/8 | | grows |
|
73
87
|
|--------------------------------------------| | down V
|
74
|
-
| Space for callee's LR 4 | |
|
88
|
+
| Space for callee's LR 4/8 | |
|
75
89
|
|--------------------------------------------| | lower addresses
|
76
|
-
| Saved CR
|
90
|
+
| Saved CR [low word for m64] 4/8 | |
|
77
91
|
|--------------------------------------------| | stack pointer here
|
78
|
-
| Current backchain pointer 4 |-/ during
|
92
|
+
| Current backchain pointer 4/8 |-/ during
|
79
93
|
|--------------------------------------------| <<< ffi_call_DARWIN
|
80
94
|
|
81
95
|
*/
|
82
96
|
|
97
|
+
#if defined(POWERPC_DARWIN64)
|
98
|
+
static void
|
99
|
+
darwin64_pass_struct_by_value
|
100
|
+
(ffi_type *, char *, unsigned, unsigned *, double **, unsigned long **);
|
101
|
+
#endif
|
102
|
+
|
103
|
+
/* This depends on GPR_SIZE = sizeof (unsigned long) */
|
104
|
+
|
83
105
|
void
|
84
106
|
ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
85
107
|
{
|
86
108
|
const unsigned bytes = ecif->cif->bytes;
|
87
109
|
const unsigned flags = ecif->cif->flags;
|
88
110
|
const unsigned nargs = ecif->cif->nargs;
|
111
|
+
#if !defined(POWERPC_DARWIN64)
|
89
112
|
const ffi_abi abi = ecif->cif->abi;
|
113
|
+
#endif
|
90
114
|
|
91
115
|
/* 'stacktop' points at the previous backchain pointer. */
|
92
116
|
unsigned long *const stacktop = stack + (bytes / sizeof(unsigned long));
|
@@ -94,18 +118,19 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|
94
118
|
/* 'fpr_base' points at the space for fpr1, and grows upwards as
|
95
119
|
we use FPR registers. */
|
96
120
|
double *fpr_base = (double *) (stacktop - ASM_NEEDS_REGISTERS) - NUM_FPR_ARG_REGISTERS;
|
97
|
-
int fparg_count = 0;
|
98
|
-
|
121
|
+
int gp_count = 0, fparg_count = 0;
|
99
122
|
|
100
123
|
/* 'next_arg' grows up as we put parameters in it. */
|
101
|
-
unsigned long *next_arg = stack +
|
124
|
+
unsigned long *next_arg = stack + LINKAGE_AREA_GPRS; /* 6 reserved positions. */
|
102
125
|
|
103
126
|
int i;
|
104
127
|
double double_tmp;
|
105
128
|
void **p_argv = ecif->avalue;
|
106
129
|
unsigned long gprvalue;
|
107
130
|
ffi_type** ptr = ecif->cif->arg_types;
|
131
|
+
#if !defined(POWERPC_DARWIN64)
|
108
132
|
char *dest_cpy;
|
133
|
+
#endif
|
109
134
|
unsigned size_al = 0;
|
110
135
|
|
111
136
|
/* Check that everything starts aligned properly. */
|
@@ -130,25 +155,30 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|
130
155
|
the size of the floating-point parameter are skipped. */
|
131
156
|
case FFI_TYPE_FLOAT:
|
132
157
|
double_tmp = *(float *) *p_argv;
|
133
|
-
if (fparg_count
|
134
|
-
*(double *)next_arg = double_tmp;
|
135
|
-
else
|
158
|
+
if (fparg_count < NUM_FPR_ARG_REGISTERS)
|
136
159
|
*fpr_base++ = double_tmp;
|
160
|
+
#if defined(POWERPC_DARWIN)
|
161
|
+
*(float *)next_arg = *(float *) *p_argv;
|
162
|
+
#else
|
163
|
+
*(double *)next_arg = double_tmp;
|
164
|
+
#endif
|
137
165
|
next_arg++;
|
166
|
+
gp_count++;
|
138
167
|
fparg_count++;
|
139
168
|
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
140
169
|
break;
|
141
170
|
|
142
171
|
case FFI_TYPE_DOUBLE:
|
143
172
|
double_tmp = *(double *) *p_argv;
|
144
|
-
if (fparg_count
|
145
|
-
*(double *)next_arg = double_tmp;
|
146
|
-
else
|
173
|
+
if (fparg_count < NUM_FPR_ARG_REGISTERS)
|
147
174
|
*fpr_base++ = double_tmp;
|
175
|
+
*(double *)next_arg = double_tmp;
|
148
176
|
#ifdef POWERPC64
|
149
177
|
next_arg++;
|
178
|
+
gp_count++;
|
150
179
|
#else
|
151
180
|
next_arg += 2;
|
181
|
+
gp_count += 2;
|
152
182
|
#endif
|
153
183
|
fparg_count++;
|
154
184
|
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
@@ -157,30 +187,41 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|
157
187
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
158
188
|
|
159
189
|
case FFI_TYPE_LONGDOUBLE:
|
160
|
-
#
|
190
|
+
# if defined(POWERPC64) && !defined(POWERPC_DARWIN64)
|
191
|
+
/* ??? This will exceed the regs count when the value starts at fp13
|
192
|
+
and it will not put the extra bit on the stack. */
|
161
193
|
if (fparg_count < NUM_FPR_ARG_REGISTERS)
|
162
194
|
*(long double *) fpr_base++ = *(long double *) *p_argv;
|
163
195
|
else
|
164
196
|
*(long double *) next_arg = *(long double *) *p_argv;
|
165
197
|
next_arg += 2;
|
166
198
|
fparg_count += 2;
|
167
|
-
#else
|
199
|
+
# else
|
168
200
|
double_tmp = ((double *) *p_argv)[0];
|
169
201
|
if (fparg_count < NUM_FPR_ARG_REGISTERS)
|
170
202
|
*fpr_base++ = double_tmp;
|
171
|
-
|
172
|
-
|
203
|
+
*(double *) next_arg = double_tmp;
|
204
|
+
# if defined(POWERPC_DARWIN64)
|
205
|
+
next_arg++;
|
206
|
+
gp_count++;
|
207
|
+
# else
|
173
208
|
next_arg += 2;
|
209
|
+
gp_count += 2;
|
210
|
+
# endif
|
174
211
|
fparg_count++;
|
175
|
-
|
176
212
|
double_tmp = ((double *) *p_argv)[1];
|
177
213
|
if (fparg_count < NUM_FPR_ARG_REGISTERS)
|
178
214
|
*fpr_base++ = double_tmp;
|
179
|
-
|
180
|
-
|
215
|
+
*(double *) next_arg = double_tmp;
|
216
|
+
# if defined(POWERPC_DARWIN64)
|
217
|
+
next_arg++;
|
218
|
+
gp_count++;
|
219
|
+
# else
|
181
220
|
next_arg += 2;
|
221
|
+
gp_count += 2;
|
222
|
+
# endif
|
182
223
|
fparg_count++;
|
183
|
-
#endif
|
224
|
+
# endif
|
184
225
|
FFI_ASSERT(flags & FLAG_FP_ARGUMENTS);
|
185
226
|
break;
|
186
227
|
#endif
|
@@ -192,6 +233,7 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|
192
233
|
#else
|
193
234
|
*(long long *) next_arg = *(long long *) *p_argv;
|
194
235
|
next_arg += 2;
|
236
|
+
gp_count += 2;
|
195
237
|
#endif
|
196
238
|
break;
|
197
239
|
case FFI_TYPE_POINTER:
|
@@ -211,32 +253,35 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|
211
253
|
goto putgpr;
|
212
254
|
|
213
255
|
case FFI_TYPE_STRUCT:
|
214
|
-
#ifdef POWERPC64
|
215
|
-
dest_cpy = (char *) next_arg;
|
216
256
|
size_al = (*ptr)->size;
|
217
|
-
|
257
|
+
#if defined(POWERPC_DARWIN64)
|
258
|
+
next_arg = (unsigned long *)ALIGN((char *)next_arg, (*ptr)->alignment);
|
259
|
+
darwin64_pass_struct_by_value (*ptr, (char *) *p_argv,
|
260
|
+
(unsigned) size_al,
|
261
|
+
(unsigned int *) &fparg_count,
|
262
|
+
&fpr_base, &next_arg);
|
263
|
+
#else
|
264
|
+
dest_cpy = (char *) next_arg;
|
265
|
+
|
266
|
+
/* If the first member of the struct is a double, then include enough
|
267
|
+
padding in the struct size to align it to double-word. */
|
268
|
+
if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
|
218
269
|
size_al = ALIGN((*ptr)->size, 8);
|
219
|
-
if (size_al < 3 && abi == FFI_DARWIN)
|
220
|
-
dest_cpy += 4 - size_al;
|
221
270
|
|
271
|
+
# if defined(POWERPC64)
|
272
|
+
FFI_ASSERT (abi != FFI_DARWIN);
|
222
273
|
memcpy ((char *) dest_cpy, (char *) *p_argv, size_al);
|
223
274
|
next_arg += (size_al + 7) / 8;
|
224
|
-
#else
|
225
|
-
dest_cpy = (char *) next_arg;
|
226
|
-
|
275
|
+
# else
|
227
276
|
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
228
277
|
SI 4 bytes) are aligned as if they were those modes.
|
229
278
|
Structures with 3 byte in size are padded upwards. */
|
230
|
-
size_al = (*ptr)->size;
|
231
|
-
/* If the first member of the struct is a double, then align
|
232
|
-
the struct to double-word. */
|
233
|
-
if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
|
234
|
-
size_al = ALIGN((*ptr)->size, 8);
|
235
279
|
if (size_al < 3 && abi == FFI_DARWIN)
|
236
280
|
dest_cpy += 4 - size_al;
|
237
281
|
|
238
282
|
memcpy((char *) dest_cpy, (char *) *p_argv, size_al);
|
239
283
|
next_arg += (size_al + 3) / 4;
|
284
|
+
# endif
|
240
285
|
#endif
|
241
286
|
break;
|
242
287
|
|
@@ -249,6 +294,7 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|
249
294
|
gprvalue = *(unsigned int *) *p_argv;
|
250
295
|
putgpr:
|
251
296
|
*next_arg++ = gprvalue;
|
297
|
+
gp_count++;
|
252
298
|
break;
|
253
299
|
default:
|
254
300
|
break;
|
@@ -262,8 +308,269 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack)
|
|
262
308
|
//FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4);
|
263
309
|
}
|
264
310
|
|
311
|
+
#if defined(POWERPC_DARWIN64)
|
312
|
+
|
313
|
+
/* See if we can put some of the struct into fprs.
|
314
|
+
This should not be called for structures of size 16 bytes, since these are not
|
315
|
+
broken out this way. */
|
316
|
+
static void
|
317
|
+
darwin64_scan_struct_for_floats (ffi_type *s, unsigned *nfpr)
|
318
|
+
{
|
319
|
+
int i;
|
320
|
+
|
321
|
+
FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
|
322
|
+
|
323
|
+
for (i = 0; s->elements[i] != NULL; i++)
|
324
|
+
{
|
325
|
+
ffi_type *p = s->elements[i];
|
326
|
+
switch (p->type)
|
327
|
+
{
|
328
|
+
case FFI_TYPE_STRUCT:
|
329
|
+
darwin64_scan_struct_for_floats (p, nfpr);
|
330
|
+
break;
|
331
|
+
case FFI_TYPE_LONGDOUBLE:
|
332
|
+
(*nfpr) += 2;
|
333
|
+
break;
|
334
|
+
case FFI_TYPE_DOUBLE:
|
335
|
+
case FFI_TYPE_FLOAT:
|
336
|
+
(*nfpr) += 1;
|
337
|
+
break;
|
338
|
+
default:
|
339
|
+
break;
|
340
|
+
}
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
344
|
+
static int
|
345
|
+
darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr)
|
346
|
+
{
|
347
|
+
unsigned struct_offset=0, i;
|
348
|
+
|
349
|
+
for (i = 0; s->elements[i] != NULL; i++)
|
350
|
+
{
|
351
|
+
char *item_base;
|
352
|
+
ffi_type *p = s->elements[i];
|
353
|
+
/* Find the start of this item (0 for the first one). */
|
354
|
+
if (i > 0)
|
355
|
+
struct_offset = ALIGN(struct_offset, p->alignment);
|
356
|
+
|
357
|
+
item_base = src + struct_offset;
|
358
|
+
|
359
|
+
switch (p->type)
|
360
|
+
{
|
361
|
+
case FFI_TYPE_STRUCT:
|
362
|
+
if (darwin64_struct_size_exceeds_gprs_p (p, item_base, nfpr))
|
363
|
+
return 1;
|
364
|
+
break;
|
365
|
+
case FFI_TYPE_LONGDOUBLE:
|
366
|
+
if (*nfpr >= NUM_FPR_ARG_REGISTERS)
|
367
|
+
return 1;
|
368
|
+
(*nfpr) += 1;
|
369
|
+
item_base += 8;
|
370
|
+
/* FALL THROUGH */
|
371
|
+
case FFI_TYPE_DOUBLE:
|
372
|
+
if (*nfpr >= NUM_FPR_ARG_REGISTERS)
|
373
|
+
return 1;
|
374
|
+
(*nfpr) += 1;
|
375
|
+
break;
|
376
|
+
case FFI_TYPE_FLOAT:
|
377
|
+
if (*nfpr >= NUM_FPR_ARG_REGISTERS)
|
378
|
+
return 1;
|
379
|
+
(*nfpr) += 1;
|
380
|
+
break;
|
381
|
+
default:
|
382
|
+
/* If we try and place any item, that is non-float, once we've
|
383
|
+
exceeded the 8 GPR mark, then we can't fit the struct. */
|
384
|
+
if ((unsigned long)item_base >= 8*8)
|
385
|
+
return 1;
|
386
|
+
break;
|
387
|
+
}
|
388
|
+
/* now count the size of what we just used. */
|
389
|
+
struct_offset += p->size;
|
390
|
+
}
|
391
|
+
return 0;
|
392
|
+
}
|
393
|
+
|
394
|
+
/* Can this struct be returned by value? */
|
395
|
+
int
|
396
|
+
darwin64_struct_ret_by_value_p (ffi_type *s)
|
397
|
+
{
|
398
|
+
unsigned nfp = 0;
|
399
|
+
|
400
|
+
FFI_ASSERT (s && s->type == FFI_TYPE_STRUCT);
|
401
|
+
|
402
|
+
/* The largest structure we can return is 8long + 13 doubles. */
|
403
|
+
if (s->size > 168)
|
404
|
+
return 0;
|
405
|
+
|
406
|
+
/* We can't pass more than 13 floats. */
|
407
|
+
darwin64_scan_struct_for_floats (s, &nfp);
|
408
|
+
if (nfp > 13)
|
409
|
+
return 0;
|
410
|
+
|
411
|
+
/* If there are not too many floats, and the struct is
|
412
|
+
small enough to accommodate in the GPRs, then it must be OK. */
|
413
|
+
if (s->size <= 64)
|
414
|
+
return 1;
|
415
|
+
|
416
|
+
/* Well, we have to look harder. */
|
417
|
+
nfp = 0;
|
418
|
+
if (darwin64_struct_size_exceeds_gprs_p (s, NULL, &nfp))
|
419
|
+
return 0;
|
420
|
+
|
421
|
+
return 1;
|
422
|
+
}
|
423
|
+
|
424
|
+
void
|
425
|
+
darwin64_pass_struct_floats (ffi_type *s, char *src,
|
426
|
+
unsigned *nfpr, double **fprs)
|
427
|
+
{
|
428
|
+
int i;
|
429
|
+
double *fpr_base = *fprs;
|
430
|
+
unsigned struct_offset = 0;
|
431
|
+
|
432
|
+
/* We don't assume anything about the alignment of the source. */
|
433
|
+
for (i = 0; s->elements[i] != NULL; i++)
|
434
|
+
{
|
435
|
+
char *item_base;
|
436
|
+
ffi_type *p = s->elements[i];
|
437
|
+
/* Find the start of this item (0 for the first one). */
|
438
|
+
if (i > 0)
|
439
|
+
struct_offset = ALIGN(struct_offset, p->alignment);
|
440
|
+
item_base = src + struct_offset;
|
441
|
+
|
442
|
+
switch (p->type)
|
443
|
+
{
|
444
|
+
case FFI_TYPE_STRUCT:
|
445
|
+
darwin64_pass_struct_floats (p, item_base, nfpr,
|
446
|
+
&fpr_base);
|
447
|
+
break;
|
448
|
+
case FFI_TYPE_LONGDOUBLE:
|
449
|
+
if (*nfpr < NUM_FPR_ARG_REGISTERS)
|
450
|
+
*fpr_base++ = *(double *)item_base;
|
451
|
+
(*nfpr) += 1;
|
452
|
+
item_base += 8;
|
453
|
+
/* FALL THROUGH */
|
454
|
+
case FFI_TYPE_DOUBLE:
|
455
|
+
if (*nfpr < NUM_FPR_ARG_REGISTERS)
|
456
|
+
*fpr_base++ = *(double *)item_base;
|
457
|
+
(*nfpr) += 1;
|
458
|
+
break;
|
459
|
+
case FFI_TYPE_FLOAT:
|
460
|
+
if (*nfpr < NUM_FPR_ARG_REGISTERS)
|
461
|
+
*fpr_base++ = (double) *(float *)item_base;
|
462
|
+
(*nfpr) += 1;
|
463
|
+
break;
|
464
|
+
default:
|
465
|
+
break;
|
466
|
+
}
|
467
|
+
/* now count the size of what we just used. */
|
468
|
+
struct_offset += p->size;
|
469
|
+
}
|
470
|
+
/* Update the scores. */
|
471
|
+
*fprs = fpr_base;
|
472
|
+
}
|
473
|
+
|
474
|
+
/* Darwin64 special rules.
|
475
|
+
Break out a struct into params and float registers. */
|
476
|
+
static void
|
477
|
+
darwin64_pass_struct_by_value (ffi_type *s, char *src, unsigned size,
|
478
|
+
unsigned *nfpr, double **fprs, unsigned long **arg)
|
479
|
+
{
|
480
|
+
unsigned long *next_arg = *arg;
|
481
|
+
char *dest_cpy = (char *)next_arg;
|
482
|
+
|
483
|
+
FFI_ASSERT (s->type == FFI_TYPE_STRUCT)
|
484
|
+
|
485
|
+
if (!size)
|
486
|
+
return;
|
487
|
+
|
488
|
+
/* First... special cases. */
|
489
|
+
if (size < 3
|
490
|
+
|| (size == 4
|
491
|
+
&& s->elements[0]
|
492
|
+
&& s->elements[0]->type != FFI_TYPE_FLOAT))
|
493
|
+
{
|
494
|
+
/* Must be at least one GPR, padding is unspecified in value,
|
495
|
+
let's make it zero. */
|
496
|
+
*next_arg = 0UL;
|
497
|
+
dest_cpy += 8 - size;
|
498
|
+
memcpy ((char *) dest_cpy, src, size);
|
499
|
+
next_arg++;
|
500
|
+
}
|
501
|
+
else if (size == 16)
|
502
|
+
{
|
503
|
+
memcpy ((char *) dest_cpy, src, size);
|
504
|
+
next_arg += 2;
|
505
|
+
}
|
506
|
+
else
|
507
|
+
{
|
508
|
+
/* now the general case, we consider embedded floats. */
|
509
|
+
memcpy ((char *) dest_cpy, src, size);
|
510
|
+
darwin64_pass_struct_floats (s, src, nfpr, fprs);
|
511
|
+
next_arg += (size+7)/8;
|
512
|
+
}
|
513
|
+
|
514
|
+
*arg = next_arg;
|
515
|
+
}
|
516
|
+
|
517
|
+
double *
|
518
|
+
darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned *nf)
|
519
|
+
{
|
520
|
+
int i;
|
521
|
+
unsigned struct_offset = 0;
|
522
|
+
|
523
|
+
/* We don't assume anything about the alignment of the source. */
|
524
|
+
for (i = 0; s->elements[i] != NULL; i++)
|
525
|
+
{
|
526
|
+
char *item_base;
|
527
|
+
ffi_type *p = s->elements[i];
|
528
|
+
/* Find the start of this item (0 for the first one). */
|
529
|
+
if (i > 0)
|
530
|
+
struct_offset = ALIGN(struct_offset, p->alignment);
|
531
|
+
item_base = dest + struct_offset;
|
532
|
+
|
533
|
+
switch (p->type)
|
534
|
+
{
|
535
|
+
case FFI_TYPE_STRUCT:
|
536
|
+
fprs = darwin64_struct_floats_to_mem (p, item_base, fprs, nf);
|
537
|
+
break;
|
538
|
+
case FFI_TYPE_LONGDOUBLE:
|
539
|
+
if (*nf < NUM_FPR_ARG_REGISTERS)
|
540
|
+
{
|
541
|
+
*(double *)item_base = *fprs++ ;
|
542
|
+
(*nf) += 1;
|
543
|
+
}
|
544
|
+
item_base += 8;
|
545
|
+
/* FALL THROUGH */
|
546
|
+
case FFI_TYPE_DOUBLE:
|
547
|
+
if (*nf < NUM_FPR_ARG_REGISTERS)
|
548
|
+
{
|
549
|
+
*(double *)item_base = *fprs++ ;
|
550
|
+
(*nf) += 1;
|
551
|
+
}
|
552
|
+
break;
|
553
|
+
case FFI_TYPE_FLOAT:
|
554
|
+
if (*nf < NUM_FPR_ARG_REGISTERS)
|
555
|
+
{
|
556
|
+
*(float *)item_base = (float) *fprs++ ;
|
557
|
+
(*nf) += 1;
|
558
|
+
}
|
559
|
+
break;
|
560
|
+
default:
|
561
|
+
break;
|
562
|
+
}
|
563
|
+
/* now count the size of what we just used. */
|
564
|
+
struct_offset += p->size;
|
565
|
+
}
|
566
|
+
return fprs;
|
567
|
+
}
|
568
|
+
|
569
|
+
#endif
|
570
|
+
|
265
571
|
/* Adjust the size of S to be correct for Darwin.
|
266
|
-
On Darwin, the first field of a structure has natural alignment.
|
572
|
+
On Darwin m32, the first field of a structure has natural alignment.
|
573
|
+
On Darwin m64, all fields have natural alignment. */
|
267
574
|
|
268
575
|
static void
|
269
576
|
darwin_adjust_aggregate_sizes (ffi_type *s)
|
@@ -280,22 +587,29 @@ darwin_adjust_aggregate_sizes (ffi_type *s)
|
|
280
587
|
int align;
|
281
588
|
|
282
589
|
p = s->elements[i];
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
590
|
+
if (p->type == FFI_TYPE_STRUCT)
|
591
|
+
darwin_adjust_aggregate_sizes (p);
|
592
|
+
#if defined(POWERPC_DARWIN64)
|
593
|
+
/* Natural alignment for all items. */
|
594
|
+
align = p->alignment;
|
595
|
+
#else
|
596
|
+
/* Natrual alignment for the first item... */
|
597
|
+
if (i == 0)
|
598
|
+
align = p->alignment;
|
290
599
|
else if (p->alignment == 16 || p->alignment < 4)
|
600
|
+
/* .. subsequent items with vector or align < 4 have natural align. */
|
291
601
|
align = p->alignment;
|
292
602
|
else
|
603
|
+
/* .. or align is 4. */
|
293
604
|
align = 4;
|
605
|
+
#endif
|
606
|
+
/* Pad, if necessary, before adding the current item. */
|
294
607
|
s->size = ALIGN(s->size, align) + p->size;
|
295
608
|
}
|
296
609
|
|
297
610
|
s->size = ALIGN(s->size, s->alignment);
|
298
611
|
|
612
|
+
/* This should not be necessary on m64, but harmless. */
|
299
613
|
if (s->elements[0]->type == FFI_TYPE_UINT64
|
300
614
|
|| s->elements[0]->type == FFI_TYPE_SINT64
|
301
615
|
|| s->elements[0]->type == FFI_TYPE_DOUBLE
|
@@ -344,10 +658,10 @@ ffi_status
|
|
344
658
|
ffi_prep_cif_machdep (ffi_cif *cif)
|
345
659
|
{
|
346
660
|
/* All this is for the DARWIN ABI. */
|
347
|
-
|
661
|
+
unsigned i;
|
348
662
|
ffi_type **ptr;
|
349
663
|
unsigned bytes;
|
350
|
-
|
664
|
+
unsigned fparg_count = 0, intarg_count = 0;
|
351
665
|
unsigned flags = 0;
|
352
666
|
unsigned size_al = 0;
|
353
667
|
|
@@ -372,16 +686,25 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|
372
686
|
/* Space for the frame pointer, callee's LR, CR, etc, and for
|
373
687
|
the asm's temp regs. */
|
374
688
|
|
375
|
-
bytes = (
|
689
|
+
bytes = (LINKAGE_AREA_GPRS + ASM_NEEDS_REGISTERS) * sizeof(unsigned long);
|
376
690
|
|
377
|
-
/* Return value handling.
|
691
|
+
/* Return value handling.
|
692
|
+
The rules m32 are as follows:
|
378
693
|
- 32-bit (or less) integer values are returned in gpr3;
|
379
|
-
-
|
380
|
-
- 64-bit integer values and structures between 5 and 8 bytes are
|
381
|
-
in gpr3 and gpr4;
|
694
|
+
- structures of size <= 4 bytes also returned in gpr3;
|
695
|
+
- 64-bit integer values [??? and structures between 5 and 8 bytes] are
|
696
|
+
returned in gpr3 and gpr4;
|
382
697
|
- Single/double FP values are returned in fpr1;
|
383
698
|
- Long double FP (if not equivalent to double) values are returned in
|
384
699
|
fpr1 and fpr2;
|
700
|
+
m64:
|
701
|
+
- 64-bit or smaller integral values are returned in GPR3
|
702
|
+
- Single/double FP values are returned in fpr1;
|
703
|
+
- Long double FP values are returned in fpr1 and fpr2;
|
704
|
+
m64 Structures:
|
705
|
+
- If the structure could be accommodated in registers were it to be the
|
706
|
+
first argument to a routine, then it is returned in those registers.
|
707
|
+
m32/m64 structures otherwise:
|
385
708
|
- Larger structures values are allocated space and a pointer is passed
|
386
709
|
as the first argument. */
|
387
710
|
switch (cif->rtype->type)
|
@@ -410,9 +733,42 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|
410
733
|
break;
|
411
734
|
|
412
735
|
case FFI_TYPE_STRUCT:
|
736
|
+
#if defined(POWERPC_DARWIN64)
|
737
|
+
{
|
738
|
+
/* Can we fit the struct into regs? */
|
739
|
+
if (darwin64_struct_ret_by_value_p (cif->rtype))
|
740
|
+
{
|
741
|
+
unsigned nfpr = 0;
|
742
|
+
flags |= FLAG_RETURNS_STRUCT;
|
743
|
+
if (cif->rtype->size != 16)
|
744
|
+
darwin64_scan_struct_for_floats (cif->rtype, &nfpr) ;
|
745
|
+
else
|
746
|
+
flags |= FLAG_RETURNS_128BITS;
|
747
|
+
/* Will be 0 for 16byte struct. */
|
748
|
+
if (nfpr)
|
749
|
+
flags |= FLAG_RETURNS_FP;
|
750
|
+
}
|
751
|
+
else /* By ref. */
|
752
|
+
{
|
753
|
+
flags |= FLAG_RETVAL_REFERENCE;
|
754
|
+
flags |= FLAG_RETURNS_NOTHING;
|
755
|
+
intarg_count++;
|
756
|
+
}
|
757
|
+
}
|
758
|
+
#elif defined(DARWIN_PPC)
|
759
|
+
if (cif->rtype->size <= 4)
|
760
|
+
flags |= FLAG_RETURNS_STRUCT;
|
761
|
+
else /* else by reference. */
|
762
|
+
{
|
763
|
+
flags |= FLAG_RETVAL_REFERENCE;
|
764
|
+
flags |= FLAG_RETURNS_NOTHING;
|
765
|
+
intarg_count++;
|
766
|
+
}
|
767
|
+
#else /* assume we pass by ref. */
|
413
768
|
flags |= FLAG_RETVAL_REFERENCE;
|
414
769
|
flags |= FLAG_RETURNS_NOTHING;
|
415
770
|
intarg_count++;
|
771
|
+
#endif
|
416
772
|
break;
|
417
773
|
case FFI_TYPE_VOID:
|
418
774
|
flags |= FLAG_RETURNS_NOTHING;
|
@@ -425,57 +781,83 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|
425
781
|
|
426
782
|
/* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the
|
427
783
|
first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest
|
428
|
-
goes on the stack.
|
429
|
-
|
784
|
+
goes on the stack.
|
785
|
+
??? Structures are passed as a pointer to a copy of the structure.
|
786
|
+
Stuff on the stack needs to keep proper alignment.
|
787
|
+
For m64 the count is effectively of half-GPRs. */
|
430
788
|
for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++)
|
431
789
|
{
|
790
|
+
unsigned align_words;
|
432
791
|
switch ((*ptr)->type)
|
433
792
|
{
|
434
793
|
case FFI_TYPE_FLOAT:
|
435
794
|
case FFI_TYPE_DOUBLE:
|
436
795
|
fparg_count++;
|
796
|
+
#if !defined(POWERPC_DARWIN64)
|
437
797
|
/* If this FP arg is going on the stack, it must be
|
438
798
|
8-byte-aligned. */
|
439
799
|
if (fparg_count > NUM_FPR_ARG_REGISTERS
|
440
|
-
&& intarg_count
|
800
|
+
&& (intarg_count & 0x01) != 0)
|
441
801
|
intarg_count++;
|
802
|
+
#endif
|
442
803
|
break;
|
443
804
|
|
444
805
|
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
|
445
|
-
|
446
806
|
case FFI_TYPE_LONGDOUBLE:
|
447
807
|
fparg_count += 2;
|
448
808
|
/* If this FP arg is going on the stack, it must be
|
449
|
-
|
450
|
-
if (fparg_count
|
451
|
-
|
452
|
-
intarg_count
|
453
|
-
|
809
|
+
16-byte-aligned. */
|
810
|
+
if (fparg_count >= NUM_FPR_ARG_REGISTERS)
|
811
|
+
#if defined (POWERPC64)
|
812
|
+
intarg_count = ALIGN(intarg_count, 2);
|
813
|
+
#else
|
814
|
+
intarg_count = ALIGN(intarg_count, 4);
|
815
|
+
#endif
|
454
816
|
break;
|
455
817
|
#endif
|
456
818
|
|
457
819
|
case FFI_TYPE_UINT64:
|
458
820
|
case FFI_TYPE_SINT64:
|
821
|
+
#if defined(POWERPC64)
|
822
|
+
intarg_count++;
|
823
|
+
#else
|
459
824
|
/* 'long long' arguments are passed as two words, but
|
460
825
|
either both words must fit in registers or both go
|
461
826
|
on the stack. If they go on the stack, they must
|
462
827
|
be 8-byte-aligned. */
|
463
828
|
if (intarg_count == NUM_GPR_ARG_REGISTERS-1
|
464
|
-
|| (intarg_count >= NUM_GPR_ARG_REGISTERS
|
829
|
+
|| (intarg_count >= NUM_GPR_ARG_REGISTERS
|
830
|
+
&& (intarg_count & 0x01) != 0))
|
465
831
|
intarg_count++;
|
466
832
|
intarg_count += 2;
|
833
|
+
#endif
|
467
834
|
break;
|
468
835
|
|
469
836
|
case FFI_TYPE_STRUCT:
|
470
837
|
size_al = (*ptr)->size;
|
838
|
+
#if defined(POWERPC_DARWIN64)
|
839
|
+
align_words = (*ptr)->alignment >> 3;
|
840
|
+
if (align_words)
|
841
|
+
intarg_count = ALIGN(intarg_count, align_words);
|
842
|
+
/* Base size of the struct. */
|
843
|
+
intarg_count += (size_al + 7) / 8;
|
844
|
+
/* If 16 bytes then don't worry about floats. */
|
845
|
+
if (size_al != 16)
|
846
|
+
/* Scan through for floats to be placed in regs. */
|
847
|
+
darwin64_scan_struct_for_floats (*ptr, &fparg_count) ;
|
848
|
+
#else
|
849
|
+
align_words = (*ptr)->alignment >> 2;
|
850
|
+
if (align_words)
|
851
|
+
intarg_count = ALIGN(intarg_count, align_words);
|
471
852
|
/* If the first member of the struct is a double, then align
|
472
|
-
the struct to double-word.
|
853
|
+
the struct to double-word.
|
473
854
|
if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE)
|
474
|
-
size_al = ALIGN((*ptr)->size, 8);
|
475
|
-
#ifdef POWERPC64
|
855
|
+
size_al = ALIGN((*ptr)->size, 8); */
|
856
|
+
# ifdef POWERPC64
|
476
857
|
intarg_count += (size_al + 7) / 8;
|
477
|
-
#else
|
858
|
+
# else
|
478
859
|
intarg_count += (size_al + 3) / 4;
|
860
|
+
# endif
|
479
861
|
#endif
|
480
862
|
break;
|
481
863
|
|
@@ -490,9 +872,18 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|
490
872
|
if (fparg_count != 0)
|
491
873
|
flags |= FLAG_FP_ARGUMENTS;
|
492
874
|
|
875
|
+
#if defined(POWERPC_DARWIN64)
|
876
|
+
/* Space to image the FPR registers, if needed - which includes when they might be
|
877
|
+
used in a struct return. */
|
878
|
+
if (fparg_count != 0
|
879
|
+
|| ((flags & FLAG_RETURNS_STRUCT)
|
880
|
+
&& (flags & FLAG_RETURNS_FP)))
|
881
|
+
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
882
|
+
#else
|
493
883
|
/* Space for the FPR registers, if needed. */
|
494
884
|
if (fparg_count != 0)
|
495
885
|
bytes += NUM_FPR_ARG_REGISTERS * sizeof(double);
|
886
|
+
#endif
|
496
887
|
|
497
888
|
/* Stack space. */
|
498
889
|
#ifdef POWERPC64
|
@@ -506,7 +897,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|
506
897
|
bytes += NUM_GPR_ARG_REGISTERS * sizeof(long);
|
507
898
|
|
508
899
|
/* The stack space allocated needs to be a multiple of 16 bytes. */
|
509
|
-
bytes = (bytes
|
900
|
+
bytes = ALIGN(bytes, 16) ;
|
510
901
|
|
511
902
|
cif->flags = flags;
|
512
903
|
cif->bytes = bytes;
|
@@ -516,8 +907,9 @@ ffi_prep_cif_machdep (ffi_cif *cif)
|
|
516
907
|
|
517
908
|
extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *,
|
518
909
|
void (*fn)(void), void (*fn2)(void));
|
910
|
+
|
519
911
|
extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *,
|
520
|
-
void (*fn)(void), void (*fn2)(void));
|
912
|
+
void (*fn)(void), void (*fn2)(void), ffi_type*);
|
521
913
|
|
522
914
|
void
|
523
915
|
ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
@@ -542,11 +934,11 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
|
|
542
934
|
{
|
543
935
|
case FFI_AIX:
|
544
936
|
ffi_call_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
|
545
|
-
ffi_prep_args);
|
937
|
+
FFI_FN(ffi_prep_args));
|
546
938
|
break;
|
547
939
|
case FFI_DARWIN:
|
548
940
|
ffi_call_DARWIN(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn,
|
549
|
-
ffi_prep_args);
|
941
|
+
FFI_FN(ffi_prep_args), cif->rtype);
|
550
942
|
break;
|
551
943
|
default:
|
552
944
|
FFI_ASSERT(0);
|
@@ -566,58 +958,48 @@ typedef struct aix_fd_struct {
|
|
566
958
|
} aix_fd;
|
567
959
|
|
568
960
|
/* here I'd like to add the stack frame layout we use in darwin_closure.S
|
569
|
-
and
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
+---------------------------------------+ 200
|
609
|
-
| always reserved 8*4=32 we store our |
|
610
|
-
| GPRs here |
|
611
|
-
| r3 |
|
612
|
-
| . |
|
613
|
-
| r10 |
|
614
|
-
+---------------------------------------+ 232
|
615
|
-
| overflow part |
|
616
|
-
+---------------------------------------+ xxx
|
617
|
-
| ???? |
|
618
|
-
+---------------------------------------+ xxx
|
961
|
+
and aix_closure.S
|
962
|
+
|
963
|
+
m32/m64
|
964
|
+
|
965
|
+
The stack layout looks like this:
|
966
|
+
|
967
|
+
| Additional params... | | Higher address
|
968
|
+
~ ~ ~
|
969
|
+
| Parameters (at least 8*4/8=32/64) | | NUM_GPR_ARG_REGISTERS
|
970
|
+
|--------------------------------------------| |
|
971
|
+
| TOC=R2 (AIX) Reserved (Darwin) 4/8 | |
|
972
|
+
|--------------------------------------------| |
|
973
|
+
| Reserved 2*4/8 | |
|
974
|
+
|--------------------------------------------| |
|
975
|
+
| Space for callee's LR 4/8 | |
|
976
|
+
|--------------------------------------------| |
|
977
|
+
| Saved CR [low word for m64] 4/8 | |
|
978
|
+
|--------------------------------------------| |
|
979
|
+
| Current backchain pointer 4/8 |-/ Parent's frame.
|
980
|
+
|--------------------------------------------| <+ <<< on entry to ffi_closure_ASM
|
981
|
+
| Result Bytes 16 | |
|
982
|
+
|--------------------------------------------| |
|
983
|
+
~ padding to 16-byte alignment ~ ~
|
984
|
+
|--------------------------------------------| |
|
985
|
+
| NUM_FPR_ARG_REGISTERS slots | |
|
986
|
+
| here fp13 .. fp1 13*8 | |
|
987
|
+
|--------------------------------------------| |
|
988
|
+
| R3..R10 8*4/8=32/64 | | NUM_GPR_ARG_REGISTERS
|
989
|
+
|--------------------------------------------| |
|
990
|
+
| TOC=R2 (AIX) Reserved (Darwin) 4/8 | |
|
991
|
+
|--------------------------------------------| | stack |
|
992
|
+
| Reserved [compiler,binder] 2*4/8 | | grows |
|
993
|
+
|--------------------------------------------| | down V
|
994
|
+
| Space for callee's LR 4/8 | |
|
995
|
+
|--------------------------------------------| | lower addresses
|
996
|
+
| Saved CR [low word for m64] 4/8 | |
|
997
|
+
|--------------------------------------------| | stack pointer here
|
998
|
+
| Current backchain pointer 4/8 |-/ during
|
999
|
+
|--------------------------------------------| <<< ffi_closure_ASM.
|
619
1000
|
|
620
1001
|
*/
|
1002
|
+
|
621
1003
|
ffi_status
|
622
1004
|
ffi_prep_closure_loc (ffi_closure* closure,
|
623
1005
|
ffi_cif* cif,
|
@@ -631,30 +1013,44 @@ ffi_prep_closure_loc (ffi_closure* closure,
|
|
631
1013
|
|
632
1014
|
switch (cif->abi)
|
633
1015
|
{
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
1016
|
+
case FFI_DARWIN:
|
1017
|
+
|
1018
|
+
FFI_ASSERT (cif->abi == FFI_DARWIN);
|
1019
|
+
|
1020
|
+
tramp = (unsigned int *) &closure->tramp[0];
|
1021
|
+
#if defined(POWERPC_DARWIN64)
|
1022
|
+
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
1023
|
+
tramp[1] = 0x429f0015; /* bcl- 20,4*cr7+so, +0x18 (L1) */
|
1024
|
+
/* We put the addresses here. */
|
1025
|
+
tramp[6] = 0x7d6802a6; /*L1: mflr r11 */
|
1026
|
+
tramp[7] = 0xe98b0000; /* ld r12,0(r11) function address */
|
1027
|
+
tramp[8] = 0x7c0803a6; /* mtlr r0 */
|
1028
|
+
tramp[9] = 0x7d8903a6; /* mtctr r12 */
|
1029
|
+
tramp[10] = 0xe96b0008; /* lwz r11,8(r11) static chain */
|
1030
|
+
tramp[11] = 0x4e800420; /* bctr */
|
1031
|
+
|
1032
|
+
*((unsigned long *)&tramp[2]) = (unsigned long) ffi_closure_ASM; /* function */
|
1033
|
+
*((unsigned long *)&tramp[4]) = (unsigned long) codeloc; /* context */
|
1034
|
+
#else
|
1035
|
+
tramp[0] = 0x7c0802a6; /* mflr r0 */
|
1036
|
+
tramp[1] = 0x429f000d; /* bcl- 20,4*cr7+so,0x10 */
|
1037
|
+
tramp[4] = 0x7d6802a6; /* mflr r11 */
|
1038
|
+
tramp[5] = 0x818b0000; /* lwz r12,0(r11) function address */
|
1039
|
+
tramp[6] = 0x7c0803a6; /* mtlr r0 */
|
1040
|
+
tramp[7] = 0x7d8903a6; /* mtctr r12 */
|
1041
|
+
tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
|
1042
|
+
tramp[9] = 0x4e800420; /* bctr */
|
1043
|
+
tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
|
1044
|
+
tramp[3] = (unsigned long) codeloc; /* context */
|
1045
|
+
#endif
|
1046
|
+
closure->cif = cif;
|
1047
|
+
closure->fun = fun;
|
1048
|
+
closure->user_data = user_data;
|
653
1049
|
|
654
|
-
|
655
|
-
|
1050
|
+
/* Flush the icache. Only necessary on Darwin. */
|
1051
|
+
flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
|
656
1052
|
|
657
|
-
|
1053
|
+
break;
|
658
1054
|
|
659
1055
|
case FFI_AIX:
|
660
1056
|
|
@@ -708,7 +1104,7 @@ typedef union
|
|
708
1104
|
double d;
|
709
1105
|
} ffi_dblfl;
|
710
1106
|
|
711
|
-
|
1107
|
+
ffi_type *
|
712
1108
|
ffi_closure_helper_DARWIN (ffi_closure *, void *,
|
713
1109
|
unsigned long *, ffi_dblfl *);
|
714
1110
|
|
@@ -719,7 +1115,7 @@ ffi_closure_helper_DARWIN (ffi_closure *, void *,
|
|
719
1115
|
up space for a return value, ffi_closure_ASM invokes the
|
720
1116
|
following helper function to do most of the work. */
|
721
1117
|
|
722
|
-
|
1118
|
+
ffi_type *
|
723
1119
|
ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
|
724
1120
|
unsigned long *pgr, ffi_dblfl *pfr)
|
725
1121
|
{
|
@@ -741,16 +1137,32 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
|
|
741
1137
|
ffi_cif * cif;
|
742
1138
|
ffi_dblfl * end_pfr = pfr + NUM_FPR_ARG_REGISTERS;
|
743
1139
|
unsigned size_al;
|
1140
|
+
#if defined(POWERPC_DARWIN64)
|
1141
|
+
unsigned fpsused = 0;
|
1142
|
+
#endif
|
744
1143
|
|
745
1144
|
cif = closure->cif;
|
746
1145
|
avalue = alloca (cif->nargs * sizeof(void *));
|
747
1146
|
|
748
|
-
/* Copy the caller's structure return value address so that the closure
|
749
|
-
returns the data directly to the caller. */
|
750
1147
|
if (cif->rtype->type == FFI_TYPE_STRUCT)
|
751
1148
|
{
|
1149
|
+
#if defined(POWERPC_DARWIN64)
|
1150
|
+
if (!darwin64_struct_ret_by_value_p (cif->rtype))
|
1151
|
+
{
|
1152
|
+
/* Won't fit into the regs - return by ref. */
|
1153
|
+
rvalue = (void *) *pgr;
|
1154
|
+
pgr++;
|
1155
|
+
}
|
1156
|
+
#elif defined(DARWIN_PPC)
|
1157
|
+
if (cif->rtype->size > 4)
|
1158
|
+
{
|
1159
|
+
rvalue = (void *) *pgr;
|
1160
|
+
pgr++;
|
1161
|
+
}
|
1162
|
+
#else /* assume we return by ref. */
|
752
1163
|
rvalue = (void *) *pgr;
|
753
1164
|
pgr++;
|
1165
|
+
#endif
|
754
1166
|
}
|
755
1167
|
|
756
1168
|
i = 0;
|
@@ -764,7 +1176,7 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
|
|
764
1176
|
{
|
765
1177
|
case FFI_TYPE_SINT8:
|
766
1178
|
case FFI_TYPE_UINT8:
|
767
|
-
#
|
1179
|
+
#if defined(POWERPC64)
|
768
1180
|
avalue[i] = (char *) pgr + 7;
|
769
1181
|
#else
|
770
1182
|
avalue[i] = (char *) pgr + 3;
|
@@ -774,7 +1186,7 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
|
|
774
1186
|
|
775
1187
|
case FFI_TYPE_SINT16:
|
776
1188
|
case FFI_TYPE_UINT16:
|
777
|
-
#
|
1189
|
+
#if defined(POWERPC64)
|
778
1190
|
avalue[i] = (char *) pgr + 6;
|
779
1191
|
#else
|
780
1192
|
avalue[i] = (char *) pgr + 2;
|
@@ -784,7 +1196,7 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
|
|
784
1196
|
|
785
1197
|
case FFI_TYPE_SINT32:
|
786
1198
|
case FFI_TYPE_UINT32:
|
787
|
-
#
|
1199
|
+
#if defined(POWERPC64)
|
788
1200
|
avalue[i] = (char *) pgr + 4;
|
789
1201
|
#else
|
790
1202
|
case FFI_TYPE_POINTER:
|
@@ -794,34 +1206,53 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
|
|
794
1206
|
break;
|
795
1207
|
|
796
1208
|
case FFI_TYPE_STRUCT:
|
797
|
-
#ifdef POWERPC64
|
798
1209
|
size_al = arg_types[i]->size;
|
799
|
-
|
800
|
-
|
801
|
-
if (size_al < 3
|
802
|
-
|
803
|
-
|
804
|
-
|
1210
|
+
#if defined(POWERPC_DARWIN64)
|
1211
|
+
pgr = (unsigned long *)ALIGN((char *)pgr, arg_types[i]->alignment);
|
1212
|
+
if (size_al < 3 || size_al == 4)
|
1213
|
+
{
|
1214
|
+
avalue[i] = ((char *)pgr)+8-size_al;
|
1215
|
+
if (arg_types[i]->elements[0]->type == FFI_TYPE_FLOAT
|
1216
|
+
&& fpsused < NUM_FPR_ARG_REGISTERS)
|
1217
|
+
{
|
1218
|
+
*(float *)pgr = (float) *(double *)pfr;
|
1219
|
+
pfr++;
|
1220
|
+
fpsused++;
|
1221
|
+
}
|
1222
|
+
}
|
1223
|
+
else
|
1224
|
+
{
|
1225
|
+
if (size_al != 16)
|
1226
|
+
pfr = (ffi_dblfl *)
|
1227
|
+
darwin64_struct_floats_to_mem (arg_types[i], (char *)pgr,
|
1228
|
+
(double *)pfr, &fpsused);
|
1229
|
+
avalue[i] = pgr;
|
1230
|
+
}
|
805
1231
|
pgr += (size_al + 7) / 8;
|
806
1232
|
#else
|
807
|
-
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
808
|
-
SI 4 bytes) are aligned as if they were those modes. */
|
809
|
-
size_al = arg_types[i]->size;
|
810
1233
|
/* If the first member of the struct is a double, then align
|
811
1234
|
the struct to double-word. */
|
812
1235
|
if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE)
|
813
1236
|
size_al = ALIGN(arg_types[i]->size, 8);
|
1237
|
+
# if defined(POWERPC64)
|
1238
|
+
FFI_ASSERT (cif->abi != FFI_DARWIN)
|
1239
|
+
avalue[i] = pgr;
|
1240
|
+
pgr += (size_al + 7) / 8;
|
1241
|
+
# else
|
1242
|
+
/* Structures that match the basic modes (QI 1 byte, HI 2 bytes,
|
1243
|
+
SI 4 bytes) are aligned as if they were those modes. */
|
814
1244
|
if (size_al < 3 && cif->abi == FFI_DARWIN)
|
815
|
-
avalue[i] = (
|
1245
|
+
avalue[i] = (char*) pgr + 4 - size_al;
|
816
1246
|
else
|
817
|
-
avalue[i] =
|
1247
|
+
avalue[i] = pgr;
|
818
1248
|
pgr += (size_al + 3) / 4;
|
1249
|
+
# endif
|
819
1250
|
#endif
|
820
1251
|
break;
|
821
1252
|
|
822
1253
|
case FFI_TYPE_SINT64:
|
823
1254
|
case FFI_TYPE_UINT64:
|
824
|
-
#
|
1255
|
+
#if defined(POWERPC64)
|
825
1256
|
case FFI_TYPE_POINTER:
|
826
1257
|
avalue[i] = pgr;
|
827
1258
|
pgr++;
|
@@ -924,5 +1355,5 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue,
|
|
924
1355
|
(closure->fun) (cif, rvalue, avalue, closure->user_data);
|
925
1356
|
|
926
1357
|
/* Tell ffi_closure_ASM to perform return type promotions. */
|
927
|
-
return cif->rtype
|
1358
|
+
return cif->rtype;
|
928
1359
|
}
|