diff --git a/plugins/python-build/share/python-build/patches/2.5.1/Python-2.5.1/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.1/Python-2.5.1/004_osx_libffi.patch new file mode 100644 index 00000000..cd500771 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/2.5.1/Python-2.5.1/004_osx_libffi.patch @@ -0,0 +1,6881 @@ +diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE +new file mode 100644 +index 0000000..f591795 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/LICENSE +@@ -0,0 +1,20 @@ ++libffi - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++``Software''), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice shall be included ++in all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++OTHER DEALINGS IN THE SOFTWARE. +diff --git ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README +new file mode 100644 +index 0000000..1fc2747 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README +@@ -0,0 +1,500 @@ ++This directory contains the libffi package, which is not part of GCC but ++shipped with GCC as convenience. ++ ++Status ++====== ++ ++libffi-2.00 has not been released yet! This is a development snapshot! ++ ++libffi-1.20 was released on October 5, 1998. Check the libffi web ++page for updates: . ++ ++ ++What is libffi? ++=============== ++ ++Compilers for high level languages generate code that follow certain ++conventions. These conventions are necessary, in part, for separate ++compilation to work. One such convention is the "calling ++convention". The "calling convention" is essentially a set of ++assumptions made by the compiler about where function arguments will ++be found on entry to a function. A "calling convention" also specifies ++where the return value for a function is found. ++ ++Some programs may not know at the time of compilation what arguments ++are to be passed to a function. For instance, an interpreter may be ++told at run-time about the number and types of arguments used to call ++a given function. Libffi can be used in such programs to provide a ++bridge from the interpreter program to compiled code. ++ ++The libffi library provides a portable, high level programming ++interface to various calling conventions. This allows a programmer to ++call any function specified by a call interface description at run ++time. ++ ++Ffi stands for Foreign Function Interface. A foreign function ++interface is the popular name for the interface that allows code ++written in one language to call code written in another language. The ++libffi library really only provides the lowest, machine dependent ++layer of a fully featured foreign function interface. A layer must ++exist above libffi that handles type conversions for values passed ++between the two languages. ++ ++ ++Supported Platforms and Prerequisites ++===================================== ++ ++Libffi has been ported to: ++ ++ SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) ++ ++ Irix 5.3 & 6.2 (System V/o32 & n32) ++ ++ Intel x86 - Linux (System V ABI) ++ ++ Alpha - Linux and OSF/1 ++ ++ m68k - Linux (System V ABI) ++ ++ PowerPC - Linux (System V ABI, Darwin, AIX) ++ ++ ARM - Linux (System V ABI) ++ ++Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are ++that other versions will work. Libffi has also been built and tested ++with the SGI compiler tools. ++ ++On PowerPC, the tests failed (see the note below). ++ ++You must use GNU make to build libffi. SGI's make will not work. ++Sun's probably won't either. ++ ++If you port libffi to another platform, please let me know! I assume ++that some will be easy (x86 NetBSD), and others will be more difficult ++(HP). ++ ++ ++Installing libffi ++================= ++ ++[Note: before actually performing any of these installation steps, ++ you may wish to read the "Platform Specific Notes" below.] ++ ++First you must configure the distribution for your particular ++system. Go to the directory you wish to build libffi in and run the ++"configure" program found in the root directory of the libffi source ++distribution. ++ ++You may want to tell configure where to install the libffi library and ++header files. To do that, use the --prefix configure switch. Libffi ++will install under /usr/local by default. ++ ++If you want to enable extra run-time debugging checks use the the ++--enable-debug configure switch. This is useful when your program dies ++mysteriously while using libffi. ++ ++Another useful configure switch is --enable-purify-safety. Using this ++will add some extra code which will suppress certain warnings when you ++are using Purify with libffi. Only use this switch when using ++Purify, as it will slow down the library. ++ ++Configure has many other options. Use "configure --help" to see them all. ++ ++Once configure has finished, type "make". Note that you must be using ++GNU make. SGI's make will not work. Sun's probably won't either. ++You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. ++ ++To ensure that libffi is working as advertised, type "make test". ++ ++To install the library and header files, type "make install". ++ ++ ++Using libffi ++============ ++ ++ The Basics ++ ---------- ++ ++Libffi assumes that you have a pointer to the function you wish to ++call and that you know the number and types of arguments to pass it, ++as well as the return type of the function. ++ ++The first thing you must do is create an ffi_cif object that matches ++the signature of the function you wish to call. The cif in ffi_cif ++stands for Call InterFace. To prepare a call interface object, use the ++following function: ++ ++ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, ++ unsigned int nargs, ++ ffi_type *rtype, ffi_type **atypes); ++ ++ CIF is a pointer to the call interface object you wish ++ to initialize. ++ ++ ABI is an enum that specifies the calling convention ++ to use for the call. FFI_DEFAULT_ABI defaults ++ to the system's native calling convention. Other ++ ABI's may be used with care. They are system ++ specific. ++ ++ NARGS is the number of arguments this function accepts. ++ libffi does not yet support vararg functions. ++ ++ RTYPE is a pointer to an ffi_type structure that represents ++ the return type of the function. Ffi_type objects ++ describe the types of values. libffi provides ++ ffi_type objects for many of the native C types: ++ signed int, unsigned int, signed char, unsigned char, ++ etc. There is also a pointer ffi_type object and ++ a void ffi_type. Use &ffi_type_void for functions that ++ don't return values. ++ ++ ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. ++ If NARGS is 0, this is ignored. ++ ++ ++ffi_prep_cif will return a status code that you are responsible ++for checking. It will be one of the following: ++ ++ FFI_OK - All is good. ++ ++ FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif ++ came across is bad. ++ ++ ++Before making the call, the VALUES vector should be initialized ++with pointers to the appropriate argument values. ++ ++To call the the function using the initialized ffi_cif, use the ++ffi_call function: ++ ++void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); ++ ++ CIF is a pointer to the ffi_cif initialized specifically ++ for this function. ++ ++ FN is a pointer to the function you want to call. ++ ++ RVALUE is a pointer to a chunk of memory that is to hold the ++ result of the function call. Currently, it must be ++ at least one word in size (except for the n32 version ++ under Irix 6.x, which must be a pointer to an 8 byte ++ aligned value (a long long). It must also be at least ++ word aligned (depending on the return type, and the ++ system's alignment requirements). If RTYPE is ++ &ffi_type_void, this is ignored. If RVALUE is NULL, ++ the return value is discarded. ++ ++ AVALUES is a vector of void* that point to the memory locations ++ holding the argument values for a call. ++ If NARGS is 0, this is ignored. ++ ++ ++If you are expecting a return value from FN it will have been stored ++at RVALUE. ++ ++ ++ ++ An Example ++ ---------- ++ ++Here is a trivial example that calls puts() a few times. ++ ++ #include ++ #include ++ ++ int main() ++ { ++ ffi_cif cif; ++ ffi_type *args[1]; ++ void *values[1]; ++ char *s; ++ int rc; ++ ++ /* Initialize the argument info vectors */ ++ args[0] = &ffi_type_uint; ++ values[0] = &s; ++ ++ /* Initialize the cif */ ++ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, ++ &ffi_type_uint, args) == FFI_OK) ++ { ++ s = "Hello World!"; ++ ffi_call(&cif, puts, &rc, values); ++ /* rc now holds the result of the call to puts */ ++ ++ /* values holds a pointer to the function's arg, so to ++ call puts() again all we need to do is change the ++ value of s */ ++ s = "This is cool!"; ++ ffi_call(&cif, puts, &rc, values); ++ } ++ ++ return 0; ++ } ++ ++ ++ ++ Aggregate Types ++ --------------- ++ ++Although libffi has no special support for unions or bit-fields, it is ++perfectly happy passing structures back and forth. You must first ++describe the structure to libffi by creating a new ffi_type object ++for it. Here is the definition of ffi_type: ++ ++ typedef struct _ffi_type ++ { ++ unsigned size; ++ short alignment; ++ short type; ++ struct _ffi_type **elements; ++ } ffi_type; ++ ++All structures must have type set to FFI_TYPE_STRUCT. You may set ++size and alignment to 0. These will be calculated and reset to the ++appropriate values by ffi_prep_cif(). ++ ++elements is a NULL terminated array of pointers to ffi_type objects ++that describe the type of the structure elements. These may, in turn, ++be structure elements. ++ ++The following example initializes a ffi_type object representing the ++tm struct from Linux's time.h: ++ ++ struct tm { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++ /* Those are for future use. */ ++ long int __tm_gmtoff__; ++ __const char *__tm_zone__; ++ }; ++ ++ { ++ ffi_type tm_type; ++ ffi_type *tm_type_elements[12]; ++ int i; ++ ++ tm_type.size = tm_type.alignment = 0; ++ tm_type.elements = &tm_type_elements; ++ ++ for (i = 0; i < 9; i++) ++ tm_type_elements[i] = &ffi_type_sint; ++ ++ tm_type_elements[9] = &ffi_type_slong; ++ tm_type_elements[10] = &ffi_type_pointer; ++ tm_type_elements[11] = NULL; ++ ++ /* tm_type can now be used to represent tm argument types and ++ return types for ffi_prep_cif() */ ++ } ++ ++ ++ ++Platform Specific Notes ++======================= ++ ++ Intel x86 ++ --------- ++ ++There are no known problems with the x86 port. ++ ++ Sun SPARC - SunOS 4.1.3 & Solaris 2.x ++ ------------------------------------- ++ ++You must use GNU Make to build libffi on Sun platforms. ++ ++ MIPS - Irix 5.3 & 6.x ++ --------------------- ++ ++Irix 6.2 and better supports three different calling conventions: o32, ++n32 and n64. Currently, libffi only supports both o32 and n32 under ++Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be ++configured for whichever calling convention it was built for. ++ ++By default, the configure script will try to build libffi with the GNU ++development tools. To build libffi with the SGI development tools, set ++the environment variable CC to either "cc -32" or "cc -n32" before ++running configure under Irix 6.x (depending on whether you want an o32 ++or n32 library), or just "cc" for Irix 5.3. ++ ++With the n32 calling convention, when returning structures smaller ++than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. ++Here's one way of forcing this: ++ ++ double struct_storage[2]; ++ my_small_struct *s = (my_small_struct *) struct_storage; ++ /* Use s for RVALUE */ ++ ++If you don't do this you are liable to get spurious bus errors. ++ ++"long long" values are not supported yet. ++ ++You must use GNU Make to build libffi on SGI platforms. ++ ++ ARM - System V ABI ++ ------------------ ++ ++The ARM port was performed on a NetWinder running ARM Linux ELF ++(2.0.31) and gcc 2.8.1. ++ ++ ++ ++ PowerPC System V ABI ++ -------------------- ++ ++There are two `System V ABI's which libffi implements for PowerPC. ++They differ only in how small structures are returned from functions. ++ ++In the FFI_SYSV version, structures that are 8 bytes or smaller are ++returned in registers. This is what GCC does when it is configured ++for solaris, and is what the System V ABI I have (dated September ++1995) says. ++ ++In the FFI_GCC_SYSV version, all structures are returned the same way: ++by passing a pointer as the first argument to the function. This is ++what GCC does when it is configured for linux or a generic sysv ++target. ++ ++EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a ++inconsistency with the SysV ABI: When a procedure is called with many ++floating-point arguments, some of them get put on the stack. They are ++all supposed to be stored in double-precision format, even if they are ++only single-precision, but EGCS stores single-precision arguments as ++single-precision anyway. This causes one test to fail (the `many ++arguments' test). ++ ++ ++What's With The Crazy Comments? ++=============================== ++ ++You might notice a number of cryptic comments in the code, delimited ++by /*@ and @*/. These are annotations read by the program LCLint, a ++tool for statically checking C programs. You can read all about it at ++. ++ ++ ++History ++======= ++ ++1.20 Oct-5-98 ++ Raffaele Sena produces ARM port. ++ ++1.19 Oct-5-98 ++ Fixed x86 long double and long long return support. ++ m68k bug fixes from Andreas Schwab. ++ Patch for DU assembler compatibility for the Alpha from Richard ++ Henderson. ++ ++1.18 Apr-17-98 ++ Bug fixes and MIPS configuration changes. ++ ++1.17 Feb-24-98 ++ Bug fixes and m68k port from Andreas Schwab. PowerPC port from ++ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. ++ ++1.16 Feb-11-98 ++ Richard Henderson produces Alpha port. ++ ++1.15 Dec-4-97 ++ Fixed an n32 ABI bug. New libtool, auto* support. ++ ++1.14 May-13-97 ++ libtool is now used to generate shared and static libraries. ++ Fixed a minor portability problem reported by Russ McManus ++ . ++ ++1.13 Dec-2-96 ++ Added --enable-purify-safety to keep Purify from complaining ++ about certain low level code. ++ Sparc fix for calling functions with < 6 args. ++ Linux x86 a.out fix. ++ ++1.12 Nov-22-96 ++ Added missing ffi_type_void, needed for supporting void return ++ types. Fixed test case for non MIPS machines. Cygnus Support ++ is now Cygnus Solutions. ++ ++1.11 Oct-30-96 ++ Added notes about GNU make. ++ ++1.10 Oct-29-96 ++ Added configuration fix for non GNU compilers. ++ ++1.09 Oct-29-96 ++ Added --enable-debug configure switch. Clean-ups based on LCLint ++ feedback. ffi_mips.h is always installed. Many configuration ++ fixes. Fixed ffitest.c for sparc builds. ++ ++1.08 Oct-15-96 ++ Fixed n32 problem. Many clean-ups. ++ ++1.07 Oct-14-96 ++ Gordon Irlam rewrites v8.S again. Bug fixes. ++ ++1.06 Oct-14-96 ++ Gordon Irlam improved the sparc port. ++ ++1.05 Oct-14-96 ++ Interface changes based on feedback. ++ ++1.04 Oct-11-96 ++ Sparc port complete (modulo struct passing bug). ++ ++1.03 Oct-10-96 ++ Passing struct args, and returning struct values works for ++ all architectures/calling conventions. Expanded tests. ++ ++1.02 Oct-9-96 ++ Added SGI n32 support. Fixed bugs in both o32 and Linux support. ++ Added "make test". ++ ++1.01 Oct-8-96 ++ Fixed float passing bug in mips version. Restructured some ++ of the code. Builds cleanly with SGI tools. ++ ++1.00 Oct-7-96 ++ First release. No public announcement. ++ ++ ++Authors & Credits ++================= ++ ++libffi was written by Anthony Green . ++ ++Portions of libffi were derived from Gianni Mariani's free gencall ++library for Silicon Graphics machines. ++ ++The closure mechanism was designed and implemented by Kresten Krab ++Thorup. ++ ++The Sparc port was derived from code contributed by the fine folks at ++Visible Decisions Inc . Further enhancements were ++made by Gordon Irlam at Cygnus Solutions . ++ ++The Alpha port was written by Richard Henderson at Cygnus Solutions. ++ ++Andreas Schwab ported libffi to m68k Linux and provided a number of ++bug fixes. ++ ++Geoffrey Keating ported libffi to the PowerPC. ++ ++Raffaele Sena ported libffi to the ARM. ++ ++Jesper Skov and Andrew Haley both did more than their fair share of ++stepping through the code and tracking down bugs. ++ ++Thanks also to Tom Tromey for bug fixes and configuration help. ++ ++Thanks to Jim Blandy, who provided some useful feedback on the libffi ++interface. ++ ++If you have a problem, or have found a bug, please send a note to ++green@cygnus.com. +diff --git ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc +new file mode 100644 +index 0000000..405d85f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README.pyobjc +@@ -0,0 +1,5 @@ ++This directory contains a slightly modified version of libffi, extracted from ++the GCC source-tree. ++ ++The only modifications are those that are necessary to compile libffi using ++the Apple provided compiler and outside of the GCC source tree. +diff --git ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c +new file mode 100644 +index 0000000..bf42093 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/ffi.c +@@ -0,0 +1,226 @@ ++/* ----------------------------------------------------------------------- ++ prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++/* Round up to FFI_SIZEOF_ARG. */ ++#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) ++ ++/* Perform machine independent initialization of aggregate type ++ specifications. */ ++ ++static ffi_status ++initialize_aggregate( ++/*@out@*/ ffi_type* arg) ++{ ++/*@-usedef@*/ ++ ++ if (arg == NULL || arg->elements == NULL || ++ arg->size != 0 || arg->alignment != 0) ++ return FFI_BAD_TYPEDEF; ++ ++ ffi_type** ptr = &(arg->elements[0]); ++ ++ while ((*ptr) != NULL) ++ { ++ if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#ifdef POWERPC_DARWIN ++ int curalign = (*ptr)->alignment; ++ ++ if (ptr != &(arg->elements[0])) ++ { ++ if (curalign > 4 && curalign != 16) ++ curalign = 4; ++ } ++ ++ arg->size = ALIGN(arg->size, curalign); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > curalign) ? ++ arg->alignment : curalign; ++#else ++ arg->size = ALIGN(arg->size, (*ptr)->alignment); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > (*ptr)->alignment) ? ++ arg->alignment : (*ptr)->alignment; ++#endif ++ ++ ptr++; ++ } ++ ++ /* Structure size includes tail padding. This is important for ++ structures that fit in one register on ABIs like the PowerPC64 ++ Linux ABI that right justify small structs in a register. ++ It's also needed for nested structure layout, for example ++ struct A { long a; char b; }; struct B { struct A x; char y; }; ++ should find y at an offset of 2*sizeof(long) and result in a ++ total size of 3*sizeof(long). */ ++ arg->size = ALIGN(arg->size, arg->alignment); ++ ++ if (arg->size == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ return FFI_OK; ++ ++/*@=usedef@*/ ++} ++ ++#ifndef __CRIS__ ++/* The CRIS ABI specifies structure elements to have byte ++ alignment only, so it completely overrides this functions, ++ which assumes "natural" alignment and padding. */ ++ ++/* Perform machine independent ffi_cif preparation, then call ++ machine dependent routine. */ ++ ++#if defined(X86_DARWIN) ++ ++static inline bool ++struct_on_stack( ++ int size) ++{ ++ if (size > 8) ++ return true; ++ ++ /* This is not what the ABI says, but is what is really implemented */ ++ switch (size) ++ { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ return false; ++ ++ default: ++ return true; ++ } ++} ++ ++#endif // defined(X86_DARWIN) ++ ++// Arguments' ffi_type->alignment must be nonzero. ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes) ++{ ++ if (cif == NULL) ++ return FFI_BAD_TYPEDEF; ++ ++ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI) ++ return FFI_BAD_ABI; ++ ++ unsigned int bytes = 0; ++ unsigned int i; ++ ffi_type** ptr; ++ ++ cif->abi = abi; ++ cif->arg_types = atypes; ++ cif->nargs = nargs; ++ cif->rtype = rtype; ++ cif->flags = 0; ++ ++ /* Initialize the return type if necessary */ ++ /*@-usedef@*/ ++ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ /*@=usedef@*/ ++ ++ /* Perform a sanity check on the return type */ ++ FFI_ASSERT_VALID_TYPE(cif->rtype); ++ ++ /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ ++#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA ++ /* Make space for the return structure pointer */ ++ if (cif->rtype->type == FFI_TYPE_STRUCT ++#ifdef SPARC ++ && (cif->abi != FFI_V9 || cif->rtype->size > 32) ++#endif ++#ifdef X86_DARWIN ++ && (struct_on_stack(cif->rtype->size)) ++#endif ++ ) ++ bytes = STACK_ARG_SIZE(sizeof(void*)); ++#endif ++ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ /* Initialize any uninitialized aggregate type definitions */ ++ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ if ((*ptr)->alignment == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type, do this ++ check after the initialization. */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#if defined(X86_DARWIN) ++ { ++ int align = (*ptr)->alignment; ++ ++ if (align > 4) ++ align = 4; ++ ++ if ((align - 1) & bytes) ++ bytes = ALIGN(bytes, align); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#elif !defined __x86_64__ && !defined S390 && !defined PA ++#ifdef SPARC ++ if (((*ptr)->type == FFI_TYPE_STRUCT ++ && ((*ptr)->size > 16 || cif->abi != FFI_V9)) ++ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE ++ && cif->abi != FFI_V9)) ++ bytes += sizeof(void*); ++ else ++#endif ++ { ++ /* Add any padding if necessary */ ++ if (((*ptr)->alignment - 1) & bytes) ++ bytes = ALIGN(bytes, (*ptr)->alignment); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#endif ++ } ++ ++ cif->bytes = bytes; ++ ++ /* Perform machine dependent cif processing */ ++ return ffi_prep_cif_machdep(cif); ++} ++#endif /* not __CRIS__ */ +diff --git ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h +new file mode 100644 +index 0000000..c104a5c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi.h +@@ -0,0 +1,355 @@ ++/* -----------------------------------------------------------------*-C-*- ++ libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++/* ------------------------------------------------------------------- ++ The basic API is described in the README file. ++ ++ The raw API is designed to bypass some of the argument packing ++ and unpacking on architectures for which it can be avoided. ++ ++ The closure API allows interpreted functions to be packaged up ++ inside a C function pointer, so that they can be called as C functions, ++ with no understanding on the client side that they are interpreted. ++ It can also be used in other cases in which it is necessary to package ++ up a user specified parameter and a function pointer as a single ++ function pointer. ++ ++ The closure API must be implemented in order to get its functionality, ++ e.g. for use by gij. Routines are provided to emulate the raw API ++ if the underlying platform doesn't allow faster implementation. ++ ++ More details on the raw and closure API can be found in: ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html ++ ++ and ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html ++ -------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_H ++#define LIBFFI_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Specify which architecture libffi is configured for. */ ++#ifdef MACOSX ++# if defined(__i386__) || defined(__x86_64__) ++# define X86_DARWIN ++# elif defined(__ppc__) || defined(__ppc64__) ++# define POWERPC_DARWIN ++# else ++# error "Unsupported MacOS X CPU type" ++# endif ++#else ++#error "Unsupported OS type" ++#endif ++ ++/* ---- System configuration information --------------------------------- */ ++ ++#include "ffitarget.h" ++#include "fficonfig.h" ++ ++#ifndef LIBFFI_ASM ++ ++#include ++#include ++ ++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). ++ But we can find it either under the correct ANSI name, or under GNU ++ C's internal name. */ ++#ifdef LONG_LONG_MAX ++# define FFI_LONG_LONG_MAX LONG_LONG_MAX ++#else ++# ifdef LLONG_MAX ++# define FFI_LONG_LONG_MAX LLONG_MAX ++# else ++# ifdef __GNUC__ ++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ ++# endif ++# endif ++#endif ++ ++#if SCHAR_MAX == 127 ++# define ffi_type_uchar ffi_type_uint8 ++# define ffi_type_schar ffi_type_sint8 ++#else ++#error "char size not supported" ++#endif ++ ++#if SHRT_MAX == 32767 ++# define ffi_type_ushort ffi_type_uint16 ++# define ffi_type_sshort ffi_type_sint16 ++#elif SHRT_MAX == 2147483647 ++# define ffi_type_ushort ffi_type_uint32 ++# define ffi_type_sshort ffi_type_sint32 ++#else ++#error "short size not supported" ++#endif ++ ++#if INT_MAX == 32767 ++# define ffi_type_uint ffi_type_uint16 ++# define ffi_type_sint ffi_type_sint16 ++#elif INT_MAX == 2147483647 ++# define ffi_type_uint ffi_type_uint32 ++# define ffi_type_sint ffi_type_sint32 ++#elif INT_MAX == 9223372036854775807 ++# define ffi_type_uint ffi_type_uint64 ++# define ffi_type_sint ffi_type_sint64 ++#else ++#error "int size not supported" ++#endif ++ ++#define ffi_type_ulong ffi_type_uint64 ++#define ffi_type_slong ffi_type_sint64 ++ ++#if LONG_MAX == 2147483647 ++# if FFI_LONG_LONG_MAX != 9223372036854775807 ++# error "no 64-bit data type supported" ++# endif ++#elif LONG_MAX != 9223372036854775807 ++#error "long size not supported" ++#endif ++ ++/* The closure code assumes that this works on pointers, i.e. a size_t ++ can hold a pointer. */ ++ ++typedef struct _ffi_type { ++ size_t size; ++ unsigned short alignment; ++ unsigned short type; ++/*@null@*/ struct _ffi_type** elements; ++} ffi_type; ++ ++/* These are defined in types.c */ ++extern ffi_type ffi_type_void; ++extern ffi_type ffi_type_uint8; ++extern ffi_type ffi_type_sint8; ++extern ffi_type ffi_type_uint16; ++extern ffi_type ffi_type_sint16; ++extern ffi_type ffi_type_uint32; ++extern ffi_type ffi_type_sint32; ++extern ffi_type ffi_type_uint64; ++extern ffi_type ffi_type_sint64; ++extern ffi_type ffi_type_float; ++extern ffi_type ffi_type_double; ++extern ffi_type ffi_type_longdouble; ++extern ffi_type ffi_type_pointer; ++ ++typedef enum ffi_status { ++ FFI_OK = 0, ++ FFI_BAD_TYPEDEF, ++ FFI_BAD_ABI ++} ffi_status; ++ ++typedef unsigned FFI_TYPE; ++ ++typedef struct ffi_cif { ++ ffi_abi abi; ++ unsigned nargs; ++/*@dependent@*/ ffi_type** arg_types; ++/*@dependent@*/ ffi_type* rtype; ++ unsigned bytes; ++ unsigned flags; ++#ifdef FFI_EXTRA_CIF_FIELDS ++ FFI_EXTRA_CIF_FIELDS; ++#endif ++} ffi_cif; ++ ++/* ---- Definitions for the raw API -------------------------------------- */ ++ ++#ifndef FFI_SIZEOF_ARG ++# if LONG_MAX == 2147483647 ++# define FFI_SIZEOF_ARG 4 ++# elif LONG_MAX == 9223372036854775807 ++# define FFI_SIZEOF_ARG 8 ++# endif ++#endif ++ ++typedef union { ++ ffi_sarg sint; ++ ffi_arg uint; ++ float flt; ++ char data[FFI_SIZEOF_ARG]; ++ void* ptr; ++} ffi_raw; ++ ++void ++ffi_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_raw_size( ++ ffi_cif* cif); ++ ++/* This is analogous to the raw API, except it uses Java parameter ++ packing, even on 64-bit machines. I.e. on 64-bit machines ++ longs and doubles are followed by an empty 64-bit word. */ ++void ++ffi_java_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_java_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_java_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_java_raw_size( ++ ffi_cif* cif); ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#if FFI_CLOSURES ++ ++typedef struct ffi_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ void (*fun)(ffi_cif*,void*,void**,void*); ++ void* user_data; ++} ffi_closure; ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void* user_data); ++ ++void ffi_closure_free(void *); ++void *ffi_closure_alloc (size_t size, void **code); ++ ++typedef struct ffi_raw_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ ++#if !FFI_NATIVE_RAW_API ++ /* if this is enabled, then a raw closure has the same layout ++ as a regular closure. We use this to install an intermediate ++ handler to do the transaltion, void** -> ffi_raw*. */ ++ void (*translate_args)(ffi_cif*,void*,void**,void*); ++ void* this_closure; ++#endif ++ ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*); ++ void* user_data; ++} ffi_raw_closure; ++ ++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_status ++ffi_prep_java_raw_closure( ++ ffi_raw_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*), ++ void* user_data); ++ ++#endif // FFI_CLOSURES ++ ++/* ---- Public interface definition -------------------------------------- */ ++ ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes); ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ void** avalue); ++ ++/* Useful for eliminating compiler warnings */ ++#define FFI_FN(f) ((void (*)(void))f) ++ ++#endif // #ifndef LIBFFI_ASM ++/* ---- Definitions shared with assembly code ---------------------------- */ ++ ++/* If these change, update src/mips/ffitarget.h. */ ++#define FFI_TYPE_VOID 0 ++#define FFI_TYPE_INT 1 ++#define FFI_TYPE_FLOAT 2 ++#define FFI_TYPE_DOUBLE 3 ++ ++#ifdef HAVE_LONG_DOUBLE ++# define FFI_TYPE_LONGDOUBLE 4 ++#else ++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE ++#endif ++ ++#define FFI_TYPE_UINT8 5 ++#define FFI_TYPE_SINT8 6 ++#define FFI_TYPE_UINT16 7 ++#define FFI_TYPE_SINT16 8 ++#define FFI_TYPE_UINT32 9 ++#define FFI_TYPE_SINT32 10 ++#define FFI_TYPE_UINT64 11 ++#define FFI_TYPE_SINT64 12 ++#define FFI_TYPE_STRUCT 13 ++#define FFI_TYPE_POINTER 14 ++ ++/* This should always refer to the last type code (for sanity checks) */ ++#define FFI_TYPE_LAST FFI_TYPE_POINTER ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef LIBFFI_H +diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h +new file mode 100644 +index 0000000..685a358 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi_common.h +@@ -0,0 +1,102 @@ ++/* ----------------------------------------------------------------------- ++ ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ++ ++ Common internal definitions and macros. Only necessary for building ++ libffi. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef FFI_COMMON_H ++#define FFI_COMMON_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fficonfig.h" ++ ++/* Do not move this. Some versions of AIX are very picky about where ++ this is positioned. */ ++#ifdef __GNUC__ ++# define alloca __builtin_alloca ++#else ++# if HAVE_ALLOCA_H ++# include ++# else ++# ifdef _AIX ++# pragma alloca ++# else ++# ifndef alloca /* predefined by HP cc +Olibcalls */ ++char* alloca(); ++# endif ++# endif ++# endif ++#endif ++ ++/* Check for the existence of memcpy. */ ++#if STDC_HEADERS ++# include ++#else ++# ifndef HAVE_MEMCPY ++# define memcpy(d, s, n) bcopy((s), (d), (n)) ++# endif ++#endif ++ ++/*#if defined(FFI_DEBUG) ++#include ++#endif*/ ++ ++#ifdef FFI_DEBUG ++#include ++ ++/*@exits@*/ void ++ffi_assert( ++/*@temp@*/ char* expr, ++/*@temp@*/ char* file, ++ int line); ++void ++ffi_stop_here(void); ++void ++ffi_type_test( ++/*@temp@*/ /*@out@*/ ffi_type* a, ++/*@temp@*/ char* file, ++ int line); ++ ++# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) ++# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) ++# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__) ++#else ++# define FFI_ASSERT(x) ++# define FFI_ASSERT_AT(x, f, l) ++# define FFI_ASSERT_VALID_TYPE(x) ++#endif // #ifdef FFI_DEBUG ++ ++#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) ++ ++/* Perform machine dependent cif processing */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif); ++ ++/* Extended cif, used in callback from assembly routine */ ++typedef struct extended_cif { ++/*@dependent@*/ ffi_cif* cif; ++/*@dependent@*/ void* rvalue; ++/*@dependent@*/ void** avalue; ++} extended_cif; ++ ++/* Terse sized type definitions. */ ++typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); ++typedef signed int SINT8 __attribute__((__mode__(__QI__))); ++typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); ++typedef signed int SINT16 __attribute__((__mode__(__HI__))); ++typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); ++typedef signed int SINT32 __attribute__((__mode__(__SI__))); ++typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); ++typedef signed int SINT64 __attribute__((__mode__(__DI__))); ++typedef float FLOAT32; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef FFI_COMMON_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h +new file mode 100644 +index 0000000..2172490 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/fficonfig.h +@@ -0,0 +1,150 @@ ++/* Manually created fficonfig.h for Darwin on PowerPC or Intel ++ ++ This file is manually generated to do away with the need for autoconf and ++ therefore make it easier to cross-compile and build fat binaries. ++ ++ NOTE: This file was added by PyObjC. ++*/ ++ ++#ifndef MACOSX ++#error "This file is only supported on Mac OS X" ++#endif ++ ++#if defined(__i386__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__x86_64__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__ppc__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# if __GNUC__ >= 4 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++# else ++# undef HAVE_LONG_DOUBLE ++# define SIZEOF_LONG_DOUBLE 8 ++# endif ++ ++#elif defined(__ppc64__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#else ++#error "Unknown CPU type" ++#endif ++ ++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP ++ systems. This function is required for `alloca.c' support on those systems. */ ++#undef CRAY_STACKSEG_END ++ ++/* Define to 1 if using `alloca.c'. */ ++/* #undef C_ALLOCA */ ++ ++/* Define to the flags needed for the .section .eh_frame directive. */ ++#define EH_FRAME_FLAGS "aw" ++ ++/* Define this if you want extra debugging. */ ++/* #undef FFI_DEBUG */ ++ ++/* Define this is you do not want support for the raw API. */ ++#define FFI_NO_RAW_API 1 ++ ++/* Define this if you do not want support for aggregate types. */ ++/* #undef FFI_NO_STRUCTS */ ++ ++/* Define to 1 if you have `alloca', as a function or macro. */ ++#define HAVE_ALLOCA 1 ++ ++/* Define to 1 if you have and it should be used (not on Ultrix). */ ++#define HAVE_ALLOCA_H 1 ++ ++/* Define if your assembler supports .register. */ ++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ ++ ++/* Define if your assembler and linker support unaligned PC relative relocs. */ ++/* #undef HAVE_AS_SPARC_UA_PCREL */ ++ ++/* Define to 1 if you have the `memcpy' function. */ ++#define HAVE_MEMCPY 1 ++ ++/* Define if mmap with MAP_ANON(YMOUS) works. */ ++#define HAVE_MMAP_ANON 1 ++ ++/* Define if mmap of /dev/zero works. */ ++/* #undef HAVE_MMAP_DEV_ZERO */ ++ ++/* Define if read-only mmap of a plain file works. */ ++#define HAVE_MMAP_FILE 1 ++ ++/* Define if .eh_frame sections should be read-only. */ ++/* #undef HAVE_RO_EH_FRAME */ ++ ++/* Define to 1 if your C compiler doesn't accept -c and -o together. */ ++/* #undef NO_MINUS_C_MINUS_O */ ++ ++/* Name of package */ ++#define PACKAGE "libffi" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "libffi" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "libffi 2.1" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libffi" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "2.1" ++ ++/* If using the C implementation of alloca, define if you know the ++ direction of stack growth for your system; otherwise it will be ++ automatically deduced at run-time. ++ STACK_DIRECTION > 0 => grows toward higher addresses ++ STACK_DIRECTION < 0 => grows toward lower addresses ++ STACK_DIRECTION = 0 => direction of growth unknown */ ++/* #undef STACK_DIRECTION */ ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this if you are using Purify and want to suppress spurious messages. */ ++/* #undef USING_PURIFY */ ++ ++/* Version number of package */ ++#define VERSION "2.1-pyobjc" ++ ++#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) .hidden name ++# else ++# define FFI_HIDDEN __attribute__((visibility ("hidden"))) ++# endif ++#else ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) ++# else ++# define FFI_HIDDEN ++# endif ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h +new file mode 100644 +index 0000000..faaa30d +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffitarget.h +@@ -0,0 +1,13 @@ ++/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a ++ normal build, the build environment copies the file to the right location or ++ sets up the right include flags. We want to do neither because that would ++ make building fat binaries harder. ++*/ ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "x86-ffitarget.h" ++#elif defined(__ppc__) || defined(__ppc64__) ++#include "ppc-ffitarget.h" ++#else ++#error "Unsupported CPU type" ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +new file mode 100644 +index 0000000..2318421 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +@@ -0,0 +1,104 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for PowerPC. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if (defined(POWERPC) && defined(__powerpc64__)) || \ ++ (defined(POWERPC_DARWIN) && defined(__ppc64__)) ++#define POWERPC64 ++#endif ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++#ifdef POWERPC ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++# ifdef POWERPC64 ++ FFI_DEFAULT_ABI = FFI_LINUX64, ++# else ++ FFI_DEFAULT_ABI = FFI_GCC_SYSV, ++# endif ++#endif ++ ++#ifdef POWERPC_AIX ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_AIX, ++#endif ++ ++#ifdef POWERPC_DARWIN ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_DARWIN, ++#endif ++ ++#ifdef POWERPC_FREEBSD ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++#define FFI_NATIVE_RAW_API 0 ++ ++/* Needed for FFI_SYSV small structure returns. */ ++#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) ++ ++#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/ ++# define FFI_TRAMPOLINE_SIZE 48 ++#elif defined(POWERPC_AIX) ++# define FFI_TRAMPOLINE_SIZE 24 ++#else ++# define FFI_TRAMPOLINE_SIZE 40 ++#endif ++ ++#ifndef LIBFFI_ASM ++# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) ++typedef struct ffi_aix_trampoline_struct { ++ void* code_pointer; /* Pointer to ffi_closure_ASM */ ++ void* toc; /* TOC */ ++ void* static_chain; /* Pointer to closure */ ++} ffi_aix_trampoline_struct; ++# endif ++#endif // #ifndef LIBFFI_ASM ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +new file mode 100644 +index 0000000..55c2b6c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +@@ -0,0 +1,88 @@ ++/* -----------------------------------------------------------------*-C-*- ++ x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for x86 and x86-64. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if defined(X86_64) && defined(__i386__) ++# undef X86_64 ++# define X86 ++#endif ++ ++#if defined(__x86_64__) ++# ifndef X86_64 ++# define X86_64 ++# endif ++#endif ++ ++/* ---- Generic type definitions ----------------------------------------- */ ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++ /* ---- Intel x86 Win32 ---------- */ ++#ifdef X86_WIN32 ++ FFI_SYSV, ++ FFI_STDCALL, ++ /* TODO: Add fastcall support for the sake of completeness */ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ /* ---- Intel x86 and AMD x86-64 - */ ++#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) ++ FFI_SYSV, ++ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ ++# ifdef __i386__ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++# else ++ FFI_DEFAULT_ABI = FFI_UNIX64, ++# endif ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++ ++#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN)) ++# define FFI_TRAMPOLINE_SIZE 24 ++# define FFI_NATIVE_RAW_API 0 ++#else ++# define FFI_TRAMPOLINE_SIZE 10 ++# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ ++#endif ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +new file mode 100644 +index 0000000..f143dbd +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +@@ -0,0 +1,365 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist ++ Copyright (c) 2004 Free Software Foundation, Inc. ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include ++#include ++#include ++ ++.text ++ .align 2 ++.globl _ffi_prep_args ++ ++.text ++ .align 2 ++.globl _ffi_call_DARWIN ++ ++.text ++ .align 2 ++_ffi_call_DARWIN: ++LFB0: ++ mr r12,r8 /* We only need r12 until the call, ++ so it doesn't have to be saved. */ ++ ++LFB1: ++ /* Save the old stack pointer as AP. */ ++ mr r8,r1 ++ ++LCFI0: ++#if defined(__ppc64__) ++ /* Allocate the stack space we need. ++ r4 (size of input data) ++ 48 bytes (linkage area) ++ 40 bytes (saved registers) ++ 8 bytes (extra FPR) ++ r4 + 96 bytes total ++ */ ++ ++ addi r4,r4,-96 // Add our overhead. ++ li r0,-32 // Align to 32 bytes. ++ and r4,r4,r0 ++#endif ++ stgux r1,r1,r4 // Grow the stack. ++ mflr r9 ++ ++ /* Save registers we use. */ ++#if defined(__ppc64__) ++ std r27,-40(r8) ++#endif ++ stg r28,MODE_CHOICE(-16,-32)(r8) ++ stg r29,MODE_CHOICE(-12,-24)(r8) ++ stg r30,MODE_CHOICE(-8,-16)(r8) ++ stg r31,MODE_CHOICE(-4,-8)(r8) ++ stg r9,SF_RETURN(r8) /* return address */ ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ stg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++LCFI1: ++#if defined(__ppc64__) ++ mr r27,r3 // our extended_cif ++#endif ++ /* Save arguments over call. */ ++ mr r31,r5 /* flags, */ ++ mr r30,r6 /* rvalue, */ ++ mr r29,r7 /* function address, */ ++ mr r28,r8 /* our AP. */ ++ ++LCFI2: ++ /* Call ffi_prep_args. */ ++ mr r4,r1 ++ li r9,0 ++ mtctr r12 /* r12 holds address of _ffi_prep_args. */ ++ bctrl ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ lg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++ /* Now do the call. ++ Set up cr1 with bits 4-7 of the flags. */ ++ mtcrf 0x40,r31 ++ ++ /* Load all those argument registers. ++ We have set up a nice stack frame, just load it into registers. */ ++ lg r3,SF_ARG1(r1) ++ lg r4,SF_ARG2(r1) ++ lg r5,SF_ARG3(r1) ++ lg r6,SF_ARG4(r1) ++ nop ++ lg r7,SF_ARG5(r1) ++ lg r8,SF_ARG6(r1) ++ lg r9,SF_ARG7(r1) ++ lg r10,SF_ARG8(r1) ++ ++ /* Load all the FP registers. */ ++ bf 6,L2 /* No floats to load. */ ++#if defined(__ppc64__) ++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#elif defined(__ppc__) ++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#else ++#error undefined architecture ++#endif ++ ++L2: ++ mr r12,r29 // Put the target address in r12 as specified. ++ mtctr r12 // Get the address to call into CTR. ++ nop ++ nop ++ bctrl // Make the call. ++ ++ // Deal with the return value. ++#if defined(__ppc64__) ++ mtcrf 0x3,r31 // flags in cr6 and cr7 ++ bt 27,L(st_return_value) ++#elif defined(__ppc__) ++ mtcrf 0x1,r31 // flags in cr7 ++#else ++#error undefined architecture ++#endif ++ ++ bt 30,L(done_return_value) ++ bt 29,L(fp_return_value) ++ stg r3,0(r30) ++#if defined(__ppc__) ++ bf 28,L(done_return_value) // Store the second long if necessary. ++ stg r4,4(r30) ++#endif ++ // Fall through ++ ++L(done_return_value): ++ lg r1,0(r1) // Restore stack pointer. ++ // Restore the registers we used. ++ lg r9,SF_RETURN(r1) // return address ++ lg r31,MODE_CHOICE(-4,-8)(r1) ++ mtlr r9 ++ lg r30,MODE_CHOICE(-8,-16)(r1) ++ lg r29,MODE_CHOICE(-12,-24)(r1) ++ lg r28,MODE_CHOICE(-16,-32)(r1) ++#if defined(__ppc64__) ++ ld r27,-40(r1) ++#endif ++ blr ++ ++#if defined(__ppc64__) ++L(st_return_value): ++ // Grow the stack enough to fit the registers. Leave room for 8 args ++ // to trample the 1st 8 slots in param area. ++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 ++ ++ // Store GPRs ++ std r3,SF_ARG9(r1) ++ std r4,SF_ARG10(r1) ++ std r5,SF_ARG11(r1) ++ std r6,SF_ARG12(r1) ++ nop ++ std r7,SF_ARG13(r1) ++ std r8,SF_ARG14(r1) ++ std r9,SF_ARG15(r1) ++ std r10,SF_ARG16(r1) ++ ++ // Store FPRs ++ nop ++ bf 26,L(call_struct_to_ram_form) ++ stfd f1,SF_ARG17(r1) ++ stfd f2,SF_ARG18(r1) ++ stfd f3,SF_ARG19(r1) ++ stfd f4,SF_ARG20(r1) ++ nop ++ stfd f5,SF_ARG21(r1) ++ stfd f6,SF_ARG22(r1) ++ stfd f7,SF_ARG23(r1) ++ stfd f8,SF_ARG24(r1) ++ nop ++ stfd f9,SF_ARG25(r1) ++ stfd f10,SF_ARG26(r1) ++ stfd f11,SF_ARG27(r1) ++ stfd f12,SF_ARG28(r1) ++ nop ++ stfd f13,SF_ARG29(r1) ++ ++L(call_struct_to_ram_form): ++ ld r3,0(r27) // extended_cif->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ addi r4,r1,SF_ARG9 // stored GPRs ++ addi r6,r1,SF_ARG17 // stored FPRs ++ li r5,0 // GPR size ptr (NULL) ++ li r7,0 // FPR size ptr (NULL) ++ li r8,0 // FPR count ptr (NULL) ++ li r10,0 // struct offset (NULL) ++ mr r9,r30 // return area ++ bl Lffi64_struct_to_ram_form$stub ++ lg r1,0(r1) // Restore stack pointer. ++ b L(done_return_value) ++#endif ++ ++L(fp_return_value): ++ /* Do we have long double to store? */ ++ bf 31,L(fd_return_value) ++ stfd f1,0(r30) ++ stfd f2,8(r30) ++ b L(done_return_value) ++ ++L(fd_return_value): ++ /* Do we have double to store? */ ++ bf 28,L(float_return_value) ++ stfd f1,0(r30) ++ b L(done_return_value) ++ ++L(float_return_value): ++ /* We only have a float to store. */ ++ stfs f1,0(r30) ++ b L(done_return_value) ++ ++LFE1: ++/* END(_ffi_call_DARWIN) */ ++ ++/* Provide a null definition of _ffi_call_AIX. */ ++.text ++ .align 2 ++.globl _ffi_call_AIX ++.text ++ .align 2 ++_ffi_call_AIX: ++ blr ++/* END(_ffi_call_AIX) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_call_DARWIN.eh ++_ffi_call_DARWIN.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x08 ; uleb128 0x08 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$5,LCFI1-LCFI0 ++ .long L$set$5 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .byte 0x9f ; DW_CFA_offset, column 0x1f ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x9e ; DW_CFA_offset, column 0x1e ++ .byte 0x2 ; uleb128 0x2 ++ .byte 0x9d ; DW_CFA_offset, column 0x1d ++ .byte 0x3 ; uleb128 0x3 ++ .byte 0x9c ; DW_CFA_offset, column 0x1c ++ .byte 0x4 ; uleb128 0x4 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$6,LCFI2-LCFI1 ++ .long L$set$6 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x1c ; uleb128 0x1c ++ .align LOG2_GPR_BYTES ++LEFDE1: ++ ++#if defined(__ppc64__) ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_ram_form$stub: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_ram_form ++ ++LO$ffi64_struct_to_ram_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_ram_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ ++#endif // __ppc__ || __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +new file mode 100644 +index 0000000..cf4bd50 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +@@ -0,0 +1,85 @@ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define L(x) x ++ ++#define SF_ARG9 MODE_CHOICE(56,112) ++#define SF_ARG10 MODE_CHOICE(60,120) ++#define SF_ARG11 MODE_CHOICE(64,128) ++#define SF_ARG12 MODE_CHOICE(68,136) ++#define SF_ARG13 MODE_CHOICE(72,144) ++#define SF_ARG14 MODE_CHOICE(76,152) ++#define SF_ARG15 MODE_CHOICE(80,160) ++#define SF_ARG16 MODE_CHOICE(84,168) ++#define SF_ARG17 MODE_CHOICE(88,176) ++#define SF_ARG18 MODE_CHOICE(92,184) ++#define SF_ARG19 MODE_CHOICE(96,192) ++#define SF_ARG20 MODE_CHOICE(100,200) ++#define SF_ARG21 MODE_CHOICE(104,208) ++#define SF_ARG22 MODE_CHOICE(108,216) ++#define SF_ARG23 MODE_CHOICE(112,224) ++#define SF_ARG24 MODE_CHOICE(116,232) ++#define SF_ARG25 MODE_CHOICE(120,240) ++#define SF_ARG26 MODE_CHOICE(124,248) ++#define SF_ARG27 MODE_CHOICE(128,256) ++#define SF_ARG28 MODE_CHOICE(132,264) ++#define SF_ARG29 MODE_CHOICE(136,272) ++ ++#define ASM_NEEDS_REGISTERS 4 ++#define NUM_GPR_ARG_REGISTERS 8 ++#define NUM_FPR_ARG_REGISTERS 13 ++ ++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8) ++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16) ++#define FFI_TYPE_4_BYTE(x) \ ++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\ ++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT) ++ ++#if !defined(LIBFFI_ASM) ++ ++enum { ++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7 ++ FLAG_RETURNS_FP = 1 << (31 - 29), ++ FLAG_RETURNS_64BITS = 1 << (31 - 28), ++ FLAG_RETURNS_128BITS = 1 << (31 - 31), ++ ++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6 ++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26), ++ ++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7), ++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI ++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5), ++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4) ++}; ++ ++#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*); ++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*); ++#endif ++ ++#endif // !defined(LIBFFI_ASM) +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +new file mode 100644 +index 0000000..c3d30c2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +@@ -0,0 +1,308 @@ ++#if defined(__ppc__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 // Save return address ++ stg r0,SF_RETURN(r1) ++ ++LCFI0: ++ /* 24/48 bytes (Linkage Area) ++ 32/64 bytes (outgoing parameter area, always reserved) ++ 104 bytes (13*8 from FPR) ++ 16/32 bytes (result) ++ 176/232 total bytes */ ++ ++ /* skip over caller save area and keep stack aligned to 16/32. */ ++ stgu r1,-SF_ROUND(176)(r1) ++ ++LCFI1: ++ /* We want to build up an area for the parameters passed ++ in registers. (both floating point and integer) */ ++ ++ /* 176/256 bytes (callee stack frame aligned to 16/32) ++ 24/48 bytes (caller linkage area) ++ 200/304 (start of caller parameter area aligned to 4/8) ++ */ ++ ++ /* Save GPRs 3 - 10 (aligned to 4/8) ++ in the parents outgoing area. */ ++ 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,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. ++ 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. Use it to look up in a table ++ so we know how to deal with each type. */ ++ 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 ++ ++LFE1: ++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ (4 instructions). For cache effectiveness we align to a 16 byte boundary ++ first. */ ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++/* case FFI_TYPE_VOID */ ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* case FFI_TYPE_INT */ ++Lret_type1: ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_FLOAT */ ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_DOUBLE */ ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_LONGDOUBLE */ ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT8 */ ++Lret_type5: ++ lbz r3,3(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT8 */ ++Lret_type6: ++ lbz r3,3(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT16 */ ++Lret_type7: ++ lhz r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT16 */ ++Lret_type8: ++ lha r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT32 */ ++Lret_type9: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT32 */ ++Lret_type10: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT64 */ ++Lret_type11: ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_SINT64 */ ++Lret_type12: // same as Lret_type11 ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_STRUCT */ ++Lret_type13: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* End 16-byte aligned cases */ ++/* case FFI_TYPE_POINTER */ ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ // fall through ++ ++/* case done */ ++Lfinish: ++ 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) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++ ++#endif // __ppc__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +new file mode 100644 +index 0000000..8953d5f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +@@ -0,0 +1,1776 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1998 Geoffrey Keating ++ ++ PowerPC Foreign Function Interface ++ ++ Darwin ABI support (c) 2001 John Hornkvist ++ AIX ABI support (c) 2002 Free Software Foundation, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#if defined(POWERPC_DARWIN) ++#include // for sys_icache_invalidate() ++#endif ++ ++#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 ++// points to one of these. ++typedef struct aix_fd_struct { ++ void* code_pointer; ++ void* toc; ++} aix_fd; ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments. ++ ++ The stack layout we want looks like this: ++ ++ | Return address from ffi_call_DARWIN | higher addresses ++ |--------------------------------------------| ++ | Previous backchain pointer 4/8 | stack pointer here ++ |--------------------------------------------|-\ <<< on entry to ++ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN ++ |--------------------------------------------| | ++ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 ++ |--------------------------------------------| | ++ | Space for GPR2 4/8 | | ++ |--------------------------------------------| | stack | ++ | Reserved (4/8)*2 | | grows | ++ |--------------------------------------------| | down V ++ | Space for callee's LR 4/8 | | ++ |--------------------------------------------| | lower addresses ++ | Saved CR 4/8 | | ++ |--------------------------------------------| | stack pointer here ++ | Current backchain pointer 4/8 | | during ++ |--------------------------------------------|-/ <<< ffi_call_DARWIN ++ ++ Note: ppc64 CR is saved in the low word of a long on the stack. ++*/ ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args( ++ extended_cif* inEcif, ++ unsigned *const stack) ++/*@=exportheader@*/ ++{ ++ /* Copy the ecif to a local var so we can trample the arg. ++ BC note: test this with GP later for possible problems... */ ++ volatile extended_cif* ecif = inEcif; ++ ++ const unsigned bytes = ecif->cif->bytes; ++ const unsigned flags = ecif->cif->flags; ++ ++ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode ++ and 8 in 64-bit mode. */ ++ unsigned long *const longStack = (unsigned long *const)stack; ++ ++ /* 'stacktop' points at the previous backchain pointer. */ ++#if defined(__ppc64__) ++ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, ++ // saved registers, and an extra FPR. ++ unsigned long *const stacktop = ++ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); ++#elif defined(__ppc__) ++ unsigned long *const stacktop = longStack + (bytes / sizeof(long)); ++#else ++#error undefined architecture ++#endif ++ ++ /* 'fpr_base' points at the space for fpr1, and grows upwards as ++ we use FPR registers. */ ++ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - ++ NUM_FPR_ARG_REGISTERS; ++ ++#if defined(__ppc64__) ++ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base ++ // down a couple pegs. ++ fpr_base -= 2; ++#endif ++ ++ unsigned int fparg_count = 0; ++ ++ /* 'next_arg' grows up as we put parameters in it. */ ++ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ ++ ++ int i; ++ double double_tmp; ++ void** p_argv = ecif->avalue; ++ unsigned long gprvalue; ++ ffi_type** ptr = ecif->cif->arg_types; ++ ++ /* Check that everything starts aligned properly. */ ++ FFI_ASSERT(stack == SF_ROUND(stack)); ++ FFI_ASSERT(stacktop == SF_ROUND(stacktop)); ++ FFI_ASSERT(bytes == SF_ROUND(bytes)); ++ ++ /* Deal with return values that are actually pass-by-reference. ++ Rule: ++ Return values are referenced by r3, so r4 is the first parameter. */ ++ ++ if (flags & FLAG_RETVAL_REFERENCE) ++ *next_arg++ = (unsigned long)(char*)ecif->rvalue; ++ ++ /* Now for the arguments. */ ++ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) ++ { ++ switch ((*ptr)->type) ++ { ++ /* If a floating-point parameter appears before all of the general- ++ purpose registers are filled, the corresponding GPRs that match ++ the size of the floating-point parameter are shadowed for the ++ benefit of vararg and pre-ANSI functions. */ ++ case FFI_TYPE_FLOAT: ++ double_tmp = *(float*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg++; ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ double_tmp = *(double*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg += MODE_CHOICE(2,1); ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++#elif defined(__ppc__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) ++ *(double*)fpr_base = *(double*)*p_argv; ++#else ++#error undefined architecture ++#endif ++ ++ *(long double*)next_arg = *(long double*)*p_argv; ++ fparg_count += 2; ++ fpr_base += 2; ++ next_arg += MODE_CHOICE(4,2); ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++#if defined(__ppc64__) ++ gprvalue = *(long long*)*p_argv; ++ goto putgpr; ++#elif defined(__ppc__) ++ *(long long*)next_arg = *(long long*)*p_argv; ++ next_arg += 2; ++ break; ++#else ++#error undefined architecture ++#endif ++ ++ case FFI_TYPE_POINTER: ++ gprvalue = *(unsigned long*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT8: ++ gprvalue = *(unsigned char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT8: ++ gprvalue = *(signed char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT16: ++ gprvalue = *(unsigned short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT16: ++ gprvalue = *(signed short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ ++ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, ++ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); ++ next_arg += gprSize / sizeof(long); ++ fpr_base += fprSize / sizeof(double); ++ ++#elif defined(__ppc__) ++ char* dest_cpy = (char*)next_arg; ++ ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. ++ Structures with 3 byte in size are padded upwards. */ ++ unsigned size_al = (*ptr)->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++ if (ecif->cif->abi == FFI_DARWIN) ++ { ++ if (size_al < 3) ++ dest_cpy += 4 - size_al; ++ } ++ ++ memcpy((char*)dest_cpy, (char*)*p_argv, size_al); ++ next_arg += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ gprvalue = *(unsigned*)*p_argv; ++ ++putgpr: ++ *next_arg++ = gprvalue; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Check that we didn't overrun the stack... */ ++ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); ++ //FFI_ASSERT((unsigned *)fpr_base ++ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); ++ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); ++} ++ ++#if defined(__ppc64__) ++ ++bool ++ffi64_struct_contains_fp( ++ const ffi_type* inType) ++{ ++ bool containsFP = false; ++ unsigned int i; ++ ++ for (i = 0; inType->elements[i] != NULL && !containsFP; i++) ++ { ++ if (inType->elements[i]->type == FFI_TYPE_FLOAT || ++ inType->elements[i]->type == FFI_TYPE_DOUBLE || ++ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) ++ containsFP = true; ++ else if (inType->elements[i]->type == FFI_TYPE_STRUCT) ++ containsFP = ffi64_struct_contains_fp(inType->elements[i]); ++ } ++ ++ return containsFP; ++} ++ ++#endif // defined(__ppc64__) ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ /* All this is for the DARWIN ABI. */ ++ int i; ++ ffi_type** ptr; ++ int intarg_count = 0; ++ int fparg_count = 0; ++ unsigned int flags = 0; ++ unsigned int size_al = 0; ++ ++ /* All the machine-independent calculation of cif->bytes will be wrong. ++ Redo the calculation for DARWIN. */ ++ ++ /* Space for the frame pointer, callee's LR, CR, etc, and for ++ the asm's temp regs. */ ++ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); ++ ++ /* Return value handling. The rules are as follows: ++ - 32-bit (or less) integer values are returned in gpr3; ++ - Structures of size <= 4 bytes also returned in gpr3; ++ - 64-bit integer values and structures between 5 and 8 bytes are ++ returned in gpr3 and gpr4; ++ - Single/double FP values are returned in fpr1; ++ - Long double FP (if not equivalent to double) values are returned in ++ fpr1 and fpr2; ++ - Larger structures values are allocated space and a pointer is passed ++ as the first argument. */ ++ switch (cif->rtype->type) ++ { ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ flags |= FLAG_RETURNS_128BITS; ++ flags |= FLAG_RETURNS_FP; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_DOUBLE: ++ flags |= FLAG_RETURNS_64BITS; ++ /* Fall through. */ ++ case FFI_TYPE_FLOAT: ++ flags |= FLAG_RETURNS_FP; ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ flags |= FLAG_RETURNS_64BITS; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ ++ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++ { ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ } ++ else ++ { ++ flags |= FLAG_RETURNS_STRUCT; ++ ++ if (ffi64_struct_contains_fp(cif->rtype)) ++ flags |= FLAG_STRUCT_CONTAINS_FP; ++ } ++ ++#elif defined(__ppc__) ++ ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_VOID: ++ flags |= FLAG_RETURNS_NOTHING; ++ break; ++ ++ default: ++ /* Returns 32-bit integer, or similar. Nothing to do here. */ ++ break; ++ } ++ ++ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the ++ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest ++ goes on the stack. Structures are passed as a pointer to a copy of ++ the structure. Stuff on the stack needs to keep proper alignment. */ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ switch ((*ptr)->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ fparg_count++; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ fparg_count += 2; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ ++ if ( ++#if defined(__ppc64__) ++ fparg_count > NUM_FPR_ARG_REGISTERS + 1 ++#elif defined(__ppc__) ++ fparg_count > NUM_FPR_ARG_REGISTERS ++#else ++#error undefined architecture ++#endif ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ ++ intarg_count += 2; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ /* 'long long' arguments are passed as two words, but ++ either both words must fit in registers or both go ++ on the stack. If they go on the stack, they must ++ be 8-byte-aligned. */ ++ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 ++ || (intarg_count >= NUM_GPR_ARG_REGISTERS ++ && intarg_count % 2 != 0)) ++ intarg_count++; ++ ++ intarg_count += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ size_al = (*ptr)->size; ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++#if defined(__ppc64__) ++ // Look for FP struct members. ++ unsigned int j; ++ ++ for (j = 0; (*ptr)->elements[j] != NULL; j++) ++ { ++ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || ++ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) ++ { ++ fparg_count++; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS) ++ intarg_count++; ++ } ++ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) ++ { ++ fparg_count += 2; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) ++ intarg_count += 2; ++ } ++ else ++ intarg_count++; ++ } ++#elif defined(__ppc__) ++ intarg_count += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ ++ break; ++ ++ default: ++ /* Everything else is passed as a 4/8-byte word in a GPR, either ++ the object itself or a pointer to it. */ ++ intarg_count++; ++ break; ++ } ++ } ++ ++ /* Space for the FPR registers, if needed. */ ++ if (fparg_count != 0) ++ { ++ flags |= FLAG_FP_ARGUMENTS; ++#if defined(__ppc64__) ++ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); ++#elif defined(__ppc__) ++ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ /* Stack space. */ ++#if defined(__ppc64__) ++ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + fparg_count) * sizeof(long); ++#elif defined(__ppc__) ++ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + 2 * fparg_count) * sizeof(long); ++#else ++#error undefined architecture ++#endif ++ else ++ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); ++ ++ /* The stack space allocated needs to be a multiple of 16/32 bytes. */ ++ bytes = SF_ROUND(bytes); ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ ++ return FFI_OK; ++} ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ++ffi_call_AIX( ++/*@out@*/ extended_cif*, ++ unsigned, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++ ++extern void ++ffi_call_DARWIN( ++/*@out@*/ extended_cif*, ++ unsigned long, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ 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) && ++ (cif->rtype->type == FFI_TYPE_STRUCT)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ switch (cif->abi) ++ { ++ case FFI_AIX: ++ /*@-usedef@*/ ++ ffi_call_AIX(&ecif, -cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ case FFI_DARWIN: ++ /*@-usedef@*/ ++ ffi_call_DARWIN(&ecif, -(long)cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++/* here I'd like to add the stack frame layout we use in darwin_closure.S ++ and aix_clsoure.S ++ ++ SP previous -> +---------------------------------------+ <--- child frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 4 ++ | saved CR 4 | ++ +---------------------------------------+ 8 ++ | saved LR 4 | ++ +---------------------------------------+ 12 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 16 ++ | reserved for binders 4 | ++ +---------------------------------------+ 20 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 24 ++ | always reserved 8*4=32 (previous GPRs)| ++ | according to the linkage convention | ++ | from AIX | ++ +---------------------------------------+ 56 ++ | our FPR area 13*8=104 | ++ | f1 | ++ | . | ++ | f13 | ++ +---------------------------------------+ 160 ++ | result area 8 | ++ +---------------------------------------+ 168 ++ | alignement to the next multiple of 16 | ++SP current --> +---------------------------------------+ 176 <- parent frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 180 ++ | saved CR 4 | ++ +---------------------------------------+ 184 ++ | saved LR 4 | ++ +---------------------------------------+ 188 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 192 ++ | reserved for binders 4 | ++ +---------------------------------------+ 196 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 200 ++ | always reserved 8*4=32 we store our | ++ | GPRs here | ++ | r3 | ++ | . | ++ | r10 | ++ +---------------------------------------+ 232 ++ | overflow part | ++ +---------------------------------------+ xxx ++ | ???? | ++ +---------------------------------------+ xxx ++*/ ++ ++#if !defined(POWERPC_DARWIN) ++ ++#define MIN_LINE_SIZE 32 ++ ++static void ++flush_icache( ++ char* addr) ++{ ++#ifndef _AIX ++ __asm__ volatile ( ++ "dcbf 0,%0\n" ++ "sync\n" ++ "icbi 0,%0\n" ++ "sync\n" ++ "isync" ++ : : "r" (addr) : "memory"); ++#endif ++} ++ ++static void ++flush_range( ++ char* addr, ++ int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i += MIN_LINE_SIZE) ++ flush_icache(addr + i); ++ ++ flush_icache(addr + size - 1); ++} ++ ++#endif // !defined(POWERPC_DARWIN) ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ switch (cif->abi) ++ { ++ case FFI_DARWIN: ++ { ++ FFI_ASSERT (cif->abi == FFI_DARWIN); ++ ++ unsigned int* tramp = (unsigned int*)&closure->tramp[0]; ++ ++#if defined(__ppc64__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0xe98b0018; // ld r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0xe96b0020; // ld r11,32(r11) ++ tramp[7] = 0x4e800420; // bctr ++ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; ++ *(unsigned long*)&tramp[10] = (unsigned long)closure; ++#elif defined(__ppc__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0x818b0018; // lwz r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0x816b001c; // lwz r11,28(r11) ++ tramp[7] = 0x4e800420; // bctr ++ tramp[8] = (unsigned long)ffi_closure_ASM; ++ tramp[9] = (unsigned long)closure; ++#else ++#error undefined architecture ++#endif ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ // Flush the icache. Only necessary on Darwin. ++#if defined(POWERPC_DARWIN) ++ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#else ++ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#endif ++ ++ break; ++ } ++ ++ case FFI_AIX: ++ { ++ FFI_ASSERT (cif->abi == FFI_AIX); ++ ++ ffi_aix_trampoline_struct* tramp_aix = ++ (ffi_aix_trampoline_struct*)(closure->tramp); ++ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; ++ ++ tramp_aix->code_pointer = fd->code_pointer; ++ tramp_aix->toc = fd->toc; ++ tramp_aix->static_chain = closure; ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ break; ++ } ++ ++ default: ++ return FFI_BAD_ABI; ++ } ++ ++ return FFI_OK; ++} ++ ++#if defined(__ppc__) ++ typedef double ldbits[2]; ++ ++ typedef union ++ { ++ ldbits lb; ++ long double ld; ++ } 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 ++ for a return value, ffi_closure_ASM invokes the following helper function ++ to do most of the work. */ ++int ++ffi_closure_helper_DARWIN( ++ ffi_closure* closure, ++ void* rvalue, ++ unsigned long* pgr, ++ ffi_dblfl* pfr) ++{ ++ /* rvalue is the pointer to space for return value in closure assembly ++ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM ++ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ ++ ++#if defined(__ppc__) ++ ldu temp_ld; ++#endif ++ ++ double temp; ++ unsigned int i; ++ unsigned int nf = 0; /* number of FPRs already used. */ ++ unsigned int ng = 0; /* number of GPRs already used. */ ++ ffi_cif* cif = closure->cif; ++ long avn = cif->nargs; ++ void** avalue = alloca(cif->nargs * sizeof(void*)); ++ ffi_type** arg_types = cif->arg_types; ++ ++ /* Copy the caller's structure return value address so that the closure ++ returns the data directly to the caller. */ ++#if defined(__ppc64__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT && ++ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++#elif defined(__ppc__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT) ++#else ++#error undefined architecture ++#endif ++ { ++ rvalue = (void*)*pgr; ++ pgr++; ++ ng++; ++ } ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ for (i = 0; i < avn; i++) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ avalue[i] = (char*)pgr + MODE_CHOICE(3,7); ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ avalue[i] = (char*)pgr + MODE_CHOICE(2,6); ++ ng++; ++ pgr++; ++ break; ++ ++#if defined(__ppc__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ avalue[i] = (char*)pgr + MODE_CHOICE(0,4); ++ ng++; ++ pgr++; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ if (cif->abi == FFI_DARWIN) ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ unsigned int savedFPRSize = fprSize; ++ ++ avalue[i] = alloca(arg_types[i]->size); ++ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, ++ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); ++ ++ ng += gprSize / sizeof(long); ++ pgr += gprSize / sizeof(long); ++ pfr += (fprSize - savedFPRSize) / sizeof(double); ++ ++#elif defined(__ppc__) ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. */ ++ unsigned int size_al = size_al = arg_types[i]->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN(arg_types[i]->size, 8); ++ ++ if (size_al < 3) ++ avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; ++ else ++ avalue[i] = (void*)pgr; ++ ++ ng += (size_al + 3) / sizeof(long); ++ pgr += (size_al + 3) / sizeof(long); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ /* Long long ints are passed in 1 or 2 GPRs. */ ++ avalue[i] = pgr; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ /* A float value consumes a GPR. ++ There are 13 64-bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ temp = pfr->d; ++ pfr->f = (float)temp; ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ /* A double value consumes one or two GPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++#elif defined(__ppc__) ++ /* A long double value consumes 2/4 GPRs and 2 FPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS - 1) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++ /* Here we have the situation where one part of the long double ++ is stored in fpr13 and the other part is already on the stack. ++ 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(temp_ld.lb[0])); ++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); ++ avalue[i] = &temp_ld.ld; ++ } ++#else ++#error undefined architecture ++#endif ++ else ++ avalue[i] = pgr; ++ ++ nf += 2; ++ ng += MODE_CHOICE(4,2); ++ pgr += MODE_CHOICE(4,2); ++ ++ break; ++ ++#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ (closure->fun)(cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell ffi_closure_ASM to perform return type promotions. */ ++ return cif->rtype->type; ++} ++ ++#if defined(__ppc64__) ++ ++/* ffi64_struct_to_ram_form ++ ++ Rebuild a struct's natural layout from buffers of concatenated registers. ++ Return the number of registers used. ++ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_ram_form( ++ const ffi_type* inType, ++ const char* inGPRs, ++ unsigned int* ioGPRMarker, ++ const char* inFPRs, ++ unsigned int* ioFPRMarker, ++ unsigned int* ioFPRsUsed, ++ char* outStruct, // caller-allocated ++ unsigned int* ioStructMarker) ++{ ++ unsigned int srcGMarker = 0; ++ unsigned int srcFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ unsigned int destMarker = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioGPRMarker) ++ srcGMarker = *ioGPRMarker; ++ ++ if (ioFPRMarker) ++ { ++ srcFMarker = *ioFPRMarker; ++ savedFMarker = srcFMarker; ++ } ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioStructMarker) ++ destMarker = *ioStructMarker; ++ ++ size_t i; ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ srcGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ srcFMarker = ALIGN(srcFMarker, 4); ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inGPRs[srcGMarker]; ++ ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcFMarker = ALIGN(srcFMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inGPRs[srcGMarker]; ++ ++ destMarker += 8; ++ ++ // Skip next GPR ++ srcGMarker += 8; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ destMarker = ALIGN(destMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ srcFMarker = ALIGN(srcFMarker, 8); ++ srcGMarker = ALIGN(srcGMarker, 8); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inFPRs[srcFMarker]; ++ srcFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ srcFMarker = ALIGN(srcFMarker, 16); ++ srcGMarker = ALIGN(srcGMarker, 16); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inGPRs[srcGMarker]; ++ } ++ ++ destMarker += 16; ++ ++ // Skip next 2 GPRs ++ srcGMarker += 16; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ if (inType->alignment == 1) // chars only ++ { ++ if (inType->size == 1) ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ else if (inType->size == 2) ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ i++; ++ } ++ else ++ { ++ memcpy(&outStruct[destMarker], ++ &inGPRs[srcGMarker], inType->size); ++ srcGMarker += inType->size; ++ destMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // chars and other stuff ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcGMarker = ALIGN(srcGMarker, 2); ++ destMarker = ALIGN(destMarker, 2); ++ ++ *(short*)&outStruct[destMarker] = ++ *(short*)&inGPRs[srcGMarker]; ++ srcGMarker += 2; ++ destMarker += 2; ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ *(int*)&outStruct[destMarker] = ++ *(int*)&inGPRs[srcGMarker]; ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcGMarker = ALIGN(srcGMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ *(long long*)&outStruct[destMarker] = ++ *(long long*)&inGPRs[srcGMarker]; ++ srcGMarker += 8; ++ destMarker += 8; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_ram_form(inType->elements[i], inGPRs, ++ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, ++ outStruct, &destMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); // unknown element type ++ break; ++ } ++ } ++ ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && srcGMarker == 16) ++ { ++ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; ++ srcFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioGPRMarker) ++ *ioGPRMarker = ALIGN(srcGMarker, 8); ++ ++ if (ioFPRMarker) ++ *ioFPRMarker = srcFMarker; ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(destMarker, 8); ++} ++ ++/* ffi64_struct_to_reg_form ++ ++ Copy a struct's elements into buffers that can be sliced into registers. ++ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers ++ to calculate size only. ++ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_reg_form( ++ const ffi_type* inType, ++ const char* inStruct, ++ unsigned int* ioStructMarker, ++ unsigned int* ioFPRsUsed, ++ char* outGPRs, // caller-allocated ++ unsigned int* ioGPRSize, ++ char* outFPRs, // caller-allocated ++ unsigned int* ioFPRSize) ++{ ++ size_t i; ++ unsigned int srcMarker = 0; ++ unsigned int destGMarker = 0; ++ unsigned int destFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioStructMarker) ++ srcMarker = *ioStructMarker; ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioGPRSize) ++ destGMarker = *ioGPRSize; ++ ++ if (ioFPRSize) ++ { ++ destFMarker = *ioFPRSize; ++ savedFMarker = destFMarker; ++ } ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ destGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ // Shadow floating-point types in GPRs for vararg and pre-ANSI ++ // functions. ++ case FFI_TYPE_FLOAT: ++ // Nudge markers to next 4/8-byte boundary ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcMarker = ALIGN(srcMarker, 8); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ ++ // Skip next GPR ++ destGMarker += 8; ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ srcMarker = ALIGN(srcMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ destFMarker = ALIGN(destFMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outFPRs != NULL && inStruct != NULL) ++ *(long double*)&outFPRs[destFMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ destFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ destGMarker = ALIGN(destGMarker, 16); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ } ++ ++ srcMarker += 16; ++ destGMarker += 16; // Skip next 2 GPRs ++ destGMarker = ALIGN(destGMarker, 8); // was 16 ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ if (inType->alignment == 1) // bytes only ++ { ++ if (inType->size == 1) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ } ++ else if (inType->size == 2) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; ++ } ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ i++; ++ } ++ else ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ // Avoid memcpy for small chunks. ++ if (inType->size <= sizeof(long)) ++ *(long*)&outGPRs[destGMarker] = ++ *(long*)&inStruct[srcMarker]; ++ else ++ memcpy(&outGPRs[destGMarker], ++ &inStruct[srcMarker], inType->size); ++ } ++ ++ srcMarker += inType->size; ++ destGMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // bytes and other stuff ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcMarker = ALIGN(srcMarker, 2); ++ destGMarker = ALIGN(destGMarker, 2); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(short*)&outGPRs[destGMarker] = ++ *(short*)&inStruct[srcMarker]; ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(int*)&outGPRs[destGMarker] = ++ *(int*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcMarker = ALIGN(srcMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long long*)&outGPRs[destGMarker] = ++ *(long long*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ destGMarker += 8; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_reg_form(inType->elements[i], ++ inStruct, &srcMarker, &fprsUsed, outGPRs, ++ &destGMarker, outFPRs, &destFMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && destGMarker == 16) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; ++ ++ destFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(srcMarker, 8); ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioGPRSize) ++ *ioGPRSize = ALIGN(destGMarker, 8); ++ ++ if (ioFPRSize) ++ *ioFPRSize = ALIGN(destFMarker, 8); ++} ++ ++/* ffi64_stret_needs_ptr ++ ++ Determine whether a returned struct needs a pointer in r3 or can fit ++ in registers. ++*/ ++ ++bool ++ffi64_stret_needs_ptr( ++ const ffi_type* inType, ++ unsigned short* ioGPRCount, ++ unsigned short* ioFPRCount) ++{ ++ // Obvious case first- struct is larger than combined FPR size. ++ if (inType->size > 14 * 8) ++ return true; ++ ++ // Now the struct can physically fit in registers, determine if it ++ // also fits logically. ++ bool needsPtr = false; ++ unsigned short gprsUsed = 0; ++ unsigned short fprsUsed = 0; ++ size_t i; ++ ++ if (ioGPRCount) ++ gprsUsed = *ioGPRCount; ++ ++ if (ioFPRCount) ++ fprsUsed = *ioFPRCount; ++ ++ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ gprsUsed++; ++ fprsUsed++; ++ ++ if (fprsUsed > 13) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ gprsUsed += 2; ++ fprsUsed += 2; ++ ++ if (fprsUsed > 14) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ { ++ needsPtr = true; ++ break; ++ } ++ ++ if (inType->elements[i + 1] == NULL) // last byte in the struct ++ break; ++ ++ // Count possible contiguous bytes ahead, up to 8. ++ unsigned short j; ++ ++ for (j = 1; j < 8; j++) ++ { ++ if (inType->elements[i + j] == NULL || ++ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) ++ break; ++ } ++ ++ i += j - 1; // allow for i++ before the test condition ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ needsPtr = ffi64_stret_needs_ptr( ++ inType->elements[i], &gprsUsed, &fprsUsed); ++ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ if (ioGPRCount) ++ *ioGPRCount = gprsUsed; ++ ++ if (ioFPRCount) ++ *ioFPRCount = fprsUsed; ++ ++ return needsPtr; ++} ++ ++/* ffi64_data_size ++ ++ Calculate the size in bytes of an ffi type. ++*/ ++ ++unsigned int ++ffi64_data_size( ++ const ffi_type* inType) ++{ ++ unsigned int size = 0; ++ ++ switch (inType->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ size = 1; ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ size = 2; ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_FLOAT: ++ size = 4; ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_DOUBLE: ++ size = 8; ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ size = 16; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ ffi64_struct_to_reg_form( ++ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); ++ break; ++ ++ case FFI_TYPE_VOID: ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ ++ return size; ++} ++ ++#endif /* defined(__ppc64__) */ ++#endif /* __ppc__ || __ppc64__ */ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +new file mode 100644 +index 0000000..7162fa1 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +@@ -0,0 +1,418 @@ ++#if defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc64-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 ++ stg r0,SF_RETURN(r1) // save return address ++ ++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. ++ stg r3,SF_ARG1(r1) ++ stg r4,SF_ARG2(r1) ++ stg r5,SF_ARG3(r1) ++ stg r6,SF_ARG4(r1) ++ stg r7,SF_ARG5(r1) ++ stg r8,SF_ARG6(r1) ++ stg r9,SF_ARG7(r1) ++ stg r10,SF_ARG8(r1) ++ ++LCFI0: ++/* 48 bytes (Linkage Area) ++ 64 bytes (outgoing parameter area, always reserved) ++ 112 bytes (14*8 for incoming FPR) ++ ? bytes (result) ++ 112 bytes (14*8 for outgoing FPR) ++ 16 bytes (2 saved registers) ++ 352 + ? total bytes ++*/ ++ ++ std r31,-8(r1) // Save registers we use. ++ std r30,-16(r1) ++ mr r30,r1 // Save the old SP. ++ mr r31,r11 // Save the ffi_closure around ffi64_data_size. ++ ++ // Calculate the space we need. ++ stdu r1,-SF_MINSIZE(r1) ++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ bl Lffi64_data_size$stub ++ ld r1,0(r1) ++ ++ addi r3,r3,352 // Add our overhead. ++ neg r3,r3 ++ li r0,-32 // Align to 32 bytes. ++ and r3,r3,r0 ++ stdux r1,r1,r3 // Grow the stack. ++ ++ mr r11,r31 // Copy the ffi_closure back. ++ ++LCFI1: ++ // We want to build up an area for the parameters passed ++ // in registers. (both floating point and integer) ++ ++/* 320 bytes (callee stack frame aligned to 32) ++ 48 bytes (caller linkage area) ++ 368 (start of caller parameter area aligned to 8) ++*/ ++ ++ // Save FPRs 1 - 14. (aligned to 8) ++ stfd f1,112(r1) ++ stfd f2,120(r1) ++ stfd f3,128(r1) ++ stfd f4,136(r1) ++ stfd f5,144(r1) ++ stfd f6,152(r1) ++ stfd f7,160(r1) ++ stfd f8,168(r1) ++ stfd f9,176(r1) ++ stfd f10,184(r1) ++ stfd f11,192(r1) ++ stfd f12,200(r1) ++ stfd f13,208(r1) ++ stfd f14,216(r1) ++ ++ // Set up registers for the routine that actually does the work. ++ mr r3,r11 // context pointer from the trampoline ++ addi r4,r1,224 // result storage ++ addi r5,r30,SF_ARG1 // saved GPRs ++ addi r6,r1,112 // saved FPRs ++ bl Lffi_closure_helper_DARWIN$stub ++ ++ // Look the proper starting point in table ++ // by using return type as an offset. ++ addi r5,r1,224 // 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. ++ mtctr r3 ++ bctr ++ ++LFE1: ++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ // (4 instructions). For cache effectiveness we align to a 16 byte ++ // boundary first. ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++// case FFI_TYPE_VOID ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++// case FFI_TYPE_INT ++Lret_type1: ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_FLOAT ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_DOUBLE ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_LONGDOUBLE ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT8 ++Lret_type5: ++ lbz r3,7(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT8 ++Lret_type6: ++ lbz r3,7(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT16 ++Lret_type7: ++ lhz r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT16 ++Lret_type8: ++ lha r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT32 ++Lret_type9: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT32 ++Lret_type10: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT64 ++Lret_type11: ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT64 ++Lret_type12: // same as Lret_type11 ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_STRUCT ++Lret_type13: ++ b Lret_struct ++ nop ++ nop ++ nop ++ ++// ** End 16-byte aligned cases ** ++// case FFI_TYPE_POINTER ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ b Lfinish ++ ++// copy struct into registers ++Lret_struct: ++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r31) // ffi_cif->rtype* ++ ld r31,24(r31) // ffi_cif->flags ++ mr r4,r5 // copy struct* to 2nd arg ++ addi r7,r1,SF_ARG9 // GPR return area ++ addi r9,r30,-16-(14*8) // FPR return area ++ li r5,0 // struct offset ptr (NULL) ++ li r6,0 // FPR used count ptr (NULL) ++ li r8,0 // GPR return area size ptr (NULL) ++ li r10,0 // FPR return area size ptr (NULL) ++ bl Lffi64_struct_to_reg_form$stub ++ ++ // Load GPRs ++ ld r3,SF_ARG9(r1) ++ ld r4,SF_ARG10(r1) ++ ld r5,SF_ARG11(r1) ++ ld r6,SF_ARG12(r1) ++ nop ++ ld r7,SF_ARG13(r1) ++ ld r8,SF_ARG14(r1) ++ ld r9,SF_ARG15(r1) ++ ld r10,SF_ARG16(r1) ++ nop ++ ++ // Load FPRs ++ mtcrf 0x2,r31 ++ bf 26,Lfinish ++ lfd f1,-16-(14*8)(r30) ++ lfd f2,-16-(13*8)(r30) ++ lfd f3,-16-(12*8)(r30) ++ lfd f4,-16-(11*8)(r30) ++ nop ++ lfd f5,-16-(10*8)(r30) ++ lfd f6,-16-(9*8)(r30) ++ lfd f7,-16-(8*8)(r30) ++ lfd f8,-16-(7*8)(r30) ++ nop ++ lfd f9,-16-(6*8)(r30) ++ lfd f10,-16-(5*8)(r30) ++ lfd f11,-16-(4*8)(r30) ++ lfd f12,-16-(3*8)(r30) ++ nop ++ lfd f13,-16-(2*8)(r30) ++ lfd f14,-16-(1*8)(r30) ++ // Fall through ++ ++// case done ++Lfinish: ++ 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. ++ blr ++ ++// END(ffi_closure_ASM) ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_reg_form$stub: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_reg_form ++ ++LO$ffi64_struct_to_reg_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) ++ mtctr r12 ++ bctr ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_data_size$stub: ++ .indirect_symbol _ffi64_data_size ++ mflr r0 ++ bcl 20,31,LO$ffi64_data_size ++ ++LO$ffi64_data_size: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_reg_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ .g_long dyld_stub_binding_helper ++ ++L_ffi64_data_size$lazy_ptr: ++ .indirect_symbol _ffi64_data_size ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c +new file mode 100644 +index 0000000..44806ae +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/types.c +@@ -0,0 +1,115 @@ ++/* ----------------------------------------------------------------------- ++ types.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Predefined ffi_types needed by libffi. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++/* Type definitions */ ++#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \ ++ ffi_type ffi_type_##n = { s, a, t, NULL } ++#define FFI_AGGREGATE_TYPEDEF(n, e) \ ++ ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } ++ ++FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); ++FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); ++FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); ++FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); ++FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); ++FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); ++FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); ++ ++/* Size and alignment are fake here. They must not be 0. */ ++FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); ++ ++#if defined ALPHA || defined SPARC64 || defined X86_64 || \ ++ defined S390X || defined IA64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); ++#else ++FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); ++#endif ++ ++#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN) ++ ++# ifdef X86_64 ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++# else ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++# endif ++ ++#elif defined(POWERPC_DARWIN) ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#elif defined SH ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++#else ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#endif ++ ++#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN) ++ ++# if defined X86_WIN32 || defined X86_64 ++ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++# endif ++ ++# ifdef X86_DARWIN ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined ARM || defined SH || defined POWERPC_AIX ++FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); ++#elif defined POWERPC_DARWIN ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# if __GNUC__ >= 4 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined SPARC ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# ifdef SPARC64 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined X86_64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++#else ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S +new file mode 100644 +index 0000000..165d469 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S +@@ -0,0 +1,417 @@ ++/* ----------------------------------------------------------------------- ++ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. ++ derived from unix64.S ++ ++ x86-64 Foreign Function Interface for Darwin. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifdef __x86_64__ ++#define LIBFFI_ASM ++#include ++#include ++ ++ .file "darwin64.S" ++.text ++ ++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, ++ void *raddr, void (*fnaddr)()); ++ ++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame ++ for this function. This has been allocated by ffi_call. We also ++ deallocate some of the stack that has been alloca'd. */ ++ ++ .align 3 ++ .globl _ffi_call_unix64 ++ ++_ffi_call_unix64: ++LUW0: ++ movq (%rsp), %r10 /* Load return address. */ ++ movq %rdi, %r12 /* Save a copy of the register area. */ ++ leaq (%rdi, %rsi), %rax /* Find local stack base. */ ++ movq %rdx, (%rax) /* Save flags. */ ++ movq %rcx, 8(%rax) /* Save raddr. */ ++ movq %rbp, 16(%rax) /* Save old frame pointer. */ ++ movq %r10, 24(%rax) /* Relocate return address. */ ++ movq %rax, %rbp /* Finalize local stack frame. */ ++LUW1: ++ /* movq %rdi, %r10 // Save a copy of the register area. */ ++ movq %r12, %r10 ++ movq %r8, %r11 /* Save a copy of the target fn. */ ++ movl %r9d, %eax /* Set number of SSE registers. */ ++ ++ /* Load up all argument registers. */ ++ movq (%r10), %rdi ++ movq 8(%r10), %rsi ++ movq 16(%r10), %rdx ++ movq 24(%r10), %rcx ++ movq 32(%r10), %r8 ++ movq 40(%r10), %r9 ++ testl %eax, %eax ++ jnz Lload_sse ++Lret_from_load_sse: ++ ++ /* Deallocate the reg arg area. */ ++ leaq 176(%r10), %rsp ++ ++ /* Call the user function. */ ++ call *%r11 ++ ++ /* Deallocate stack arg area; local stack frame in redzone. */ ++ leaq 24(%rbp), %rsp ++ ++ movq 0(%rbp), %rcx /* Reload flags. */ ++ movq 8(%rbp), %rdi /* Reload raddr. */ ++ movq 16(%rbp), %rbp /* Reload old frame pointer. */ ++LUW2: ++ ++ /* The first byte of the flags contains the FFI_TYPE. */ ++ movzbl %cl, %r10d ++ leaq Lstore_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lstore_table: ++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ ++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ ++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ ++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ ++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ ++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ ++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ ++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ ++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lst_void: ++ ret ++ .align 3 ++Lst_uint8: ++ movzbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_sint8: ++ movsbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint16: ++ movzwq %ax, %rax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint16: ++ movswq %ax, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint32: ++ movl %eax, %eax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint32: ++ cltq ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_int64: ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_float: ++ movss %xmm0, (%rdi) ++ ret ++ .align 3 ++Lst_double: ++ movsd %xmm0, (%rdi) ++ ret ++Lst_ldouble: ++ fstpt (%rdi) ++ ret ++ .align 3 ++Lst_struct: ++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */ ++ ++ /* We have to locate the values now, and since we don't want to ++ write too much data into the user's return value, we spill the ++ value to a 16 byte scratch area first. Bits 8, 9, and 10 ++ control where the values are located. Only one of the three ++ bits will be set; see ffi_prep_cif_machdep for the pattern. */ ++ movd %xmm0, %r10 ++ movd %xmm1, %r11 ++ testl $0x100, %ecx ++ cmovnz %rax, %rdx ++ cmovnz %r10, %rax ++ testl $0x200, %ecx ++ cmovnz %r10, %rdx ++ testl $0x400, %ecx ++ cmovnz %r10, %rax ++ cmovnz %r11, %rdx ++ movq %rax, (%rsi) ++ movq %rdx, 8(%rsi) ++ ++ /* Bits 12-31 contain the true size of the structure. Copy from ++ the scratch area to the true destination. */ ++ shrl $12, %ecx ++ rep movsb ++ ret ++ ++ /* Many times we can avoid loading any SSE registers at all. ++ It's not worth an indirect jump to load the exact set of ++ SSE registers needed; zero or all is a good compromise. */ ++ .align 3 ++LUW3: ++Lload_sse: ++ movdqa 48(%r10), %xmm0 ++ movdqa 64(%r10), %xmm1 ++ movdqa 80(%r10), %xmm2 ++ movdqa 96(%r10), %xmm3 ++ movdqa 112(%r10), %xmm4 ++ movdqa 128(%r10), %xmm5 ++ movdqa 144(%r10), %xmm6 ++ movdqa 160(%r10), %xmm7 ++ jmp Lret_from_load_sse ++ ++LUW4: ++ .align 3 ++ .globl _ffi_closure_unix64 ++ ++_ffi_closure_unix64: ++LUW5: ++ /* The carry flag is set by the trampoline iff SSE registers ++ are used. Don't clobber it before the branch instruction. */ ++ leaq -200(%rsp), %rsp ++LUW6: ++ movq %rdi, (%rsp) ++ movq %rsi, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rcx, 24(%rsp) ++ movq %r8, 32(%rsp) ++ movq %r9, 40(%rsp) ++ jc Lsave_sse ++Lret_from_save_sse: ++ ++ movq %r10, %rdi ++ leaq 176(%rsp), %rsi ++ movq %rsp, %rdx ++ leaq 208(%rsp), %rcx ++ call _ffi_closure_unix64_inner ++ ++ /* Deallocate stack frame early; return value is now in redzone. */ ++ addq $200, %rsp ++LUW7: ++ ++ /* The first byte of the return value contains the FFI_TYPE. */ ++ movzbl %al, %r10d ++ leaq Lload_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lload_table: ++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */ ++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ ++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ ++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ ++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lld_void: ++ ret ++ .align 3 ++Lld_int8: ++ movzbl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int16: ++ movzwl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int32: ++ movl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int64: ++ movq -24(%rsp), %rax ++ ret ++ .align 3 ++Lld_float: ++ movss -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_double: ++ movsd -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_ldouble: ++ fldt -24(%rsp) ++ ret ++ .align 3 ++Lld_struct: ++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, ++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading ++ both rdx and xmm1 with the second word. For the remaining, ++ bit 8 set means xmm0 gets the second word, and bit 9 means ++ that rax gets the second word. */ ++ movq -24(%rsp), %rcx ++ movq -16(%rsp), %rdx ++ movq -16(%rsp), %xmm1 ++ testl $0x100, %eax ++ cmovnz %rdx, %rcx ++ movd %rcx, %xmm0 ++ testl $0x200, %eax ++ movq -24(%rsp), %rax ++ cmovnz %rdx, %rax ++ ret ++ ++ /* See the comment above Lload_sse; the same logic applies here. */ ++ .align 3 ++LUW8: ++Lsave_sse: ++ movdqa %xmm0, 48(%rsp) ++ movdqa %xmm1, 64(%rsp) ++ movdqa %xmm2, 80(%rsp) ++ movdqa %xmm3, 96(%rsp) ++ movdqa %xmm4, 112(%rsp) ++ movdqa %xmm5, 128(%rsp) ++ movdqa %xmm6, 144(%rsp) ++ movdqa %xmm7, 160(%rsp) ++ jmp Lret_from_save_sse ++ ++LUW9: ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ ++ .long L$set$0 ++LSCIE1: ++ .long 0x0 /* CIE Identifier Tag */ ++ .byte 0x1 /* CIE Version */ ++ .ascii "zR\0" /* CIE Augmentation */ ++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ ++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ ++ .byte 0x10 /* CIE RA Column */ ++ .byte 0x1 /* uleb128 0x1; Augmentation size */ ++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */ ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 /* uleb128 0x7 */ ++ .byte 0x8 /* uleb128 0x8 */ ++ .byte 0x90 /* DW_CFA_offset, column 0x10 */ ++ .byte 0x1 ++ .align 3 ++LECIE1: ++ .globl _ffi_call_unix64.eh ++_ffi_call_unix64.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ ++ .long L$set$1 ++LASFDE1: ++ .long LASFDE1-EH_frame1 /* FDE CIE offset */ ++ .quad LUW0-. /* FDE initial location */ ++ .set L$set$2,LUW4-LUW0 /* FDE address range */ ++ .quad L$set$2 ++ .byte 0x0 /* Augmentation size */ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$3,LUW1-LUW0 ++ .long L$set$3 ++ ++ /* New stack frame based off rbp. This is a itty bit of unwind ++ trickery in that the CFA *has* changed. There is no easy way ++ to describe it correctly on entry to the function. Fortunately, ++ it doesn't matter too much since at all points we can correctly ++ unwind back to ffi_call. Note that the location to which we ++ moved the return address is (the new) CFA-8, so from the ++ perspective of the unwind info, it hasn't moved. */ ++ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ ++ .byte 0x6 ++ .byte 0x20 ++ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ ++ .byte 0x2 ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$4,LUW2-LUW1 ++ .long L$set$4 ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 ++ .byte 0x8 ++ .byte 0xc0+6 /* DW_CFA_restore, %rbp */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$5,LUW3-LUW2 ++ .long L$set$5 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE1: ++ .globl _ffi_closure_unix64.eh ++_ffi_closure_unix64.eh: ++LSFDE3: ++ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ ++ .long L$set$6 ++LASFDE3: ++ .long LASFDE3-EH_frame1 /* FDE CIE offset */ ++ .quad LUW5-. /* FDE initial location */ ++ .set L$set$7,LUW9-LUW5 /* FDE address range */ ++ .quad L$set$7 ++ .byte 0x0 /* Augmentation size */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$8,LUW6-LUW5 ++ .long L$set$8 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 208,1 /* uleb128 208 */ ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$9,LUW7-LUW6 ++ .long L$set$9 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 0x8 ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$10,LUW8-LUW7 ++ .long L$set$10 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE3: ++ .subsections_via_symbols ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +new file mode 100644 +index 0000000..925a841 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +@@ -0,0 +1,422 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. ++ ++ X86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++/* ++ * This file is based on sysv.S and then hacked up by Ronald who hasn't done ++ * assembly programming in 8 years. ++ */ ++ ++#ifndef __x86_64__ ++ ++#define LIBFFI_ASM ++#include ++#include ++ ++#ifdef PyObjC_STRICT_DEBUGGING ++ /* XXX: Debugging of stack alignment, to be removed */ ++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 ++#else ++#define ASSERT_STACK_ALIGNED ++#endif ++ ++.text ++ ++.globl _ffi_prep_args ++ ++ .align 4 ++.globl _ffi_call_SYSV ++ ++_ffi_call_SYSV: ++LFB1: ++ pushl %ebp ++LCFI0: ++ movl %esp,%ebp ++LCFI1: ++ subl $8,%esp ++ /* Make room for all of the new args. */ ++ movl 16(%ebp),%ecx ++ subl %ecx,%esp ++ ++ movl %esp,%eax ++ ++ /* Place all of the ffi_prep_args in position */ ++ subl $8,%esp ++ pushl 12(%ebp) ++ pushl %eax ++ call *8(%ebp) ++ ++ /* Return stack to previous state and call the function */ ++ addl $16,%esp ++ ++ call *28(%ebp) ++ ++ /* 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 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 Lnoretval ++ fstp %st(0) ++ ++ jmp Lepilogue ++ ++Lretint: ++ cmpl $FFI_TYPE_INT,%ecx ++ jne Lretfloat ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ movl %eax,0(%ecx) ++ jmp Lepilogue ++ ++Lretfloat: ++ cmpl $FFI_TYPE_FLOAT,%ecx ++ jne Lretdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstps (%ecx) ++ jmp Lepilogue ++ ++Lretdouble: ++ cmpl $FFI_TYPE_DOUBLE,%ecx ++ jne Lretlongdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpl (%ecx) ++ jmp Lepilogue ++ ++Lretlongdouble: ++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx ++ jne Lretint64 ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpt (%ecx) ++ jmp Lepilogue ++ ++Lretint64: ++ cmpl $FFI_TYPE_SINT64,%ecx ++ 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 Lepilogue ++ ++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 ++ ++Lnoretval: ++Lepilogue: ++ addl $8,%esp ++ movl %ebp,%esp ++ popl %ebp ++ ret ++LFE1: ++.ffi_call_SYSV_end: ++ ++ .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_UINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_SINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_UINT16, %eax ++ je Lcls_retstruct2 ++ 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 ++ ++.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__ */ ++ ++#endif /* defined __i386__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +new file mode 100644 +index 0000000..06feaf2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +@@ -0,0 +1,734 @@ ++#ifdef __x86_64__ ++ ++/* ----------------------------------------------------------------------- ++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen ++ ++ x86-64 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_GPR_REGS 6 ++#define MAX_SSE_REGS 8 ++ ++typedef struct RegisterArgs { ++ /* Registers for argument passing. */ ++ UINT64 gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++} RegisterArgs; ++ ++extern void ++ffi_call_unix64( ++ void* args, ++ unsigned long bytes, ++ unsigned flags, ++ void* raddr, ++ void (*fnaddr)(), ++ unsigned ssecount); ++ ++/* All reference to register classes here is identical to the code in ++ gcc/config/i386/i386.c. Do *not* change one without the other. */ ++ ++/* 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 reformating penalties. ++ ++ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves ++ whenever possible (upper half does contain padding). */ ++enum x86_64_reg_class ++{ ++ X86_64_NO_CLASS, ++ X86_64_INTEGER_CLASS, ++ X86_64_INTEGERSI_CLASS, ++ X86_64_SSE_CLASS, ++ X86_64_SSESF_CLASS, ++ X86_64_SSEDF_CLASS, ++ X86_64_SSEUP_CLASS, ++ X86_64_X87_CLASS, ++ X86_64_X87UP_CLASS, ++ X86_64_COMPLEX_X87_CLASS, ++ X86_64_MEMORY_CLASS ++}; ++ ++#define MAX_CLASSES 4 ++#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) ++ ++/* x86-64 register passing implementation. See x86-64 ABI for details. Goal ++ of this code is to classify each 8bytes of incoming argument by the register ++ class and assign registers accordingly. */ ++ ++/* Return the union class of CLASS1 and CLASS2. ++ See the x86-64 PS ABI for details. */ ++static enum x86_64_reg_class ++merge_classes( ++ enum x86_64_reg_class class1, ++ enum x86_64_reg_class class2) ++{ ++ /* Rule #1: If both classes are equal, this is the resulting class. */ ++ if (class1 == class2) ++ return class1; ++ ++ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is ++ the other class. */ ++ if (class1 == X86_64_NO_CLASS) ++ return class2; ++ ++ if (class2 == X86_64_NO_CLASS) ++ return class1; ++ ++ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ ++ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ ++ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) ++ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) ++ return X86_64_INTEGERSI_CLASS; ++ ++ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS ++ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) ++ return X86_64_INTEGER_CLASS; ++ ++ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, ++ MEMORY is used. */ ++ if (class1 == X86_64_X87_CLASS ++ || class1 == X86_64_X87UP_CLASS ++ || class1 == X86_64_COMPLEX_X87_CLASS ++ || class2 == X86_64_X87_CLASS ++ || class2 == X86_64_X87UP_CLASS ++ || class2 == X86_64_COMPLEX_X87_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #6: Otherwise class SSE is used. */ ++ return X86_64_SSE_CLASS; ++} ++ ++/* Classify the argument of type TYPE and mode MODE. ++ CLASSES will be filled by the register class used to pass each word ++ of the operand. The number of words is returned. In case the parameter ++ should be passed in memory, 0 is returned. As a special case for zero ++ sized containers, classes[0] will be NO_CLASS and 1 is returned. ++ ++ See the x86-64 PS ABI for details. */ ++ ++static int ++classify_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[], ++ size_t byte_offset) ++{ ++ switch (type->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++#if 0 ++ if (byte_offset + type->size <= 4) ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ else ++ classes[0] = X86_64_INTEGER_CLASS; ++ ++ return 1; ++#else ++ { ++ int size = byte_offset + type->size; ++ ++ if (size <= 4) ++ { ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ return 1; ++ } ++ else if (size <= 8) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ return 1; ++ } ++ else if (size <= 12) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else if (size <= 16) ++ { ++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else ++ FFI_ASSERT (0); ++ } ++#endif ++ ++ case FFI_TYPE_FLOAT: ++ if (byte_offset == 0) ++ classes[0] = X86_64_SSESF_CLASS; ++ else ++ classes[0] = X86_64_SSE_CLASS; ++ ++ return 1; ++ ++ case FFI_TYPE_DOUBLE: ++ classes[0] = X86_64_SSEDF_CLASS; ++ return 1; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ classes[0] = X86_64_X87_CLASS; ++ classes[1] = X86_64_X87UP_CLASS; ++ return 2; ++ ++ case FFI_TYPE_STRUCT: ++ { ++ ffi_type** ptr; ++ int i; ++ enum x86_64_reg_class subclasses[MAX_CLASSES]; ++ const int UNITS_PER_WORD = 8; ++ int words = ++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ++ ++ /* If the struct is larger than 16 bytes, pass it on the stack. */ ++ if (type->size > 16) ++ return 0; ++ ++ for (i = 0; i < words; i++) ++ classes[i] = X86_64_NO_CLASS; ++ ++ /* Merge the fields of structure. */ ++ for (ptr = type->elements; *ptr != NULL; ptr++) ++ { ++ byte_offset = ALIGN(byte_offset, (*ptr)->alignment); ++ ++ int num = classify_argument(*ptr, subclasses, byte_offset % 8); ++ ++ if (num == 0) ++ return 0; ++ ++ int pos = byte_offset / 8; ++ ++ for (i = 0; i < num; i++) ++ { ++ classes[i + pos] = ++ merge_classes(subclasses[i], classes[i + pos]); ++ } ++ ++ byte_offset += (*ptr)->size; ++ } ++ ++ if (words > 2) ++ { ++ /* When size > 16 bytes, if the first one isn't ++ X86_64_SSE_CLASS or any other ones aren't ++ X86_64_SSEUP_CLASS, everything should be passed in ++ memory. */ ++ if (classes[0] != X86_64_SSE_CLASS) ++ return 0; ++ ++ for (i = 1; i < words; i++) ++ if (classes[i] != X86_64_SSEUP_CLASS) ++ return 0; ++ } ++ ++ ++ /* Final merger cleanup. */ ++ for (i = 0; i < words; i++) ++ { ++ /* If one class is MEMORY, everything should be passed in ++ memory. */ ++ if (classes[i] == X86_64_MEMORY_CLASS) ++ return 0; ++ ++ /* The X86_64_SSEUP_CLASS should be always preceded by ++ X86_64_SSE_CLASS. */ ++ if (classes[i] == X86_64_SSEUP_CLASS ++ && classes[i - 1] != X86_64_SSE_CLASS ++ && classes[i - 1] != X86_64_SSEUP_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ ++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ ++ if (classes[i] == X86_64_X87UP_CLASS ++ && classes[i - 1] != X86_64_X87_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ } ++ ++ return words; ++ } ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ return 0; /* Never reached. */ ++} ++ ++/* Examine the argument and return set number of register required in each ++ class. Return zero if parameter should be passed in memory, otherwise ++ the number of registers. */ ++static int ++examine_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[MAX_CLASSES], ++ _Bool in_return, ++ int* pngpr, ++ int* pnsse) ++{ ++ int n = classify_argument(type, classes, 0); ++ int ngpr = 0; ++ int nsse = 0; ++ int i; ++ ++ if (n == 0) ++ return 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ ngpr++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ nsse++; ++ break; ++ ++ case X86_64_NO_CLASS: ++ case X86_64_SSEUP_CLASS: ++ break; ++ ++ case X86_64_X87_CLASS: ++ case X86_64_X87UP_CLASS: ++ case X86_64_COMPLEX_X87_CLASS: ++ return in_return != 0; ++ ++ default: ++ abort(); ++ } ++ } ++ ++ *pngpr = ngpr; ++ *pnsse = nsse; ++ ++ return n; ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ int gprcount = 0; ++ int ssecount = 0; ++ int flags = cif->rtype->type; ++ int i, avn, n, ngpr, nsse; ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ size_t bytes; ++ ++ if (flags != FFI_TYPE_VOID) ++ { ++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value is passed in memory. A pointer to that ++ memory is the first argument. Allocate a register for it. */ ++ gprcount++; ++ ++ /* We don't have to do anything in asm for the return. */ ++ flags = FFI_TYPE_VOID; ++ } ++ else if (flags == FFI_TYPE_STRUCT) ++ { ++ /* Mark which registers the result appears in. */ ++ _Bool sse0 = SSE_CLASS_P(classes[0]); ++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]); ++ ++ if (sse0 && !sse1) ++ flags |= 1 << 8; ++ else if (!sse0 && sse1) ++ flags |= 1 << 9; ++ else if (sse0 && sse1) ++ flags |= 1 << 10; ++ ++ /* Mark the true size of the structure. */ ++ flags |= cif->rtype->size << 12; ++ } ++ } ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) ++ { ++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = cif->arg_types[i]->alignment; ++ ++ if (align < 8) ++ align = 8; ++ ++ bytes = ALIGN(bytes, align); ++ bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += ngpr; ++ ssecount += nsse; ++ } ++ } ++ ++ if (ssecount) ++ flags |= 1 << 11; ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ cif->bytes = ALIGN(bytes,8); ++ ++ return FFI_OK; ++} ++ ++void ++ffi_call( ++ ffi_cif* cif, ++ void (*fn)(), ++ void* rvalue, ++ void** avalue) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ char* stack; ++ char* argp; ++ ffi_type** arg_types; ++ int gprcount, ssecount, ngpr, nsse, i, avn; ++ _Bool ret_in_memory; ++ RegisterArgs* reg_args; ++ ++ /* Can't call 32-bit mode from 64-bit mode. */ ++ FFI_ASSERT(cif->abi == FFI_UNIX64); ++ ++ /* If the return value is a struct and we don't have a return value ++ address then we need to make one. Note the setting of flags to ++ VOID above in ffi_prep_cif_machdep. */ ++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT ++ && (cif->flags & 0xff) == FFI_TYPE_VOID); ++ ++ if (rvalue == NULL && ret_in_memory) ++ rvalue = alloca (cif->rtype->size); ++ ++ /* Allocate the space for the arguments, plus 4 words of temp space. */ ++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8); ++ reg_args = (RegisterArgs*)stack; ++ argp = stack + sizeof(RegisterArgs); ++ ++ gprcount = ssecount = 0; ++ ++ /* If the return value is passed in memory, add the pointer as the ++ first integer argument. */ ++ if (ret_in_memory) ++ reg_args->gpr[gprcount++] = (long) rvalue; ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ size_t size = arg_types[i]->size; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ memcpy (argp, avalue[i], size); ++ argp += size; ++ } ++ else ++ { /* The argument is passed entirely in registers. */ ++ char *a = (char *) avalue[i]; ++ int j; ++ ++ for (j = 0; j < n; j++, a += 8, size -= 8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ reg_args->gpr[gprcount] = 0; ++ switch (arg_types[i]->type) { ++ case FFI_TYPE_SINT8: ++ { ++ int8_t shortval = *(int8_t*)a; ++ int64_t actval = (int64_t)shortval; ++ reg_args->gpr[gprcount] = actval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ break; ++ } ++ ++ case FFI_TYPE_SINT16: ++ { ++ int16_t shortval = *(int16_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_SINT32: ++ { ++ int32_t shortval = *(int32_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT8: ++ { ++ u_int8_t shortval = *(u_int8_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ reg_args->gpr[gprcount] = actval; ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ { ++ u_int16_t shortval = *(u_int16_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT32: ++ { ++ u_int32_t shortval = *(u_int32_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ default: ++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); ++ reg_args->gpr[gprcount] = *(int64_t*)a; ++ } ++ gprcount++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSEDF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT64 *) a; ++ break; ++ ++ case X86_64_SSESF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT32 *) a; ++ break; ++ ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++ ++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs), ++ cif->flags, rvalue, fn, ssecount); ++} ++ ++extern void ffi_closure_unix64(void); ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ if (cif->abi != FFI_UNIX64) ++ return FFI_BAD_ABI; ++ ++ volatile unsigned short* tramp = ++ (volatile unsigned short*)&closure->tramp[0]; ++ ++ tramp[0] = 0xbb49; /* mov , %r11 */ ++ *(void* volatile*)&tramp[1] = ffi_closure_unix64; ++ tramp[5] = 0xba49; /* mov , %r10 */ ++ *(void* volatile*)&tramp[6] = closure; ++ ++ /* Set the carry bit if the function uses any sse registers. ++ This is clc or stc, together with the first byte of the jmp. */ ++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; ++ tramp[11] = 0xe3ff; /* jmp *%r11 */ ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wmissing-prototypes" ++int ++ffi_closure_unix64_inner( ++ ffi_closure* closure, ++ void* rvalue, ++ RegisterArgs* reg_args, ++ char* argp) ++#pragma clang diagnostic pop ++{ ++ ffi_cif* cif = closure->cif; ++ void** avalue = alloca(cif->nargs * sizeof(void *)); ++ ffi_type** arg_types; ++ long i, avn; ++ int gprcount = 0; ++ int ssecount = 0; ++ int ngpr, nsse; ++ int ret; ++ ++ ret = cif->rtype->type; ++ ++ if (ret != FFI_TYPE_VOID) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value goes in memory. Arrange for the closure ++ return value to go directly back to the original caller. */ ++ rvalue = (void *) reg_args->gpr[gprcount++]; ++ ++ /* We don't have to do anything in asm for the return. */ ++ ret = FFI_TYPE_VOID; ++ } ++ else if (ret == FFI_TYPE_STRUCT && n == 2) ++ { ++ /* Mark which register the second word of the structure goes in. */ ++ _Bool sse0 = SSE_CLASS_P (classes[0]); ++ _Bool sse1 = SSE_CLASS_P (classes[1]); ++ ++ if (!sse0 && sse1) ++ ret |= 1 << 8; ++ else if (sse0 && !sse1) ++ ret |= 1 << 9; ++ } ++ } ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ avalue[i] = argp; ++ argp += arg_types[i]->size; ++ } ++ ++#if !defined(X86_DARWIN) ++ /* If the argument is in a single register, or two consecutive ++ registers, then we can use that address directly. */ ++ else if (n == 1 || (n == 2 && ++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1]))) ++ { ++ // The argument is in a single register. ++ if (SSE_CLASS_P (classes[0])) ++ { ++ avalue[i] = ®_args->sse[ssecount]; ++ ssecount += n; ++ } ++ else ++ { ++ avalue[i] = ®_args->gpr[gprcount]; ++ gprcount += n; ++ } ++ } ++#endif ++ ++ /* Otherwise, allocate space to make them consecutive. */ ++ else ++ { ++ char *a = alloca (16); ++ int j; ++ ++ avalue[i] = a; ++ ++ for (j = 0; j < n; j++, a += 8) ++ { ++ if (SSE_CLASS_P (classes[j])) ++ memcpy (a, ®_args->sse[ssecount++], 8); ++ else ++ memcpy (a, ®_args->gpr[gprcount++], 8); ++ } ++ } ++ } ++ ++ /* Invoke the closure. */ ++ closure->fun (cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell assembly how to perform return type promotions. */ ++ return ret; ++} ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +new file mode 100644 +index 0000000..706ea0f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +@@ -0,0 +1,438 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ++ Copyright (c) 2002 Ranjit Mathew ++ Copyright (c) 2002 Bo Thorsen ++ Copyright (c) 2002 Roger Sayle ++ ++ x86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments */ ++ ++void ffi_prep_args(char *stack, extended_cif *ecif); ++ ++void ffi_prep_args(char *stack, extended_cif *ecif) ++{ ++ 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) ++ { ++ *(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) ++{ ++ /* 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_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; ++ } ++ ++#ifdef X86_DARWIN ++ cif->bytes = (cif->bytes + 15) & ~0xF; ++#endif ++ ++ return FFI_OK; ++} ++ ++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 *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); ++ ++#endif /* X86_WIN32 */ ++ ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++ ++/** private members **/ ++ ++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 */ ++ ++unsigned int FFI_HIDDEN ++ffi_closure_SYSV_inner (closure, respp, args) ++ffi_closure *closure; ++void **respp; ++void *args; ++{ ++ // 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 - (__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) ++{ ++ if (cif->abi != FFI_SYSV) ++ return FFI_BAD_ABI; ++ ++ 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 ++ ++ffi_status ++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) ++{ ++ 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) ++{ ++ 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 *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++ ++#ifdef X86_WIN32 ++extern void ++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++#endif /* X86_WIN32 */ ++ ++void ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++#endif ++#endif // __i386__ +diff --git ./setup.py ./setup.py +index 46b92fe..2bf6b4b 100644 +--- ./setup.py ++++ ./setup.py +@@ -98,8 +98,14 @@ class PyBuildExt(build_ext): + self.detect_modules() + + # Remove modules that are present on the disabled list +- self.extensions = [ext for ext in self.extensions +- if ext.name not in disabled_module_list] ++ extensions = [ext for ext in self.extensions ++ if ext.name not in disabled_module_list] ++ # move ctypes to the end, it depends on other modules ++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) ++ if "_ctypes" in ext_map: ++ ctypes = extensions.pop(ext_map["_ctypes"]) ++ extensions.append(ctypes) ++ self.extensions = extensions + + # Fix up the autodetected modules, prefixing all the source files + # with Modules/ and adding Python's include directory to the path. +@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext): + # *** Uncomment these for TOGL extension only: + # -lGL -lGLU -lXext -lXmu \ + ++ def configure_ctypes_darwin(self, ext): ++ # Darwin (OS X) uses preconfigured files, in ++ # the Modules/_ctypes/libffi_osx directory. ++ srcdir = sysconfig.get_config_var('srcdir') ++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', ++ '_ctypes', 'libffi_osx')) ++ sources = [os.path.join(ffi_srcdir, p) ++ for p in ['ffi.c', ++ 'x86/darwin64.S', ++ 'x86/x86-darwin.S', ++ 'x86/x86-ffi_darwin.c', ++ 'x86/x86-ffi64.c', ++ 'powerpc/ppc-darwin.S', ++ 'powerpc/ppc-darwin_closure.S', ++ 'powerpc/ppc-ffi_darwin.c', ++ 'powerpc/ppc64-darwin_closure.S', ++ ]] ++ ++ # Add .S (preprocessed assembly) to C compiler source extensions. ++ self.compiler.src_extensions.append('.S') ++ ++ include_dirs = [os.path.join(ffi_srcdir, 'include'), ++ os.path.join(ffi_srcdir, 'powerpc')] ++ ext.include_dirs.extend(include_dirs) ++ ext.sources.extend(sources) ++ return True ++ + def configure_ctypes(self, ext): + if not self.use_system_libffi: +- (srcdir,) = sysconfig.get_config_vars('srcdir') ++ if sys.platform == 'darwin': ++ return self.configure_ctypes_darwin(ext) ++ ++ srcdir = sysconfig.get_config_var('srcdir') + ffi_builddir = os.path.join(self.build_temp, 'libffi') + ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + '_ctypes', 'libffi')) +@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext): + ffi_configfile): + from distutils.dir_util import mkpath + mkpath(ffi_builddir) +- config_args = [] ++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() ++ if (('--host=' in arg) or ('--build=' in arg))] ++ if not self.verbose: ++ config_args.append("-q") + + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. +@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext): + self.compiler.src_extensions.append('.S') + + include_dirs = [os.path.join(ffi_builddir, 'include'), +- ffi_builddir, ffi_srcdir] ++ ffi_builddir, ++ os.path.join(ffi_srcdir, 'src')] + extra_compile_args = fficonfig['ffi_cflags'].split() + +- ext.sources.extend(fficonfig['ffi_sources']) ++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in ++ fficonfig['ffi_sources']) + ext.include_dirs.extend(include_dirs) + ext.extra_compile_args.extend(extra_compile_args) + return True +@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext): + + if sys.platform == 'darwin': + sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + # XXX Is this still needed? + ## extra_link_args.extend(['-read_only_relocs', 'warning']) +@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext): + if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = find_file('ffi.h', [], inc_dirs) ++ if sys.platform == 'darwin': ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') ++ ++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] ++ if not ffi_inc or ffi_inc[0] == '': ++ ffi_inc = find_file('ffi.h', [], inc_dirs) + if ffi_inc is not None: + ffi_h = ffi_inc[0] + '/ffi.h' + fp = open(ffi_h) diff --git a/plugins/python-build/share/python-build/patches/2.5.2/Python-2.5.2/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.2/Python-2.5.2/004_osx_libffi.patch new file mode 100644 index 00000000..cd500771 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/2.5.2/Python-2.5.2/004_osx_libffi.patch @@ -0,0 +1,6881 @@ +diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE +new file mode 100644 +index 0000000..f591795 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/LICENSE +@@ -0,0 +1,20 @@ ++libffi - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++``Software''), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice shall be included ++in all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++OTHER DEALINGS IN THE SOFTWARE. +diff --git ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README +new file mode 100644 +index 0000000..1fc2747 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README +@@ -0,0 +1,500 @@ ++This directory contains the libffi package, which is not part of GCC but ++shipped with GCC as convenience. ++ ++Status ++====== ++ ++libffi-2.00 has not been released yet! This is a development snapshot! ++ ++libffi-1.20 was released on October 5, 1998. Check the libffi web ++page for updates: . ++ ++ ++What is libffi? ++=============== ++ ++Compilers for high level languages generate code that follow certain ++conventions. These conventions are necessary, in part, for separate ++compilation to work. One such convention is the "calling ++convention". The "calling convention" is essentially a set of ++assumptions made by the compiler about where function arguments will ++be found on entry to a function. A "calling convention" also specifies ++where the return value for a function is found. ++ ++Some programs may not know at the time of compilation what arguments ++are to be passed to a function. For instance, an interpreter may be ++told at run-time about the number and types of arguments used to call ++a given function. Libffi can be used in such programs to provide a ++bridge from the interpreter program to compiled code. ++ ++The libffi library provides a portable, high level programming ++interface to various calling conventions. This allows a programmer to ++call any function specified by a call interface description at run ++time. ++ ++Ffi stands for Foreign Function Interface. A foreign function ++interface is the popular name for the interface that allows code ++written in one language to call code written in another language. The ++libffi library really only provides the lowest, machine dependent ++layer of a fully featured foreign function interface. A layer must ++exist above libffi that handles type conversions for values passed ++between the two languages. ++ ++ ++Supported Platforms and Prerequisites ++===================================== ++ ++Libffi has been ported to: ++ ++ SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) ++ ++ Irix 5.3 & 6.2 (System V/o32 & n32) ++ ++ Intel x86 - Linux (System V ABI) ++ ++ Alpha - Linux and OSF/1 ++ ++ m68k - Linux (System V ABI) ++ ++ PowerPC - Linux (System V ABI, Darwin, AIX) ++ ++ ARM - Linux (System V ABI) ++ ++Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are ++that other versions will work. Libffi has also been built and tested ++with the SGI compiler tools. ++ ++On PowerPC, the tests failed (see the note below). ++ ++You must use GNU make to build libffi. SGI's make will not work. ++Sun's probably won't either. ++ ++If you port libffi to another platform, please let me know! I assume ++that some will be easy (x86 NetBSD), and others will be more difficult ++(HP). ++ ++ ++Installing libffi ++================= ++ ++[Note: before actually performing any of these installation steps, ++ you may wish to read the "Platform Specific Notes" below.] ++ ++First you must configure the distribution for your particular ++system. Go to the directory you wish to build libffi in and run the ++"configure" program found in the root directory of the libffi source ++distribution. ++ ++You may want to tell configure where to install the libffi library and ++header files. To do that, use the --prefix configure switch. Libffi ++will install under /usr/local by default. ++ ++If you want to enable extra run-time debugging checks use the the ++--enable-debug configure switch. This is useful when your program dies ++mysteriously while using libffi. ++ ++Another useful configure switch is --enable-purify-safety. Using this ++will add some extra code which will suppress certain warnings when you ++are using Purify with libffi. Only use this switch when using ++Purify, as it will slow down the library. ++ ++Configure has many other options. Use "configure --help" to see them all. ++ ++Once configure has finished, type "make". Note that you must be using ++GNU make. SGI's make will not work. Sun's probably won't either. ++You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. ++ ++To ensure that libffi is working as advertised, type "make test". ++ ++To install the library and header files, type "make install". ++ ++ ++Using libffi ++============ ++ ++ The Basics ++ ---------- ++ ++Libffi assumes that you have a pointer to the function you wish to ++call and that you know the number and types of arguments to pass it, ++as well as the return type of the function. ++ ++The first thing you must do is create an ffi_cif object that matches ++the signature of the function you wish to call. The cif in ffi_cif ++stands for Call InterFace. To prepare a call interface object, use the ++following function: ++ ++ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, ++ unsigned int nargs, ++ ffi_type *rtype, ffi_type **atypes); ++ ++ CIF is a pointer to the call interface object you wish ++ to initialize. ++ ++ ABI is an enum that specifies the calling convention ++ to use for the call. FFI_DEFAULT_ABI defaults ++ to the system's native calling convention. Other ++ ABI's may be used with care. They are system ++ specific. ++ ++ NARGS is the number of arguments this function accepts. ++ libffi does not yet support vararg functions. ++ ++ RTYPE is a pointer to an ffi_type structure that represents ++ the return type of the function. Ffi_type objects ++ describe the types of values. libffi provides ++ ffi_type objects for many of the native C types: ++ signed int, unsigned int, signed char, unsigned char, ++ etc. There is also a pointer ffi_type object and ++ a void ffi_type. Use &ffi_type_void for functions that ++ don't return values. ++ ++ ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. ++ If NARGS is 0, this is ignored. ++ ++ ++ffi_prep_cif will return a status code that you are responsible ++for checking. It will be one of the following: ++ ++ FFI_OK - All is good. ++ ++ FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif ++ came across is bad. ++ ++ ++Before making the call, the VALUES vector should be initialized ++with pointers to the appropriate argument values. ++ ++To call the the function using the initialized ffi_cif, use the ++ffi_call function: ++ ++void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); ++ ++ CIF is a pointer to the ffi_cif initialized specifically ++ for this function. ++ ++ FN is a pointer to the function you want to call. ++ ++ RVALUE is a pointer to a chunk of memory that is to hold the ++ result of the function call. Currently, it must be ++ at least one word in size (except for the n32 version ++ under Irix 6.x, which must be a pointer to an 8 byte ++ aligned value (a long long). It must also be at least ++ word aligned (depending on the return type, and the ++ system's alignment requirements). If RTYPE is ++ &ffi_type_void, this is ignored. If RVALUE is NULL, ++ the return value is discarded. ++ ++ AVALUES is a vector of void* that point to the memory locations ++ holding the argument values for a call. ++ If NARGS is 0, this is ignored. ++ ++ ++If you are expecting a return value from FN it will have been stored ++at RVALUE. ++ ++ ++ ++ An Example ++ ---------- ++ ++Here is a trivial example that calls puts() a few times. ++ ++ #include ++ #include ++ ++ int main() ++ { ++ ffi_cif cif; ++ ffi_type *args[1]; ++ void *values[1]; ++ char *s; ++ int rc; ++ ++ /* Initialize the argument info vectors */ ++ args[0] = &ffi_type_uint; ++ values[0] = &s; ++ ++ /* Initialize the cif */ ++ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, ++ &ffi_type_uint, args) == FFI_OK) ++ { ++ s = "Hello World!"; ++ ffi_call(&cif, puts, &rc, values); ++ /* rc now holds the result of the call to puts */ ++ ++ /* values holds a pointer to the function's arg, so to ++ call puts() again all we need to do is change the ++ value of s */ ++ s = "This is cool!"; ++ ffi_call(&cif, puts, &rc, values); ++ } ++ ++ return 0; ++ } ++ ++ ++ ++ Aggregate Types ++ --------------- ++ ++Although libffi has no special support for unions or bit-fields, it is ++perfectly happy passing structures back and forth. You must first ++describe the structure to libffi by creating a new ffi_type object ++for it. Here is the definition of ffi_type: ++ ++ typedef struct _ffi_type ++ { ++ unsigned size; ++ short alignment; ++ short type; ++ struct _ffi_type **elements; ++ } ffi_type; ++ ++All structures must have type set to FFI_TYPE_STRUCT. You may set ++size and alignment to 0. These will be calculated and reset to the ++appropriate values by ffi_prep_cif(). ++ ++elements is a NULL terminated array of pointers to ffi_type objects ++that describe the type of the structure elements. These may, in turn, ++be structure elements. ++ ++The following example initializes a ffi_type object representing the ++tm struct from Linux's time.h: ++ ++ struct tm { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++ /* Those are for future use. */ ++ long int __tm_gmtoff__; ++ __const char *__tm_zone__; ++ }; ++ ++ { ++ ffi_type tm_type; ++ ffi_type *tm_type_elements[12]; ++ int i; ++ ++ tm_type.size = tm_type.alignment = 0; ++ tm_type.elements = &tm_type_elements; ++ ++ for (i = 0; i < 9; i++) ++ tm_type_elements[i] = &ffi_type_sint; ++ ++ tm_type_elements[9] = &ffi_type_slong; ++ tm_type_elements[10] = &ffi_type_pointer; ++ tm_type_elements[11] = NULL; ++ ++ /* tm_type can now be used to represent tm argument types and ++ return types for ffi_prep_cif() */ ++ } ++ ++ ++ ++Platform Specific Notes ++======================= ++ ++ Intel x86 ++ --------- ++ ++There are no known problems with the x86 port. ++ ++ Sun SPARC - SunOS 4.1.3 & Solaris 2.x ++ ------------------------------------- ++ ++You must use GNU Make to build libffi on Sun platforms. ++ ++ MIPS - Irix 5.3 & 6.x ++ --------------------- ++ ++Irix 6.2 and better supports three different calling conventions: o32, ++n32 and n64. Currently, libffi only supports both o32 and n32 under ++Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be ++configured for whichever calling convention it was built for. ++ ++By default, the configure script will try to build libffi with the GNU ++development tools. To build libffi with the SGI development tools, set ++the environment variable CC to either "cc -32" or "cc -n32" before ++running configure under Irix 6.x (depending on whether you want an o32 ++or n32 library), or just "cc" for Irix 5.3. ++ ++With the n32 calling convention, when returning structures smaller ++than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. ++Here's one way of forcing this: ++ ++ double struct_storage[2]; ++ my_small_struct *s = (my_small_struct *) struct_storage; ++ /* Use s for RVALUE */ ++ ++If you don't do this you are liable to get spurious bus errors. ++ ++"long long" values are not supported yet. ++ ++You must use GNU Make to build libffi on SGI platforms. ++ ++ ARM - System V ABI ++ ------------------ ++ ++The ARM port was performed on a NetWinder running ARM Linux ELF ++(2.0.31) and gcc 2.8.1. ++ ++ ++ ++ PowerPC System V ABI ++ -------------------- ++ ++There are two `System V ABI's which libffi implements for PowerPC. ++They differ only in how small structures are returned from functions. ++ ++In the FFI_SYSV version, structures that are 8 bytes or smaller are ++returned in registers. This is what GCC does when it is configured ++for solaris, and is what the System V ABI I have (dated September ++1995) says. ++ ++In the FFI_GCC_SYSV version, all structures are returned the same way: ++by passing a pointer as the first argument to the function. This is ++what GCC does when it is configured for linux or a generic sysv ++target. ++ ++EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a ++inconsistency with the SysV ABI: When a procedure is called with many ++floating-point arguments, some of them get put on the stack. They are ++all supposed to be stored in double-precision format, even if they are ++only single-precision, but EGCS stores single-precision arguments as ++single-precision anyway. This causes one test to fail (the `many ++arguments' test). ++ ++ ++What's With The Crazy Comments? ++=============================== ++ ++You might notice a number of cryptic comments in the code, delimited ++by /*@ and @*/. These are annotations read by the program LCLint, a ++tool for statically checking C programs. You can read all about it at ++. ++ ++ ++History ++======= ++ ++1.20 Oct-5-98 ++ Raffaele Sena produces ARM port. ++ ++1.19 Oct-5-98 ++ Fixed x86 long double and long long return support. ++ m68k bug fixes from Andreas Schwab. ++ Patch for DU assembler compatibility for the Alpha from Richard ++ Henderson. ++ ++1.18 Apr-17-98 ++ Bug fixes and MIPS configuration changes. ++ ++1.17 Feb-24-98 ++ Bug fixes and m68k port from Andreas Schwab. PowerPC port from ++ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. ++ ++1.16 Feb-11-98 ++ Richard Henderson produces Alpha port. ++ ++1.15 Dec-4-97 ++ Fixed an n32 ABI bug. New libtool, auto* support. ++ ++1.14 May-13-97 ++ libtool is now used to generate shared and static libraries. ++ Fixed a minor portability problem reported by Russ McManus ++ . ++ ++1.13 Dec-2-96 ++ Added --enable-purify-safety to keep Purify from complaining ++ about certain low level code. ++ Sparc fix for calling functions with < 6 args. ++ Linux x86 a.out fix. ++ ++1.12 Nov-22-96 ++ Added missing ffi_type_void, needed for supporting void return ++ types. Fixed test case for non MIPS machines. Cygnus Support ++ is now Cygnus Solutions. ++ ++1.11 Oct-30-96 ++ Added notes about GNU make. ++ ++1.10 Oct-29-96 ++ Added configuration fix for non GNU compilers. ++ ++1.09 Oct-29-96 ++ Added --enable-debug configure switch. Clean-ups based on LCLint ++ feedback. ffi_mips.h is always installed. Many configuration ++ fixes. Fixed ffitest.c for sparc builds. ++ ++1.08 Oct-15-96 ++ Fixed n32 problem. Many clean-ups. ++ ++1.07 Oct-14-96 ++ Gordon Irlam rewrites v8.S again. Bug fixes. ++ ++1.06 Oct-14-96 ++ Gordon Irlam improved the sparc port. ++ ++1.05 Oct-14-96 ++ Interface changes based on feedback. ++ ++1.04 Oct-11-96 ++ Sparc port complete (modulo struct passing bug). ++ ++1.03 Oct-10-96 ++ Passing struct args, and returning struct values works for ++ all architectures/calling conventions. Expanded tests. ++ ++1.02 Oct-9-96 ++ Added SGI n32 support. Fixed bugs in both o32 and Linux support. ++ Added "make test". ++ ++1.01 Oct-8-96 ++ Fixed float passing bug in mips version. Restructured some ++ of the code. Builds cleanly with SGI tools. ++ ++1.00 Oct-7-96 ++ First release. No public announcement. ++ ++ ++Authors & Credits ++================= ++ ++libffi was written by Anthony Green . ++ ++Portions of libffi were derived from Gianni Mariani's free gencall ++library for Silicon Graphics machines. ++ ++The closure mechanism was designed and implemented by Kresten Krab ++Thorup. ++ ++The Sparc port was derived from code contributed by the fine folks at ++Visible Decisions Inc . Further enhancements were ++made by Gordon Irlam at Cygnus Solutions . ++ ++The Alpha port was written by Richard Henderson at Cygnus Solutions. ++ ++Andreas Schwab ported libffi to m68k Linux and provided a number of ++bug fixes. ++ ++Geoffrey Keating ported libffi to the PowerPC. ++ ++Raffaele Sena ported libffi to the ARM. ++ ++Jesper Skov and Andrew Haley both did more than their fair share of ++stepping through the code and tracking down bugs. ++ ++Thanks also to Tom Tromey for bug fixes and configuration help. ++ ++Thanks to Jim Blandy, who provided some useful feedback on the libffi ++interface. ++ ++If you have a problem, or have found a bug, please send a note to ++green@cygnus.com. +diff --git ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc +new file mode 100644 +index 0000000..405d85f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README.pyobjc +@@ -0,0 +1,5 @@ ++This directory contains a slightly modified version of libffi, extracted from ++the GCC source-tree. ++ ++The only modifications are those that are necessary to compile libffi using ++the Apple provided compiler and outside of the GCC source tree. +diff --git ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c +new file mode 100644 +index 0000000..bf42093 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/ffi.c +@@ -0,0 +1,226 @@ ++/* ----------------------------------------------------------------------- ++ prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++/* Round up to FFI_SIZEOF_ARG. */ ++#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) ++ ++/* Perform machine independent initialization of aggregate type ++ specifications. */ ++ ++static ffi_status ++initialize_aggregate( ++/*@out@*/ ffi_type* arg) ++{ ++/*@-usedef@*/ ++ ++ if (arg == NULL || arg->elements == NULL || ++ arg->size != 0 || arg->alignment != 0) ++ return FFI_BAD_TYPEDEF; ++ ++ ffi_type** ptr = &(arg->elements[0]); ++ ++ while ((*ptr) != NULL) ++ { ++ if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#ifdef POWERPC_DARWIN ++ int curalign = (*ptr)->alignment; ++ ++ if (ptr != &(arg->elements[0])) ++ { ++ if (curalign > 4 && curalign != 16) ++ curalign = 4; ++ } ++ ++ arg->size = ALIGN(arg->size, curalign); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > curalign) ? ++ arg->alignment : curalign; ++#else ++ arg->size = ALIGN(arg->size, (*ptr)->alignment); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > (*ptr)->alignment) ? ++ arg->alignment : (*ptr)->alignment; ++#endif ++ ++ ptr++; ++ } ++ ++ /* Structure size includes tail padding. This is important for ++ structures that fit in one register on ABIs like the PowerPC64 ++ Linux ABI that right justify small structs in a register. ++ It's also needed for nested structure layout, for example ++ struct A { long a; char b; }; struct B { struct A x; char y; }; ++ should find y at an offset of 2*sizeof(long) and result in a ++ total size of 3*sizeof(long). */ ++ arg->size = ALIGN(arg->size, arg->alignment); ++ ++ if (arg->size == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ return FFI_OK; ++ ++/*@=usedef@*/ ++} ++ ++#ifndef __CRIS__ ++/* The CRIS ABI specifies structure elements to have byte ++ alignment only, so it completely overrides this functions, ++ which assumes "natural" alignment and padding. */ ++ ++/* Perform machine independent ffi_cif preparation, then call ++ machine dependent routine. */ ++ ++#if defined(X86_DARWIN) ++ ++static inline bool ++struct_on_stack( ++ int size) ++{ ++ if (size > 8) ++ return true; ++ ++ /* This is not what the ABI says, but is what is really implemented */ ++ switch (size) ++ { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ return false; ++ ++ default: ++ return true; ++ } ++} ++ ++#endif // defined(X86_DARWIN) ++ ++// Arguments' ffi_type->alignment must be nonzero. ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes) ++{ ++ if (cif == NULL) ++ return FFI_BAD_TYPEDEF; ++ ++ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI) ++ return FFI_BAD_ABI; ++ ++ unsigned int bytes = 0; ++ unsigned int i; ++ ffi_type** ptr; ++ ++ cif->abi = abi; ++ cif->arg_types = atypes; ++ cif->nargs = nargs; ++ cif->rtype = rtype; ++ cif->flags = 0; ++ ++ /* Initialize the return type if necessary */ ++ /*@-usedef@*/ ++ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ /*@=usedef@*/ ++ ++ /* Perform a sanity check on the return type */ ++ FFI_ASSERT_VALID_TYPE(cif->rtype); ++ ++ /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ ++#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA ++ /* Make space for the return structure pointer */ ++ if (cif->rtype->type == FFI_TYPE_STRUCT ++#ifdef SPARC ++ && (cif->abi != FFI_V9 || cif->rtype->size > 32) ++#endif ++#ifdef X86_DARWIN ++ && (struct_on_stack(cif->rtype->size)) ++#endif ++ ) ++ bytes = STACK_ARG_SIZE(sizeof(void*)); ++#endif ++ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ /* Initialize any uninitialized aggregate type definitions */ ++ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ if ((*ptr)->alignment == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type, do this ++ check after the initialization. */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#if defined(X86_DARWIN) ++ { ++ int align = (*ptr)->alignment; ++ ++ if (align > 4) ++ align = 4; ++ ++ if ((align - 1) & bytes) ++ bytes = ALIGN(bytes, align); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#elif !defined __x86_64__ && !defined S390 && !defined PA ++#ifdef SPARC ++ if (((*ptr)->type == FFI_TYPE_STRUCT ++ && ((*ptr)->size > 16 || cif->abi != FFI_V9)) ++ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE ++ && cif->abi != FFI_V9)) ++ bytes += sizeof(void*); ++ else ++#endif ++ { ++ /* Add any padding if necessary */ ++ if (((*ptr)->alignment - 1) & bytes) ++ bytes = ALIGN(bytes, (*ptr)->alignment); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#endif ++ } ++ ++ cif->bytes = bytes; ++ ++ /* Perform machine dependent cif processing */ ++ return ffi_prep_cif_machdep(cif); ++} ++#endif /* not __CRIS__ */ +diff --git ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h +new file mode 100644 +index 0000000..c104a5c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi.h +@@ -0,0 +1,355 @@ ++/* -----------------------------------------------------------------*-C-*- ++ libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++/* ------------------------------------------------------------------- ++ The basic API is described in the README file. ++ ++ The raw API is designed to bypass some of the argument packing ++ and unpacking on architectures for which it can be avoided. ++ ++ The closure API allows interpreted functions to be packaged up ++ inside a C function pointer, so that they can be called as C functions, ++ with no understanding on the client side that they are interpreted. ++ It can also be used in other cases in which it is necessary to package ++ up a user specified parameter and a function pointer as a single ++ function pointer. ++ ++ The closure API must be implemented in order to get its functionality, ++ e.g. for use by gij. Routines are provided to emulate the raw API ++ if the underlying platform doesn't allow faster implementation. ++ ++ More details on the raw and closure API can be found in: ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html ++ ++ and ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html ++ -------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_H ++#define LIBFFI_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Specify which architecture libffi is configured for. */ ++#ifdef MACOSX ++# if defined(__i386__) || defined(__x86_64__) ++# define X86_DARWIN ++# elif defined(__ppc__) || defined(__ppc64__) ++# define POWERPC_DARWIN ++# else ++# error "Unsupported MacOS X CPU type" ++# endif ++#else ++#error "Unsupported OS type" ++#endif ++ ++/* ---- System configuration information --------------------------------- */ ++ ++#include "ffitarget.h" ++#include "fficonfig.h" ++ ++#ifndef LIBFFI_ASM ++ ++#include ++#include ++ ++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). ++ But we can find it either under the correct ANSI name, or under GNU ++ C's internal name. */ ++#ifdef LONG_LONG_MAX ++# define FFI_LONG_LONG_MAX LONG_LONG_MAX ++#else ++# ifdef LLONG_MAX ++# define FFI_LONG_LONG_MAX LLONG_MAX ++# else ++# ifdef __GNUC__ ++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ ++# endif ++# endif ++#endif ++ ++#if SCHAR_MAX == 127 ++# define ffi_type_uchar ffi_type_uint8 ++# define ffi_type_schar ffi_type_sint8 ++#else ++#error "char size not supported" ++#endif ++ ++#if SHRT_MAX == 32767 ++# define ffi_type_ushort ffi_type_uint16 ++# define ffi_type_sshort ffi_type_sint16 ++#elif SHRT_MAX == 2147483647 ++# define ffi_type_ushort ffi_type_uint32 ++# define ffi_type_sshort ffi_type_sint32 ++#else ++#error "short size not supported" ++#endif ++ ++#if INT_MAX == 32767 ++# define ffi_type_uint ffi_type_uint16 ++# define ffi_type_sint ffi_type_sint16 ++#elif INT_MAX == 2147483647 ++# define ffi_type_uint ffi_type_uint32 ++# define ffi_type_sint ffi_type_sint32 ++#elif INT_MAX == 9223372036854775807 ++# define ffi_type_uint ffi_type_uint64 ++# define ffi_type_sint ffi_type_sint64 ++#else ++#error "int size not supported" ++#endif ++ ++#define ffi_type_ulong ffi_type_uint64 ++#define ffi_type_slong ffi_type_sint64 ++ ++#if LONG_MAX == 2147483647 ++# if FFI_LONG_LONG_MAX != 9223372036854775807 ++# error "no 64-bit data type supported" ++# endif ++#elif LONG_MAX != 9223372036854775807 ++#error "long size not supported" ++#endif ++ ++/* The closure code assumes that this works on pointers, i.e. a size_t ++ can hold a pointer. */ ++ ++typedef struct _ffi_type { ++ size_t size; ++ unsigned short alignment; ++ unsigned short type; ++/*@null@*/ struct _ffi_type** elements; ++} ffi_type; ++ ++/* These are defined in types.c */ ++extern ffi_type ffi_type_void; ++extern ffi_type ffi_type_uint8; ++extern ffi_type ffi_type_sint8; ++extern ffi_type ffi_type_uint16; ++extern ffi_type ffi_type_sint16; ++extern ffi_type ffi_type_uint32; ++extern ffi_type ffi_type_sint32; ++extern ffi_type ffi_type_uint64; ++extern ffi_type ffi_type_sint64; ++extern ffi_type ffi_type_float; ++extern ffi_type ffi_type_double; ++extern ffi_type ffi_type_longdouble; ++extern ffi_type ffi_type_pointer; ++ ++typedef enum ffi_status { ++ FFI_OK = 0, ++ FFI_BAD_TYPEDEF, ++ FFI_BAD_ABI ++} ffi_status; ++ ++typedef unsigned FFI_TYPE; ++ ++typedef struct ffi_cif { ++ ffi_abi abi; ++ unsigned nargs; ++/*@dependent@*/ ffi_type** arg_types; ++/*@dependent@*/ ffi_type* rtype; ++ unsigned bytes; ++ unsigned flags; ++#ifdef FFI_EXTRA_CIF_FIELDS ++ FFI_EXTRA_CIF_FIELDS; ++#endif ++} ffi_cif; ++ ++/* ---- Definitions for the raw API -------------------------------------- */ ++ ++#ifndef FFI_SIZEOF_ARG ++# if LONG_MAX == 2147483647 ++# define FFI_SIZEOF_ARG 4 ++# elif LONG_MAX == 9223372036854775807 ++# define FFI_SIZEOF_ARG 8 ++# endif ++#endif ++ ++typedef union { ++ ffi_sarg sint; ++ ffi_arg uint; ++ float flt; ++ char data[FFI_SIZEOF_ARG]; ++ void* ptr; ++} ffi_raw; ++ ++void ++ffi_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_raw_size( ++ ffi_cif* cif); ++ ++/* This is analogous to the raw API, except it uses Java parameter ++ packing, even on 64-bit machines. I.e. on 64-bit machines ++ longs and doubles are followed by an empty 64-bit word. */ ++void ++ffi_java_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_java_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_java_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_java_raw_size( ++ ffi_cif* cif); ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#if FFI_CLOSURES ++ ++typedef struct ffi_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ void (*fun)(ffi_cif*,void*,void**,void*); ++ void* user_data; ++} ffi_closure; ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void* user_data); ++ ++void ffi_closure_free(void *); ++void *ffi_closure_alloc (size_t size, void **code); ++ ++typedef struct ffi_raw_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ ++#if !FFI_NATIVE_RAW_API ++ /* if this is enabled, then a raw closure has the same layout ++ as a regular closure. We use this to install an intermediate ++ handler to do the transaltion, void** -> ffi_raw*. */ ++ void (*translate_args)(ffi_cif*,void*,void**,void*); ++ void* this_closure; ++#endif ++ ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*); ++ void* user_data; ++} ffi_raw_closure; ++ ++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_status ++ffi_prep_java_raw_closure( ++ ffi_raw_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*), ++ void* user_data); ++ ++#endif // FFI_CLOSURES ++ ++/* ---- Public interface definition -------------------------------------- */ ++ ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes); ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ void** avalue); ++ ++/* Useful for eliminating compiler warnings */ ++#define FFI_FN(f) ((void (*)(void))f) ++ ++#endif // #ifndef LIBFFI_ASM ++/* ---- Definitions shared with assembly code ---------------------------- */ ++ ++/* If these change, update src/mips/ffitarget.h. */ ++#define FFI_TYPE_VOID 0 ++#define FFI_TYPE_INT 1 ++#define FFI_TYPE_FLOAT 2 ++#define FFI_TYPE_DOUBLE 3 ++ ++#ifdef HAVE_LONG_DOUBLE ++# define FFI_TYPE_LONGDOUBLE 4 ++#else ++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE ++#endif ++ ++#define FFI_TYPE_UINT8 5 ++#define FFI_TYPE_SINT8 6 ++#define FFI_TYPE_UINT16 7 ++#define FFI_TYPE_SINT16 8 ++#define FFI_TYPE_UINT32 9 ++#define FFI_TYPE_SINT32 10 ++#define FFI_TYPE_UINT64 11 ++#define FFI_TYPE_SINT64 12 ++#define FFI_TYPE_STRUCT 13 ++#define FFI_TYPE_POINTER 14 ++ ++/* This should always refer to the last type code (for sanity checks) */ ++#define FFI_TYPE_LAST FFI_TYPE_POINTER ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef LIBFFI_H +diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h +new file mode 100644 +index 0000000..685a358 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi_common.h +@@ -0,0 +1,102 @@ ++/* ----------------------------------------------------------------------- ++ ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ++ ++ Common internal definitions and macros. Only necessary for building ++ libffi. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef FFI_COMMON_H ++#define FFI_COMMON_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fficonfig.h" ++ ++/* Do not move this. Some versions of AIX are very picky about where ++ this is positioned. */ ++#ifdef __GNUC__ ++# define alloca __builtin_alloca ++#else ++# if HAVE_ALLOCA_H ++# include ++# else ++# ifdef _AIX ++# pragma alloca ++# else ++# ifndef alloca /* predefined by HP cc +Olibcalls */ ++char* alloca(); ++# endif ++# endif ++# endif ++#endif ++ ++/* Check for the existence of memcpy. */ ++#if STDC_HEADERS ++# include ++#else ++# ifndef HAVE_MEMCPY ++# define memcpy(d, s, n) bcopy((s), (d), (n)) ++# endif ++#endif ++ ++/*#if defined(FFI_DEBUG) ++#include ++#endif*/ ++ ++#ifdef FFI_DEBUG ++#include ++ ++/*@exits@*/ void ++ffi_assert( ++/*@temp@*/ char* expr, ++/*@temp@*/ char* file, ++ int line); ++void ++ffi_stop_here(void); ++void ++ffi_type_test( ++/*@temp@*/ /*@out@*/ ffi_type* a, ++/*@temp@*/ char* file, ++ int line); ++ ++# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) ++# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) ++# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__) ++#else ++# define FFI_ASSERT(x) ++# define FFI_ASSERT_AT(x, f, l) ++# define FFI_ASSERT_VALID_TYPE(x) ++#endif // #ifdef FFI_DEBUG ++ ++#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) ++ ++/* Perform machine dependent cif processing */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif); ++ ++/* Extended cif, used in callback from assembly routine */ ++typedef struct extended_cif { ++/*@dependent@*/ ffi_cif* cif; ++/*@dependent@*/ void* rvalue; ++/*@dependent@*/ void** avalue; ++} extended_cif; ++ ++/* Terse sized type definitions. */ ++typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); ++typedef signed int SINT8 __attribute__((__mode__(__QI__))); ++typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); ++typedef signed int SINT16 __attribute__((__mode__(__HI__))); ++typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); ++typedef signed int SINT32 __attribute__((__mode__(__SI__))); ++typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); ++typedef signed int SINT64 __attribute__((__mode__(__DI__))); ++typedef float FLOAT32; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef FFI_COMMON_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h +new file mode 100644 +index 0000000..2172490 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/fficonfig.h +@@ -0,0 +1,150 @@ ++/* Manually created fficonfig.h for Darwin on PowerPC or Intel ++ ++ This file is manually generated to do away with the need for autoconf and ++ therefore make it easier to cross-compile and build fat binaries. ++ ++ NOTE: This file was added by PyObjC. ++*/ ++ ++#ifndef MACOSX ++#error "This file is only supported on Mac OS X" ++#endif ++ ++#if defined(__i386__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__x86_64__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__ppc__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# if __GNUC__ >= 4 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++# else ++# undef HAVE_LONG_DOUBLE ++# define SIZEOF_LONG_DOUBLE 8 ++# endif ++ ++#elif defined(__ppc64__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#else ++#error "Unknown CPU type" ++#endif ++ ++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP ++ systems. This function is required for `alloca.c' support on those systems. */ ++#undef CRAY_STACKSEG_END ++ ++/* Define to 1 if using `alloca.c'. */ ++/* #undef C_ALLOCA */ ++ ++/* Define to the flags needed for the .section .eh_frame directive. */ ++#define EH_FRAME_FLAGS "aw" ++ ++/* Define this if you want extra debugging. */ ++/* #undef FFI_DEBUG */ ++ ++/* Define this is you do not want support for the raw API. */ ++#define FFI_NO_RAW_API 1 ++ ++/* Define this if you do not want support for aggregate types. */ ++/* #undef FFI_NO_STRUCTS */ ++ ++/* Define to 1 if you have `alloca', as a function or macro. */ ++#define HAVE_ALLOCA 1 ++ ++/* Define to 1 if you have and it should be used (not on Ultrix). */ ++#define HAVE_ALLOCA_H 1 ++ ++/* Define if your assembler supports .register. */ ++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ ++ ++/* Define if your assembler and linker support unaligned PC relative relocs. */ ++/* #undef HAVE_AS_SPARC_UA_PCREL */ ++ ++/* Define to 1 if you have the `memcpy' function. */ ++#define HAVE_MEMCPY 1 ++ ++/* Define if mmap with MAP_ANON(YMOUS) works. */ ++#define HAVE_MMAP_ANON 1 ++ ++/* Define if mmap of /dev/zero works. */ ++/* #undef HAVE_MMAP_DEV_ZERO */ ++ ++/* Define if read-only mmap of a plain file works. */ ++#define HAVE_MMAP_FILE 1 ++ ++/* Define if .eh_frame sections should be read-only. */ ++/* #undef HAVE_RO_EH_FRAME */ ++ ++/* Define to 1 if your C compiler doesn't accept -c and -o together. */ ++/* #undef NO_MINUS_C_MINUS_O */ ++ ++/* Name of package */ ++#define PACKAGE "libffi" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "libffi" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "libffi 2.1" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libffi" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "2.1" ++ ++/* If using the C implementation of alloca, define if you know the ++ direction of stack growth for your system; otherwise it will be ++ automatically deduced at run-time. ++ STACK_DIRECTION > 0 => grows toward higher addresses ++ STACK_DIRECTION < 0 => grows toward lower addresses ++ STACK_DIRECTION = 0 => direction of growth unknown */ ++/* #undef STACK_DIRECTION */ ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this if you are using Purify and want to suppress spurious messages. */ ++/* #undef USING_PURIFY */ ++ ++/* Version number of package */ ++#define VERSION "2.1-pyobjc" ++ ++#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) .hidden name ++# else ++# define FFI_HIDDEN __attribute__((visibility ("hidden"))) ++# endif ++#else ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) ++# else ++# define FFI_HIDDEN ++# endif ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h +new file mode 100644 +index 0000000..faaa30d +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffitarget.h +@@ -0,0 +1,13 @@ ++/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a ++ normal build, the build environment copies the file to the right location or ++ sets up the right include flags. We want to do neither because that would ++ make building fat binaries harder. ++*/ ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "x86-ffitarget.h" ++#elif defined(__ppc__) || defined(__ppc64__) ++#include "ppc-ffitarget.h" ++#else ++#error "Unsupported CPU type" ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +new file mode 100644 +index 0000000..2318421 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +@@ -0,0 +1,104 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for PowerPC. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if (defined(POWERPC) && defined(__powerpc64__)) || \ ++ (defined(POWERPC_DARWIN) && defined(__ppc64__)) ++#define POWERPC64 ++#endif ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++#ifdef POWERPC ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++# ifdef POWERPC64 ++ FFI_DEFAULT_ABI = FFI_LINUX64, ++# else ++ FFI_DEFAULT_ABI = FFI_GCC_SYSV, ++# endif ++#endif ++ ++#ifdef POWERPC_AIX ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_AIX, ++#endif ++ ++#ifdef POWERPC_DARWIN ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_DARWIN, ++#endif ++ ++#ifdef POWERPC_FREEBSD ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++#define FFI_NATIVE_RAW_API 0 ++ ++/* Needed for FFI_SYSV small structure returns. */ ++#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) ++ ++#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/ ++# define FFI_TRAMPOLINE_SIZE 48 ++#elif defined(POWERPC_AIX) ++# define FFI_TRAMPOLINE_SIZE 24 ++#else ++# define FFI_TRAMPOLINE_SIZE 40 ++#endif ++ ++#ifndef LIBFFI_ASM ++# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) ++typedef struct ffi_aix_trampoline_struct { ++ void* code_pointer; /* Pointer to ffi_closure_ASM */ ++ void* toc; /* TOC */ ++ void* static_chain; /* Pointer to closure */ ++} ffi_aix_trampoline_struct; ++# endif ++#endif // #ifndef LIBFFI_ASM ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +new file mode 100644 +index 0000000..55c2b6c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +@@ -0,0 +1,88 @@ ++/* -----------------------------------------------------------------*-C-*- ++ x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for x86 and x86-64. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if defined(X86_64) && defined(__i386__) ++# undef X86_64 ++# define X86 ++#endif ++ ++#if defined(__x86_64__) ++# ifndef X86_64 ++# define X86_64 ++# endif ++#endif ++ ++/* ---- Generic type definitions ----------------------------------------- */ ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++ /* ---- Intel x86 Win32 ---------- */ ++#ifdef X86_WIN32 ++ FFI_SYSV, ++ FFI_STDCALL, ++ /* TODO: Add fastcall support for the sake of completeness */ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ /* ---- Intel x86 and AMD x86-64 - */ ++#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) ++ FFI_SYSV, ++ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ ++# ifdef __i386__ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++# else ++ FFI_DEFAULT_ABI = FFI_UNIX64, ++# endif ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++ ++#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN)) ++# define FFI_TRAMPOLINE_SIZE 24 ++# define FFI_NATIVE_RAW_API 0 ++#else ++# define FFI_TRAMPOLINE_SIZE 10 ++# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ ++#endif ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +new file mode 100644 +index 0000000..f143dbd +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +@@ -0,0 +1,365 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist ++ Copyright (c) 2004 Free Software Foundation, Inc. ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include ++#include ++#include ++ ++.text ++ .align 2 ++.globl _ffi_prep_args ++ ++.text ++ .align 2 ++.globl _ffi_call_DARWIN ++ ++.text ++ .align 2 ++_ffi_call_DARWIN: ++LFB0: ++ mr r12,r8 /* We only need r12 until the call, ++ so it doesn't have to be saved. */ ++ ++LFB1: ++ /* Save the old stack pointer as AP. */ ++ mr r8,r1 ++ ++LCFI0: ++#if defined(__ppc64__) ++ /* Allocate the stack space we need. ++ r4 (size of input data) ++ 48 bytes (linkage area) ++ 40 bytes (saved registers) ++ 8 bytes (extra FPR) ++ r4 + 96 bytes total ++ */ ++ ++ addi r4,r4,-96 // Add our overhead. ++ li r0,-32 // Align to 32 bytes. ++ and r4,r4,r0 ++#endif ++ stgux r1,r1,r4 // Grow the stack. ++ mflr r9 ++ ++ /* Save registers we use. */ ++#if defined(__ppc64__) ++ std r27,-40(r8) ++#endif ++ stg r28,MODE_CHOICE(-16,-32)(r8) ++ stg r29,MODE_CHOICE(-12,-24)(r8) ++ stg r30,MODE_CHOICE(-8,-16)(r8) ++ stg r31,MODE_CHOICE(-4,-8)(r8) ++ stg r9,SF_RETURN(r8) /* return address */ ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ stg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++LCFI1: ++#if defined(__ppc64__) ++ mr r27,r3 // our extended_cif ++#endif ++ /* Save arguments over call. */ ++ mr r31,r5 /* flags, */ ++ mr r30,r6 /* rvalue, */ ++ mr r29,r7 /* function address, */ ++ mr r28,r8 /* our AP. */ ++ ++LCFI2: ++ /* Call ffi_prep_args. */ ++ mr r4,r1 ++ li r9,0 ++ mtctr r12 /* r12 holds address of _ffi_prep_args. */ ++ bctrl ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ lg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++ /* Now do the call. ++ Set up cr1 with bits 4-7 of the flags. */ ++ mtcrf 0x40,r31 ++ ++ /* Load all those argument registers. ++ We have set up a nice stack frame, just load it into registers. */ ++ lg r3,SF_ARG1(r1) ++ lg r4,SF_ARG2(r1) ++ lg r5,SF_ARG3(r1) ++ lg r6,SF_ARG4(r1) ++ nop ++ lg r7,SF_ARG5(r1) ++ lg r8,SF_ARG6(r1) ++ lg r9,SF_ARG7(r1) ++ lg r10,SF_ARG8(r1) ++ ++ /* Load all the FP registers. */ ++ bf 6,L2 /* No floats to load. */ ++#if defined(__ppc64__) ++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#elif defined(__ppc__) ++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#else ++#error undefined architecture ++#endif ++ ++L2: ++ mr r12,r29 // Put the target address in r12 as specified. ++ mtctr r12 // Get the address to call into CTR. ++ nop ++ nop ++ bctrl // Make the call. ++ ++ // Deal with the return value. ++#if defined(__ppc64__) ++ mtcrf 0x3,r31 // flags in cr6 and cr7 ++ bt 27,L(st_return_value) ++#elif defined(__ppc__) ++ mtcrf 0x1,r31 // flags in cr7 ++#else ++#error undefined architecture ++#endif ++ ++ bt 30,L(done_return_value) ++ bt 29,L(fp_return_value) ++ stg r3,0(r30) ++#if defined(__ppc__) ++ bf 28,L(done_return_value) // Store the second long if necessary. ++ stg r4,4(r30) ++#endif ++ // Fall through ++ ++L(done_return_value): ++ lg r1,0(r1) // Restore stack pointer. ++ // Restore the registers we used. ++ lg r9,SF_RETURN(r1) // return address ++ lg r31,MODE_CHOICE(-4,-8)(r1) ++ mtlr r9 ++ lg r30,MODE_CHOICE(-8,-16)(r1) ++ lg r29,MODE_CHOICE(-12,-24)(r1) ++ lg r28,MODE_CHOICE(-16,-32)(r1) ++#if defined(__ppc64__) ++ ld r27,-40(r1) ++#endif ++ blr ++ ++#if defined(__ppc64__) ++L(st_return_value): ++ // Grow the stack enough to fit the registers. Leave room for 8 args ++ // to trample the 1st 8 slots in param area. ++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 ++ ++ // Store GPRs ++ std r3,SF_ARG9(r1) ++ std r4,SF_ARG10(r1) ++ std r5,SF_ARG11(r1) ++ std r6,SF_ARG12(r1) ++ nop ++ std r7,SF_ARG13(r1) ++ std r8,SF_ARG14(r1) ++ std r9,SF_ARG15(r1) ++ std r10,SF_ARG16(r1) ++ ++ // Store FPRs ++ nop ++ bf 26,L(call_struct_to_ram_form) ++ stfd f1,SF_ARG17(r1) ++ stfd f2,SF_ARG18(r1) ++ stfd f3,SF_ARG19(r1) ++ stfd f4,SF_ARG20(r1) ++ nop ++ stfd f5,SF_ARG21(r1) ++ stfd f6,SF_ARG22(r1) ++ stfd f7,SF_ARG23(r1) ++ stfd f8,SF_ARG24(r1) ++ nop ++ stfd f9,SF_ARG25(r1) ++ stfd f10,SF_ARG26(r1) ++ stfd f11,SF_ARG27(r1) ++ stfd f12,SF_ARG28(r1) ++ nop ++ stfd f13,SF_ARG29(r1) ++ ++L(call_struct_to_ram_form): ++ ld r3,0(r27) // extended_cif->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ addi r4,r1,SF_ARG9 // stored GPRs ++ addi r6,r1,SF_ARG17 // stored FPRs ++ li r5,0 // GPR size ptr (NULL) ++ li r7,0 // FPR size ptr (NULL) ++ li r8,0 // FPR count ptr (NULL) ++ li r10,0 // struct offset (NULL) ++ mr r9,r30 // return area ++ bl Lffi64_struct_to_ram_form$stub ++ lg r1,0(r1) // Restore stack pointer. ++ b L(done_return_value) ++#endif ++ ++L(fp_return_value): ++ /* Do we have long double to store? */ ++ bf 31,L(fd_return_value) ++ stfd f1,0(r30) ++ stfd f2,8(r30) ++ b L(done_return_value) ++ ++L(fd_return_value): ++ /* Do we have double to store? */ ++ bf 28,L(float_return_value) ++ stfd f1,0(r30) ++ b L(done_return_value) ++ ++L(float_return_value): ++ /* We only have a float to store. */ ++ stfs f1,0(r30) ++ b L(done_return_value) ++ ++LFE1: ++/* END(_ffi_call_DARWIN) */ ++ ++/* Provide a null definition of _ffi_call_AIX. */ ++.text ++ .align 2 ++.globl _ffi_call_AIX ++.text ++ .align 2 ++_ffi_call_AIX: ++ blr ++/* END(_ffi_call_AIX) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_call_DARWIN.eh ++_ffi_call_DARWIN.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x08 ; uleb128 0x08 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$5,LCFI1-LCFI0 ++ .long L$set$5 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .byte 0x9f ; DW_CFA_offset, column 0x1f ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x9e ; DW_CFA_offset, column 0x1e ++ .byte 0x2 ; uleb128 0x2 ++ .byte 0x9d ; DW_CFA_offset, column 0x1d ++ .byte 0x3 ; uleb128 0x3 ++ .byte 0x9c ; DW_CFA_offset, column 0x1c ++ .byte 0x4 ; uleb128 0x4 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$6,LCFI2-LCFI1 ++ .long L$set$6 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x1c ; uleb128 0x1c ++ .align LOG2_GPR_BYTES ++LEFDE1: ++ ++#if defined(__ppc64__) ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_ram_form$stub: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_ram_form ++ ++LO$ffi64_struct_to_ram_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_ram_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ ++#endif // __ppc__ || __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +new file mode 100644 +index 0000000..cf4bd50 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +@@ -0,0 +1,85 @@ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define L(x) x ++ ++#define SF_ARG9 MODE_CHOICE(56,112) ++#define SF_ARG10 MODE_CHOICE(60,120) ++#define SF_ARG11 MODE_CHOICE(64,128) ++#define SF_ARG12 MODE_CHOICE(68,136) ++#define SF_ARG13 MODE_CHOICE(72,144) ++#define SF_ARG14 MODE_CHOICE(76,152) ++#define SF_ARG15 MODE_CHOICE(80,160) ++#define SF_ARG16 MODE_CHOICE(84,168) ++#define SF_ARG17 MODE_CHOICE(88,176) ++#define SF_ARG18 MODE_CHOICE(92,184) ++#define SF_ARG19 MODE_CHOICE(96,192) ++#define SF_ARG20 MODE_CHOICE(100,200) ++#define SF_ARG21 MODE_CHOICE(104,208) ++#define SF_ARG22 MODE_CHOICE(108,216) ++#define SF_ARG23 MODE_CHOICE(112,224) ++#define SF_ARG24 MODE_CHOICE(116,232) ++#define SF_ARG25 MODE_CHOICE(120,240) ++#define SF_ARG26 MODE_CHOICE(124,248) ++#define SF_ARG27 MODE_CHOICE(128,256) ++#define SF_ARG28 MODE_CHOICE(132,264) ++#define SF_ARG29 MODE_CHOICE(136,272) ++ ++#define ASM_NEEDS_REGISTERS 4 ++#define NUM_GPR_ARG_REGISTERS 8 ++#define NUM_FPR_ARG_REGISTERS 13 ++ ++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8) ++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16) ++#define FFI_TYPE_4_BYTE(x) \ ++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\ ++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT) ++ ++#if !defined(LIBFFI_ASM) ++ ++enum { ++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7 ++ FLAG_RETURNS_FP = 1 << (31 - 29), ++ FLAG_RETURNS_64BITS = 1 << (31 - 28), ++ FLAG_RETURNS_128BITS = 1 << (31 - 31), ++ ++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6 ++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26), ++ ++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7), ++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI ++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5), ++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4) ++}; ++ ++#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*); ++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*); ++#endif ++ ++#endif // !defined(LIBFFI_ASM) +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +new file mode 100644 +index 0000000..c3d30c2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +@@ -0,0 +1,308 @@ ++#if defined(__ppc__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 // Save return address ++ stg r0,SF_RETURN(r1) ++ ++LCFI0: ++ /* 24/48 bytes (Linkage Area) ++ 32/64 bytes (outgoing parameter area, always reserved) ++ 104 bytes (13*8 from FPR) ++ 16/32 bytes (result) ++ 176/232 total bytes */ ++ ++ /* skip over caller save area and keep stack aligned to 16/32. */ ++ stgu r1,-SF_ROUND(176)(r1) ++ ++LCFI1: ++ /* We want to build up an area for the parameters passed ++ in registers. (both floating point and integer) */ ++ ++ /* 176/256 bytes (callee stack frame aligned to 16/32) ++ 24/48 bytes (caller linkage area) ++ 200/304 (start of caller parameter area aligned to 4/8) ++ */ ++ ++ /* Save GPRs 3 - 10 (aligned to 4/8) ++ in the parents outgoing area. */ ++ 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,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. ++ 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. Use it to look up in a table ++ so we know how to deal with each type. */ ++ 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 ++ ++LFE1: ++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ (4 instructions). For cache effectiveness we align to a 16 byte boundary ++ first. */ ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++/* case FFI_TYPE_VOID */ ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* case FFI_TYPE_INT */ ++Lret_type1: ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_FLOAT */ ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_DOUBLE */ ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_LONGDOUBLE */ ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT8 */ ++Lret_type5: ++ lbz r3,3(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT8 */ ++Lret_type6: ++ lbz r3,3(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT16 */ ++Lret_type7: ++ lhz r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT16 */ ++Lret_type8: ++ lha r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT32 */ ++Lret_type9: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT32 */ ++Lret_type10: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT64 */ ++Lret_type11: ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_SINT64 */ ++Lret_type12: // same as Lret_type11 ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_STRUCT */ ++Lret_type13: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* End 16-byte aligned cases */ ++/* case FFI_TYPE_POINTER */ ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ // fall through ++ ++/* case done */ ++Lfinish: ++ 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) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++ ++#endif // __ppc__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +new file mode 100644 +index 0000000..8953d5f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +@@ -0,0 +1,1776 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1998 Geoffrey Keating ++ ++ PowerPC Foreign Function Interface ++ ++ Darwin ABI support (c) 2001 John Hornkvist ++ AIX ABI support (c) 2002 Free Software Foundation, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#if defined(POWERPC_DARWIN) ++#include // for sys_icache_invalidate() ++#endif ++ ++#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 ++// points to one of these. ++typedef struct aix_fd_struct { ++ void* code_pointer; ++ void* toc; ++} aix_fd; ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments. ++ ++ The stack layout we want looks like this: ++ ++ | Return address from ffi_call_DARWIN | higher addresses ++ |--------------------------------------------| ++ | Previous backchain pointer 4/8 | stack pointer here ++ |--------------------------------------------|-\ <<< on entry to ++ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN ++ |--------------------------------------------| | ++ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 ++ |--------------------------------------------| | ++ | Space for GPR2 4/8 | | ++ |--------------------------------------------| | stack | ++ | Reserved (4/8)*2 | | grows | ++ |--------------------------------------------| | down V ++ | Space for callee's LR 4/8 | | ++ |--------------------------------------------| | lower addresses ++ | Saved CR 4/8 | | ++ |--------------------------------------------| | stack pointer here ++ | Current backchain pointer 4/8 | | during ++ |--------------------------------------------|-/ <<< ffi_call_DARWIN ++ ++ Note: ppc64 CR is saved in the low word of a long on the stack. ++*/ ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args( ++ extended_cif* inEcif, ++ unsigned *const stack) ++/*@=exportheader@*/ ++{ ++ /* Copy the ecif to a local var so we can trample the arg. ++ BC note: test this with GP later for possible problems... */ ++ volatile extended_cif* ecif = inEcif; ++ ++ const unsigned bytes = ecif->cif->bytes; ++ const unsigned flags = ecif->cif->flags; ++ ++ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode ++ and 8 in 64-bit mode. */ ++ unsigned long *const longStack = (unsigned long *const)stack; ++ ++ /* 'stacktop' points at the previous backchain pointer. */ ++#if defined(__ppc64__) ++ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, ++ // saved registers, and an extra FPR. ++ unsigned long *const stacktop = ++ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); ++#elif defined(__ppc__) ++ unsigned long *const stacktop = longStack + (bytes / sizeof(long)); ++#else ++#error undefined architecture ++#endif ++ ++ /* 'fpr_base' points at the space for fpr1, and grows upwards as ++ we use FPR registers. */ ++ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - ++ NUM_FPR_ARG_REGISTERS; ++ ++#if defined(__ppc64__) ++ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base ++ // down a couple pegs. ++ fpr_base -= 2; ++#endif ++ ++ unsigned int fparg_count = 0; ++ ++ /* 'next_arg' grows up as we put parameters in it. */ ++ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ ++ ++ int i; ++ double double_tmp; ++ void** p_argv = ecif->avalue; ++ unsigned long gprvalue; ++ ffi_type** ptr = ecif->cif->arg_types; ++ ++ /* Check that everything starts aligned properly. */ ++ FFI_ASSERT(stack == SF_ROUND(stack)); ++ FFI_ASSERT(stacktop == SF_ROUND(stacktop)); ++ FFI_ASSERT(bytes == SF_ROUND(bytes)); ++ ++ /* Deal with return values that are actually pass-by-reference. ++ Rule: ++ Return values are referenced by r3, so r4 is the first parameter. */ ++ ++ if (flags & FLAG_RETVAL_REFERENCE) ++ *next_arg++ = (unsigned long)(char*)ecif->rvalue; ++ ++ /* Now for the arguments. */ ++ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) ++ { ++ switch ((*ptr)->type) ++ { ++ /* If a floating-point parameter appears before all of the general- ++ purpose registers are filled, the corresponding GPRs that match ++ the size of the floating-point parameter are shadowed for the ++ benefit of vararg and pre-ANSI functions. */ ++ case FFI_TYPE_FLOAT: ++ double_tmp = *(float*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg++; ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ double_tmp = *(double*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg += MODE_CHOICE(2,1); ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++#elif defined(__ppc__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) ++ *(double*)fpr_base = *(double*)*p_argv; ++#else ++#error undefined architecture ++#endif ++ ++ *(long double*)next_arg = *(long double*)*p_argv; ++ fparg_count += 2; ++ fpr_base += 2; ++ next_arg += MODE_CHOICE(4,2); ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++#if defined(__ppc64__) ++ gprvalue = *(long long*)*p_argv; ++ goto putgpr; ++#elif defined(__ppc__) ++ *(long long*)next_arg = *(long long*)*p_argv; ++ next_arg += 2; ++ break; ++#else ++#error undefined architecture ++#endif ++ ++ case FFI_TYPE_POINTER: ++ gprvalue = *(unsigned long*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT8: ++ gprvalue = *(unsigned char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT8: ++ gprvalue = *(signed char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT16: ++ gprvalue = *(unsigned short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT16: ++ gprvalue = *(signed short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ ++ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, ++ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); ++ next_arg += gprSize / sizeof(long); ++ fpr_base += fprSize / sizeof(double); ++ ++#elif defined(__ppc__) ++ char* dest_cpy = (char*)next_arg; ++ ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. ++ Structures with 3 byte in size are padded upwards. */ ++ unsigned size_al = (*ptr)->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++ if (ecif->cif->abi == FFI_DARWIN) ++ { ++ if (size_al < 3) ++ dest_cpy += 4 - size_al; ++ } ++ ++ memcpy((char*)dest_cpy, (char*)*p_argv, size_al); ++ next_arg += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ gprvalue = *(unsigned*)*p_argv; ++ ++putgpr: ++ *next_arg++ = gprvalue; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Check that we didn't overrun the stack... */ ++ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); ++ //FFI_ASSERT((unsigned *)fpr_base ++ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); ++ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); ++} ++ ++#if defined(__ppc64__) ++ ++bool ++ffi64_struct_contains_fp( ++ const ffi_type* inType) ++{ ++ bool containsFP = false; ++ unsigned int i; ++ ++ for (i = 0; inType->elements[i] != NULL && !containsFP; i++) ++ { ++ if (inType->elements[i]->type == FFI_TYPE_FLOAT || ++ inType->elements[i]->type == FFI_TYPE_DOUBLE || ++ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) ++ containsFP = true; ++ else if (inType->elements[i]->type == FFI_TYPE_STRUCT) ++ containsFP = ffi64_struct_contains_fp(inType->elements[i]); ++ } ++ ++ return containsFP; ++} ++ ++#endif // defined(__ppc64__) ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ /* All this is for the DARWIN ABI. */ ++ int i; ++ ffi_type** ptr; ++ int intarg_count = 0; ++ int fparg_count = 0; ++ unsigned int flags = 0; ++ unsigned int size_al = 0; ++ ++ /* All the machine-independent calculation of cif->bytes will be wrong. ++ Redo the calculation for DARWIN. */ ++ ++ /* Space for the frame pointer, callee's LR, CR, etc, and for ++ the asm's temp regs. */ ++ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); ++ ++ /* Return value handling. The rules are as follows: ++ - 32-bit (or less) integer values are returned in gpr3; ++ - Structures of size <= 4 bytes also returned in gpr3; ++ - 64-bit integer values and structures between 5 and 8 bytes are ++ returned in gpr3 and gpr4; ++ - Single/double FP values are returned in fpr1; ++ - Long double FP (if not equivalent to double) values are returned in ++ fpr1 and fpr2; ++ - Larger structures values are allocated space and a pointer is passed ++ as the first argument. */ ++ switch (cif->rtype->type) ++ { ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ flags |= FLAG_RETURNS_128BITS; ++ flags |= FLAG_RETURNS_FP; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_DOUBLE: ++ flags |= FLAG_RETURNS_64BITS; ++ /* Fall through. */ ++ case FFI_TYPE_FLOAT: ++ flags |= FLAG_RETURNS_FP; ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ flags |= FLAG_RETURNS_64BITS; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ ++ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++ { ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ } ++ else ++ { ++ flags |= FLAG_RETURNS_STRUCT; ++ ++ if (ffi64_struct_contains_fp(cif->rtype)) ++ flags |= FLAG_STRUCT_CONTAINS_FP; ++ } ++ ++#elif defined(__ppc__) ++ ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_VOID: ++ flags |= FLAG_RETURNS_NOTHING; ++ break; ++ ++ default: ++ /* Returns 32-bit integer, or similar. Nothing to do here. */ ++ break; ++ } ++ ++ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the ++ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest ++ goes on the stack. Structures are passed as a pointer to a copy of ++ the structure. Stuff on the stack needs to keep proper alignment. */ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ switch ((*ptr)->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ fparg_count++; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ fparg_count += 2; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ ++ if ( ++#if defined(__ppc64__) ++ fparg_count > NUM_FPR_ARG_REGISTERS + 1 ++#elif defined(__ppc__) ++ fparg_count > NUM_FPR_ARG_REGISTERS ++#else ++#error undefined architecture ++#endif ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ ++ intarg_count += 2; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ /* 'long long' arguments are passed as two words, but ++ either both words must fit in registers or both go ++ on the stack. If they go on the stack, they must ++ be 8-byte-aligned. */ ++ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 ++ || (intarg_count >= NUM_GPR_ARG_REGISTERS ++ && intarg_count % 2 != 0)) ++ intarg_count++; ++ ++ intarg_count += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ size_al = (*ptr)->size; ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++#if defined(__ppc64__) ++ // Look for FP struct members. ++ unsigned int j; ++ ++ for (j = 0; (*ptr)->elements[j] != NULL; j++) ++ { ++ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || ++ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) ++ { ++ fparg_count++; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS) ++ intarg_count++; ++ } ++ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) ++ { ++ fparg_count += 2; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) ++ intarg_count += 2; ++ } ++ else ++ intarg_count++; ++ } ++#elif defined(__ppc__) ++ intarg_count += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ ++ break; ++ ++ default: ++ /* Everything else is passed as a 4/8-byte word in a GPR, either ++ the object itself or a pointer to it. */ ++ intarg_count++; ++ break; ++ } ++ } ++ ++ /* Space for the FPR registers, if needed. */ ++ if (fparg_count != 0) ++ { ++ flags |= FLAG_FP_ARGUMENTS; ++#if defined(__ppc64__) ++ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); ++#elif defined(__ppc__) ++ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ /* Stack space. */ ++#if defined(__ppc64__) ++ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + fparg_count) * sizeof(long); ++#elif defined(__ppc__) ++ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + 2 * fparg_count) * sizeof(long); ++#else ++#error undefined architecture ++#endif ++ else ++ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); ++ ++ /* The stack space allocated needs to be a multiple of 16/32 bytes. */ ++ bytes = SF_ROUND(bytes); ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ ++ return FFI_OK; ++} ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ++ffi_call_AIX( ++/*@out@*/ extended_cif*, ++ unsigned, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++ ++extern void ++ffi_call_DARWIN( ++/*@out@*/ extended_cif*, ++ unsigned long, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ 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) && ++ (cif->rtype->type == FFI_TYPE_STRUCT)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ switch (cif->abi) ++ { ++ case FFI_AIX: ++ /*@-usedef@*/ ++ ffi_call_AIX(&ecif, -cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ case FFI_DARWIN: ++ /*@-usedef@*/ ++ ffi_call_DARWIN(&ecif, -(long)cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++/* here I'd like to add the stack frame layout we use in darwin_closure.S ++ and aix_clsoure.S ++ ++ SP previous -> +---------------------------------------+ <--- child frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 4 ++ | saved CR 4 | ++ +---------------------------------------+ 8 ++ | saved LR 4 | ++ +---------------------------------------+ 12 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 16 ++ | reserved for binders 4 | ++ +---------------------------------------+ 20 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 24 ++ | always reserved 8*4=32 (previous GPRs)| ++ | according to the linkage convention | ++ | from AIX | ++ +---------------------------------------+ 56 ++ | our FPR area 13*8=104 | ++ | f1 | ++ | . | ++ | f13 | ++ +---------------------------------------+ 160 ++ | result area 8 | ++ +---------------------------------------+ 168 ++ | alignement to the next multiple of 16 | ++SP current --> +---------------------------------------+ 176 <- parent frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 180 ++ | saved CR 4 | ++ +---------------------------------------+ 184 ++ | saved LR 4 | ++ +---------------------------------------+ 188 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 192 ++ | reserved for binders 4 | ++ +---------------------------------------+ 196 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 200 ++ | always reserved 8*4=32 we store our | ++ | GPRs here | ++ | r3 | ++ | . | ++ | r10 | ++ +---------------------------------------+ 232 ++ | overflow part | ++ +---------------------------------------+ xxx ++ | ???? | ++ +---------------------------------------+ xxx ++*/ ++ ++#if !defined(POWERPC_DARWIN) ++ ++#define MIN_LINE_SIZE 32 ++ ++static void ++flush_icache( ++ char* addr) ++{ ++#ifndef _AIX ++ __asm__ volatile ( ++ "dcbf 0,%0\n" ++ "sync\n" ++ "icbi 0,%0\n" ++ "sync\n" ++ "isync" ++ : : "r" (addr) : "memory"); ++#endif ++} ++ ++static void ++flush_range( ++ char* addr, ++ int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i += MIN_LINE_SIZE) ++ flush_icache(addr + i); ++ ++ flush_icache(addr + size - 1); ++} ++ ++#endif // !defined(POWERPC_DARWIN) ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ switch (cif->abi) ++ { ++ case FFI_DARWIN: ++ { ++ FFI_ASSERT (cif->abi == FFI_DARWIN); ++ ++ unsigned int* tramp = (unsigned int*)&closure->tramp[0]; ++ ++#if defined(__ppc64__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0xe98b0018; // ld r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0xe96b0020; // ld r11,32(r11) ++ tramp[7] = 0x4e800420; // bctr ++ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; ++ *(unsigned long*)&tramp[10] = (unsigned long)closure; ++#elif defined(__ppc__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0x818b0018; // lwz r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0x816b001c; // lwz r11,28(r11) ++ tramp[7] = 0x4e800420; // bctr ++ tramp[8] = (unsigned long)ffi_closure_ASM; ++ tramp[9] = (unsigned long)closure; ++#else ++#error undefined architecture ++#endif ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ // Flush the icache. Only necessary on Darwin. ++#if defined(POWERPC_DARWIN) ++ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#else ++ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#endif ++ ++ break; ++ } ++ ++ case FFI_AIX: ++ { ++ FFI_ASSERT (cif->abi == FFI_AIX); ++ ++ ffi_aix_trampoline_struct* tramp_aix = ++ (ffi_aix_trampoline_struct*)(closure->tramp); ++ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; ++ ++ tramp_aix->code_pointer = fd->code_pointer; ++ tramp_aix->toc = fd->toc; ++ tramp_aix->static_chain = closure; ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ break; ++ } ++ ++ default: ++ return FFI_BAD_ABI; ++ } ++ ++ return FFI_OK; ++} ++ ++#if defined(__ppc__) ++ typedef double ldbits[2]; ++ ++ typedef union ++ { ++ ldbits lb; ++ long double ld; ++ } 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 ++ for a return value, ffi_closure_ASM invokes the following helper function ++ to do most of the work. */ ++int ++ffi_closure_helper_DARWIN( ++ ffi_closure* closure, ++ void* rvalue, ++ unsigned long* pgr, ++ ffi_dblfl* pfr) ++{ ++ /* rvalue is the pointer to space for return value in closure assembly ++ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM ++ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ ++ ++#if defined(__ppc__) ++ ldu temp_ld; ++#endif ++ ++ double temp; ++ unsigned int i; ++ unsigned int nf = 0; /* number of FPRs already used. */ ++ unsigned int ng = 0; /* number of GPRs already used. */ ++ ffi_cif* cif = closure->cif; ++ long avn = cif->nargs; ++ void** avalue = alloca(cif->nargs * sizeof(void*)); ++ ffi_type** arg_types = cif->arg_types; ++ ++ /* Copy the caller's structure return value address so that the closure ++ returns the data directly to the caller. */ ++#if defined(__ppc64__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT && ++ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++#elif defined(__ppc__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT) ++#else ++#error undefined architecture ++#endif ++ { ++ rvalue = (void*)*pgr; ++ pgr++; ++ ng++; ++ } ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ for (i = 0; i < avn; i++) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ avalue[i] = (char*)pgr + MODE_CHOICE(3,7); ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ avalue[i] = (char*)pgr + MODE_CHOICE(2,6); ++ ng++; ++ pgr++; ++ break; ++ ++#if defined(__ppc__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ avalue[i] = (char*)pgr + MODE_CHOICE(0,4); ++ ng++; ++ pgr++; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ if (cif->abi == FFI_DARWIN) ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ unsigned int savedFPRSize = fprSize; ++ ++ avalue[i] = alloca(arg_types[i]->size); ++ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, ++ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); ++ ++ ng += gprSize / sizeof(long); ++ pgr += gprSize / sizeof(long); ++ pfr += (fprSize - savedFPRSize) / sizeof(double); ++ ++#elif defined(__ppc__) ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. */ ++ unsigned int size_al = size_al = arg_types[i]->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN(arg_types[i]->size, 8); ++ ++ if (size_al < 3) ++ avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; ++ else ++ avalue[i] = (void*)pgr; ++ ++ ng += (size_al + 3) / sizeof(long); ++ pgr += (size_al + 3) / sizeof(long); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ /* Long long ints are passed in 1 or 2 GPRs. */ ++ avalue[i] = pgr; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ /* A float value consumes a GPR. ++ There are 13 64-bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ temp = pfr->d; ++ pfr->f = (float)temp; ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ /* A double value consumes one or two GPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++#elif defined(__ppc__) ++ /* A long double value consumes 2/4 GPRs and 2 FPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS - 1) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++ /* Here we have the situation where one part of the long double ++ is stored in fpr13 and the other part is already on the stack. ++ 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(temp_ld.lb[0])); ++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); ++ avalue[i] = &temp_ld.ld; ++ } ++#else ++#error undefined architecture ++#endif ++ else ++ avalue[i] = pgr; ++ ++ nf += 2; ++ ng += MODE_CHOICE(4,2); ++ pgr += MODE_CHOICE(4,2); ++ ++ break; ++ ++#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ (closure->fun)(cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell ffi_closure_ASM to perform return type promotions. */ ++ return cif->rtype->type; ++} ++ ++#if defined(__ppc64__) ++ ++/* ffi64_struct_to_ram_form ++ ++ Rebuild a struct's natural layout from buffers of concatenated registers. ++ Return the number of registers used. ++ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_ram_form( ++ const ffi_type* inType, ++ const char* inGPRs, ++ unsigned int* ioGPRMarker, ++ const char* inFPRs, ++ unsigned int* ioFPRMarker, ++ unsigned int* ioFPRsUsed, ++ char* outStruct, // caller-allocated ++ unsigned int* ioStructMarker) ++{ ++ unsigned int srcGMarker = 0; ++ unsigned int srcFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ unsigned int destMarker = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioGPRMarker) ++ srcGMarker = *ioGPRMarker; ++ ++ if (ioFPRMarker) ++ { ++ srcFMarker = *ioFPRMarker; ++ savedFMarker = srcFMarker; ++ } ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioStructMarker) ++ destMarker = *ioStructMarker; ++ ++ size_t i; ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ srcGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ srcFMarker = ALIGN(srcFMarker, 4); ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inGPRs[srcGMarker]; ++ ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcFMarker = ALIGN(srcFMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inGPRs[srcGMarker]; ++ ++ destMarker += 8; ++ ++ // Skip next GPR ++ srcGMarker += 8; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ destMarker = ALIGN(destMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ srcFMarker = ALIGN(srcFMarker, 8); ++ srcGMarker = ALIGN(srcGMarker, 8); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inFPRs[srcFMarker]; ++ srcFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ srcFMarker = ALIGN(srcFMarker, 16); ++ srcGMarker = ALIGN(srcGMarker, 16); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inGPRs[srcGMarker]; ++ } ++ ++ destMarker += 16; ++ ++ // Skip next 2 GPRs ++ srcGMarker += 16; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ if (inType->alignment == 1) // chars only ++ { ++ if (inType->size == 1) ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ else if (inType->size == 2) ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ i++; ++ } ++ else ++ { ++ memcpy(&outStruct[destMarker], ++ &inGPRs[srcGMarker], inType->size); ++ srcGMarker += inType->size; ++ destMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // chars and other stuff ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcGMarker = ALIGN(srcGMarker, 2); ++ destMarker = ALIGN(destMarker, 2); ++ ++ *(short*)&outStruct[destMarker] = ++ *(short*)&inGPRs[srcGMarker]; ++ srcGMarker += 2; ++ destMarker += 2; ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ *(int*)&outStruct[destMarker] = ++ *(int*)&inGPRs[srcGMarker]; ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcGMarker = ALIGN(srcGMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ *(long long*)&outStruct[destMarker] = ++ *(long long*)&inGPRs[srcGMarker]; ++ srcGMarker += 8; ++ destMarker += 8; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_ram_form(inType->elements[i], inGPRs, ++ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, ++ outStruct, &destMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); // unknown element type ++ break; ++ } ++ } ++ ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && srcGMarker == 16) ++ { ++ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; ++ srcFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioGPRMarker) ++ *ioGPRMarker = ALIGN(srcGMarker, 8); ++ ++ if (ioFPRMarker) ++ *ioFPRMarker = srcFMarker; ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(destMarker, 8); ++} ++ ++/* ffi64_struct_to_reg_form ++ ++ Copy a struct's elements into buffers that can be sliced into registers. ++ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers ++ to calculate size only. ++ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_reg_form( ++ const ffi_type* inType, ++ const char* inStruct, ++ unsigned int* ioStructMarker, ++ unsigned int* ioFPRsUsed, ++ char* outGPRs, // caller-allocated ++ unsigned int* ioGPRSize, ++ char* outFPRs, // caller-allocated ++ unsigned int* ioFPRSize) ++{ ++ size_t i; ++ unsigned int srcMarker = 0; ++ unsigned int destGMarker = 0; ++ unsigned int destFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioStructMarker) ++ srcMarker = *ioStructMarker; ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioGPRSize) ++ destGMarker = *ioGPRSize; ++ ++ if (ioFPRSize) ++ { ++ destFMarker = *ioFPRSize; ++ savedFMarker = destFMarker; ++ } ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ destGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ // Shadow floating-point types in GPRs for vararg and pre-ANSI ++ // functions. ++ case FFI_TYPE_FLOAT: ++ // Nudge markers to next 4/8-byte boundary ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcMarker = ALIGN(srcMarker, 8); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ ++ // Skip next GPR ++ destGMarker += 8; ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ srcMarker = ALIGN(srcMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ destFMarker = ALIGN(destFMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outFPRs != NULL && inStruct != NULL) ++ *(long double*)&outFPRs[destFMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ destFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ destGMarker = ALIGN(destGMarker, 16); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ } ++ ++ srcMarker += 16; ++ destGMarker += 16; // Skip next 2 GPRs ++ destGMarker = ALIGN(destGMarker, 8); // was 16 ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ if (inType->alignment == 1) // bytes only ++ { ++ if (inType->size == 1) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ } ++ else if (inType->size == 2) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; ++ } ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ i++; ++ } ++ else ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ // Avoid memcpy for small chunks. ++ if (inType->size <= sizeof(long)) ++ *(long*)&outGPRs[destGMarker] = ++ *(long*)&inStruct[srcMarker]; ++ else ++ memcpy(&outGPRs[destGMarker], ++ &inStruct[srcMarker], inType->size); ++ } ++ ++ srcMarker += inType->size; ++ destGMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // bytes and other stuff ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcMarker = ALIGN(srcMarker, 2); ++ destGMarker = ALIGN(destGMarker, 2); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(short*)&outGPRs[destGMarker] = ++ *(short*)&inStruct[srcMarker]; ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(int*)&outGPRs[destGMarker] = ++ *(int*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcMarker = ALIGN(srcMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long long*)&outGPRs[destGMarker] = ++ *(long long*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ destGMarker += 8; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_reg_form(inType->elements[i], ++ inStruct, &srcMarker, &fprsUsed, outGPRs, ++ &destGMarker, outFPRs, &destFMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && destGMarker == 16) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; ++ ++ destFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(srcMarker, 8); ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioGPRSize) ++ *ioGPRSize = ALIGN(destGMarker, 8); ++ ++ if (ioFPRSize) ++ *ioFPRSize = ALIGN(destFMarker, 8); ++} ++ ++/* ffi64_stret_needs_ptr ++ ++ Determine whether a returned struct needs a pointer in r3 or can fit ++ in registers. ++*/ ++ ++bool ++ffi64_stret_needs_ptr( ++ const ffi_type* inType, ++ unsigned short* ioGPRCount, ++ unsigned short* ioFPRCount) ++{ ++ // Obvious case first- struct is larger than combined FPR size. ++ if (inType->size > 14 * 8) ++ return true; ++ ++ // Now the struct can physically fit in registers, determine if it ++ // also fits logically. ++ bool needsPtr = false; ++ unsigned short gprsUsed = 0; ++ unsigned short fprsUsed = 0; ++ size_t i; ++ ++ if (ioGPRCount) ++ gprsUsed = *ioGPRCount; ++ ++ if (ioFPRCount) ++ fprsUsed = *ioFPRCount; ++ ++ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ gprsUsed++; ++ fprsUsed++; ++ ++ if (fprsUsed > 13) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ gprsUsed += 2; ++ fprsUsed += 2; ++ ++ if (fprsUsed > 14) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ { ++ needsPtr = true; ++ break; ++ } ++ ++ if (inType->elements[i + 1] == NULL) // last byte in the struct ++ break; ++ ++ // Count possible contiguous bytes ahead, up to 8. ++ unsigned short j; ++ ++ for (j = 1; j < 8; j++) ++ { ++ if (inType->elements[i + j] == NULL || ++ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) ++ break; ++ } ++ ++ i += j - 1; // allow for i++ before the test condition ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ needsPtr = ffi64_stret_needs_ptr( ++ inType->elements[i], &gprsUsed, &fprsUsed); ++ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ if (ioGPRCount) ++ *ioGPRCount = gprsUsed; ++ ++ if (ioFPRCount) ++ *ioFPRCount = fprsUsed; ++ ++ return needsPtr; ++} ++ ++/* ffi64_data_size ++ ++ Calculate the size in bytes of an ffi type. ++*/ ++ ++unsigned int ++ffi64_data_size( ++ const ffi_type* inType) ++{ ++ unsigned int size = 0; ++ ++ switch (inType->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ size = 1; ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ size = 2; ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_FLOAT: ++ size = 4; ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_DOUBLE: ++ size = 8; ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ size = 16; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ ffi64_struct_to_reg_form( ++ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); ++ break; ++ ++ case FFI_TYPE_VOID: ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ ++ return size; ++} ++ ++#endif /* defined(__ppc64__) */ ++#endif /* __ppc__ || __ppc64__ */ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +new file mode 100644 +index 0000000..7162fa1 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +@@ -0,0 +1,418 @@ ++#if defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc64-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 ++ stg r0,SF_RETURN(r1) // save return address ++ ++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. ++ stg r3,SF_ARG1(r1) ++ stg r4,SF_ARG2(r1) ++ stg r5,SF_ARG3(r1) ++ stg r6,SF_ARG4(r1) ++ stg r7,SF_ARG5(r1) ++ stg r8,SF_ARG6(r1) ++ stg r9,SF_ARG7(r1) ++ stg r10,SF_ARG8(r1) ++ ++LCFI0: ++/* 48 bytes (Linkage Area) ++ 64 bytes (outgoing parameter area, always reserved) ++ 112 bytes (14*8 for incoming FPR) ++ ? bytes (result) ++ 112 bytes (14*8 for outgoing FPR) ++ 16 bytes (2 saved registers) ++ 352 + ? total bytes ++*/ ++ ++ std r31,-8(r1) // Save registers we use. ++ std r30,-16(r1) ++ mr r30,r1 // Save the old SP. ++ mr r31,r11 // Save the ffi_closure around ffi64_data_size. ++ ++ // Calculate the space we need. ++ stdu r1,-SF_MINSIZE(r1) ++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ bl Lffi64_data_size$stub ++ ld r1,0(r1) ++ ++ addi r3,r3,352 // Add our overhead. ++ neg r3,r3 ++ li r0,-32 // Align to 32 bytes. ++ and r3,r3,r0 ++ stdux r1,r1,r3 // Grow the stack. ++ ++ mr r11,r31 // Copy the ffi_closure back. ++ ++LCFI1: ++ // We want to build up an area for the parameters passed ++ // in registers. (both floating point and integer) ++ ++/* 320 bytes (callee stack frame aligned to 32) ++ 48 bytes (caller linkage area) ++ 368 (start of caller parameter area aligned to 8) ++*/ ++ ++ // Save FPRs 1 - 14. (aligned to 8) ++ stfd f1,112(r1) ++ stfd f2,120(r1) ++ stfd f3,128(r1) ++ stfd f4,136(r1) ++ stfd f5,144(r1) ++ stfd f6,152(r1) ++ stfd f7,160(r1) ++ stfd f8,168(r1) ++ stfd f9,176(r1) ++ stfd f10,184(r1) ++ stfd f11,192(r1) ++ stfd f12,200(r1) ++ stfd f13,208(r1) ++ stfd f14,216(r1) ++ ++ // Set up registers for the routine that actually does the work. ++ mr r3,r11 // context pointer from the trampoline ++ addi r4,r1,224 // result storage ++ addi r5,r30,SF_ARG1 // saved GPRs ++ addi r6,r1,112 // saved FPRs ++ bl Lffi_closure_helper_DARWIN$stub ++ ++ // Look the proper starting point in table ++ // by using return type as an offset. ++ addi r5,r1,224 // 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. ++ mtctr r3 ++ bctr ++ ++LFE1: ++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ // (4 instructions). For cache effectiveness we align to a 16 byte ++ // boundary first. ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++// case FFI_TYPE_VOID ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++// case FFI_TYPE_INT ++Lret_type1: ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_FLOAT ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_DOUBLE ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_LONGDOUBLE ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT8 ++Lret_type5: ++ lbz r3,7(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT8 ++Lret_type6: ++ lbz r3,7(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT16 ++Lret_type7: ++ lhz r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT16 ++Lret_type8: ++ lha r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT32 ++Lret_type9: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT32 ++Lret_type10: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT64 ++Lret_type11: ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT64 ++Lret_type12: // same as Lret_type11 ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_STRUCT ++Lret_type13: ++ b Lret_struct ++ nop ++ nop ++ nop ++ ++// ** End 16-byte aligned cases ** ++// case FFI_TYPE_POINTER ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ b Lfinish ++ ++// copy struct into registers ++Lret_struct: ++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r31) // ffi_cif->rtype* ++ ld r31,24(r31) // ffi_cif->flags ++ mr r4,r5 // copy struct* to 2nd arg ++ addi r7,r1,SF_ARG9 // GPR return area ++ addi r9,r30,-16-(14*8) // FPR return area ++ li r5,0 // struct offset ptr (NULL) ++ li r6,0 // FPR used count ptr (NULL) ++ li r8,0 // GPR return area size ptr (NULL) ++ li r10,0 // FPR return area size ptr (NULL) ++ bl Lffi64_struct_to_reg_form$stub ++ ++ // Load GPRs ++ ld r3,SF_ARG9(r1) ++ ld r4,SF_ARG10(r1) ++ ld r5,SF_ARG11(r1) ++ ld r6,SF_ARG12(r1) ++ nop ++ ld r7,SF_ARG13(r1) ++ ld r8,SF_ARG14(r1) ++ ld r9,SF_ARG15(r1) ++ ld r10,SF_ARG16(r1) ++ nop ++ ++ // Load FPRs ++ mtcrf 0x2,r31 ++ bf 26,Lfinish ++ lfd f1,-16-(14*8)(r30) ++ lfd f2,-16-(13*8)(r30) ++ lfd f3,-16-(12*8)(r30) ++ lfd f4,-16-(11*8)(r30) ++ nop ++ lfd f5,-16-(10*8)(r30) ++ lfd f6,-16-(9*8)(r30) ++ lfd f7,-16-(8*8)(r30) ++ lfd f8,-16-(7*8)(r30) ++ nop ++ lfd f9,-16-(6*8)(r30) ++ lfd f10,-16-(5*8)(r30) ++ lfd f11,-16-(4*8)(r30) ++ lfd f12,-16-(3*8)(r30) ++ nop ++ lfd f13,-16-(2*8)(r30) ++ lfd f14,-16-(1*8)(r30) ++ // Fall through ++ ++// case done ++Lfinish: ++ 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. ++ blr ++ ++// END(ffi_closure_ASM) ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_reg_form$stub: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_reg_form ++ ++LO$ffi64_struct_to_reg_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) ++ mtctr r12 ++ bctr ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_data_size$stub: ++ .indirect_symbol _ffi64_data_size ++ mflr r0 ++ bcl 20,31,LO$ffi64_data_size ++ ++LO$ffi64_data_size: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_reg_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ .g_long dyld_stub_binding_helper ++ ++L_ffi64_data_size$lazy_ptr: ++ .indirect_symbol _ffi64_data_size ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c +new file mode 100644 +index 0000000..44806ae +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/types.c +@@ -0,0 +1,115 @@ ++/* ----------------------------------------------------------------------- ++ types.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Predefined ffi_types needed by libffi. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++/* Type definitions */ ++#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \ ++ ffi_type ffi_type_##n = { s, a, t, NULL } ++#define FFI_AGGREGATE_TYPEDEF(n, e) \ ++ ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } ++ ++FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); ++FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); ++FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); ++FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); ++FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); ++FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); ++FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); ++ ++/* Size and alignment are fake here. They must not be 0. */ ++FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); ++ ++#if defined ALPHA || defined SPARC64 || defined X86_64 || \ ++ defined S390X || defined IA64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); ++#else ++FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); ++#endif ++ ++#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN) ++ ++# ifdef X86_64 ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++# else ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++# endif ++ ++#elif defined(POWERPC_DARWIN) ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#elif defined SH ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++#else ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#endif ++ ++#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN) ++ ++# if defined X86_WIN32 || defined X86_64 ++ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++# endif ++ ++# ifdef X86_DARWIN ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined ARM || defined SH || defined POWERPC_AIX ++FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); ++#elif defined POWERPC_DARWIN ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# if __GNUC__ >= 4 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined SPARC ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# ifdef SPARC64 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined X86_64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++#else ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S +new file mode 100644 +index 0000000..165d469 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S +@@ -0,0 +1,417 @@ ++/* ----------------------------------------------------------------------- ++ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. ++ derived from unix64.S ++ ++ x86-64 Foreign Function Interface for Darwin. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifdef __x86_64__ ++#define LIBFFI_ASM ++#include ++#include ++ ++ .file "darwin64.S" ++.text ++ ++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, ++ void *raddr, void (*fnaddr)()); ++ ++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame ++ for this function. This has been allocated by ffi_call. We also ++ deallocate some of the stack that has been alloca'd. */ ++ ++ .align 3 ++ .globl _ffi_call_unix64 ++ ++_ffi_call_unix64: ++LUW0: ++ movq (%rsp), %r10 /* Load return address. */ ++ movq %rdi, %r12 /* Save a copy of the register area. */ ++ leaq (%rdi, %rsi), %rax /* Find local stack base. */ ++ movq %rdx, (%rax) /* Save flags. */ ++ movq %rcx, 8(%rax) /* Save raddr. */ ++ movq %rbp, 16(%rax) /* Save old frame pointer. */ ++ movq %r10, 24(%rax) /* Relocate return address. */ ++ movq %rax, %rbp /* Finalize local stack frame. */ ++LUW1: ++ /* movq %rdi, %r10 // Save a copy of the register area. */ ++ movq %r12, %r10 ++ movq %r8, %r11 /* Save a copy of the target fn. */ ++ movl %r9d, %eax /* Set number of SSE registers. */ ++ ++ /* Load up all argument registers. */ ++ movq (%r10), %rdi ++ movq 8(%r10), %rsi ++ movq 16(%r10), %rdx ++ movq 24(%r10), %rcx ++ movq 32(%r10), %r8 ++ movq 40(%r10), %r9 ++ testl %eax, %eax ++ jnz Lload_sse ++Lret_from_load_sse: ++ ++ /* Deallocate the reg arg area. */ ++ leaq 176(%r10), %rsp ++ ++ /* Call the user function. */ ++ call *%r11 ++ ++ /* Deallocate stack arg area; local stack frame in redzone. */ ++ leaq 24(%rbp), %rsp ++ ++ movq 0(%rbp), %rcx /* Reload flags. */ ++ movq 8(%rbp), %rdi /* Reload raddr. */ ++ movq 16(%rbp), %rbp /* Reload old frame pointer. */ ++LUW2: ++ ++ /* The first byte of the flags contains the FFI_TYPE. */ ++ movzbl %cl, %r10d ++ leaq Lstore_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lstore_table: ++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ ++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ ++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ ++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ ++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ ++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ ++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ ++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ ++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lst_void: ++ ret ++ .align 3 ++Lst_uint8: ++ movzbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_sint8: ++ movsbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint16: ++ movzwq %ax, %rax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint16: ++ movswq %ax, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint32: ++ movl %eax, %eax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint32: ++ cltq ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_int64: ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_float: ++ movss %xmm0, (%rdi) ++ ret ++ .align 3 ++Lst_double: ++ movsd %xmm0, (%rdi) ++ ret ++Lst_ldouble: ++ fstpt (%rdi) ++ ret ++ .align 3 ++Lst_struct: ++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */ ++ ++ /* We have to locate the values now, and since we don't want to ++ write too much data into the user's return value, we spill the ++ value to a 16 byte scratch area first. Bits 8, 9, and 10 ++ control where the values are located. Only one of the three ++ bits will be set; see ffi_prep_cif_machdep for the pattern. */ ++ movd %xmm0, %r10 ++ movd %xmm1, %r11 ++ testl $0x100, %ecx ++ cmovnz %rax, %rdx ++ cmovnz %r10, %rax ++ testl $0x200, %ecx ++ cmovnz %r10, %rdx ++ testl $0x400, %ecx ++ cmovnz %r10, %rax ++ cmovnz %r11, %rdx ++ movq %rax, (%rsi) ++ movq %rdx, 8(%rsi) ++ ++ /* Bits 12-31 contain the true size of the structure. Copy from ++ the scratch area to the true destination. */ ++ shrl $12, %ecx ++ rep movsb ++ ret ++ ++ /* Many times we can avoid loading any SSE registers at all. ++ It's not worth an indirect jump to load the exact set of ++ SSE registers needed; zero or all is a good compromise. */ ++ .align 3 ++LUW3: ++Lload_sse: ++ movdqa 48(%r10), %xmm0 ++ movdqa 64(%r10), %xmm1 ++ movdqa 80(%r10), %xmm2 ++ movdqa 96(%r10), %xmm3 ++ movdqa 112(%r10), %xmm4 ++ movdqa 128(%r10), %xmm5 ++ movdqa 144(%r10), %xmm6 ++ movdqa 160(%r10), %xmm7 ++ jmp Lret_from_load_sse ++ ++LUW4: ++ .align 3 ++ .globl _ffi_closure_unix64 ++ ++_ffi_closure_unix64: ++LUW5: ++ /* The carry flag is set by the trampoline iff SSE registers ++ are used. Don't clobber it before the branch instruction. */ ++ leaq -200(%rsp), %rsp ++LUW6: ++ movq %rdi, (%rsp) ++ movq %rsi, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rcx, 24(%rsp) ++ movq %r8, 32(%rsp) ++ movq %r9, 40(%rsp) ++ jc Lsave_sse ++Lret_from_save_sse: ++ ++ movq %r10, %rdi ++ leaq 176(%rsp), %rsi ++ movq %rsp, %rdx ++ leaq 208(%rsp), %rcx ++ call _ffi_closure_unix64_inner ++ ++ /* Deallocate stack frame early; return value is now in redzone. */ ++ addq $200, %rsp ++LUW7: ++ ++ /* The first byte of the return value contains the FFI_TYPE. */ ++ movzbl %al, %r10d ++ leaq Lload_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lload_table: ++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */ ++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ ++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ ++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ ++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lld_void: ++ ret ++ .align 3 ++Lld_int8: ++ movzbl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int16: ++ movzwl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int32: ++ movl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int64: ++ movq -24(%rsp), %rax ++ ret ++ .align 3 ++Lld_float: ++ movss -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_double: ++ movsd -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_ldouble: ++ fldt -24(%rsp) ++ ret ++ .align 3 ++Lld_struct: ++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, ++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading ++ both rdx and xmm1 with the second word. For the remaining, ++ bit 8 set means xmm0 gets the second word, and bit 9 means ++ that rax gets the second word. */ ++ movq -24(%rsp), %rcx ++ movq -16(%rsp), %rdx ++ movq -16(%rsp), %xmm1 ++ testl $0x100, %eax ++ cmovnz %rdx, %rcx ++ movd %rcx, %xmm0 ++ testl $0x200, %eax ++ movq -24(%rsp), %rax ++ cmovnz %rdx, %rax ++ ret ++ ++ /* See the comment above Lload_sse; the same logic applies here. */ ++ .align 3 ++LUW8: ++Lsave_sse: ++ movdqa %xmm0, 48(%rsp) ++ movdqa %xmm1, 64(%rsp) ++ movdqa %xmm2, 80(%rsp) ++ movdqa %xmm3, 96(%rsp) ++ movdqa %xmm4, 112(%rsp) ++ movdqa %xmm5, 128(%rsp) ++ movdqa %xmm6, 144(%rsp) ++ movdqa %xmm7, 160(%rsp) ++ jmp Lret_from_save_sse ++ ++LUW9: ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ ++ .long L$set$0 ++LSCIE1: ++ .long 0x0 /* CIE Identifier Tag */ ++ .byte 0x1 /* CIE Version */ ++ .ascii "zR\0" /* CIE Augmentation */ ++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ ++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ ++ .byte 0x10 /* CIE RA Column */ ++ .byte 0x1 /* uleb128 0x1; Augmentation size */ ++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */ ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 /* uleb128 0x7 */ ++ .byte 0x8 /* uleb128 0x8 */ ++ .byte 0x90 /* DW_CFA_offset, column 0x10 */ ++ .byte 0x1 ++ .align 3 ++LECIE1: ++ .globl _ffi_call_unix64.eh ++_ffi_call_unix64.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ ++ .long L$set$1 ++LASFDE1: ++ .long LASFDE1-EH_frame1 /* FDE CIE offset */ ++ .quad LUW0-. /* FDE initial location */ ++ .set L$set$2,LUW4-LUW0 /* FDE address range */ ++ .quad L$set$2 ++ .byte 0x0 /* Augmentation size */ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$3,LUW1-LUW0 ++ .long L$set$3 ++ ++ /* New stack frame based off rbp. This is a itty bit of unwind ++ trickery in that the CFA *has* changed. There is no easy way ++ to describe it correctly on entry to the function. Fortunately, ++ it doesn't matter too much since at all points we can correctly ++ unwind back to ffi_call. Note that the location to which we ++ moved the return address is (the new) CFA-8, so from the ++ perspective of the unwind info, it hasn't moved. */ ++ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ ++ .byte 0x6 ++ .byte 0x20 ++ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ ++ .byte 0x2 ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$4,LUW2-LUW1 ++ .long L$set$4 ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 ++ .byte 0x8 ++ .byte 0xc0+6 /* DW_CFA_restore, %rbp */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$5,LUW3-LUW2 ++ .long L$set$5 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE1: ++ .globl _ffi_closure_unix64.eh ++_ffi_closure_unix64.eh: ++LSFDE3: ++ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ ++ .long L$set$6 ++LASFDE3: ++ .long LASFDE3-EH_frame1 /* FDE CIE offset */ ++ .quad LUW5-. /* FDE initial location */ ++ .set L$set$7,LUW9-LUW5 /* FDE address range */ ++ .quad L$set$7 ++ .byte 0x0 /* Augmentation size */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$8,LUW6-LUW5 ++ .long L$set$8 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 208,1 /* uleb128 208 */ ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$9,LUW7-LUW6 ++ .long L$set$9 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 0x8 ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$10,LUW8-LUW7 ++ .long L$set$10 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE3: ++ .subsections_via_symbols ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +new file mode 100644 +index 0000000..925a841 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +@@ -0,0 +1,422 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. ++ ++ X86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++/* ++ * This file is based on sysv.S and then hacked up by Ronald who hasn't done ++ * assembly programming in 8 years. ++ */ ++ ++#ifndef __x86_64__ ++ ++#define LIBFFI_ASM ++#include ++#include ++ ++#ifdef PyObjC_STRICT_DEBUGGING ++ /* XXX: Debugging of stack alignment, to be removed */ ++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 ++#else ++#define ASSERT_STACK_ALIGNED ++#endif ++ ++.text ++ ++.globl _ffi_prep_args ++ ++ .align 4 ++.globl _ffi_call_SYSV ++ ++_ffi_call_SYSV: ++LFB1: ++ pushl %ebp ++LCFI0: ++ movl %esp,%ebp ++LCFI1: ++ subl $8,%esp ++ /* Make room for all of the new args. */ ++ movl 16(%ebp),%ecx ++ subl %ecx,%esp ++ ++ movl %esp,%eax ++ ++ /* Place all of the ffi_prep_args in position */ ++ subl $8,%esp ++ pushl 12(%ebp) ++ pushl %eax ++ call *8(%ebp) ++ ++ /* Return stack to previous state and call the function */ ++ addl $16,%esp ++ ++ call *28(%ebp) ++ ++ /* 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 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 Lnoretval ++ fstp %st(0) ++ ++ jmp Lepilogue ++ ++Lretint: ++ cmpl $FFI_TYPE_INT,%ecx ++ jne Lretfloat ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ movl %eax,0(%ecx) ++ jmp Lepilogue ++ ++Lretfloat: ++ cmpl $FFI_TYPE_FLOAT,%ecx ++ jne Lretdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstps (%ecx) ++ jmp Lepilogue ++ ++Lretdouble: ++ cmpl $FFI_TYPE_DOUBLE,%ecx ++ jne Lretlongdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpl (%ecx) ++ jmp Lepilogue ++ ++Lretlongdouble: ++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx ++ jne Lretint64 ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpt (%ecx) ++ jmp Lepilogue ++ ++Lretint64: ++ cmpl $FFI_TYPE_SINT64,%ecx ++ 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 Lepilogue ++ ++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 ++ ++Lnoretval: ++Lepilogue: ++ addl $8,%esp ++ movl %ebp,%esp ++ popl %ebp ++ ret ++LFE1: ++.ffi_call_SYSV_end: ++ ++ .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_UINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_SINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_UINT16, %eax ++ je Lcls_retstruct2 ++ 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 ++ ++.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__ */ ++ ++#endif /* defined __i386__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +new file mode 100644 +index 0000000..06feaf2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +@@ -0,0 +1,734 @@ ++#ifdef __x86_64__ ++ ++/* ----------------------------------------------------------------------- ++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen ++ ++ x86-64 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_GPR_REGS 6 ++#define MAX_SSE_REGS 8 ++ ++typedef struct RegisterArgs { ++ /* Registers for argument passing. */ ++ UINT64 gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++} RegisterArgs; ++ ++extern void ++ffi_call_unix64( ++ void* args, ++ unsigned long bytes, ++ unsigned flags, ++ void* raddr, ++ void (*fnaddr)(), ++ unsigned ssecount); ++ ++/* All reference to register classes here is identical to the code in ++ gcc/config/i386/i386.c. Do *not* change one without the other. */ ++ ++/* 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 reformating penalties. ++ ++ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves ++ whenever possible (upper half does contain padding). */ ++enum x86_64_reg_class ++{ ++ X86_64_NO_CLASS, ++ X86_64_INTEGER_CLASS, ++ X86_64_INTEGERSI_CLASS, ++ X86_64_SSE_CLASS, ++ X86_64_SSESF_CLASS, ++ X86_64_SSEDF_CLASS, ++ X86_64_SSEUP_CLASS, ++ X86_64_X87_CLASS, ++ X86_64_X87UP_CLASS, ++ X86_64_COMPLEX_X87_CLASS, ++ X86_64_MEMORY_CLASS ++}; ++ ++#define MAX_CLASSES 4 ++#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) ++ ++/* x86-64 register passing implementation. See x86-64 ABI for details. Goal ++ of this code is to classify each 8bytes of incoming argument by the register ++ class and assign registers accordingly. */ ++ ++/* Return the union class of CLASS1 and CLASS2. ++ See the x86-64 PS ABI for details. */ ++static enum x86_64_reg_class ++merge_classes( ++ enum x86_64_reg_class class1, ++ enum x86_64_reg_class class2) ++{ ++ /* Rule #1: If both classes are equal, this is the resulting class. */ ++ if (class1 == class2) ++ return class1; ++ ++ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is ++ the other class. */ ++ if (class1 == X86_64_NO_CLASS) ++ return class2; ++ ++ if (class2 == X86_64_NO_CLASS) ++ return class1; ++ ++ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ ++ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ ++ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) ++ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) ++ return X86_64_INTEGERSI_CLASS; ++ ++ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS ++ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) ++ return X86_64_INTEGER_CLASS; ++ ++ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, ++ MEMORY is used. */ ++ if (class1 == X86_64_X87_CLASS ++ || class1 == X86_64_X87UP_CLASS ++ || class1 == X86_64_COMPLEX_X87_CLASS ++ || class2 == X86_64_X87_CLASS ++ || class2 == X86_64_X87UP_CLASS ++ || class2 == X86_64_COMPLEX_X87_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #6: Otherwise class SSE is used. */ ++ return X86_64_SSE_CLASS; ++} ++ ++/* Classify the argument of type TYPE and mode MODE. ++ CLASSES will be filled by the register class used to pass each word ++ of the operand. The number of words is returned. In case the parameter ++ should be passed in memory, 0 is returned. As a special case for zero ++ sized containers, classes[0] will be NO_CLASS and 1 is returned. ++ ++ See the x86-64 PS ABI for details. */ ++ ++static int ++classify_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[], ++ size_t byte_offset) ++{ ++ switch (type->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++#if 0 ++ if (byte_offset + type->size <= 4) ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ else ++ classes[0] = X86_64_INTEGER_CLASS; ++ ++ return 1; ++#else ++ { ++ int size = byte_offset + type->size; ++ ++ if (size <= 4) ++ { ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ return 1; ++ } ++ else if (size <= 8) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ return 1; ++ } ++ else if (size <= 12) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else if (size <= 16) ++ { ++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else ++ FFI_ASSERT (0); ++ } ++#endif ++ ++ case FFI_TYPE_FLOAT: ++ if (byte_offset == 0) ++ classes[0] = X86_64_SSESF_CLASS; ++ else ++ classes[0] = X86_64_SSE_CLASS; ++ ++ return 1; ++ ++ case FFI_TYPE_DOUBLE: ++ classes[0] = X86_64_SSEDF_CLASS; ++ return 1; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ classes[0] = X86_64_X87_CLASS; ++ classes[1] = X86_64_X87UP_CLASS; ++ return 2; ++ ++ case FFI_TYPE_STRUCT: ++ { ++ ffi_type** ptr; ++ int i; ++ enum x86_64_reg_class subclasses[MAX_CLASSES]; ++ const int UNITS_PER_WORD = 8; ++ int words = ++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ++ ++ /* If the struct is larger than 16 bytes, pass it on the stack. */ ++ if (type->size > 16) ++ return 0; ++ ++ for (i = 0; i < words; i++) ++ classes[i] = X86_64_NO_CLASS; ++ ++ /* Merge the fields of structure. */ ++ for (ptr = type->elements; *ptr != NULL; ptr++) ++ { ++ byte_offset = ALIGN(byte_offset, (*ptr)->alignment); ++ ++ int num = classify_argument(*ptr, subclasses, byte_offset % 8); ++ ++ if (num == 0) ++ return 0; ++ ++ int pos = byte_offset / 8; ++ ++ for (i = 0; i < num; i++) ++ { ++ classes[i + pos] = ++ merge_classes(subclasses[i], classes[i + pos]); ++ } ++ ++ byte_offset += (*ptr)->size; ++ } ++ ++ if (words > 2) ++ { ++ /* When size > 16 bytes, if the first one isn't ++ X86_64_SSE_CLASS or any other ones aren't ++ X86_64_SSEUP_CLASS, everything should be passed in ++ memory. */ ++ if (classes[0] != X86_64_SSE_CLASS) ++ return 0; ++ ++ for (i = 1; i < words; i++) ++ if (classes[i] != X86_64_SSEUP_CLASS) ++ return 0; ++ } ++ ++ ++ /* Final merger cleanup. */ ++ for (i = 0; i < words; i++) ++ { ++ /* If one class is MEMORY, everything should be passed in ++ memory. */ ++ if (classes[i] == X86_64_MEMORY_CLASS) ++ return 0; ++ ++ /* The X86_64_SSEUP_CLASS should be always preceded by ++ X86_64_SSE_CLASS. */ ++ if (classes[i] == X86_64_SSEUP_CLASS ++ && classes[i - 1] != X86_64_SSE_CLASS ++ && classes[i - 1] != X86_64_SSEUP_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ ++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ ++ if (classes[i] == X86_64_X87UP_CLASS ++ && classes[i - 1] != X86_64_X87_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ } ++ ++ return words; ++ } ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ return 0; /* Never reached. */ ++} ++ ++/* Examine the argument and return set number of register required in each ++ class. Return zero if parameter should be passed in memory, otherwise ++ the number of registers. */ ++static int ++examine_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[MAX_CLASSES], ++ _Bool in_return, ++ int* pngpr, ++ int* pnsse) ++{ ++ int n = classify_argument(type, classes, 0); ++ int ngpr = 0; ++ int nsse = 0; ++ int i; ++ ++ if (n == 0) ++ return 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ ngpr++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ nsse++; ++ break; ++ ++ case X86_64_NO_CLASS: ++ case X86_64_SSEUP_CLASS: ++ break; ++ ++ case X86_64_X87_CLASS: ++ case X86_64_X87UP_CLASS: ++ case X86_64_COMPLEX_X87_CLASS: ++ return in_return != 0; ++ ++ default: ++ abort(); ++ } ++ } ++ ++ *pngpr = ngpr; ++ *pnsse = nsse; ++ ++ return n; ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ int gprcount = 0; ++ int ssecount = 0; ++ int flags = cif->rtype->type; ++ int i, avn, n, ngpr, nsse; ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ size_t bytes; ++ ++ if (flags != FFI_TYPE_VOID) ++ { ++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value is passed in memory. A pointer to that ++ memory is the first argument. Allocate a register for it. */ ++ gprcount++; ++ ++ /* We don't have to do anything in asm for the return. */ ++ flags = FFI_TYPE_VOID; ++ } ++ else if (flags == FFI_TYPE_STRUCT) ++ { ++ /* Mark which registers the result appears in. */ ++ _Bool sse0 = SSE_CLASS_P(classes[0]); ++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]); ++ ++ if (sse0 && !sse1) ++ flags |= 1 << 8; ++ else if (!sse0 && sse1) ++ flags |= 1 << 9; ++ else if (sse0 && sse1) ++ flags |= 1 << 10; ++ ++ /* Mark the true size of the structure. */ ++ flags |= cif->rtype->size << 12; ++ } ++ } ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) ++ { ++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = cif->arg_types[i]->alignment; ++ ++ if (align < 8) ++ align = 8; ++ ++ bytes = ALIGN(bytes, align); ++ bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += ngpr; ++ ssecount += nsse; ++ } ++ } ++ ++ if (ssecount) ++ flags |= 1 << 11; ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ cif->bytes = ALIGN(bytes,8); ++ ++ return FFI_OK; ++} ++ ++void ++ffi_call( ++ ffi_cif* cif, ++ void (*fn)(), ++ void* rvalue, ++ void** avalue) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ char* stack; ++ char* argp; ++ ffi_type** arg_types; ++ int gprcount, ssecount, ngpr, nsse, i, avn; ++ _Bool ret_in_memory; ++ RegisterArgs* reg_args; ++ ++ /* Can't call 32-bit mode from 64-bit mode. */ ++ FFI_ASSERT(cif->abi == FFI_UNIX64); ++ ++ /* If the return value is a struct and we don't have a return value ++ address then we need to make one. Note the setting of flags to ++ VOID above in ffi_prep_cif_machdep. */ ++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT ++ && (cif->flags & 0xff) == FFI_TYPE_VOID); ++ ++ if (rvalue == NULL && ret_in_memory) ++ rvalue = alloca (cif->rtype->size); ++ ++ /* Allocate the space for the arguments, plus 4 words of temp space. */ ++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8); ++ reg_args = (RegisterArgs*)stack; ++ argp = stack + sizeof(RegisterArgs); ++ ++ gprcount = ssecount = 0; ++ ++ /* If the return value is passed in memory, add the pointer as the ++ first integer argument. */ ++ if (ret_in_memory) ++ reg_args->gpr[gprcount++] = (long) rvalue; ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ size_t size = arg_types[i]->size; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ memcpy (argp, avalue[i], size); ++ argp += size; ++ } ++ else ++ { /* The argument is passed entirely in registers. */ ++ char *a = (char *) avalue[i]; ++ int j; ++ ++ for (j = 0; j < n; j++, a += 8, size -= 8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ reg_args->gpr[gprcount] = 0; ++ switch (arg_types[i]->type) { ++ case FFI_TYPE_SINT8: ++ { ++ int8_t shortval = *(int8_t*)a; ++ int64_t actval = (int64_t)shortval; ++ reg_args->gpr[gprcount] = actval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ break; ++ } ++ ++ case FFI_TYPE_SINT16: ++ { ++ int16_t shortval = *(int16_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_SINT32: ++ { ++ int32_t shortval = *(int32_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT8: ++ { ++ u_int8_t shortval = *(u_int8_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ reg_args->gpr[gprcount] = actval; ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ { ++ u_int16_t shortval = *(u_int16_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT32: ++ { ++ u_int32_t shortval = *(u_int32_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ default: ++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); ++ reg_args->gpr[gprcount] = *(int64_t*)a; ++ } ++ gprcount++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSEDF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT64 *) a; ++ break; ++ ++ case X86_64_SSESF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT32 *) a; ++ break; ++ ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++ ++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs), ++ cif->flags, rvalue, fn, ssecount); ++} ++ ++extern void ffi_closure_unix64(void); ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ if (cif->abi != FFI_UNIX64) ++ return FFI_BAD_ABI; ++ ++ volatile unsigned short* tramp = ++ (volatile unsigned short*)&closure->tramp[0]; ++ ++ tramp[0] = 0xbb49; /* mov , %r11 */ ++ *(void* volatile*)&tramp[1] = ffi_closure_unix64; ++ tramp[5] = 0xba49; /* mov , %r10 */ ++ *(void* volatile*)&tramp[6] = closure; ++ ++ /* Set the carry bit if the function uses any sse registers. ++ This is clc or stc, together with the first byte of the jmp. */ ++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; ++ tramp[11] = 0xe3ff; /* jmp *%r11 */ ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wmissing-prototypes" ++int ++ffi_closure_unix64_inner( ++ ffi_closure* closure, ++ void* rvalue, ++ RegisterArgs* reg_args, ++ char* argp) ++#pragma clang diagnostic pop ++{ ++ ffi_cif* cif = closure->cif; ++ void** avalue = alloca(cif->nargs * sizeof(void *)); ++ ffi_type** arg_types; ++ long i, avn; ++ int gprcount = 0; ++ int ssecount = 0; ++ int ngpr, nsse; ++ int ret; ++ ++ ret = cif->rtype->type; ++ ++ if (ret != FFI_TYPE_VOID) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value goes in memory. Arrange for the closure ++ return value to go directly back to the original caller. */ ++ rvalue = (void *) reg_args->gpr[gprcount++]; ++ ++ /* We don't have to do anything in asm for the return. */ ++ ret = FFI_TYPE_VOID; ++ } ++ else if (ret == FFI_TYPE_STRUCT && n == 2) ++ { ++ /* Mark which register the second word of the structure goes in. */ ++ _Bool sse0 = SSE_CLASS_P (classes[0]); ++ _Bool sse1 = SSE_CLASS_P (classes[1]); ++ ++ if (!sse0 && sse1) ++ ret |= 1 << 8; ++ else if (sse0 && !sse1) ++ ret |= 1 << 9; ++ } ++ } ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ avalue[i] = argp; ++ argp += arg_types[i]->size; ++ } ++ ++#if !defined(X86_DARWIN) ++ /* If the argument is in a single register, or two consecutive ++ registers, then we can use that address directly. */ ++ else if (n == 1 || (n == 2 && ++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1]))) ++ { ++ // The argument is in a single register. ++ if (SSE_CLASS_P (classes[0])) ++ { ++ avalue[i] = ®_args->sse[ssecount]; ++ ssecount += n; ++ } ++ else ++ { ++ avalue[i] = ®_args->gpr[gprcount]; ++ gprcount += n; ++ } ++ } ++#endif ++ ++ /* Otherwise, allocate space to make them consecutive. */ ++ else ++ { ++ char *a = alloca (16); ++ int j; ++ ++ avalue[i] = a; ++ ++ for (j = 0; j < n; j++, a += 8) ++ { ++ if (SSE_CLASS_P (classes[j])) ++ memcpy (a, ®_args->sse[ssecount++], 8); ++ else ++ memcpy (a, ®_args->gpr[gprcount++], 8); ++ } ++ } ++ } ++ ++ /* Invoke the closure. */ ++ closure->fun (cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell assembly how to perform return type promotions. */ ++ return ret; ++} ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +new file mode 100644 +index 0000000..706ea0f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +@@ -0,0 +1,438 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ++ Copyright (c) 2002 Ranjit Mathew ++ Copyright (c) 2002 Bo Thorsen ++ Copyright (c) 2002 Roger Sayle ++ ++ x86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments */ ++ ++void ffi_prep_args(char *stack, extended_cif *ecif); ++ ++void ffi_prep_args(char *stack, extended_cif *ecif) ++{ ++ 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) ++ { ++ *(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) ++{ ++ /* 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_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; ++ } ++ ++#ifdef X86_DARWIN ++ cif->bytes = (cif->bytes + 15) & ~0xF; ++#endif ++ ++ return FFI_OK; ++} ++ ++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 *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); ++ ++#endif /* X86_WIN32 */ ++ ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++ ++/** private members **/ ++ ++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 */ ++ ++unsigned int FFI_HIDDEN ++ffi_closure_SYSV_inner (closure, respp, args) ++ffi_closure *closure; ++void **respp; ++void *args; ++{ ++ // 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 - (__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) ++{ ++ if (cif->abi != FFI_SYSV) ++ return FFI_BAD_ABI; ++ ++ 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 ++ ++ffi_status ++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) ++{ ++ 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) ++{ ++ 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 *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++ ++#ifdef X86_WIN32 ++extern void ++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++#endif /* X86_WIN32 */ ++ ++void ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++#endif ++#endif // __i386__ +diff --git ./setup.py ./setup.py +index 46b92fe..2bf6b4b 100644 +--- ./setup.py ++++ ./setup.py +@@ -98,8 +98,14 @@ class PyBuildExt(build_ext): + self.detect_modules() + + # Remove modules that are present on the disabled list +- self.extensions = [ext for ext in self.extensions +- if ext.name not in disabled_module_list] ++ extensions = [ext for ext in self.extensions ++ if ext.name not in disabled_module_list] ++ # move ctypes to the end, it depends on other modules ++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) ++ if "_ctypes" in ext_map: ++ ctypes = extensions.pop(ext_map["_ctypes"]) ++ extensions.append(ctypes) ++ self.extensions = extensions + + # Fix up the autodetected modules, prefixing all the source files + # with Modules/ and adding Python's include directory to the path. +@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext): + # *** Uncomment these for TOGL extension only: + # -lGL -lGLU -lXext -lXmu \ + ++ def configure_ctypes_darwin(self, ext): ++ # Darwin (OS X) uses preconfigured files, in ++ # the Modules/_ctypes/libffi_osx directory. ++ srcdir = sysconfig.get_config_var('srcdir') ++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', ++ '_ctypes', 'libffi_osx')) ++ sources = [os.path.join(ffi_srcdir, p) ++ for p in ['ffi.c', ++ 'x86/darwin64.S', ++ 'x86/x86-darwin.S', ++ 'x86/x86-ffi_darwin.c', ++ 'x86/x86-ffi64.c', ++ 'powerpc/ppc-darwin.S', ++ 'powerpc/ppc-darwin_closure.S', ++ 'powerpc/ppc-ffi_darwin.c', ++ 'powerpc/ppc64-darwin_closure.S', ++ ]] ++ ++ # Add .S (preprocessed assembly) to C compiler source extensions. ++ self.compiler.src_extensions.append('.S') ++ ++ include_dirs = [os.path.join(ffi_srcdir, 'include'), ++ os.path.join(ffi_srcdir, 'powerpc')] ++ ext.include_dirs.extend(include_dirs) ++ ext.sources.extend(sources) ++ return True ++ + def configure_ctypes(self, ext): + if not self.use_system_libffi: +- (srcdir,) = sysconfig.get_config_vars('srcdir') ++ if sys.platform == 'darwin': ++ return self.configure_ctypes_darwin(ext) ++ ++ srcdir = sysconfig.get_config_var('srcdir') + ffi_builddir = os.path.join(self.build_temp, 'libffi') + ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + '_ctypes', 'libffi')) +@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext): + ffi_configfile): + from distutils.dir_util import mkpath + mkpath(ffi_builddir) +- config_args = [] ++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() ++ if (('--host=' in arg) or ('--build=' in arg))] ++ if not self.verbose: ++ config_args.append("-q") + + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. +@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext): + self.compiler.src_extensions.append('.S') + + include_dirs = [os.path.join(ffi_builddir, 'include'), +- ffi_builddir, ffi_srcdir] ++ ffi_builddir, ++ os.path.join(ffi_srcdir, 'src')] + extra_compile_args = fficonfig['ffi_cflags'].split() + +- ext.sources.extend(fficonfig['ffi_sources']) ++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in ++ fficonfig['ffi_sources']) + ext.include_dirs.extend(include_dirs) + ext.extra_compile_args.extend(extra_compile_args) + return True +@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext): + + if sys.platform == 'darwin': + sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + # XXX Is this still needed? + ## extra_link_args.extend(['-read_only_relocs', 'warning']) +@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext): + if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = find_file('ffi.h', [], inc_dirs) ++ if sys.platform == 'darwin': ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') ++ ++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] ++ if not ffi_inc or ffi_inc[0] == '': ++ ffi_inc = find_file('ffi.h', [], inc_dirs) + if ffi_inc is not None: + ffi_h = ffi_inc[0] + '/ffi.h' + fp = open(ffi_h) diff --git a/plugins/python-build/share/python-build/patches/2.5.3/Python-2.5.3/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.3/Python-2.5.3/004_osx_libffi.patch new file mode 100644 index 00000000..cd500771 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/2.5.3/Python-2.5.3/004_osx_libffi.patch @@ -0,0 +1,6881 @@ +diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE +new file mode 100644 +index 0000000..f591795 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/LICENSE +@@ -0,0 +1,20 @@ ++libffi - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++``Software''), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice shall be included ++in all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++OTHER DEALINGS IN THE SOFTWARE. +diff --git ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README +new file mode 100644 +index 0000000..1fc2747 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README +@@ -0,0 +1,500 @@ ++This directory contains the libffi package, which is not part of GCC but ++shipped with GCC as convenience. ++ ++Status ++====== ++ ++libffi-2.00 has not been released yet! This is a development snapshot! ++ ++libffi-1.20 was released on October 5, 1998. Check the libffi web ++page for updates: . ++ ++ ++What is libffi? ++=============== ++ ++Compilers for high level languages generate code that follow certain ++conventions. These conventions are necessary, in part, for separate ++compilation to work. One such convention is the "calling ++convention". The "calling convention" is essentially a set of ++assumptions made by the compiler about where function arguments will ++be found on entry to a function. A "calling convention" also specifies ++where the return value for a function is found. ++ ++Some programs may not know at the time of compilation what arguments ++are to be passed to a function. For instance, an interpreter may be ++told at run-time about the number and types of arguments used to call ++a given function. Libffi can be used in such programs to provide a ++bridge from the interpreter program to compiled code. ++ ++The libffi library provides a portable, high level programming ++interface to various calling conventions. This allows a programmer to ++call any function specified by a call interface description at run ++time. ++ ++Ffi stands for Foreign Function Interface. A foreign function ++interface is the popular name for the interface that allows code ++written in one language to call code written in another language. The ++libffi library really only provides the lowest, machine dependent ++layer of a fully featured foreign function interface. A layer must ++exist above libffi that handles type conversions for values passed ++between the two languages. ++ ++ ++Supported Platforms and Prerequisites ++===================================== ++ ++Libffi has been ported to: ++ ++ SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) ++ ++ Irix 5.3 & 6.2 (System V/o32 & n32) ++ ++ Intel x86 - Linux (System V ABI) ++ ++ Alpha - Linux and OSF/1 ++ ++ m68k - Linux (System V ABI) ++ ++ PowerPC - Linux (System V ABI, Darwin, AIX) ++ ++ ARM - Linux (System V ABI) ++ ++Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are ++that other versions will work. Libffi has also been built and tested ++with the SGI compiler tools. ++ ++On PowerPC, the tests failed (see the note below). ++ ++You must use GNU make to build libffi. SGI's make will not work. ++Sun's probably won't either. ++ ++If you port libffi to another platform, please let me know! I assume ++that some will be easy (x86 NetBSD), and others will be more difficult ++(HP). ++ ++ ++Installing libffi ++================= ++ ++[Note: before actually performing any of these installation steps, ++ you may wish to read the "Platform Specific Notes" below.] ++ ++First you must configure the distribution for your particular ++system. Go to the directory you wish to build libffi in and run the ++"configure" program found in the root directory of the libffi source ++distribution. ++ ++You may want to tell configure where to install the libffi library and ++header files. To do that, use the --prefix configure switch. Libffi ++will install under /usr/local by default. ++ ++If you want to enable extra run-time debugging checks use the the ++--enable-debug configure switch. This is useful when your program dies ++mysteriously while using libffi. ++ ++Another useful configure switch is --enable-purify-safety. Using this ++will add some extra code which will suppress certain warnings when you ++are using Purify with libffi. Only use this switch when using ++Purify, as it will slow down the library. ++ ++Configure has many other options. Use "configure --help" to see them all. ++ ++Once configure has finished, type "make". Note that you must be using ++GNU make. SGI's make will not work. Sun's probably won't either. ++You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. ++ ++To ensure that libffi is working as advertised, type "make test". ++ ++To install the library and header files, type "make install". ++ ++ ++Using libffi ++============ ++ ++ The Basics ++ ---------- ++ ++Libffi assumes that you have a pointer to the function you wish to ++call and that you know the number and types of arguments to pass it, ++as well as the return type of the function. ++ ++The first thing you must do is create an ffi_cif object that matches ++the signature of the function you wish to call. The cif in ffi_cif ++stands for Call InterFace. To prepare a call interface object, use the ++following function: ++ ++ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, ++ unsigned int nargs, ++ ffi_type *rtype, ffi_type **atypes); ++ ++ CIF is a pointer to the call interface object you wish ++ to initialize. ++ ++ ABI is an enum that specifies the calling convention ++ to use for the call. FFI_DEFAULT_ABI defaults ++ to the system's native calling convention. Other ++ ABI's may be used with care. They are system ++ specific. ++ ++ NARGS is the number of arguments this function accepts. ++ libffi does not yet support vararg functions. ++ ++ RTYPE is a pointer to an ffi_type structure that represents ++ the return type of the function. Ffi_type objects ++ describe the types of values. libffi provides ++ ffi_type objects for many of the native C types: ++ signed int, unsigned int, signed char, unsigned char, ++ etc. There is also a pointer ffi_type object and ++ a void ffi_type. Use &ffi_type_void for functions that ++ don't return values. ++ ++ ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. ++ If NARGS is 0, this is ignored. ++ ++ ++ffi_prep_cif will return a status code that you are responsible ++for checking. It will be one of the following: ++ ++ FFI_OK - All is good. ++ ++ FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif ++ came across is bad. ++ ++ ++Before making the call, the VALUES vector should be initialized ++with pointers to the appropriate argument values. ++ ++To call the the function using the initialized ffi_cif, use the ++ffi_call function: ++ ++void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); ++ ++ CIF is a pointer to the ffi_cif initialized specifically ++ for this function. ++ ++ FN is a pointer to the function you want to call. ++ ++ RVALUE is a pointer to a chunk of memory that is to hold the ++ result of the function call. Currently, it must be ++ at least one word in size (except for the n32 version ++ under Irix 6.x, which must be a pointer to an 8 byte ++ aligned value (a long long). It must also be at least ++ word aligned (depending on the return type, and the ++ system's alignment requirements). If RTYPE is ++ &ffi_type_void, this is ignored. If RVALUE is NULL, ++ the return value is discarded. ++ ++ AVALUES is a vector of void* that point to the memory locations ++ holding the argument values for a call. ++ If NARGS is 0, this is ignored. ++ ++ ++If you are expecting a return value from FN it will have been stored ++at RVALUE. ++ ++ ++ ++ An Example ++ ---------- ++ ++Here is a trivial example that calls puts() a few times. ++ ++ #include ++ #include ++ ++ int main() ++ { ++ ffi_cif cif; ++ ffi_type *args[1]; ++ void *values[1]; ++ char *s; ++ int rc; ++ ++ /* Initialize the argument info vectors */ ++ args[0] = &ffi_type_uint; ++ values[0] = &s; ++ ++ /* Initialize the cif */ ++ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, ++ &ffi_type_uint, args) == FFI_OK) ++ { ++ s = "Hello World!"; ++ ffi_call(&cif, puts, &rc, values); ++ /* rc now holds the result of the call to puts */ ++ ++ /* values holds a pointer to the function's arg, so to ++ call puts() again all we need to do is change the ++ value of s */ ++ s = "This is cool!"; ++ ffi_call(&cif, puts, &rc, values); ++ } ++ ++ return 0; ++ } ++ ++ ++ ++ Aggregate Types ++ --------------- ++ ++Although libffi has no special support for unions or bit-fields, it is ++perfectly happy passing structures back and forth. You must first ++describe the structure to libffi by creating a new ffi_type object ++for it. Here is the definition of ffi_type: ++ ++ typedef struct _ffi_type ++ { ++ unsigned size; ++ short alignment; ++ short type; ++ struct _ffi_type **elements; ++ } ffi_type; ++ ++All structures must have type set to FFI_TYPE_STRUCT. You may set ++size and alignment to 0. These will be calculated and reset to the ++appropriate values by ffi_prep_cif(). ++ ++elements is a NULL terminated array of pointers to ffi_type objects ++that describe the type of the structure elements. These may, in turn, ++be structure elements. ++ ++The following example initializes a ffi_type object representing the ++tm struct from Linux's time.h: ++ ++ struct tm { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++ /* Those are for future use. */ ++ long int __tm_gmtoff__; ++ __const char *__tm_zone__; ++ }; ++ ++ { ++ ffi_type tm_type; ++ ffi_type *tm_type_elements[12]; ++ int i; ++ ++ tm_type.size = tm_type.alignment = 0; ++ tm_type.elements = &tm_type_elements; ++ ++ for (i = 0; i < 9; i++) ++ tm_type_elements[i] = &ffi_type_sint; ++ ++ tm_type_elements[9] = &ffi_type_slong; ++ tm_type_elements[10] = &ffi_type_pointer; ++ tm_type_elements[11] = NULL; ++ ++ /* tm_type can now be used to represent tm argument types and ++ return types for ffi_prep_cif() */ ++ } ++ ++ ++ ++Platform Specific Notes ++======================= ++ ++ Intel x86 ++ --------- ++ ++There are no known problems with the x86 port. ++ ++ Sun SPARC - SunOS 4.1.3 & Solaris 2.x ++ ------------------------------------- ++ ++You must use GNU Make to build libffi on Sun platforms. ++ ++ MIPS - Irix 5.3 & 6.x ++ --------------------- ++ ++Irix 6.2 and better supports three different calling conventions: o32, ++n32 and n64. Currently, libffi only supports both o32 and n32 under ++Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be ++configured for whichever calling convention it was built for. ++ ++By default, the configure script will try to build libffi with the GNU ++development tools. To build libffi with the SGI development tools, set ++the environment variable CC to either "cc -32" or "cc -n32" before ++running configure under Irix 6.x (depending on whether you want an o32 ++or n32 library), or just "cc" for Irix 5.3. ++ ++With the n32 calling convention, when returning structures smaller ++than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. ++Here's one way of forcing this: ++ ++ double struct_storage[2]; ++ my_small_struct *s = (my_small_struct *) struct_storage; ++ /* Use s for RVALUE */ ++ ++If you don't do this you are liable to get spurious bus errors. ++ ++"long long" values are not supported yet. ++ ++You must use GNU Make to build libffi on SGI platforms. ++ ++ ARM - System V ABI ++ ------------------ ++ ++The ARM port was performed on a NetWinder running ARM Linux ELF ++(2.0.31) and gcc 2.8.1. ++ ++ ++ ++ PowerPC System V ABI ++ -------------------- ++ ++There are two `System V ABI's which libffi implements for PowerPC. ++They differ only in how small structures are returned from functions. ++ ++In the FFI_SYSV version, structures that are 8 bytes or smaller are ++returned in registers. This is what GCC does when it is configured ++for solaris, and is what the System V ABI I have (dated September ++1995) says. ++ ++In the FFI_GCC_SYSV version, all structures are returned the same way: ++by passing a pointer as the first argument to the function. This is ++what GCC does when it is configured for linux or a generic sysv ++target. ++ ++EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a ++inconsistency with the SysV ABI: When a procedure is called with many ++floating-point arguments, some of them get put on the stack. They are ++all supposed to be stored in double-precision format, even if they are ++only single-precision, but EGCS stores single-precision arguments as ++single-precision anyway. This causes one test to fail (the `many ++arguments' test). ++ ++ ++What's With The Crazy Comments? ++=============================== ++ ++You might notice a number of cryptic comments in the code, delimited ++by /*@ and @*/. These are annotations read by the program LCLint, a ++tool for statically checking C programs. You can read all about it at ++. ++ ++ ++History ++======= ++ ++1.20 Oct-5-98 ++ Raffaele Sena produces ARM port. ++ ++1.19 Oct-5-98 ++ Fixed x86 long double and long long return support. ++ m68k bug fixes from Andreas Schwab. ++ Patch for DU assembler compatibility for the Alpha from Richard ++ Henderson. ++ ++1.18 Apr-17-98 ++ Bug fixes and MIPS configuration changes. ++ ++1.17 Feb-24-98 ++ Bug fixes and m68k port from Andreas Schwab. PowerPC port from ++ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. ++ ++1.16 Feb-11-98 ++ Richard Henderson produces Alpha port. ++ ++1.15 Dec-4-97 ++ Fixed an n32 ABI bug. New libtool, auto* support. ++ ++1.14 May-13-97 ++ libtool is now used to generate shared and static libraries. ++ Fixed a minor portability problem reported by Russ McManus ++ . ++ ++1.13 Dec-2-96 ++ Added --enable-purify-safety to keep Purify from complaining ++ about certain low level code. ++ Sparc fix for calling functions with < 6 args. ++ Linux x86 a.out fix. ++ ++1.12 Nov-22-96 ++ Added missing ffi_type_void, needed for supporting void return ++ types. Fixed test case for non MIPS machines. Cygnus Support ++ is now Cygnus Solutions. ++ ++1.11 Oct-30-96 ++ Added notes about GNU make. ++ ++1.10 Oct-29-96 ++ Added configuration fix for non GNU compilers. ++ ++1.09 Oct-29-96 ++ Added --enable-debug configure switch. Clean-ups based on LCLint ++ feedback. ffi_mips.h is always installed. Many configuration ++ fixes. Fixed ffitest.c for sparc builds. ++ ++1.08 Oct-15-96 ++ Fixed n32 problem. Many clean-ups. ++ ++1.07 Oct-14-96 ++ Gordon Irlam rewrites v8.S again. Bug fixes. ++ ++1.06 Oct-14-96 ++ Gordon Irlam improved the sparc port. ++ ++1.05 Oct-14-96 ++ Interface changes based on feedback. ++ ++1.04 Oct-11-96 ++ Sparc port complete (modulo struct passing bug). ++ ++1.03 Oct-10-96 ++ Passing struct args, and returning struct values works for ++ all architectures/calling conventions. Expanded tests. ++ ++1.02 Oct-9-96 ++ Added SGI n32 support. Fixed bugs in both o32 and Linux support. ++ Added "make test". ++ ++1.01 Oct-8-96 ++ Fixed float passing bug in mips version. Restructured some ++ of the code. Builds cleanly with SGI tools. ++ ++1.00 Oct-7-96 ++ First release. No public announcement. ++ ++ ++Authors & Credits ++================= ++ ++libffi was written by Anthony Green . ++ ++Portions of libffi were derived from Gianni Mariani's free gencall ++library for Silicon Graphics machines. ++ ++The closure mechanism was designed and implemented by Kresten Krab ++Thorup. ++ ++The Sparc port was derived from code contributed by the fine folks at ++Visible Decisions Inc . Further enhancements were ++made by Gordon Irlam at Cygnus Solutions . ++ ++The Alpha port was written by Richard Henderson at Cygnus Solutions. ++ ++Andreas Schwab ported libffi to m68k Linux and provided a number of ++bug fixes. ++ ++Geoffrey Keating ported libffi to the PowerPC. ++ ++Raffaele Sena ported libffi to the ARM. ++ ++Jesper Skov and Andrew Haley both did more than their fair share of ++stepping through the code and tracking down bugs. ++ ++Thanks also to Tom Tromey for bug fixes and configuration help. ++ ++Thanks to Jim Blandy, who provided some useful feedback on the libffi ++interface. ++ ++If you have a problem, or have found a bug, please send a note to ++green@cygnus.com. +diff --git ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc +new file mode 100644 +index 0000000..405d85f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README.pyobjc +@@ -0,0 +1,5 @@ ++This directory contains a slightly modified version of libffi, extracted from ++the GCC source-tree. ++ ++The only modifications are those that are necessary to compile libffi using ++the Apple provided compiler and outside of the GCC source tree. +diff --git ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c +new file mode 100644 +index 0000000..bf42093 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/ffi.c +@@ -0,0 +1,226 @@ ++/* ----------------------------------------------------------------------- ++ prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++/* Round up to FFI_SIZEOF_ARG. */ ++#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) ++ ++/* Perform machine independent initialization of aggregate type ++ specifications. */ ++ ++static ffi_status ++initialize_aggregate( ++/*@out@*/ ffi_type* arg) ++{ ++/*@-usedef@*/ ++ ++ if (arg == NULL || arg->elements == NULL || ++ arg->size != 0 || arg->alignment != 0) ++ return FFI_BAD_TYPEDEF; ++ ++ ffi_type** ptr = &(arg->elements[0]); ++ ++ while ((*ptr) != NULL) ++ { ++ if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#ifdef POWERPC_DARWIN ++ int curalign = (*ptr)->alignment; ++ ++ if (ptr != &(arg->elements[0])) ++ { ++ if (curalign > 4 && curalign != 16) ++ curalign = 4; ++ } ++ ++ arg->size = ALIGN(arg->size, curalign); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > curalign) ? ++ arg->alignment : curalign; ++#else ++ arg->size = ALIGN(arg->size, (*ptr)->alignment); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > (*ptr)->alignment) ? ++ arg->alignment : (*ptr)->alignment; ++#endif ++ ++ ptr++; ++ } ++ ++ /* Structure size includes tail padding. This is important for ++ structures that fit in one register on ABIs like the PowerPC64 ++ Linux ABI that right justify small structs in a register. ++ It's also needed for nested structure layout, for example ++ struct A { long a; char b; }; struct B { struct A x; char y; }; ++ should find y at an offset of 2*sizeof(long) and result in a ++ total size of 3*sizeof(long). */ ++ arg->size = ALIGN(arg->size, arg->alignment); ++ ++ if (arg->size == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ return FFI_OK; ++ ++/*@=usedef@*/ ++} ++ ++#ifndef __CRIS__ ++/* The CRIS ABI specifies structure elements to have byte ++ alignment only, so it completely overrides this functions, ++ which assumes "natural" alignment and padding. */ ++ ++/* Perform machine independent ffi_cif preparation, then call ++ machine dependent routine. */ ++ ++#if defined(X86_DARWIN) ++ ++static inline bool ++struct_on_stack( ++ int size) ++{ ++ if (size > 8) ++ return true; ++ ++ /* This is not what the ABI says, but is what is really implemented */ ++ switch (size) ++ { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ return false; ++ ++ default: ++ return true; ++ } ++} ++ ++#endif // defined(X86_DARWIN) ++ ++// Arguments' ffi_type->alignment must be nonzero. ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes) ++{ ++ if (cif == NULL) ++ return FFI_BAD_TYPEDEF; ++ ++ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI) ++ return FFI_BAD_ABI; ++ ++ unsigned int bytes = 0; ++ unsigned int i; ++ ffi_type** ptr; ++ ++ cif->abi = abi; ++ cif->arg_types = atypes; ++ cif->nargs = nargs; ++ cif->rtype = rtype; ++ cif->flags = 0; ++ ++ /* Initialize the return type if necessary */ ++ /*@-usedef@*/ ++ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ /*@=usedef@*/ ++ ++ /* Perform a sanity check on the return type */ ++ FFI_ASSERT_VALID_TYPE(cif->rtype); ++ ++ /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ ++#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA ++ /* Make space for the return structure pointer */ ++ if (cif->rtype->type == FFI_TYPE_STRUCT ++#ifdef SPARC ++ && (cif->abi != FFI_V9 || cif->rtype->size > 32) ++#endif ++#ifdef X86_DARWIN ++ && (struct_on_stack(cif->rtype->size)) ++#endif ++ ) ++ bytes = STACK_ARG_SIZE(sizeof(void*)); ++#endif ++ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ /* Initialize any uninitialized aggregate type definitions */ ++ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ if ((*ptr)->alignment == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type, do this ++ check after the initialization. */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#if defined(X86_DARWIN) ++ { ++ int align = (*ptr)->alignment; ++ ++ if (align > 4) ++ align = 4; ++ ++ if ((align - 1) & bytes) ++ bytes = ALIGN(bytes, align); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#elif !defined __x86_64__ && !defined S390 && !defined PA ++#ifdef SPARC ++ if (((*ptr)->type == FFI_TYPE_STRUCT ++ && ((*ptr)->size > 16 || cif->abi != FFI_V9)) ++ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE ++ && cif->abi != FFI_V9)) ++ bytes += sizeof(void*); ++ else ++#endif ++ { ++ /* Add any padding if necessary */ ++ if (((*ptr)->alignment - 1) & bytes) ++ bytes = ALIGN(bytes, (*ptr)->alignment); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#endif ++ } ++ ++ cif->bytes = bytes; ++ ++ /* Perform machine dependent cif processing */ ++ return ffi_prep_cif_machdep(cif); ++} ++#endif /* not __CRIS__ */ +diff --git ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h +new file mode 100644 +index 0000000..c104a5c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi.h +@@ -0,0 +1,355 @@ ++/* -----------------------------------------------------------------*-C-*- ++ libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++/* ------------------------------------------------------------------- ++ The basic API is described in the README file. ++ ++ The raw API is designed to bypass some of the argument packing ++ and unpacking on architectures for which it can be avoided. ++ ++ The closure API allows interpreted functions to be packaged up ++ inside a C function pointer, so that they can be called as C functions, ++ with no understanding on the client side that they are interpreted. ++ It can also be used in other cases in which it is necessary to package ++ up a user specified parameter and a function pointer as a single ++ function pointer. ++ ++ The closure API must be implemented in order to get its functionality, ++ e.g. for use by gij. Routines are provided to emulate the raw API ++ if the underlying platform doesn't allow faster implementation. ++ ++ More details on the raw and closure API can be found in: ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html ++ ++ and ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html ++ -------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_H ++#define LIBFFI_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Specify which architecture libffi is configured for. */ ++#ifdef MACOSX ++# if defined(__i386__) || defined(__x86_64__) ++# define X86_DARWIN ++# elif defined(__ppc__) || defined(__ppc64__) ++# define POWERPC_DARWIN ++# else ++# error "Unsupported MacOS X CPU type" ++# endif ++#else ++#error "Unsupported OS type" ++#endif ++ ++/* ---- System configuration information --------------------------------- */ ++ ++#include "ffitarget.h" ++#include "fficonfig.h" ++ ++#ifndef LIBFFI_ASM ++ ++#include ++#include ++ ++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). ++ But we can find it either under the correct ANSI name, or under GNU ++ C's internal name. */ ++#ifdef LONG_LONG_MAX ++# define FFI_LONG_LONG_MAX LONG_LONG_MAX ++#else ++# ifdef LLONG_MAX ++# define FFI_LONG_LONG_MAX LLONG_MAX ++# else ++# ifdef __GNUC__ ++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ ++# endif ++# endif ++#endif ++ ++#if SCHAR_MAX == 127 ++# define ffi_type_uchar ffi_type_uint8 ++# define ffi_type_schar ffi_type_sint8 ++#else ++#error "char size not supported" ++#endif ++ ++#if SHRT_MAX == 32767 ++# define ffi_type_ushort ffi_type_uint16 ++# define ffi_type_sshort ffi_type_sint16 ++#elif SHRT_MAX == 2147483647 ++# define ffi_type_ushort ffi_type_uint32 ++# define ffi_type_sshort ffi_type_sint32 ++#else ++#error "short size not supported" ++#endif ++ ++#if INT_MAX == 32767 ++# define ffi_type_uint ffi_type_uint16 ++# define ffi_type_sint ffi_type_sint16 ++#elif INT_MAX == 2147483647 ++# define ffi_type_uint ffi_type_uint32 ++# define ffi_type_sint ffi_type_sint32 ++#elif INT_MAX == 9223372036854775807 ++# define ffi_type_uint ffi_type_uint64 ++# define ffi_type_sint ffi_type_sint64 ++#else ++#error "int size not supported" ++#endif ++ ++#define ffi_type_ulong ffi_type_uint64 ++#define ffi_type_slong ffi_type_sint64 ++ ++#if LONG_MAX == 2147483647 ++# if FFI_LONG_LONG_MAX != 9223372036854775807 ++# error "no 64-bit data type supported" ++# endif ++#elif LONG_MAX != 9223372036854775807 ++#error "long size not supported" ++#endif ++ ++/* The closure code assumes that this works on pointers, i.e. a size_t ++ can hold a pointer. */ ++ ++typedef struct _ffi_type { ++ size_t size; ++ unsigned short alignment; ++ unsigned short type; ++/*@null@*/ struct _ffi_type** elements; ++} ffi_type; ++ ++/* These are defined in types.c */ ++extern ffi_type ffi_type_void; ++extern ffi_type ffi_type_uint8; ++extern ffi_type ffi_type_sint8; ++extern ffi_type ffi_type_uint16; ++extern ffi_type ffi_type_sint16; ++extern ffi_type ffi_type_uint32; ++extern ffi_type ffi_type_sint32; ++extern ffi_type ffi_type_uint64; ++extern ffi_type ffi_type_sint64; ++extern ffi_type ffi_type_float; ++extern ffi_type ffi_type_double; ++extern ffi_type ffi_type_longdouble; ++extern ffi_type ffi_type_pointer; ++ ++typedef enum ffi_status { ++ FFI_OK = 0, ++ FFI_BAD_TYPEDEF, ++ FFI_BAD_ABI ++} ffi_status; ++ ++typedef unsigned FFI_TYPE; ++ ++typedef struct ffi_cif { ++ ffi_abi abi; ++ unsigned nargs; ++/*@dependent@*/ ffi_type** arg_types; ++/*@dependent@*/ ffi_type* rtype; ++ unsigned bytes; ++ unsigned flags; ++#ifdef FFI_EXTRA_CIF_FIELDS ++ FFI_EXTRA_CIF_FIELDS; ++#endif ++} ffi_cif; ++ ++/* ---- Definitions for the raw API -------------------------------------- */ ++ ++#ifndef FFI_SIZEOF_ARG ++# if LONG_MAX == 2147483647 ++# define FFI_SIZEOF_ARG 4 ++# elif LONG_MAX == 9223372036854775807 ++# define FFI_SIZEOF_ARG 8 ++# endif ++#endif ++ ++typedef union { ++ ffi_sarg sint; ++ ffi_arg uint; ++ float flt; ++ char data[FFI_SIZEOF_ARG]; ++ void* ptr; ++} ffi_raw; ++ ++void ++ffi_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_raw_size( ++ ffi_cif* cif); ++ ++/* This is analogous to the raw API, except it uses Java parameter ++ packing, even on 64-bit machines. I.e. on 64-bit machines ++ longs and doubles are followed by an empty 64-bit word. */ ++void ++ffi_java_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_java_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_java_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_java_raw_size( ++ ffi_cif* cif); ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#if FFI_CLOSURES ++ ++typedef struct ffi_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ void (*fun)(ffi_cif*,void*,void**,void*); ++ void* user_data; ++} ffi_closure; ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void* user_data); ++ ++void ffi_closure_free(void *); ++void *ffi_closure_alloc (size_t size, void **code); ++ ++typedef struct ffi_raw_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ ++#if !FFI_NATIVE_RAW_API ++ /* if this is enabled, then a raw closure has the same layout ++ as a regular closure. We use this to install an intermediate ++ handler to do the transaltion, void** -> ffi_raw*. */ ++ void (*translate_args)(ffi_cif*,void*,void**,void*); ++ void* this_closure; ++#endif ++ ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*); ++ void* user_data; ++} ffi_raw_closure; ++ ++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_status ++ffi_prep_java_raw_closure( ++ ffi_raw_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*), ++ void* user_data); ++ ++#endif // FFI_CLOSURES ++ ++/* ---- Public interface definition -------------------------------------- */ ++ ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes); ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ void** avalue); ++ ++/* Useful for eliminating compiler warnings */ ++#define FFI_FN(f) ((void (*)(void))f) ++ ++#endif // #ifndef LIBFFI_ASM ++/* ---- Definitions shared with assembly code ---------------------------- */ ++ ++/* If these change, update src/mips/ffitarget.h. */ ++#define FFI_TYPE_VOID 0 ++#define FFI_TYPE_INT 1 ++#define FFI_TYPE_FLOAT 2 ++#define FFI_TYPE_DOUBLE 3 ++ ++#ifdef HAVE_LONG_DOUBLE ++# define FFI_TYPE_LONGDOUBLE 4 ++#else ++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE ++#endif ++ ++#define FFI_TYPE_UINT8 5 ++#define FFI_TYPE_SINT8 6 ++#define FFI_TYPE_UINT16 7 ++#define FFI_TYPE_SINT16 8 ++#define FFI_TYPE_UINT32 9 ++#define FFI_TYPE_SINT32 10 ++#define FFI_TYPE_UINT64 11 ++#define FFI_TYPE_SINT64 12 ++#define FFI_TYPE_STRUCT 13 ++#define FFI_TYPE_POINTER 14 ++ ++/* This should always refer to the last type code (for sanity checks) */ ++#define FFI_TYPE_LAST FFI_TYPE_POINTER ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef LIBFFI_H +diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h +new file mode 100644 +index 0000000..685a358 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi_common.h +@@ -0,0 +1,102 @@ ++/* ----------------------------------------------------------------------- ++ ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ++ ++ Common internal definitions and macros. Only necessary for building ++ libffi. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef FFI_COMMON_H ++#define FFI_COMMON_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fficonfig.h" ++ ++/* Do not move this. Some versions of AIX are very picky about where ++ this is positioned. */ ++#ifdef __GNUC__ ++# define alloca __builtin_alloca ++#else ++# if HAVE_ALLOCA_H ++# include ++# else ++# ifdef _AIX ++# pragma alloca ++# else ++# ifndef alloca /* predefined by HP cc +Olibcalls */ ++char* alloca(); ++# endif ++# endif ++# endif ++#endif ++ ++/* Check for the existence of memcpy. */ ++#if STDC_HEADERS ++# include ++#else ++# ifndef HAVE_MEMCPY ++# define memcpy(d, s, n) bcopy((s), (d), (n)) ++# endif ++#endif ++ ++/*#if defined(FFI_DEBUG) ++#include ++#endif*/ ++ ++#ifdef FFI_DEBUG ++#include ++ ++/*@exits@*/ void ++ffi_assert( ++/*@temp@*/ char* expr, ++/*@temp@*/ char* file, ++ int line); ++void ++ffi_stop_here(void); ++void ++ffi_type_test( ++/*@temp@*/ /*@out@*/ ffi_type* a, ++/*@temp@*/ char* file, ++ int line); ++ ++# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) ++# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) ++# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__) ++#else ++# define FFI_ASSERT(x) ++# define FFI_ASSERT_AT(x, f, l) ++# define FFI_ASSERT_VALID_TYPE(x) ++#endif // #ifdef FFI_DEBUG ++ ++#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) ++ ++/* Perform machine dependent cif processing */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif); ++ ++/* Extended cif, used in callback from assembly routine */ ++typedef struct extended_cif { ++/*@dependent@*/ ffi_cif* cif; ++/*@dependent@*/ void* rvalue; ++/*@dependent@*/ void** avalue; ++} extended_cif; ++ ++/* Terse sized type definitions. */ ++typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); ++typedef signed int SINT8 __attribute__((__mode__(__QI__))); ++typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); ++typedef signed int SINT16 __attribute__((__mode__(__HI__))); ++typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); ++typedef signed int SINT32 __attribute__((__mode__(__SI__))); ++typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); ++typedef signed int SINT64 __attribute__((__mode__(__DI__))); ++typedef float FLOAT32; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef FFI_COMMON_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h +new file mode 100644 +index 0000000..2172490 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/fficonfig.h +@@ -0,0 +1,150 @@ ++/* Manually created fficonfig.h for Darwin on PowerPC or Intel ++ ++ This file is manually generated to do away with the need for autoconf and ++ therefore make it easier to cross-compile and build fat binaries. ++ ++ NOTE: This file was added by PyObjC. ++*/ ++ ++#ifndef MACOSX ++#error "This file is only supported on Mac OS X" ++#endif ++ ++#if defined(__i386__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__x86_64__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__ppc__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# if __GNUC__ >= 4 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++# else ++# undef HAVE_LONG_DOUBLE ++# define SIZEOF_LONG_DOUBLE 8 ++# endif ++ ++#elif defined(__ppc64__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#else ++#error "Unknown CPU type" ++#endif ++ ++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP ++ systems. This function is required for `alloca.c' support on those systems. */ ++#undef CRAY_STACKSEG_END ++ ++/* Define to 1 if using `alloca.c'. */ ++/* #undef C_ALLOCA */ ++ ++/* Define to the flags needed for the .section .eh_frame directive. */ ++#define EH_FRAME_FLAGS "aw" ++ ++/* Define this if you want extra debugging. */ ++/* #undef FFI_DEBUG */ ++ ++/* Define this is you do not want support for the raw API. */ ++#define FFI_NO_RAW_API 1 ++ ++/* Define this if you do not want support for aggregate types. */ ++/* #undef FFI_NO_STRUCTS */ ++ ++/* Define to 1 if you have `alloca', as a function or macro. */ ++#define HAVE_ALLOCA 1 ++ ++/* Define to 1 if you have and it should be used (not on Ultrix). */ ++#define HAVE_ALLOCA_H 1 ++ ++/* Define if your assembler supports .register. */ ++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ ++ ++/* Define if your assembler and linker support unaligned PC relative relocs. */ ++/* #undef HAVE_AS_SPARC_UA_PCREL */ ++ ++/* Define to 1 if you have the `memcpy' function. */ ++#define HAVE_MEMCPY 1 ++ ++/* Define if mmap with MAP_ANON(YMOUS) works. */ ++#define HAVE_MMAP_ANON 1 ++ ++/* Define if mmap of /dev/zero works. */ ++/* #undef HAVE_MMAP_DEV_ZERO */ ++ ++/* Define if read-only mmap of a plain file works. */ ++#define HAVE_MMAP_FILE 1 ++ ++/* Define if .eh_frame sections should be read-only. */ ++/* #undef HAVE_RO_EH_FRAME */ ++ ++/* Define to 1 if your C compiler doesn't accept -c and -o together. */ ++/* #undef NO_MINUS_C_MINUS_O */ ++ ++/* Name of package */ ++#define PACKAGE "libffi" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "libffi" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "libffi 2.1" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libffi" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "2.1" ++ ++/* If using the C implementation of alloca, define if you know the ++ direction of stack growth for your system; otherwise it will be ++ automatically deduced at run-time. ++ STACK_DIRECTION > 0 => grows toward higher addresses ++ STACK_DIRECTION < 0 => grows toward lower addresses ++ STACK_DIRECTION = 0 => direction of growth unknown */ ++/* #undef STACK_DIRECTION */ ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this if you are using Purify and want to suppress spurious messages. */ ++/* #undef USING_PURIFY */ ++ ++/* Version number of package */ ++#define VERSION "2.1-pyobjc" ++ ++#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) .hidden name ++# else ++# define FFI_HIDDEN __attribute__((visibility ("hidden"))) ++# endif ++#else ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) ++# else ++# define FFI_HIDDEN ++# endif ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h +new file mode 100644 +index 0000000..faaa30d +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffitarget.h +@@ -0,0 +1,13 @@ ++/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a ++ normal build, the build environment copies the file to the right location or ++ sets up the right include flags. We want to do neither because that would ++ make building fat binaries harder. ++*/ ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "x86-ffitarget.h" ++#elif defined(__ppc__) || defined(__ppc64__) ++#include "ppc-ffitarget.h" ++#else ++#error "Unsupported CPU type" ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +new file mode 100644 +index 0000000..2318421 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +@@ -0,0 +1,104 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for PowerPC. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if (defined(POWERPC) && defined(__powerpc64__)) || \ ++ (defined(POWERPC_DARWIN) && defined(__ppc64__)) ++#define POWERPC64 ++#endif ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++#ifdef POWERPC ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++# ifdef POWERPC64 ++ FFI_DEFAULT_ABI = FFI_LINUX64, ++# else ++ FFI_DEFAULT_ABI = FFI_GCC_SYSV, ++# endif ++#endif ++ ++#ifdef POWERPC_AIX ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_AIX, ++#endif ++ ++#ifdef POWERPC_DARWIN ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_DARWIN, ++#endif ++ ++#ifdef POWERPC_FREEBSD ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++#define FFI_NATIVE_RAW_API 0 ++ ++/* Needed for FFI_SYSV small structure returns. */ ++#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) ++ ++#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/ ++# define FFI_TRAMPOLINE_SIZE 48 ++#elif defined(POWERPC_AIX) ++# define FFI_TRAMPOLINE_SIZE 24 ++#else ++# define FFI_TRAMPOLINE_SIZE 40 ++#endif ++ ++#ifndef LIBFFI_ASM ++# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) ++typedef struct ffi_aix_trampoline_struct { ++ void* code_pointer; /* Pointer to ffi_closure_ASM */ ++ void* toc; /* TOC */ ++ void* static_chain; /* Pointer to closure */ ++} ffi_aix_trampoline_struct; ++# endif ++#endif // #ifndef LIBFFI_ASM ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +new file mode 100644 +index 0000000..55c2b6c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +@@ -0,0 +1,88 @@ ++/* -----------------------------------------------------------------*-C-*- ++ x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for x86 and x86-64. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if defined(X86_64) && defined(__i386__) ++# undef X86_64 ++# define X86 ++#endif ++ ++#if defined(__x86_64__) ++# ifndef X86_64 ++# define X86_64 ++# endif ++#endif ++ ++/* ---- Generic type definitions ----------------------------------------- */ ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++ /* ---- Intel x86 Win32 ---------- */ ++#ifdef X86_WIN32 ++ FFI_SYSV, ++ FFI_STDCALL, ++ /* TODO: Add fastcall support for the sake of completeness */ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ /* ---- Intel x86 and AMD x86-64 - */ ++#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) ++ FFI_SYSV, ++ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ ++# ifdef __i386__ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++# else ++ FFI_DEFAULT_ABI = FFI_UNIX64, ++# endif ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++ ++#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN)) ++# define FFI_TRAMPOLINE_SIZE 24 ++# define FFI_NATIVE_RAW_API 0 ++#else ++# define FFI_TRAMPOLINE_SIZE 10 ++# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ ++#endif ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +new file mode 100644 +index 0000000..f143dbd +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +@@ -0,0 +1,365 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist ++ Copyright (c) 2004 Free Software Foundation, Inc. ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include ++#include ++#include ++ ++.text ++ .align 2 ++.globl _ffi_prep_args ++ ++.text ++ .align 2 ++.globl _ffi_call_DARWIN ++ ++.text ++ .align 2 ++_ffi_call_DARWIN: ++LFB0: ++ mr r12,r8 /* We only need r12 until the call, ++ so it doesn't have to be saved. */ ++ ++LFB1: ++ /* Save the old stack pointer as AP. */ ++ mr r8,r1 ++ ++LCFI0: ++#if defined(__ppc64__) ++ /* Allocate the stack space we need. ++ r4 (size of input data) ++ 48 bytes (linkage area) ++ 40 bytes (saved registers) ++ 8 bytes (extra FPR) ++ r4 + 96 bytes total ++ */ ++ ++ addi r4,r4,-96 // Add our overhead. ++ li r0,-32 // Align to 32 bytes. ++ and r4,r4,r0 ++#endif ++ stgux r1,r1,r4 // Grow the stack. ++ mflr r9 ++ ++ /* Save registers we use. */ ++#if defined(__ppc64__) ++ std r27,-40(r8) ++#endif ++ stg r28,MODE_CHOICE(-16,-32)(r8) ++ stg r29,MODE_CHOICE(-12,-24)(r8) ++ stg r30,MODE_CHOICE(-8,-16)(r8) ++ stg r31,MODE_CHOICE(-4,-8)(r8) ++ stg r9,SF_RETURN(r8) /* return address */ ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ stg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++LCFI1: ++#if defined(__ppc64__) ++ mr r27,r3 // our extended_cif ++#endif ++ /* Save arguments over call. */ ++ mr r31,r5 /* flags, */ ++ mr r30,r6 /* rvalue, */ ++ mr r29,r7 /* function address, */ ++ mr r28,r8 /* our AP. */ ++ ++LCFI2: ++ /* Call ffi_prep_args. */ ++ mr r4,r1 ++ li r9,0 ++ mtctr r12 /* r12 holds address of _ffi_prep_args. */ ++ bctrl ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ lg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++ /* Now do the call. ++ Set up cr1 with bits 4-7 of the flags. */ ++ mtcrf 0x40,r31 ++ ++ /* Load all those argument registers. ++ We have set up a nice stack frame, just load it into registers. */ ++ lg r3,SF_ARG1(r1) ++ lg r4,SF_ARG2(r1) ++ lg r5,SF_ARG3(r1) ++ lg r6,SF_ARG4(r1) ++ nop ++ lg r7,SF_ARG5(r1) ++ lg r8,SF_ARG6(r1) ++ lg r9,SF_ARG7(r1) ++ lg r10,SF_ARG8(r1) ++ ++ /* Load all the FP registers. */ ++ bf 6,L2 /* No floats to load. */ ++#if defined(__ppc64__) ++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#elif defined(__ppc__) ++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#else ++#error undefined architecture ++#endif ++ ++L2: ++ mr r12,r29 // Put the target address in r12 as specified. ++ mtctr r12 // Get the address to call into CTR. ++ nop ++ nop ++ bctrl // Make the call. ++ ++ // Deal with the return value. ++#if defined(__ppc64__) ++ mtcrf 0x3,r31 // flags in cr6 and cr7 ++ bt 27,L(st_return_value) ++#elif defined(__ppc__) ++ mtcrf 0x1,r31 // flags in cr7 ++#else ++#error undefined architecture ++#endif ++ ++ bt 30,L(done_return_value) ++ bt 29,L(fp_return_value) ++ stg r3,0(r30) ++#if defined(__ppc__) ++ bf 28,L(done_return_value) // Store the second long if necessary. ++ stg r4,4(r30) ++#endif ++ // Fall through ++ ++L(done_return_value): ++ lg r1,0(r1) // Restore stack pointer. ++ // Restore the registers we used. ++ lg r9,SF_RETURN(r1) // return address ++ lg r31,MODE_CHOICE(-4,-8)(r1) ++ mtlr r9 ++ lg r30,MODE_CHOICE(-8,-16)(r1) ++ lg r29,MODE_CHOICE(-12,-24)(r1) ++ lg r28,MODE_CHOICE(-16,-32)(r1) ++#if defined(__ppc64__) ++ ld r27,-40(r1) ++#endif ++ blr ++ ++#if defined(__ppc64__) ++L(st_return_value): ++ // Grow the stack enough to fit the registers. Leave room for 8 args ++ // to trample the 1st 8 slots in param area. ++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 ++ ++ // Store GPRs ++ std r3,SF_ARG9(r1) ++ std r4,SF_ARG10(r1) ++ std r5,SF_ARG11(r1) ++ std r6,SF_ARG12(r1) ++ nop ++ std r7,SF_ARG13(r1) ++ std r8,SF_ARG14(r1) ++ std r9,SF_ARG15(r1) ++ std r10,SF_ARG16(r1) ++ ++ // Store FPRs ++ nop ++ bf 26,L(call_struct_to_ram_form) ++ stfd f1,SF_ARG17(r1) ++ stfd f2,SF_ARG18(r1) ++ stfd f3,SF_ARG19(r1) ++ stfd f4,SF_ARG20(r1) ++ nop ++ stfd f5,SF_ARG21(r1) ++ stfd f6,SF_ARG22(r1) ++ stfd f7,SF_ARG23(r1) ++ stfd f8,SF_ARG24(r1) ++ nop ++ stfd f9,SF_ARG25(r1) ++ stfd f10,SF_ARG26(r1) ++ stfd f11,SF_ARG27(r1) ++ stfd f12,SF_ARG28(r1) ++ nop ++ stfd f13,SF_ARG29(r1) ++ ++L(call_struct_to_ram_form): ++ ld r3,0(r27) // extended_cif->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ addi r4,r1,SF_ARG9 // stored GPRs ++ addi r6,r1,SF_ARG17 // stored FPRs ++ li r5,0 // GPR size ptr (NULL) ++ li r7,0 // FPR size ptr (NULL) ++ li r8,0 // FPR count ptr (NULL) ++ li r10,0 // struct offset (NULL) ++ mr r9,r30 // return area ++ bl Lffi64_struct_to_ram_form$stub ++ lg r1,0(r1) // Restore stack pointer. ++ b L(done_return_value) ++#endif ++ ++L(fp_return_value): ++ /* Do we have long double to store? */ ++ bf 31,L(fd_return_value) ++ stfd f1,0(r30) ++ stfd f2,8(r30) ++ b L(done_return_value) ++ ++L(fd_return_value): ++ /* Do we have double to store? */ ++ bf 28,L(float_return_value) ++ stfd f1,0(r30) ++ b L(done_return_value) ++ ++L(float_return_value): ++ /* We only have a float to store. */ ++ stfs f1,0(r30) ++ b L(done_return_value) ++ ++LFE1: ++/* END(_ffi_call_DARWIN) */ ++ ++/* Provide a null definition of _ffi_call_AIX. */ ++.text ++ .align 2 ++.globl _ffi_call_AIX ++.text ++ .align 2 ++_ffi_call_AIX: ++ blr ++/* END(_ffi_call_AIX) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_call_DARWIN.eh ++_ffi_call_DARWIN.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x08 ; uleb128 0x08 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$5,LCFI1-LCFI0 ++ .long L$set$5 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .byte 0x9f ; DW_CFA_offset, column 0x1f ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x9e ; DW_CFA_offset, column 0x1e ++ .byte 0x2 ; uleb128 0x2 ++ .byte 0x9d ; DW_CFA_offset, column 0x1d ++ .byte 0x3 ; uleb128 0x3 ++ .byte 0x9c ; DW_CFA_offset, column 0x1c ++ .byte 0x4 ; uleb128 0x4 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$6,LCFI2-LCFI1 ++ .long L$set$6 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x1c ; uleb128 0x1c ++ .align LOG2_GPR_BYTES ++LEFDE1: ++ ++#if defined(__ppc64__) ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_ram_form$stub: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_ram_form ++ ++LO$ffi64_struct_to_ram_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_ram_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ ++#endif // __ppc__ || __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +new file mode 100644 +index 0000000..cf4bd50 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +@@ -0,0 +1,85 @@ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define L(x) x ++ ++#define SF_ARG9 MODE_CHOICE(56,112) ++#define SF_ARG10 MODE_CHOICE(60,120) ++#define SF_ARG11 MODE_CHOICE(64,128) ++#define SF_ARG12 MODE_CHOICE(68,136) ++#define SF_ARG13 MODE_CHOICE(72,144) ++#define SF_ARG14 MODE_CHOICE(76,152) ++#define SF_ARG15 MODE_CHOICE(80,160) ++#define SF_ARG16 MODE_CHOICE(84,168) ++#define SF_ARG17 MODE_CHOICE(88,176) ++#define SF_ARG18 MODE_CHOICE(92,184) ++#define SF_ARG19 MODE_CHOICE(96,192) ++#define SF_ARG20 MODE_CHOICE(100,200) ++#define SF_ARG21 MODE_CHOICE(104,208) ++#define SF_ARG22 MODE_CHOICE(108,216) ++#define SF_ARG23 MODE_CHOICE(112,224) ++#define SF_ARG24 MODE_CHOICE(116,232) ++#define SF_ARG25 MODE_CHOICE(120,240) ++#define SF_ARG26 MODE_CHOICE(124,248) ++#define SF_ARG27 MODE_CHOICE(128,256) ++#define SF_ARG28 MODE_CHOICE(132,264) ++#define SF_ARG29 MODE_CHOICE(136,272) ++ ++#define ASM_NEEDS_REGISTERS 4 ++#define NUM_GPR_ARG_REGISTERS 8 ++#define NUM_FPR_ARG_REGISTERS 13 ++ ++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8) ++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16) ++#define FFI_TYPE_4_BYTE(x) \ ++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\ ++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT) ++ ++#if !defined(LIBFFI_ASM) ++ ++enum { ++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7 ++ FLAG_RETURNS_FP = 1 << (31 - 29), ++ FLAG_RETURNS_64BITS = 1 << (31 - 28), ++ FLAG_RETURNS_128BITS = 1 << (31 - 31), ++ ++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6 ++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26), ++ ++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7), ++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI ++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5), ++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4) ++}; ++ ++#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*); ++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*); ++#endif ++ ++#endif // !defined(LIBFFI_ASM) +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +new file mode 100644 +index 0000000..c3d30c2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +@@ -0,0 +1,308 @@ ++#if defined(__ppc__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 // Save return address ++ stg r0,SF_RETURN(r1) ++ ++LCFI0: ++ /* 24/48 bytes (Linkage Area) ++ 32/64 bytes (outgoing parameter area, always reserved) ++ 104 bytes (13*8 from FPR) ++ 16/32 bytes (result) ++ 176/232 total bytes */ ++ ++ /* skip over caller save area and keep stack aligned to 16/32. */ ++ stgu r1,-SF_ROUND(176)(r1) ++ ++LCFI1: ++ /* We want to build up an area for the parameters passed ++ in registers. (both floating point and integer) */ ++ ++ /* 176/256 bytes (callee stack frame aligned to 16/32) ++ 24/48 bytes (caller linkage area) ++ 200/304 (start of caller parameter area aligned to 4/8) ++ */ ++ ++ /* Save GPRs 3 - 10 (aligned to 4/8) ++ in the parents outgoing area. */ ++ 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,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. ++ 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. Use it to look up in a table ++ so we know how to deal with each type. */ ++ 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 ++ ++LFE1: ++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ (4 instructions). For cache effectiveness we align to a 16 byte boundary ++ first. */ ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++/* case FFI_TYPE_VOID */ ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* case FFI_TYPE_INT */ ++Lret_type1: ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_FLOAT */ ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_DOUBLE */ ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_LONGDOUBLE */ ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT8 */ ++Lret_type5: ++ lbz r3,3(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT8 */ ++Lret_type6: ++ lbz r3,3(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT16 */ ++Lret_type7: ++ lhz r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT16 */ ++Lret_type8: ++ lha r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT32 */ ++Lret_type9: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT32 */ ++Lret_type10: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT64 */ ++Lret_type11: ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_SINT64 */ ++Lret_type12: // same as Lret_type11 ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_STRUCT */ ++Lret_type13: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* End 16-byte aligned cases */ ++/* case FFI_TYPE_POINTER */ ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ // fall through ++ ++/* case done */ ++Lfinish: ++ 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) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++ ++#endif // __ppc__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +new file mode 100644 +index 0000000..8953d5f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +@@ -0,0 +1,1776 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1998 Geoffrey Keating ++ ++ PowerPC Foreign Function Interface ++ ++ Darwin ABI support (c) 2001 John Hornkvist ++ AIX ABI support (c) 2002 Free Software Foundation, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#if defined(POWERPC_DARWIN) ++#include // for sys_icache_invalidate() ++#endif ++ ++#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 ++// points to one of these. ++typedef struct aix_fd_struct { ++ void* code_pointer; ++ void* toc; ++} aix_fd; ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments. ++ ++ The stack layout we want looks like this: ++ ++ | Return address from ffi_call_DARWIN | higher addresses ++ |--------------------------------------------| ++ | Previous backchain pointer 4/8 | stack pointer here ++ |--------------------------------------------|-\ <<< on entry to ++ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN ++ |--------------------------------------------| | ++ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 ++ |--------------------------------------------| | ++ | Space for GPR2 4/8 | | ++ |--------------------------------------------| | stack | ++ | Reserved (4/8)*2 | | grows | ++ |--------------------------------------------| | down V ++ | Space for callee's LR 4/8 | | ++ |--------------------------------------------| | lower addresses ++ | Saved CR 4/8 | | ++ |--------------------------------------------| | stack pointer here ++ | Current backchain pointer 4/8 | | during ++ |--------------------------------------------|-/ <<< ffi_call_DARWIN ++ ++ Note: ppc64 CR is saved in the low word of a long on the stack. ++*/ ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args( ++ extended_cif* inEcif, ++ unsigned *const stack) ++/*@=exportheader@*/ ++{ ++ /* Copy the ecif to a local var so we can trample the arg. ++ BC note: test this with GP later for possible problems... */ ++ volatile extended_cif* ecif = inEcif; ++ ++ const unsigned bytes = ecif->cif->bytes; ++ const unsigned flags = ecif->cif->flags; ++ ++ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode ++ and 8 in 64-bit mode. */ ++ unsigned long *const longStack = (unsigned long *const)stack; ++ ++ /* 'stacktop' points at the previous backchain pointer. */ ++#if defined(__ppc64__) ++ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, ++ // saved registers, and an extra FPR. ++ unsigned long *const stacktop = ++ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); ++#elif defined(__ppc__) ++ unsigned long *const stacktop = longStack + (bytes / sizeof(long)); ++#else ++#error undefined architecture ++#endif ++ ++ /* 'fpr_base' points at the space for fpr1, and grows upwards as ++ we use FPR registers. */ ++ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - ++ NUM_FPR_ARG_REGISTERS; ++ ++#if defined(__ppc64__) ++ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base ++ // down a couple pegs. ++ fpr_base -= 2; ++#endif ++ ++ unsigned int fparg_count = 0; ++ ++ /* 'next_arg' grows up as we put parameters in it. */ ++ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ ++ ++ int i; ++ double double_tmp; ++ void** p_argv = ecif->avalue; ++ unsigned long gprvalue; ++ ffi_type** ptr = ecif->cif->arg_types; ++ ++ /* Check that everything starts aligned properly. */ ++ FFI_ASSERT(stack == SF_ROUND(stack)); ++ FFI_ASSERT(stacktop == SF_ROUND(stacktop)); ++ FFI_ASSERT(bytes == SF_ROUND(bytes)); ++ ++ /* Deal with return values that are actually pass-by-reference. ++ Rule: ++ Return values are referenced by r3, so r4 is the first parameter. */ ++ ++ if (flags & FLAG_RETVAL_REFERENCE) ++ *next_arg++ = (unsigned long)(char*)ecif->rvalue; ++ ++ /* Now for the arguments. */ ++ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) ++ { ++ switch ((*ptr)->type) ++ { ++ /* If a floating-point parameter appears before all of the general- ++ purpose registers are filled, the corresponding GPRs that match ++ the size of the floating-point parameter are shadowed for the ++ benefit of vararg and pre-ANSI functions. */ ++ case FFI_TYPE_FLOAT: ++ double_tmp = *(float*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg++; ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ double_tmp = *(double*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg += MODE_CHOICE(2,1); ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++#elif defined(__ppc__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) ++ *(double*)fpr_base = *(double*)*p_argv; ++#else ++#error undefined architecture ++#endif ++ ++ *(long double*)next_arg = *(long double*)*p_argv; ++ fparg_count += 2; ++ fpr_base += 2; ++ next_arg += MODE_CHOICE(4,2); ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++#if defined(__ppc64__) ++ gprvalue = *(long long*)*p_argv; ++ goto putgpr; ++#elif defined(__ppc__) ++ *(long long*)next_arg = *(long long*)*p_argv; ++ next_arg += 2; ++ break; ++#else ++#error undefined architecture ++#endif ++ ++ case FFI_TYPE_POINTER: ++ gprvalue = *(unsigned long*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT8: ++ gprvalue = *(unsigned char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT8: ++ gprvalue = *(signed char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT16: ++ gprvalue = *(unsigned short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT16: ++ gprvalue = *(signed short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ ++ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, ++ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); ++ next_arg += gprSize / sizeof(long); ++ fpr_base += fprSize / sizeof(double); ++ ++#elif defined(__ppc__) ++ char* dest_cpy = (char*)next_arg; ++ ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. ++ Structures with 3 byte in size are padded upwards. */ ++ unsigned size_al = (*ptr)->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++ if (ecif->cif->abi == FFI_DARWIN) ++ { ++ if (size_al < 3) ++ dest_cpy += 4 - size_al; ++ } ++ ++ memcpy((char*)dest_cpy, (char*)*p_argv, size_al); ++ next_arg += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ gprvalue = *(unsigned*)*p_argv; ++ ++putgpr: ++ *next_arg++ = gprvalue; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Check that we didn't overrun the stack... */ ++ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); ++ //FFI_ASSERT((unsigned *)fpr_base ++ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); ++ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); ++} ++ ++#if defined(__ppc64__) ++ ++bool ++ffi64_struct_contains_fp( ++ const ffi_type* inType) ++{ ++ bool containsFP = false; ++ unsigned int i; ++ ++ for (i = 0; inType->elements[i] != NULL && !containsFP; i++) ++ { ++ if (inType->elements[i]->type == FFI_TYPE_FLOAT || ++ inType->elements[i]->type == FFI_TYPE_DOUBLE || ++ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) ++ containsFP = true; ++ else if (inType->elements[i]->type == FFI_TYPE_STRUCT) ++ containsFP = ffi64_struct_contains_fp(inType->elements[i]); ++ } ++ ++ return containsFP; ++} ++ ++#endif // defined(__ppc64__) ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ /* All this is for the DARWIN ABI. */ ++ int i; ++ ffi_type** ptr; ++ int intarg_count = 0; ++ int fparg_count = 0; ++ unsigned int flags = 0; ++ unsigned int size_al = 0; ++ ++ /* All the machine-independent calculation of cif->bytes will be wrong. ++ Redo the calculation for DARWIN. */ ++ ++ /* Space for the frame pointer, callee's LR, CR, etc, and for ++ the asm's temp regs. */ ++ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); ++ ++ /* Return value handling. The rules are as follows: ++ - 32-bit (or less) integer values are returned in gpr3; ++ - Structures of size <= 4 bytes also returned in gpr3; ++ - 64-bit integer values and structures between 5 and 8 bytes are ++ returned in gpr3 and gpr4; ++ - Single/double FP values are returned in fpr1; ++ - Long double FP (if not equivalent to double) values are returned in ++ fpr1 and fpr2; ++ - Larger structures values are allocated space and a pointer is passed ++ as the first argument. */ ++ switch (cif->rtype->type) ++ { ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ flags |= FLAG_RETURNS_128BITS; ++ flags |= FLAG_RETURNS_FP; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_DOUBLE: ++ flags |= FLAG_RETURNS_64BITS; ++ /* Fall through. */ ++ case FFI_TYPE_FLOAT: ++ flags |= FLAG_RETURNS_FP; ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ flags |= FLAG_RETURNS_64BITS; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ ++ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++ { ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ } ++ else ++ { ++ flags |= FLAG_RETURNS_STRUCT; ++ ++ if (ffi64_struct_contains_fp(cif->rtype)) ++ flags |= FLAG_STRUCT_CONTAINS_FP; ++ } ++ ++#elif defined(__ppc__) ++ ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_VOID: ++ flags |= FLAG_RETURNS_NOTHING; ++ break; ++ ++ default: ++ /* Returns 32-bit integer, or similar. Nothing to do here. */ ++ break; ++ } ++ ++ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the ++ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest ++ goes on the stack. Structures are passed as a pointer to a copy of ++ the structure. Stuff on the stack needs to keep proper alignment. */ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ switch ((*ptr)->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ fparg_count++; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ fparg_count += 2; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ ++ if ( ++#if defined(__ppc64__) ++ fparg_count > NUM_FPR_ARG_REGISTERS + 1 ++#elif defined(__ppc__) ++ fparg_count > NUM_FPR_ARG_REGISTERS ++#else ++#error undefined architecture ++#endif ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ ++ intarg_count += 2; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ /* 'long long' arguments are passed as two words, but ++ either both words must fit in registers or both go ++ on the stack. If they go on the stack, they must ++ be 8-byte-aligned. */ ++ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 ++ || (intarg_count >= NUM_GPR_ARG_REGISTERS ++ && intarg_count % 2 != 0)) ++ intarg_count++; ++ ++ intarg_count += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ size_al = (*ptr)->size; ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++#if defined(__ppc64__) ++ // Look for FP struct members. ++ unsigned int j; ++ ++ for (j = 0; (*ptr)->elements[j] != NULL; j++) ++ { ++ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || ++ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) ++ { ++ fparg_count++; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS) ++ intarg_count++; ++ } ++ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) ++ { ++ fparg_count += 2; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) ++ intarg_count += 2; ++ } ++ else ++ intarg_count++; ++ } ++#elif defined(__ppc__) ++ intarg_count += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ ++ break; ++ ++ default: ++ /* Everything else is passed as a 4/8-byte word in a GPR, either ++ the object itself or a pointer to it. */ ++ intarg_count++; ++ break; ++ } ++ } ++ ++ /* Space for the FPR registers, if needed. */ ++ if (fparg_count != 0) ++ { ++ flags |= FLAG_FP_ARGUMENTS; ++#if defined(__ppc64__) ++ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); ++#elif defined(__ppc__) ++ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ /* Stack space. */ ++#if defined(__ppc64__) ++ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + fparg_count) * sizeof(long); ++#elif defined(__ppc__) ++ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + 2 * fparg_count) * sizeof(long); ++#else ++#error undefined architecture ++#endif ++ else ++ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); ++ ++ /* The stack space allocated needs to be a multiple of 16/32 bytes. */ ++ bytes = SF_ROUND(bytes); ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ ++ return FFI_OK; ++} ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ++ffi_call_AIX( ++/*@out@*/ extended_cif*, ++ unsigned, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++ ++extern void ++ffi_call_DARWIN( ++/*@out@*/ extended_cif*, ++ unsigned long, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ 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) && ++ (cif->rtype->type == FFI_TYPE_STRUCT)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ switch (cif->abi) ++ { ++ case FFI_AIX: ++ /*@-usedef@*/ ++ ffi_call_AIX(&ecif, -cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ case FFI_DARWIN: ++ /*@-usedef@*/ ++ ffi_call_DARWIN(&ecif, -(long)cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++/* here I'd like to add the stack frame layout we use in darwin_closure.S ++ and aix_clsoure.S ++ ++ SP previous -> +---------------------------------------+ <--- child frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 4 ++ | saved CR 4 | ++ +---------------------------------------+ 8 ++ | saved LR 4 | ++ +---------------------------------------+ 12 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 16 ++ | reserved for binders 4 | ++ +---------------------------------------+ 20 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 24 ++ | always reserved 8*4=32 (previous GPRs)| ++ | according to the linkage convention | ++ | from AIX | ++ +---------------------------------------+ 56 ++ | our FPR area 13*8=104 | ++ | f1 | ++ | . | ++ | f13 | ++ +---------------------------------------+ 160 ++ | result area 8 | ++ +---------------------------------------+ 168 ++ | alignement to the next multiple of 16 | ++SP current --> +---------------------------------------+ 176 <- parent frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 180 ++ | saved CR 4 | ++ +---------------------------------------+ 184 ++ | saved LR 4 | ++ +---------------------------------------+ 188 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 192 ++ | reserved for binders 4 | ++ +---------------------------------------+ 196 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 200 ++ | always reserved 8*4=32 we store our | ++ | GPRs here | ++ | r3 | ++ | . | ++ | r10 | ++ +---------------------------------------+ 232 ++ | overflow part | ++ +---------------------------------------+ xxx ++ | ???? | ++ +---------------------------------------+ xxx ++*/ ++ ++#if !defined(POWERPC_DARWIN) ++ ++#define MIN_LINE_SIZE 32 ++ ++static void ++flush_icache( ++ char* addr) ++{ ++#ifndef _AIX ++ __asm__ volatile ( ++ "dcbf 0,%0\n" ++ "sync\n" ++ "icbi 0,%0\n" ++ "sync\n" ++ "isync" ++ : : "r" (addr) : "memory"); ++#endif ++} ++ ++static void ++flush_range( ++ char* addr, ++ int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i += MIN_LINE_SIZE) ++ flush_icache(addr + i); ++ ++ flush_icache(addr + size - 1); ++} ++ ++#endif // !defined(POWERPC_DARWIN) ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ switch (cif->abi) ++ { ++ case FFI_DARWIN: ++ { ++ FFI_ASSERT (cif->abi == FFI_DARWIN); ++ ++ unsigned int* tramp = (unsigned int*)&closure->tramp[0]; ++ ++#if defined(__ppc64__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0xe98b0018; // ld r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0xe96b0020; // ld r11,32(r11) ++ tramp[7] = 0x4e800420; // bctr ++ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; ++ *(unsigned long*)&tramp[10] = (unsigned long)closure; ++#elif defined(__ppc__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0x818b0018; // lwz r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0x816b001c; // lwz r11,28(r11) ++ tramp[7] = 0x4e800420; // bctr ++ tramp[8] = (unsigned long)ffi_closure_ASM; ++ tramp[9] = (unsigned long)closure; ++#else ++#error undefined architecture ++#endif ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ // Flush the icache. Only necessary on Darwin. ++#if defined(POWERPC_DARWIN) ++ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#else ++ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#endif ++ ++ break; ++ } ++ ++ case FFI_AIX: ++ { ++ FFI_ASSERT (cif->abi == FFI_AIX); ++ ++ ffi_aix_trampoline_struct* tramp_aix = ++ (ffi_aix_trampoline_struct*)(closure->tramp); ++ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; ++ ++ tramp_aix->code_pointer = fd->code_pointer; ++ tramp_aix->toc = fd->toc; ++ tramp_aix->static_chain = closure; ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ break; ++ } ++ ++ default: ++ return FFI_BAD_ABI; ++ } ++ ++ return FFI_OK; ++} ++ ++#if defined(__ppc__) ++ typedef double ldbits[2]; ++ ++ typedef union ++ { ++ ldbits lb; ++ long double ld; ++ } 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 ++ for a return value, ffi_closure_ASM invokes the following helper function ++ to do most of the work. */ ++int ++ffi_closure_helper_DARWIN( ++ ffi_closure* closure, ++ void* rvalue, ++ unsigned long* pgr, ++ ffi_dblfl* pfr) ++{ ++ /* rvalue is the pointer to space for return value in closure assembly ++ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM ++ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ ++ ++#if defined(__ppc__) ++ ldu temp_ld; ++#endif ++ ++ double temp; ++ unsigned int i; ++ unsigned int nf = 0; /* number of FPRs already used. */ ++ unsigned int ng = 0; /* number of GPRs already used. */ ++ ffi_cif* cif = closure->cif; ++ long avn = cif->nargs; ++ void** avalue = alloca(cif->nargs * sizeof(void*)); ++ ffi_type** arg_types = cif->arg_types; ++ ++ /* Copy the caller's structure return value address so that the closure ++ returns the data directly to the caller. */ ++#if defined(__ppc64__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT && ++ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++#elif defined(__ppc__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT) ++#else ++#error undefined architecture ++#endif ++ { ++ rvalue = (void*)*pgr; ++ pgr++; ++ ng++; ++ } ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ for (i = 0; i < avn; i++) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ avalue[i] = (char*)pgr + MODE_CHOICE(3,7); ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ avalue[i] = (char*)pgr + MODE_CHOICE(2,6); ++ ng++; ++ pgr++; ++ break; ++ ++#if defined(__ppc__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ avalue[i] = (char*)pgr + MODE_CHOICE(0,4); ++ ng++; ++ pgr++; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ if (cif->abi == FFI_DARWIN) ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ unsigned int savedFPRSize = fprSize; ++ ++ avalue[i] = alloca(arg_types[i]->size); ++ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, ++ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); ++ ++ ng += gprSize / sizeof(long); ++ pgr += gprSize / sizeof(long); ++ pfr += (fprSize - savedFPRSize) / sizeof(double); ++ ++#elif defined(__ppc__) ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. */ ++ unsigned int size_al = size_al = arg_types[i]->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN(arg_types[i]->size, 8); ++ ++ if (size_al < 3) ++ avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; ++ else ++ avalue[i] = (void*)pgr; ++ ++ ng += (size_al + 3) / sizeof(long); ++ pgr += (size_al + 3) / sizeof(long); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ /* Long long ints are passed in 1 or 2 GPRs. */ ++ avalue[i] = pgr; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ /* A float value consumes a GPR. ++ There are 13 64-bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ temp = pfr->d; ++ pfr->f = (float)temp; ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ /* A double value consumes one or two GPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++#elif defined(__ppc__) ++ /* A long double value consumes 2/4 GPRs and 2 FPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS - 1) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++ /* Here we have the situation where one part of the long double ++ is stored in fpr13 and the other part is already on the stack. ++ 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(temp_ld.lb[0])); ++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); ++ avalue[i] = &temp_ld.ld; ++ } ++#else ++#error undefined architecture ++#endif ++ else ++ avalue[i] = pgr; ++ ++ nf += 2; ++ ng += MODE_CHOICE(4,2); ++ pgr += MODE_CHOICE(4,2); ++ ++ break; ++ ++#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ (closure->fun)(cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell ffi_closure_ASM to perform return type promotions. */ ++ return cif->rtype->type; ++} ++ ++#if defined(__ppc64__) ++ ++/* ffi64_struct_to_ram_form ++ ++ Rebuild a struct's natural layout from buffers of concatenated registers. ++ Return the number of registers used. ++ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_ram_form( ++ const ffi_type* inType, ++ const char* inGPRs, ++ unsigned int* ioGPRMarker, ++ const char* inFPRs, ++ unsigned int* ioFPRMarker, ++ unsigned int* ioFPRsUsed, ++ char* outStruct, // caller-allocated ++ unsigned int* ioStructMarker) ++{ ++ unsigned int srcGMarker = 0; ++ unsigned int srcFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ unsigned int destMarker = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioGPRMarker) ++ srcGMarker = *ioGPRMarker; ++ ++ if (ioFPRMarker) ++ { ++ srcFMarker = *ioFPRMarker; ++ savedFMarker = srcFMarker; ++ } ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioStructMarker) ++ destMarker = *ioStructMarker; ++ ++ size_t i; ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ srcGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ srcFMarker = ALIGN(srcFMarker, 4); ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inGPRs[srcGMarker]; ++ ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcFMarker = ALIGN(srcFMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inGPRs[srcGMarker]; ++ ++ destMarker += 8; ++ ++ // Skip next GPR ++ srcGMarker += 8; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ destMarker = ALIGN(destMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ srcFMarker = ALIGN(srcFMarker, 8); ++ srcGMarker = ALIGN(srcGMarker, 8); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inFPRs[srcFMarker]; ++ srcFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ srcFMarker = ALIGN(srcFMarker, 16); ++ srcGMarker = ALIGN(srcGMarker, 16); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inGPRs[srcGMarker]; ++ } ++ ++ destMarker += 16; ++ ++ // Skip next 2 GPRs ++ srcGMarker += 16; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ if (inType->alignment == 1) // chars only ++ { ++ if (inType->size == 1) ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ else if (inType->size == 2) ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ i++; ++ } ++ else ++ { ++ memcpy(&outStruct[destMarker], ++ &inGPRs[srcGMarker], inType->size); ++ srcGMarker += inType->size; ++ destMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // chars and other stuff ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcGMarker = ALIGN(srcGMarker, 2); ++ destMarker = ALIGN(destMarker, 2); ++ ++ *(short*)&outStruct[destMarker] = ++ *(short*)&inGPRs[srcGMarker]; ++ srcGMarker += 2; ++ destMarker += 2; ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ *(int*)&outStruct[destMarker] = ++ *(int*)&inGPRs[srcGMarker]; ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcGMarker = ALIGN(srcGMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ *(long long*)&outStruct[destMarker] = ++ *(long long*)&inGPRs[srcGMarker]; ++ srcGMarker += 8; ++ destMarker += 8; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_ram_form(inType->elements[i], inGPRs, ++ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, ++ outStruct, &destMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); // unknown element type ++ break; ++ } ++ } ++ ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && srcGMarker == 16) ++ { ++ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; ++ srcFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioGPRMarker) ++ *ioGPRMarker = ALIGN(srcGMarker, 8); ++ ++ if (ioFPRMarker) ++ *ioFPRMarker = srcFMarker; ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(destMarker, 8); ++} ++ ++/* ffi64_struct_to_reg_form ++ ++ Copy a struct's elements into buffers that can be sliced into registers. ++ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers ++ to calculate size only. ++ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_reg_form( ++ const ffi_type* inType, ++ const char* inStruct, ++ unsigned int* ioStructMarker, ++ unsigned int* ioFPRsUsed, ++ char* outGPRs, // caller-allocated ++ unsigned int* ioGPRSize, ++ char* outFPRs, // caller-allocated ++ unsigned int* ioFPRSize) ++{ ++ size_t i; ++ unsigned int srcMarker = 0; ++ unsigned int destGMarker = 0; ++ unsigned int destFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioStructMarker) ++ srcMarker = *ioStructMarker; ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioGPRSize) ++ destGMarker = *ioGPRSize; ++ ++ if (ioFPRSize) ++ { ++ destFMarker = *ioFPRSize; ++ savedFMarker = destFMarker; ++ } ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ destGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ // Shadow floating-point types in GPRs for vararg and pre-ANSI ++ // functions. ++ case FFI_TYPE_FLOAT: ++ // Nudge markers to next 4/8-byte boundary ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcMarker = ALIGN(srcMarker, 8); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ ++ // Skip next GPR ++ destGMarker += 8; ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ srcMarker = ALIGN(srcMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ destFMarker = ALIGN(destFMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outFPRs != NULL && inStruct != NULL) ++ *(long double*)&outFPRs[destFMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ destFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ destGMarker = ALIGN(destGMarker, 16); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ } ++ ++ srcMarker += 16; ++ destGMarker += 16; // Skip next 2 GPRs ++ destGMarker = ALIGN(destGMarker, 8); // was 16 ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ if (inType->alignment == 1) // bytes only ++ { ++ if (inType->size == 1) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ } ++ else if (inType->size == 2) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; ++ } ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ i++; ++ } ++ else ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ // Avoid memcpy for small chunks. ++ if (inType->size <= sizeof(long)) ++ *(long*)&outGPRs[destGMarker] = ++ *(long*)&inStruct[srcMarker]; ++ else ++ memcpy(&outGPRs[destGMarker], ++ &inStruct[srcMarker], inType->size); ++ } ++ ++ srcMarker += inType->size; ++ destGMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // bytes and other stuff ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcMarker = ALIGN(srcMarker, 2); ++ destGMarker = ALIGN(destGMarker, 2); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(short*)&outGPRs[destGMarker] = ++ *(short*)&inStruct[srcMarker]; ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(int*)&outGPRs[destGMarker] = ++ *(int*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcMarker = ALIGN(srcMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long long*)&outGPRs[destGMarker] = ++ *(long long*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ destGMarker += 8; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_reg_form(inType->elements[i], ++ inStruct, &srcMarker, &fprsUsed, outGPRs, ++ &destGMarker, outFPRs, &destFMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && destGMarker == 16) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; ++ ++ destFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(srcMarker, 8); ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioGPRSize) ++ *ioGPRSize = ALIGN(destGMarker, 8); ++ ++ if (ioFPRSize) ++ *ioFPRSize = ALIGN(destFMarker, 8); ++} ++ ++/* ffi64_stret_needs_ptr ++ ++ Determine whether a returned struct needs a pointer in r3 or can fit ++ in registers. ++*/ ++ ++bool ++ffi64_stret_needs_ptr( ++ const ffi_type* inType, ++ unsigned short* ioGPRCount, ++ unsigned short* ioFPRCount) ++{ ++ // Obvious case first- struct is larger than combined FPR size. ++ if (inType->size > 14 * 8) ++ return true; ++ ++ // Now the struct can physically fit in registers, determine if it ++ // also fits logically. ++ bool needsPtr = false; ++ unsigned short gprsUsed = 0; ++ unsigned short fprsUsed = 0; ++ size_t i; ++ ++ if (ioGPRCount) ++ gprsUsed = *ioGPRCount; ++ ++ if (ioFPRCount) ++ fprsUsed = *ioFPRCount; ++ ++ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ gprsUsed++; ++ fprsUsed++; ++ ++ if (fprsUsed > 13) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ gprsUsed += 2; ++ fprsUsed += 2; ++ ++ if (fprsUsed > 14) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ { ++ needsPtr = true; ++ break; ++ } ++ ++ if (inType->elements[i + 1] == NULL) // last byte in the struct ++ break; ++ ++ // Count possible contiguous bytes ahead, up to 8. ++ unsigned short j; ++ ++ for (j = 1; j < 8; j++) ++ { ++ if (inType->elements[i + j] == NULL || ++ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) ++ break; ++ } ++ ++ i += j - 1; // allow for i++ before the test condition ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ needsPtr = ffi64_stret_needs_ptr( ++ inType->elements[i], &gprsUsed, &fprsUsed); ++ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ if (ioGPRCount) ++ *ioGPRCount = gprsUsed; ++ ++ if (ioFPRCount) ++ *ioFPRCount = fprsUsed; ++ ++ return needsPtr; ++} ++ ++/* ffi64_data_size ++ ++ Calculate the size in bytes of an ffi type. ++*/ ++ ++unsigned int ++ffi64_data_size( ++ const ffi_type* inType) ++{ ++ unsigned int size = 0; ++ ++ switch (inType->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ size = 1; ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ size = 2; ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_FLOAT: ++ size = 4; ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_DOUBLE: ++ size = 8; ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ size = 16; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ ffi64_struct_to_reg_form( ++ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); ++ break; ++ ++ case FFI_TYPE_VOID: ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ ++ return size; ++} ++ ++#endif /* defined(__ppc64__) */ ++#endif /* __ppc__ || __ppc64__ */ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +new file mode 100644 +index 0000000..7162fa1 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +@@ -0,0 +1,418 @@ ++#if defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc64-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 ++ stg r0,SF_RETURN(r1) // save return address ++ ++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. ++ stg r3,SF_ARG1(r1) ++ stg r4,SF_ARG2(r1) ++ stg r5,SF_ARG3(r1) ++ stg r6,SF_ARG4(r1) ++ stg r7,SF_ARG5(r1) ++ stg r8,SF_ARG6(r1) ++ stg r9,SF_ARG7(r1) ++ stg r10,SF_ARG8(r1) ++ ++LCFI0: ++/* 48 bytes (Linkage Area) ++ 64 bytes (outgoing parameter area, always reserved) ++ 112 bytes (14*8 for incoming FPR) ++ ? bytes (result) ++ 112 bytes (14*8 for outgoing FPR) ++ 16 bytes (2 saved registers) ++ 352 + ? total bytes ++*/ ++ ++ std r31,-8(r1) // Save registers we use. ++ std r30,-16(r1) ++ mr r30,r1 // Save the old SP. ++ mr r31,r11 // Save the ffi_closure around ffi64_data_size. ++ ++ // Calculate the space we need. ++ stdu r1,-SF_MINSIZE(r1) ++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ bl Lffi64_data_size$stub ++ ld r1,0(r1) ++ ++ addi r3,r3,352 // Add our overhead. ++ neg r3,r3 ++ li r0,-32 // Align to 32 bytes. ++ and r3,r3,r0 ++ stdux r1,r1,r3 // Grow the stack. ++ ++ mr r11,r31 // Copy the ffi_closure back. ++ ++LCFI1: ++ // We want to build up an area for the parameters passed ++ // in registers. (both floating point and integer) ++ ++/* 320 bytes (callee stack frame aligned to 32) ++ 48 bytes (caller linkage area) ++ 368 (start of caller parameter area aligned to 8) ++*/ ++ ++ // Save FPRs 1 - 14. (aligned to 8) ++ stfd f1,112(r1) ++ stfd f2,120(r1) ++ stfd f3,128(r1) ++ stfd f4,136(r1) ++ stfd f5,144(r1) ++ stfd f6,152(r1) ++ stfd f7,160(r1) ++ stfd f8,168(r1) ++ stfd f9,176(r1) ++ stfd f10,184(r1) ++ stfd f11,192(r1) ++ stfd f12,200(r1) ++ stfd f13,208(r1) ++ stfd f14,216(r1) ++ ++ // Set up registers for the routine that actually does the work. ++ mr r3,r11 // context pointer from the trampoline ++ addi r4,r1,224 // result storage ++ addi r5,r30,SF_ARG1 // saved GPRs ++ addi r6,r1,112 // saved FPRs ++ bl Lffi_closure_helper_DARWIN$stub ++ ++ // Look the proper starting point in table ++ // by using return type as an offset. ++ addi r5,r1,224 // 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. ++ mtctr r3 ++ bctr ++ ++LFE1: ++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ // (4 instructions). For cache effectiveness we align to a 16 byte ++ // boundary first. ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++// case FFI_TYPE_VOID ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++// case FFI_TYPE_INT ++Lret_type1: ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_FLOAT ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_DOUBLE ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_LONGDOUBLE ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT8 ++Lret_type5: ++ lbz r3,7(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT8 ++Lret_type6: ++ lbz r3,7(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT16 ++Lret_type7: ++ lhz r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT16 ++Lret_type8: ++ lha r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT32 ++Lret_type9: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT32 ++Lret_type10: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT64 ++Lret_type11: ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT64 ++Lret_type12: // same as Lret_type11 ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_STRUCT ++Lret_type13: ++ b Lret_struct ++ nop ++ nop ++ nop ++ ++// ** End 16-byte aligned cases ** ++// case FFI_TYPE_POINTER ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ b Lfinish ++ ++// copy struct into registers ++Lret_struct: ++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r31) // ffi_cif->rtype* ++ ld r31,24(r31) // ffi_cif->flags ++ mr r4,r5 // copy struct* to 2nd arg ++ addi r7,r1,SF_ARG9 // GPR return area ++ addi r9,r30,-16-(14*8) // FPR return area ++ li r5,0 // struct offset ptr (NULL) ++ li r6,0 // FPR used count ptr (NULL) ++ li r8,0 // GPR return area size ptr (NULL) ++ li r10,0 // FPR return area size ptr (NULL) ++ bl Lffi64_struct_to_reg_form$stub ++ ++ // Load GPRs ++ ld r3,SF_ARG9(r1) ++ ld r4,SF_ARG10(r1) ++ ld r5,SF_ARG11(r1) ++ ld r6,SF_ARG12(r1) ++ nop ++ ld r7,SF_ARG13(r1) ++ ld r8,SF_ARG14(r1) ++ ld r9,SF_ARG15(r1) ++ ld r10,SF_ARG16(r1) ++ nop ++ ++ // Load FPRs ++ mtcrf 0x2,r31 ++ bf 26,Lfinish ++ lfd f1,-16-(14*8)(r30) ++ lfd f2,-16-(13*8)(r30) ++ lfd f3,-16-(12*8)(r30) ++ lfd f4,-16-(11*8)(r30) ++ nop ++ lfd f5,-16-(10*8)(r30) ++ lfd f6,-16-(9*8)(r30) ++ lfd f7,-16-(8*8)(r30) ++ lfd f8,-16-(7*8)(r30) ++ nop ++ lfd f9,-16-(6*8)(r30) ++ lfd f10,-16-(5*8)(r30) ++ lfd f11,-16-(4*8)(r30) ++ lfd f12,-16-(3*8)(r30) ++ nop ++ lfd f13,-16-(2*8)(r30) ++ lfd f14,-16-(1*8)(r30) ++ // Fall through ++ ++// case done ++Lfinish: ++ 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. ++ blr ++ ++// END(ffi_closure_ASM) ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_reg_form$stub: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_reg_form ++ ++LO$ffi64_struct_to_reg_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) ++ mtctr r12 ++ bctr ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_data_size$stub: ++ .indirect_symbol _ffi64_data_size ++ mflr r0 ++ bcl 20,31,LO$ffi64_data_size ++ ++LO$ffi64_data_size: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_reg_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ .g_long dyld_stub_binding_helper ++ ++L_ffi64_data_size$lazy_ptr: ++ .indirect_symbol _ffi64_data_size ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c +new file mode 100644 +index 0000000..44806ae +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/types.c +@@ -0,0 +1,115 @@ ++/* ----------------------------------------------------------------------- ++ types.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Predefined ffi_types needed by libffi. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++/* Type definitions */ ++#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \ ++ ffi_type ffi_type_##n = { s, a, t, NULL } ++#define FFI_AGGREGATE_TYPEDEF(n, e) \ ++ ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } ++ ++FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); ++FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); ++FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); ++FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); ++FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); ++FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); ++FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); ++ ++/* Size and alignment are fake here. They must not be 0. */ ++FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); ++ ++#if defined ALPHA || defined SPARC64 || defined X86_64 || \ ++ defined S390X || defined IA64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); ++#else ++FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); ++#endif ++ ++#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN) ++ ++# ifdef X86_64 ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++# else ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++# endif ++ ++#elif defined(POWERPC_DARWIN) ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#elif defined SH ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++#else ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#endif ++ ++#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN) ++ ++# if defined X86_WIN32 || defined X86_64 ++ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++# endif ++ ++# ifdef X86_DARWIN ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined ARM || defined SH || defined POWERPC_AIX ++FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); ++#elif defined POWERPC_DARWIN ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# if __GNUC__ >= 4 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined SPARC ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# ifdef SPARC64 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined X86_64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++#else ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S +new file mode 100644 +index 0000000..165d469 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S +@@ -0,0 +1,417 @@ ++/* ----------------------------------------------------------------------- ++ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. ++ derived from unix64.S ++ ++ x86-64 Foreign Function Interface for Darwin. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifdef __x86_64__ ++#define LIBFFI_ASM ++#include ++#include ++ ++ .file "darwin64.S" ++.text ++ ++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, ++ void *raddr, void (*fnaddr)()); ++ ++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame ++ for this function. This has been allocated by ffi_call. We also ++ deallocate some of the stack that has been alloca'd. */ ++ ++ .align 3 ++ .globl _ffi_call_unix64 ++ ++_ffi_call_unix64: ++LUW0: ++ movq (%rsp), %r10 /* Load return address. */ ++ movq %rdi, %r12 /* Save a copy of the register area. */ ++ leaq (%rdi, %rsi), %rax /* Find local stack base. */ ++ movq %rdx, (%rax) /* Save flags. */ ++ movq %rcx, 8(%rax) /* Save raddr. */ ++ movq %rbp, 16(%rax) /* Save old frame pointer. */ ++ movq %r10, 24(%rax) /* Relocate return address. */ ++ movq %rax, %rbp /* Finalize local stack frame. */ ++LUW1: ++ /* movq %rdi, %r10 // Save a copy of the register area. */ ++ movq %r12, %r10 ++ movq %r8, %r11 /* Save a copy of the target fn. */ ++ movl %r9d, %eax /* Set number of SSE registers. */ ++ ++ /* Load up all argument registers. */ ++ movq (%r10), %rdi ++ movq 8(%r10), %rsi ++ movq 16(%r10), %rdx ++ movq 24(%r10), %rcx ++ movq 32(%r10), %r8 ++ movq 40(%r10), %r9 ++ testl %eax, %eax ++ jnz Lload_sse ++Lret_from_load_sse: ++ ++ /* Deallocate the reg arg area. */ ++ leaq 176(%r10), %rsp ++ ++ /* Call the user function. */ ++ call *%r11 ++ ++ /* Deallocate stack arg area; local stack frame in redzone. */ ++ leaq 24(%rbp), %rsp ++ ++ movq 0(%rbp), %rcx /* Reload flags. */ ++ movq 8(%rbp), %rdi /* Reload raddr. */ ++ movq 16(%rbp), %rbp /* Reload old frame pointer. */ ++LUW2: ++ ++ /* The first byte of the flags contains the FFI_TYPE. */ ++ movzbl %cl, %r10d ++ leaq Lstore_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lstore_table: ++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ ++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ ++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ ++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ ++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ ++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ ++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ ++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ ++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lst_void: ++ ret ++ .align 3 ++Lst_uint8: ++ movzbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_sint8: ++ movsbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint16: ++ movzwq %ax, %rax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint16: ++ movswq %ax, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint32: ++ movl %eax, %eax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint32: ++ cltq ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_int64: ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_float: ++ movss %xmm0, (%rdi) ++ ret ++ .align 3 ++Lst_double: ++ movsd %xmm0, (%rdi) ++ ret ++Lst_ldouble: ++ fstpt (%rdi) ++ ret ++ .align 3 ++Lst_struct: ++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */ ++ ++ /* We have to locate the values now, and since we don't want to ++ write too much data into the user's return value, we spill the ++ value to a 16 byte scratch area first. Bits 8, 9, and 10 ++ control where the values are located. Only one of the three ++ bits will be set; see ffi_prep_cif_machdep for the pattern. */ ++ movd %xmm0, %r10 ++ movd %xmm1, %r11 ++ testl $0x100, %ecx ++ cmovnz %rax, %rdx ++ cmovnz %r10, %rax ++ testl $0x200, %ecx ++ cmovnz %r10, %rdx ++ testl $0x400, %ecx ++ cmovnz %r10, %rax ++ cmovnz %r11, %rdx ++ movq %rax, (%rsi) ++ movq %rdx, 8(%rsi) ++ ++ /* Bits 12-31 contain the true size of the structure. Copy from ++ the scratch area to the true destination. */ ++ shrl $12, %ecx ++ rep movsb ++ ret ++ ++ /* Many times we can avoid loading any SSE registers at all. ++ It's not worth an indirect jump to load the exact set of ++ SSE registers needed; zero or all is a good compromise. */ ++ .align 3 ++LUW3: ++Lload_sse: ++ movdqa 48(%r10), %xmm0 ++ movdqa 64(%r10), %xmm1 ++ movdqa 80(%r10), %xmm2 ++ movdqa 96(%r10), %xmm3 ++ movdqa 112(%r10), %xmm4 ++ movdqa 128(%r10), %xmm5 ++ movdqa 144(%r10), %xmm6 ++ movdqa 160(%r10), %xmm7 ++ jmp Lret_from_load_sse ++ ++LUW4: ++ .align 3 ++ .globl _ffi_closure_unix64 ++ ++_ffi_closure_unix64: ++LUW5: ++ /* The carry flag is set by the trampoline iff SSE registers ++ are used. Don't clobber it before the branch instruction. */ ++ leaq -200(%rsp), %rsp ++LUW6: ++ movq %rdi, (%rsp) ++ movq %rsi, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rcx, 24(%rsp) ++ movq %r8, 32(%rsp) ++ movq %r9, 40(%rsp) ++ jc Lsave_sse ++Lret_from_save_sse: ++ ++ movq %r10, %rdi ++ leaq 176(%rsp), %rsi ++ movq %rsp, %rdx ++ leaq 208(%rsp), %rcx ++ call _ffi_closure_unix64_inner ++ ++ /* Deallocate stack frame early; return value is now in redzone. */ ++ addq $200, %rsp ++LUW7: ++ ++ /* The first byte of the return value contains the FFI_TYPE. */ ++ movzbl %al, %r10d ++ leaq Lload_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lload_table: ++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */ ++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ ++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ ++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ ++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lld_void: ++ ret ++ .align 3 ++Lld_int8: ++ movzbl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int16: ++ movzwl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int32: ++ movl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int64: ++ movq -24(%rsp), %rax ++ ret ++ .align 3 ++Lld_float: ++ movss -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_double: ++ movsd -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_ldouble: ++ fldt -24(%rsp) ++ ret ++ .align 3 ++Lld_struct: ++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, ++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading ++ both rdx and xmm1 with the second word. For the remaining, ++ bit 8 set means xmm0 gets the second word, and bit 9 means ++ that rax gets the second word. */ ++ movq -24(%rsp), %rcx ++ movq -16(%rsp), %rdx ++ movq -16(%rsp), %xmm1 ++ testl $0x100, %eax ++ cmovnz %rdx, %rcx ++ movd %rcx, %xmm0 ++ testl $0x200, %eax ++ movq -24(%rsp), %rax ++ cmovnz %rdx, %rax ++ ret ++ ++ /* See the comment above Lload_sse; the same logic applies here. */ ++ .align 3 ++LUW8: ++Lsave_sse: ++ movdqa %xmm0, 48(%rsp) ++ movdqa %xmm1, 64(%rsp) ++ movdqa %xmm2, 80(%rsp) ++ movdqa %xmm3, 96(%rsp) ++ movdqa %xmm4, 112(%rsp) ++ movdqa %xmm5, 128(%rsp) ++ movdqa %xmm6, 144(%rsp) ++ movdqa %xmm7, 160(%rsp) ++ jmp Lret_from_save_sse ++ ++LUW9: ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ ++ .long L$set$0 ++LSCIE1: ++ .long 0x0 /* CIE Identifier Tag */ ++ .byte 0x1 /* CIE Version */ ++ .ascii "zR\0" /* CIE Augmentation */ ++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ ++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ ++ .byte 0x10 /* CIE RA Column */ ++ .byte 0x1 /* uleb128 0x1; Augmentation size */ ++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */ ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 /* uleb128 0x7 */ ++ .byte 0x8 /* uleb128 0x8 */ ++ .byte 0x90 /* DW_CFA_offset, column 0x10 */ ++ .byte 0x1 ++ .align 3 ++LECIE1: ++ .globl _ffi_call_unix64.eh ++_ffi_call_unix64.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ ++ .long L$set$1 ++LASFDE1: ++ .long LASFDE1-EH_frame1 /* FDE CIE offset */ ++ .quad LUW0-. /* FDE initial location */ ++ .set L$set$2,LUW4-LUW0 /* FDE address range */ ++ .quad L$set$2 ++ .byte 0x0 /* Augmentation size */ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$3,LUW1-LUW0 ++ .long L$set$3 ++ ++ /* New stack frame based off rbp. This is a itty bit of unwind ++ trickery in that the CFA *has* changed. There is no easy way ++ to describe it correctly on entry to the function. Fortunately, ++ it doesn't matter too much since at all points we can correctly ++ unwind back to ffi_call. Note that the location to which we ++ moved the return address is (the new) CFA-8, so from the ++ perspective of the unwind info, it hasn't moved. */ ++ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ ++ .byte 0x6 ++ .byte 0x20 ++ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ ++ .byte 0x2 ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$4,LUW2-LUW1 ++ .long L$set$4 ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 ++ .byte 0x8 ++ .byte 0xc0+6 /* DW_CFA_restore, %rbp */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$5,LUW3-LUW2 ++ .long L$set$5 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE1: ++ .globl _ffi_closure_unix64.eh ++_ffi_closure_unix64.eh: ++LSFDE3: ++ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ ++ .long L$set$6 ++LASFDE3: ++ .long LASFDE3-EH_frame1 /* FDE CIE offset */ ++ .quad LUW5-. /* FDE initial location */ ++ .set L$set$7,LUW9-LUW5 /* FDE address range */ ++ .quad L$set$7 ++ .byte 0x0 /* Augmentation size */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$8,LUW6-LUW5 ++ .long L$set$8 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 208,1 /* uleb128 208 */ ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$9,LUW7-LUW6 ++ .long L$set$9 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 0x8 ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$10,LUW8-LUW7 ++ .long L$set$10 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE3: ++ .subsections_via_symbols ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +new file mode 100644 +index 0000000..925a841 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +@@ -0,0 +1,422 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. ++ ++ X86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++/* ++ * This file is based on sysv.S and then hacked up by Ronald who hasn't done ++ * assembly programming in 8 years. ++ */ ++ ++#ifndef __x86_64__ ++ ++#define LIBFFI_ASM ++#include ++#include ++ ++#ifdef PyObjC_STRICT_DEBUGGING ++ /* XXX: Debugging of stack alignment, to be removed */ ++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 ++#else ++#define ASSERT_STACK_ALIGNED ++#endif ++ ++.text ++ ++.globl _ffi_prep_args ++ ++ .align 4 ++.globl _ffi_call_SYSV ++ ++_ffi_call_SYSV: ++LFB1: ++ pushl %ebp ++LCFI0: ++ movl %esp,%ebp ++LCFI1: ++ subl $8,%esp ++ /* Make room for all of the new args. */ ++ movl 16(%ebp),%ecx ++ subl %ecx,%esp ++ ++ movl %esp,%eax ++ ++ /* Place all of the ffi_prep_args in position */ ++ subl $8,%esp ++ pushl 12(%ebp) ++ pushl %eax ++ call *8(%ebp) ++ ++ /* Return stack to previous state and call the function */ ++ addl $16,%esp ++ ++ call *28(%ebp) ++ ++ /* 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 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 Lnoretval ++ fstp %st(0) ++ ++ jmp Lepilogue ++ ++Lretint: ++ cmpl $FFI_TYPE_INT,%ecx ++ jne Lretfloat ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ movl %eax,0(%ecx) ++ jmp Lepilogue ++ ++Lretfloat: ++ cmpl $FFI_TYPE_FLOAT,%ecx ++ jne Lretdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstps (%ecx) ++ jmp Lepilogue ++ ++Lretdouble: ++ cmpl $FFI_TYPE_DOUBLE,%ecx ++ jne Lretlongdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpl (%ecx) ++ jmp Lepilogue ++ ++Lretlongdouble: ++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx ++ jne Lretint64 ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpt (%ecx) ++ jmp Lepilogue ++ ++Lretint64: ++ cmpl $FFI_TYPE_SINT64,%ecx ++ 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 Lepilogue ++ ++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 ++ ++Lnoretval: ++Lepilogue: ++ addl $8,%esp ++ movl %ebp,%esp ++ popl %ebp ++ ret ++LFE1: ++.ffi_call_SYSV_end: ++ ++ .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_UINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_SINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_UINT16, %eax ++ je Lcls_retstruct2 ++ 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 ++ ++.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__ */ ++ ++#endif /* defined __i386__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +new file mode 100644 +index 0000000..06feaf2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +@@ -0,0 +1,734 @@ ++#ifdef __x86_64__ ++ ++/* ----------------------------------------------------------------------- ++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen ++ ++ x86-64 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_GPR_REGS 6 ++#define MAX_SSE_REGS 8 ++ ++typedef struct RegisterArgs { ++ /* Registers for argument passing. */ ++ UINT64 gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++} RegisterArgs; ++ ++extern void ++ffi_call_unix64( ++ void* args, ++ unsigned long bytes, ++ unsigned flags, ++ void* raddr, ++ void (*fnaddr)(), ++ unsigned ssecount); ++ ++/* All reference to register classes here is identical to the code in ++ gcc/config/i386/i386.c. Do *not* change one without the other. */ ++ ++/* 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 reformating penalties. ++ ++ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves ++ whenever possible (upper half does contain padding). */ ++enum x86_64_reg_class ++{ ++ X86_64_NO_CLASS, ++ X86_64_INTEGER_CLASS, ++ X86_64_INTEGERSI_CLASS, ++ X86_64_SSE_CLASS, ++ X86_64_SSESF_CLASS, ++ X86_64_SSEDF_CLASS, ++ X86_64_SSEUP_CLASS, ++ X86_64_X87_CLASS, ++ X86_64_X87UP_CLASS, ++ X86_64_COMPLEX_X87_CLASS, ++ X86_64_MEMORY_CLASS ++}; ++ ++#define MAX_CLASSES 4 ++#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) ++ ++/* x86-64 register passing implementation. See x86-64 ABI for details. Goal ++ of this code is to classify each 8bytes of incoming argument by the register ++ class and assign registers accordingly. */ ++ ++/* Return the union class of CLASS1 and CLASS2. ++ See the x86-64 PS ABI for details. */ ++static enum x86_64_reg_class ++merge_classes( ++ enum x86_64_reg_class class1, ++ enum x86_64_reg_class class2) ++{ ++ /* Rule #1: If both classes are equal, this is the resulting class. */ ++ if (class1 == class2) ++ return class1; ++ ++ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is ++ the other class. */ ++ if (class1 == X86_64_NO_CLASS) ++ return class2; ++ ++ if (class2 == X86_64_NO_CLASS) ++ return class1; ++ ++ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ ++ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ ++ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) ++ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) ++ return X86_64_INTEGERSI_CLASS; ++ ++ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS ++ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) ++ return X86_64_INTEGER_CLASS; ++ ++ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, ++ MEMORY is used. */ ++ if (class1 == X86_64_X87_CLASS ++ || class1 == X86_64_X87UP_CLASS ++ || class1 == X86_64_COMPLEX_X87_CLASS ++ || class2 == X86_64_X87_CLASS ++ || class2 == X86_64_X87UP_CLASS ++ || class2 == X86_64_COMPLEX_X87_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #6: Otherwise class SSE is used. */ ++ return X86_64_SSE_CLASS; ++} ++ ++/* Classify the argument of type TYPE and mode MODE. ++ CLASSES will be filled by the register class used to pass each word ++ of the operand. The number of words is returned. In case the parameter ++ should be passed in memory, 0 is returned. As a special case for zero ++ sized containers, classes[0] will be NO_CLASS and 1 is returned. ++ ++ See the x86-64 PS ABI for details. */ ++ ++static int ++classify_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[], ++ size_t byte_offset) ++{ ++ switch (type->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++#if 0 ++ if (byte_offset + type->size <= 4) ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ else ++ classes[0] = X86_64_INTEGER_CLASS; ++ ++ return 1; ++#else ++ { ++ int size = byte_offset + type->size; ++ ++ if (size <= 4) ++ { ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ return 1; ++ } ++ else if (size <= 8) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ return 1; ++ } ++ else if (size <= 12) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else if (size <= 16) ++ { ++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else ++ FFI_ASSERT (0); ++ } ++#endif ++ ++ case FFI_TYPE_FLOAT: ++ if (byte_offset == 0) ++ classes[0] = X86_64_SSESF_CLASS; ++ else ++ classes[0] = X86_64_SSE_CLASS; ++ ++ return 1; ++ ++ case FFI_TYPE_DOUBLE: ++ classes[0] = X86_64_SSEDF_CLASS; ++ return 1; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ classes[0] = X86_64_X87_CLASS; ++ classes[1] = X86_64_X87UP_CLASS; ++ return 2; ++ ++ case FFI_TYPE_STRUCT: ++ { ++ ffi_type** ptr; ++ int i; ++ enum x86_64_reg_class subclasses[MAX_CLASSES]; ++ const int UNITS_PER_WORD = 8; ++ int words = ++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ++ ++ /* If the struct is larger than 16 bytes, pass it on the stack. */ ++ if (type->size > 16) ++ return 0; ++ ++ for (i = 0; i < words; i++) ++ classes[i] = X86_64_NO_CLASS; ++ ++ /* Merge the fields of structure. */ ++ for (ptr = type->elements; *ptr != NULL; ptr++) ++ { ++ byte_offset = ALIGN(byte_offset, (*ptr)->alignment); ++ ++ int num = classify_argument(*ptr, subclasses, byte_offset % 8); ++ ++ if (num == 0) ++ return 0; ++ ++ int pos = byte_offset / 8; ++ ++ for (i = 0; i < num; i++) ++ { ++ classes[i + pos] = ++ merge_classes(subclasses[i], classes[i + pos]); ++ } ++ ++ byte_offset += (*ptr)->size; ++ } ++ ++ if (words > 2) ++ { ++ /* When size > 16 bytes, if the first one isn't ++ X86_64_SSE_CLASS or any other ones aren't ++ X86_64_SSEUP_CLASS, everything should be passed in ++ memory. */ ++ if (classes[0] != X86_64_SSE_CLASS) ++ return 0; ++ ++ for (i = 1; i < words; i++) ++ if (classes[i] != X86_64_SSEUP_CLASS) ++ return 0; ++ } ++ ++ ++ /* Final merger cleanup. */ ++ for (i = 0; i < words; i++) ++ { ++ /* If one class is MEMORY, everything should be passed in ++ memory. */ ++ if (classes[i] == X86_64_MEMORY_CLASS) ++ return 0; ++ ++ /* The X86_64_SSEUP_CLASS should be always preceded by ++ X86_64_SSE_CLASS. */ ++ if (classes[i] == X86_64_SSEUP_CLASS ++ && classes[i - 1] != X86_64_SSE_CLASS ++ && classes[i - 1] != X86_64_SSEUP_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ ++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ ++ if (classes[i] == X86_64_X87UP_CLASS ++ && classes[i - 1] != X86_64_X87_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ } ++ ++ return words; ++ } ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ return 0; /* Never reached. */ ++} ++ ++/* Examine the argument and return set number of register required in each ++ class. Return zero if parameter should be passed in memory, otherwise ++ the number of registers. */ ++static int ++examine_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[MAX_CLASSES], ++ _Bool in_return, ++ int* pngpr, ++ int* pnsse) ++{ ++ int n = classify_argument(type, classes, 0); ++ int ngpr = 0; ++ int nsse = 0; ++ int i; ++ ++ if (n == 0) ++ return 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ ngpr++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ nsse++; ++ break; ++ ++ case X86_64_NO_CLASS: ++ case X86_64_SSEUP_CLASS: ++ break; ++ ++ case X86_64_X87_CLASS: ++ case X86_64_X87UP_CLASS: ++ case X86_64_COMPLEX_X87_CLASS: ++ return in_return != 0; ++ ++ default: ++ abort(); ++ } ++ } ++ ++ *pngpr = ngpr; ++ *pnsse = nsse; ++ ++ return n; ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ int gprcount = 0; ++ int ssecount = 0; ++ int flags = cif->rtype->type; ++ int i, avn, n, ngpr, nsse; ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ size_t bytes; ++ ++ if (flags != FFI_TYPE_VOID) ++ { ++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value is passed in memory. A pointer to that ++ memory is the first argument. Allocate a register for it. */ ++ gprcount++; ++ ++ /* We don't have to do anything in asm for the return. */ ++ flags = FFI_TYPE_VOID; ++ } ++ else if (flags == FFI_TYPE_STRUCT) ++ { ++ /* Mark which registers the result appears in. */ ++ _Bool sse0 = SSE_CLASS_P(classes[0]); ++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]); ++ ++ if (sse0 && !sse1) ++ flags |= 1 << 8; ++ else if (!sse0 && sse1) ++ flags |= 1 << 9; ++ else if (sse0 && sse1) ++ flags |= 1 << 10; ++ ++ /* Mark the true size of the structure. */ ++ flags |= cif->rtype->size << 12; ++ } ++ } ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) ++ { ++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = cif->arg_types[i]->alignment; ++ ++ if (align < 8) ++ align = 8; ++ ++ bytes = ALIGN(bytes, align); ++ bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += ngpr; ++ ssecount += nsse; ++ } ++ } ++ ++ if (ssecount) ++ flags |= 1 << 11; ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ cif->bytes = ALIGN(bytes,8); ++ ++ return FFI_OK; ++} ++ ++void ++ffi_call( ++ ffi_cif* cif, ++ void (*fn)(), ++ void* rvalue, ++ void** avalue) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ char* stack; ++ char* argp; ++ ffi_type** arg_types; ++ int gprcount, ssecount, ngpr, nsse, i, avn; ++ _Bool ret_in_memory; ++ RegisterArgs* reg_args; ++ ++ /* Can't call 32-bit mode from 64-bit mode. */ ++ FFI_ASSERT(cif->abi == FFI_UNIX64); ++ ++ /* If the return value is a struct and we don't have a return value ++ address then we need to make one. Note the setting of flags to ++ VOID above in ffi_prep_cif_machdep. */ ++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT ++ && (cif->flags & 0xff) == FFI_TYPE_VOID); ++ ++ if (rvalue == NULL && ret_in_memory) ++ rvalue = alloca (cif->rtype->size); ++ ++ /* Allocate the space for the arguments, plus 4 words of temp space. */ ++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8); ++ reg_args = (RegisterArgs*)stack; ++ argp = stack + sizeof(RegisterArgs); ++ ++ gprcount = ssecount = 0; ++ ++ /* If the return value is passed in memory, add the pointer as the ++ first integer argument. */ ++ if (ret_in_memory) ++ reg_args->gpr[gprcount++] = (long) rvalue; ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ size_t size = arg_types[i]->size; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ memcpy (argp, avalue[i], size); ++ argp += size; ++ } ++ else ++ { /* The argument is passed entirely in registers. */ ++ char *a = (char *) avalue[i]; ++ int j; ++ ++ for (j = 0; j < n; j++, a += 8, size -= 8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ reg_args->gpr[gprcount] = 0; ++ switch (arg_types[i]->type) { ++ case FFI_TYPE_SINT8: ++ { ++ int8_t shortval = *(int8_t*)a; ++ int64_t actval = (int64_t)shortval; ++ reg_args->gpr[gprcount] = actval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ break; ++ } ++ ++ case FFI_TYPE_SINT16: ++ { ++ int16_t shortval = *(int16_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_SINT32: ++ { ++ int32_t shortval = *(int32_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT8: ++ { ++ u_int8_t shortval = *(u_int8_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ reg_args->gpr[gprcount] = actval; ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ { ++ u_int16_t shortval = *(u_int16_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT32: ++ { ++ u_int32_t shortval = *(u_int32_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ default: ++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); ++ reg_args->gpr[gprcount] = *(int64_t*)a; ++ } ++ gprcount++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSEDF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT64 *) a; ++ break; ++ ++ case X86_64_SSESF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT32 *) a; ++ break; ++ ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++ ++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs), ++ cif->flags, rvalue, fn, ssecount); ++} ++ ++extern void ffi_closure_unix64(void); ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ if (cif->abi != FFI_UNIX64) ++ return FFI_BAD_ABI; ++ ++ volatile unsigned short* tramp = ++ (volatile unsigned short*)&closure->tramp[0]; ++ ++ tramp[0] = 0xbb49; /* mov , %r11 */ ++ *(void* volatile*)&tramp[1] = ffi_closure_unix64; ++ tramp[5] = 0xba49; /* mov , %r10 */ ++ *(void* volatile*)&tramp[6] = closure; ++ ++ /* Set the carry bit if the function uses any sse registers. ++ This is clc or stc, together with the first byte of the jmp. */ ++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; ++ tramp[11] = 0xe3ff; /* jmp *%r11 */ ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wmissing-prototypes" ++int ++ffi_closure_unix64_inner( ++ ffi_closure* closure, ++ void* rvalue, ++ RegisterArgs* reg_args, ++ char* argp) ++#pragma clang diagnostic pop ++{ ++ ffi_cif* cif = closure->cif; ++ void** avalue = alloca(cif->nargs * sizeof(void *)); ++ ffi_type** arg_types; ++ long i, avn; ++ int gprcount = 0; ++ int ssecount = 0; ++ int ngpr, nsse; ++ int ret; ++ ++ ret = cif->rtype->type; ++ ++ if (ret != FFI_TYPE_VOID) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value goes in memory. Arrange for the closure ++ return value to go directly back to the original caller. */ ++ rvalue = (void *) reg_args->gpr[gprcount++]; ++ ++ /* We don't have to do anything in asm for the return. */ ++ ret = FFI_TYPE_VOID; ++ } ++ else if (ret == FFI_TYPE_STRUCT && n == 2) ++ { ++ /* Mark which register the second word of the structure goes in. */ ++ _Bool sse0 = SSE_CLASS_P (classes[0]); ++ _Bool sse1 = SSE_CLASS_P (classes[1]); ++ ++ if (!sse0 && sse1) ++ ret |= 1 << 8; ++ else if (sse0 && !sse1) ++ ret |= 1 << 9; ++ } ++ } ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ avalue[i] = argp; ++ argp += arg_types[i]->size; ++ } ++ ++#if !defined(X86_DARWIN) ++ /* If the argument is in a single register, or two consecutive ++ registers, then we can use that address directly. */ ++ else if (n == 1 || (n == 2 && ++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1]))) ++ { ++ // The argument is in a single register. ++ if (SSE_CLASS_P (classes[0])) ++ { ++ avalue[i] = ®_args->sse[ssecount]; ++ ssecount += n; ++ } ++ else ++ { ++ avalue[i] = ®_args->gpr[gprcount]; ++ gprcount += n; ++ } ++ } ++#endif ++ ++ /* Otherwise, allocate space to make them consecutive. */ ++ else ++ { ++ char *a = alloca (16); ++ int j; ++ ++ avalue[i] = a; ++ ++ for (j = 0; j < n; j++, a += 8) ++ { ++ if (SSE_CLASS_P (classes[j])) ++ memcpy (a, ®_args->sse[ssecount++], 8); ++ else ++ memcpy (a, ®_args->gpr[gprcount++], 8); ++ } ++ } ++ } ++ ++ /* Invoke the closure. */ ++ closure->fun (cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell assembly how to perform return type promotions. */ ++ return ret; ++} ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +new file mode 100644 +index 0000000..706ea0f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +@@ -0,0 +1,438 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ++ Copyright (c) 2002 Ranjit Mathew ++ Copyright (c) 2002 Bo Thorsen ++ Copyright (c) 2002 Roger Sayle ++ ++ x86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments */ ++ ++void ffi_prep_args(char *stack, extended_cif *ecif); ++ ++void ffi_prep_args(char *stack, extended_cif *ecif) ++{ ++ 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) ++ { ++ *(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) ++{ ++ /* 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_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; ++ } ++ ++#ifdef X86_DARWIN ++ cif->bytes = (cif->bytes + 15) & ~0xF; ++#endif ++ ++ return FFI_OK; ++} ++ ++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 *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); ++ ++#endif /* X86_WIN32 */ ++ ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++ ++/** private members **/ ++ ++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 */ ++ ++unsigned int FFI_HIDDEN ++ffi_closure_SYSV_inner (closure, respp, args) ++ffi_closure *closure; ++void **respp; ++void *args; ++{ ++ // 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 - (__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) ++{ ++ if (cif->abi != FFI_SYSV) ++ return FFI_BAD_ABI; ++ ++ 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 ++ ++ffi_status ++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) ++{ ++ 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) ++{ ++ 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 *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++ ++#ifdef X86_WIN32 ++extern void ++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++#endif /* X86_WIN32 */ ++ ++void ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++#endif ++#endif // __i386__ +diff --git ./setup.py ./setup.py +index 46b92fe..2bf6b4b 100644 +--- ./setup.py ++++ ./setup.py +@@ -98,8 +98,14 @@ class PyBuildExt(build_ext): + self.detect_modules() + + # Remove modules that are present on the disabled list +- self.extensions = [ext for ext in self.extensions +- if ext.name not in disabled_module_list] ++ extensions = [ext for ext in self.extensions ++ if ext.name not in disabled_module_list] ++ # move ctypes to the end, it depends on other modules ++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) ++ if "_ctypes" in ext_map: ++ ctypes = extensions.pop(ext_map["_ctypes"]) ++ extensions.append(ctypes) ++ self.extensions = extensions + + # Fix up the autodetected modules, prefixing all the source files + # with Modules/ and adding Python's include directory to the path. +@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext): + # *** Uncomment these for TOGL extension only: + # -lGL -lGLU -lXext -lXmu \ + ++ def configure_ctypes_darwin(self, ext): ++ # Darwin (OS X) uses preconfigured files, in ++ # the Modules/_ctypes/libffi_osx directory. ++ srcdir = sysconfig.get_config_var('srcdir') ++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', ++ '_ctypes', 'libffi_osx')) ++ sources = [os.path.join(ffi_srcdir, p) ++ for p in ['ffi.c', ++ 'x86/darwin64.S', ++ 'x86/x86-darwin.S', ++ 'x86/x86-ffi_darwin.c', ++ 'x86/x86-ffi64.c', ++ 'powerpc/ppc-darwin.S', ++ 'powerpc/ppc-darwin_closure.S', ++ 'powerpc/ppc-ffi_darwin.c', ++ 'powerpc/ppc64-darwin_closure.S', ++ ]] ++ ++ # Add .S (preprocessed assembly) to C compiler source extensions. ++ self.compiler.src_extensions.append('.S') ++ ++ include_dirs = [os.path.join(ffi_srcdir, 'include'), ++ os.path.join(ffi_srcdir, 'powerpc')] ++ ext.include_dirs.extend(include_dirs) ++ ext.sources.extend(sources) ++ return True ++ + def configure_ctypes(self, ext): + if not self.use_system_libffi: +- (srcdir,) = sysconfig.get_config_vars('srcdir') ++ if sys.platform == 'darwin': ++ return self.configure_ctypes_darwin(ext) ++ ++ srcdir = sysconfig.get_config_var('srcdir') + ffi_builddir = os.path.join(self.build_temp, 'libffi') + ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + '_ctypes', 'libffi')) +@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext): + ffi_configfile): + from distutils.dir_util import mkpath + mkpath(ffi_builddir) +- config_args = [] ++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() ++ if (('--host=' in arg) or ('--build=' in arg))] ++ if not self.verbose: ++ config_args.append("-q") + + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. +@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext): + self.compiler.src_extensions.append('.S') + + include_dirs = [os.path.join(ffi_builddir, 'include'), +- ffi_builddir, ffi_srcdir] ++ ffi_builddir, ++ os.path.join(ffi_srcdir, 'src')] + extra_compile_args = fficonfig['ffi_cflags'].split() + +- ext.sources.extend(fficonfig['ffi_sources']) ++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in ++ fficonfig['ffi_sources']) + ext.include_dirs.extend(include_dirs) + ext.extra_compile_args.extend(extra_compile_args) + return True +@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext): + + if sys.platform == 'darwin': + sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + # XXX Is this still needed? + ## extra_link_args.extend(['-read_only_relocs', 'warning']) +@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext): + if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = find_file('ffi.h', [], inc_dirs) ++ if sys.platform == 'darwin': ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') ++ ++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] ++ if not ffi_inc or ffi_inc[0] == '': ++ ffi_inc = find_file('ffi.h', [], inc_dirs) + if ffi_inc is not None: + ffi_h = ffi_inc[0] + '/ffi.h' + fp = open(ffi_h) diff --git a/plugins/python-build/share/python-build/patches/2.5.4/Python-2.5.4/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.4/Python-2.5.4/004_osx_libffi.patch new file mode 100644 index 00000000..cd500771 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/2.5.4/Python-2.5.4/004_osx_libffi.patch @@ -0,0 +1,6881 @@ +diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE +new file mode 100644 +index 0000000..f591795 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/LICENSE +@@ -0,0 +1,20 @@ ++libffi - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++``Software''), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice shall be included ++in all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++OTHER DEALINGS IN THE SOFTWARE. +diff --git ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README +new file mode 100644 +index 0000000..1fc2747 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README +@@ -0,0 +1,500 @@ ++This directory contains the libffi package, which is not part of GCC but ++shipped with GCC as convenience. ++ ++Status ++====== ++ ++libffi-2.00 has not been released yet! This is a development snapshot! ++ ++libffi-1.20 was released on October 5, 1998. Check the libffi web ++page for updates: . ++ ++ ++What is libffi? ++=============== ++ ++Compilers for high level languages generate code that follow certain ++conventions. These conventions are necessary, in part, for separate ++compilation to work. One such convention is the "calling ++convention". The "calling convention" is essentially a set of ++assumptions made by the compiler about where function arguments will ++be found on entry to a function. A "calling convention" also specifies ++where the return value for a function is found. ++ ++Some programs may not know at the time of compilation what arguments ++are to be passed to a function. For instance, an interpreter may be ++told at run-time about the number and types of arguments used to call ++a given function. Libffi can be used in such programs to provide a ++bridge from the interpreter program to compiled code. ++ ++The libffi library provides a portable, high level programming ++interface to various calling conventions. This allows a programmer to ++call any function specified by a call interface description at run ++time. ++ ++Ffi stands for Foreign Function Interface. A foreign function ++interface is the popular name for the interface that allows code ++written in one language to call code written in another language. The ++libffi library really only provides the lowest, machine dependent ++layer of a fully featured foreign function interface. A layer must ++exist above libffi that handles type conversions for values passed ++between the two languages. ++ ++ ++Supported Platforms and Prerequisites ++===================================== ++ ++Libffi has been ported to: ++ ++ SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) ++ ++ Irix 5.3 & 6.2 (System V/o32 & n32) ++ ++ Intel x86 - Linux (System V ABI) ++ ++ Alpha - Linux and OSF/1 ++ ++ m68k - Linux (System V ABI) ++ ++ PowerPC - Linux (System V ABI, Darwin, AIX) ++ ++ ARM - Linux (System V ABI) ++ ++Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are ++that other versions will work. Libffi has also been built and tested ++with the SGI compiler tools. ++ ++On PowerPC, the tests failed (see the note below). ++ ++You must use GNU make to build libffi. SGI's make will not work. ++Sun's probably won't either. ++ ++If you port libffi to another platform, please let me know! I assume ++that some will be easy (x86 NetBSD), and others will be more difficult ++(HP). ++ ++ ++Installing libffi ++================= ++ ++[Note: before actually performing any of these installation steps, ++ you may wish to read the "Platform Specific Notes" below.] ++ ++First you must configure the distribution for your particular ++system. Go to the directory you wish to build libffi in and run the ++"configure" program found in the root directory of the libffi source ++distribution. ++ ++You may want to tell configure where to install the libffi library and ++header files. To do that, use the --prefix configure switch. Libffi ++will install under /usr/local by default. ++ ++If you want to enable extra run-time debugging checks use the the ++--enable-debug configure switch. This is useful when your program dies ++mysteriously while using libffi. ++ ++Another useful configure switch is --enable-purify-safety. Using this ++will add some extra code which will suppress certain warnings when you ++are using Purify with libffi. Only use this switch when using ++Purify, as it will slow down the library. ++ ++Configure has many other options. Use "configure --help" to see them all. ++ ++Once configure has finished, type "make". Note that you must be using ++GNU make. SGI's make will not work. Sun's probably won't either. ++You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. ++ ++To ensure that libffi is working as advertised, type "make test". ++ ++To install the library and header files, type "make install". ++ ++ ++Using libffi ++============ ++ ++ The Basics ++ ---------- ++ ++Libffi assumes that you have a pointer to the function you wish to ++call and that you know the number and types of arguments to pass it, ++as well as the return type of the function. ++ ++The first thing you must do is create an ffi_cif object that matches ++the signature of the function you wish to call. The cif in ffi_cif ++stands for Call InterFace. To prepare a call interface object, use the ++following function: ++ ++ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, ++ unsigned int nargs, ++ ffi_type *rtype, ffi_type **atypes); ++ ++ CIF is a pointer to the call interface object you wish ++ to initialize. ++ ++ ABI is an enum that specifies the calling convention ++ to use for the call. FFI_DEFAULT_ABI defaults ++ to the system's native calling convention. Other ++ ABI's may be used with care. They are system ++ specific. ++ ++ NARGS is the number of arguments this function accepts. ++ libffi does not yet support vararg functions. ++ ++ RTYPE is a pointer to an ffi_type structure that represents ++ the return type of the function. Ffi_type objects ++ describe the types of values. libffi provides ++ ffi_type objects for many of the native C types: ++ signed int, unsigned int, signed char, unsigned char, ++ etc. There is also a pointer ffi_type object and ++ a void ffi_type. Use &ffi_type_void for functions that ++ don't return values. ++ ++ ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. ++ If NARGS is 0, this is ignored. ++ ++ ++ffi_prep_cif will return a status code that you are responsible ++for checking. It will be one of the following: ++ ++ FFI_OK - All is good. ++ ++ FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif ++ came across is bad. ++ ++ ++Before making the call, the VALUES vector should be initialized ++with pointers to the appropriate argument values. ++ ++To call the the function using the initialized ffi_cif, use the ++ffi_call function: ++ ++void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); ++ ++ CIF is a pointer to the ffi_cif initialized specifically ++ for this function. ++ ++ FN is a pointer to the function you want to call. ++ ++ RVALUE is a pointer to a chunk of memory that is to hold the ++ result of the function call. Currently, it must be ++ at least one word in size (except for the n32 version ++ under Irix 6.x, which must be a pointer to an 8 byte ++ aligned value (a long long). It must also be at least ++ word aligned (depending on the return type, and the ++ system's alignment requirements). If RTYPE is ++ &ffi_type_void, this is ignored. If RVALUE is NULL, ++ the return value is discarded. ++ ++ AVALUES is a vector of void* that point to the memory locations ++ holding the argument values for a call. ++ If NARGS is 0, this is ignored. ++ ++ ++If you are expecting a return value from FN it will have been stored ++at RVALUE. ++ ++ ++ ++ An Example ++ ---------- ++ ++Here is a trivial example that calls puts() a few times. ++ ++ #include ++ #include ++ ++ int main() ++ { ++ ffi_cif cif; ++ ffi_type *args[1]; ++ void *values[1]; ++ char *s; ++ int rc; ++ ++ /* Initialize the argument info vectors */ ++ args[0] = &ffi_type_uint; ++ values[0] = &s; ++ ++ /* Initialize the cif */ ++ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, ++ &ffi_type_uint, args) == FFI_OK) ++ { ++ s = "Hello World!"; ++ ffi_call(&cif, puts, &rc, values); ++ /* rc now holds the result of the call to puts */ ++ ++ /* values holds a pointer to the function's arg, so to ++ call puts() again all we need to do is change the ++ value of s */ ++ s = "This is cool!"; ++ ffi_call(&cif, puts, &rc, values); ++ } ++ ++ return 0; ++ } ++ ++ ++ ++ Aggregate Types ++ --------------- ++ ++Although libffi has no special support for unions or bit-fields, it is ++perfectly happy passing structures back and forth. You must first ++describe the structure to libffi by creating a new ffi_type object ++for it. Here is the definition of ffi_type: ++ ++ typedef struct _ffi_type ++ { ++ unsigned size; ++ short alignment; ++ short type; ++ struct _ffi_type **elements; ++ } ffi_type; ++ ++All structures must have type set to FFI_TYPE_STRUCT. You may set ++size and alignment to 0. These will be calculated and reset to the ++appropriate values by ffi_prep_cif(). ++ ++elements is a NULL terminated array of pointers to ffi_type objects ++that describe the type of the structure elements. These may, in turn, ++be structure elements. ++ ++The following example initializes a ffi_type object representing the ++tm struct from Linux's time.h: ++ ++ struct tm { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++ /* Those are for future use. */ ++ long int __tm_gmtoff__; ++ __const char *__tm_zone__; ++ }; ++ ++ { ++ ffi_type tm_type; ++ ffi_type *tm_type_elements[12]; ++ int i; ++ ++ tm_type.size = tm_type.alignment = 0; ++ tm_type.elements = &tm_type_elements; ++ ++ for (i = 0; i < 9; i++) ++ tm_type_elements[i] = &ffi_type_sint; ++ ++ tm_type_elements[9] = &ffi_type_slong; ++ tm_type_elements[10] = &ffi_type_pointer; ++ tm_type_elements[11] = NULL; ++ ++ /* tm_type can now be used to represent tm argument types and ++ return types for ffi_prep_cif() */ ++ } ++ ++ ++ ++Platform Specific Notes ++======================= ++ ++ Intel x86 ++ --------- ++ ++There are no known problems with the x86 port. ++ ++ Sun SPARC - SunOS 4.1.3 & Solaris 2.x ++ ------------------------------------- ++ ++You must use GNU Make to build libffi on Sun platforms. ++ ++ MIPS - Irix 5.3 & 6.x ++ --------------------- ++ ++Irix 6.2 and better supports three different calling conventions: o32, ++n32 and n64. Currently, libffi only supports both o32 and n32 under ++Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be ++configured for whichever calling convention it was built for. ++ ++By default, the configure script will try to build libffi with the GNU ++development tools. To build libffi with the SGI development tools, set ++the environment variable CC to either "cc -32" or "cc -n32" before ++running configure under Irix 6.x (depending on whether you want an o32 ++or n32 library), or just "cc" for Irix 5.3. ++ ++With the n32 calling convention, when returning structures smaller ++than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. ++Here's one way of forcing this: ++ ++ double struct_storage[2]; ++ my_small_struct *s = (my_small_struct *) struct_storage; ++ /* Use s for RVALUE */ ++ ++If you don't do this you are liable to get spurious bus errors. ++ ++"long long" values are not supported yet. ++ ++You must use GNU Make to build libffi on SGI platforms. ++ ++ ARM - System V ABI ++ ------------------ ++ ++The ARM port was performed on a NetWinder running ARM Linux ELF ++(2.0.31) and gcc 2.8.1. ++ ++ ++ ++ PowerPC System V ABI ++ -------------------- ++ ++There are two `System V ABI's which libffi implements for PowerPC. ++They differ only in how small structures are returned from functions. ++ ++In the FFI_SYSV version, structures that are 8 bytes or smaller are ++returned in registers. This is what GCC does when it is configured ++for solaris, and is what the System V ABI I have (dated September ++1995) says. ++ ++In the FFI_GCC_SYSV version, all structures are returned the same way: ++by passing a pointer as the first argument to the function. This is ++what GCC does when it is configured for linux or a generic sysv ++target. ++ ++EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a ++inconsistency with the SysV ABI: When a procedure is called with many ++floating-point arguments, some of them get put on the stack. They are ++all supposed to be stored in double-precision format, even if they are ++only single-precision, but EGCS stores single-precision arguments as ++single-precision anyway. This causes one test to fail (the `many ++arguments' test). ++ ++ ++What's With The Crazy Comments? ++=============================== ++ ++You might notice a number of cryptic comments in the code, delimited ++by /*@ and @*/. These are annotations read by the program LCLint, a ++tool for statically checking C programs. You can read all about it at ++. ++ ++ ++History ++======= ++ ++1.20 Oct-5-98 ++ Raffaele Sena produces ARM port. ++ ++1.19 Oct-5-98 ++ Fixed x86 long double and long long return support. ++ m68k bug fixes from Andreas Schwab. ++ Patch for DU assembler compatibility for the Alpha from Richard ++ Henderson. ++ ++1.18 Apr-17-98 ++ Bug fixes and MIPS configuration changes. ++ ++1.17 Feb-24-98 ++ Bug fixes and m68k port from Andreas Schwab. PowerPC port from ++ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. ++ ++1.16 Feb-11-98 ++ Richard Henderson produces Alpha port. ++ ++1.15 Dec-4-97 ++ Fixed an n32 ABI bug. New libtool, auto* support. ++ ++1.14 May-13-97 ++ libtool is now used to generate shared and static libraries. ++ Fixed a minor portability problem reported by Russ McManus ++ . ++ ++1.13 Dec-2-96 ++ Added --enable-purify-safety to keep Purify from complaining ++ about certain low level code. ++ Sparc fix for calling functions with < 6 args. ++ Linux x86 a.out fix. ++ ++1.12 Nov-22-96 ++ Added missing ffi_type_void, needed for supporting void return ++ types. Fixed test case for non MIPS machines. Cygnus Support ++ is now Cygnus Solutions. ++ ++1.11 Oct-30-96 ++ Added notes about GNU make. ++ ++1.10 Oct-29-96 ++ Added configuration fix for non GNU compilers. ++ ++1.09 Oct-29-96 ++ Added --enable-debug configure switch. Clean-ups based on LCLint ++ feedback. ffi_mips.h is always installed. Many configuration ++ fixes. Fixed ffitest.c for sparc builds. ++ ++1.08 Oct-15-96 ++ Fixed n32 problem. Many clean-ups. ++ ++1.07 Oct-14-96 ++ Gordon Irlam rewrites v8.S again. Bug fixes. ++ ++1.06 Oct-14-96 ++ Gordon Irlam improved the sparc port. ++ ++1.05 Oct-14-96 ++ Interface changes based on feedback. ++ ++1.04 Oct-11-96 ++ Sparc port complete (modulo struct passing bug). ++ ++1.03 Oct-10-96 ++ Passing struct args, and returning struct values works for ++ all architectures/calling conventions. Expanded tests. ++ ++1.02 Oct-9-96 ++ Added SGI n32 support. Fixed bugs in both o32 and Linux support. ++ Added "make test". ++ ++1.01 Oct-8-96 ++ Fixed float passing bug in mips version. Restructured some ++ of the code. Builds cleanly with SGI tools. ++ ++1.00 Oct-7-96 ++ First release. No public announcement. ++ ++ ++Authors & Credits ++================= ++ ++libffi was written by Anthony Green . ++ ++Portions of libffi were derived from Gianni Mariani's free gencall ++library for Silicon Graphics machines. ++ ++The closure mechanism was designed and implemented by Kresten Krab ++Thorup. ++ ++The Sparc port was derived from code contributed by the fine folks at ++Visible Decisions Inc . Further enhancements were ++made by Gordon Irlam at Cygnus Solutions . ++ ++The Alpha port was written by Richard Henderson at Cygnus Solutions. ++ ++Andreas Schwab ported libffi to m68k Linux and provided a number of ++bug fixes. ++ ++Geoffrey Keating ported libffi to the PowerPC. ++ ++Raffaele Sena ported libffi to the ARM. ++ ++Jesper Skov and Andrew Haley both did more than their fair share of ++stepping through the code and tracking down bugs. ++ ++Thanks also to Tom Tromey for bug fixes and configuration help. ++ ++Thanks to Jim Blandy, who provided some useful feedback on the libffi ++interface. ++ ++If you have a problem, or have found a bug, please send a note to ++green@cygnus.com. +diff --git ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc +new file mode 100644 +index 0000000..405d85f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README.pyobjc +@@ -0,0 +1,5 @@ ++This directory contains a slightly modified version of libffi, extracted from ++the GCC source-tree. ++ ++The only modifications are those that are necessary to compile libffi using ++the Apple provided compiler and outside of the GCC source tree. +diff --git ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c +new file mode 100644 +index 0000000..bf42093 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/ffi.c +@@ -0,0 +1,226 @@ ++/* ----------------------------------------------------------------------- ++ prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++/* Round up to FFI_SIZEOF_ARG. */ ++#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) ++ ++/* Perform machine independent initialization of aggregate type ++ specifications. */ ++ ++static ffi_status ++initialize_aggregate( ++/*@out@*/ ffi_type* arg) ++{ ++/*@-usedef@*/ ++ ++ if (arg == NULL || arg->elements == NULL || ++ arg->size != 0 || arg->alignment != 0) ++ return FFI_BAD_TYPEDEF; ++ ++ ffi_type** ptr = &(arg->elements[0]); ++ ++ while ((*ptr) != NULL) ++ { ++ if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#ifdef POWERPC_DARWIN ++ int curalign = (*ptr)->alignment; ++ ++ if (ptr != &(arg->elements[0])) ++ { ++ if (curalign > 4 && curalign != 16) ++ curalign = 4; ++ } ++ ++ arg->size = ALIGN(arg->size, curalign); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > curalign) ? ++ arg->alignment : curalign; ++#else ++ arg->size = ALIGN(arg->size, (*ptr)->alignment); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > (*ptr)->alignment) ? ++ arg->alignment : (*ptr)->alignment; ++#endif ++ ++ ptr++; ++ } ++ ++ /* Structure size includes tail padding. This is important for ++ structures that fit in one register on ABIs like the PowerPC64 ++ Linux ABI that right justify small structs in a register. ++ It's also needed for nested structure layout, for example ++ struct A { long a; char b; }; struct B { struct A x; char y; }; ++ should find y at an offset of 2*sizeof(long) and result in a ++ total size of 3*sizeof(long). */ ++ arg->size = ALIGN(arg->size, arg->alignment); ++ ++ if (arg->size == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ return FFI_OK; ++ ++/*@=usedef@*/ ++} ++ ++#ifndef __CRIS__ ++/* The CRIS ABI specifies structure elements to have byte ++ alignment only, so it completely overrides this functions, ++ which assumes "natural" alignment and padding. */ ++ ++/* Perform machine independent ffi_cif preparation, then call ++ machine dependent routine. */ ++ ++#if defined(X86_DARWIN) ++ ++static inline bool ++struct_on_stack( ++ int size) ++{ ++ if (size > 8) ++ return true; ++ ++ /* This is not what the ABI says, but is what is really implemented */ ++ switch (size) ++ { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ return false; ++ ++ default: ++ return true; ++ } ++} ++ ++#endif // defined(X86_DARWIN) ++ ++// Arguments' ffi_type->alignment must be nonzero. ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes) ++{ ++ if (cif == NULL) ++ return FFI_BAD_TYPEDEF; ++ ++ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI) ++ return FFI_BAD_ABI; ++ ++ unsigned int bytes = 0; ++ unsigned int i; ++ ffi_type** ptr; ++ ++ cif->abi = abi; ++ cif->arg_types = atypes; ++ cif->nargs = nargs; ++ cif->rtype = rtype; ++ cif->flags = 0; ++ ++ /* Initialize the return type if necessary */ ++ /*@-usedef@*/ ++ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ /*@=usedef@*/ ++ ++ /* Perform a sanity check on the return type */ ++ FFI_ASSERT_VALID_TYPE(cif->rtype); ++ ++ /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ ++#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA ++ /* Make space for the return structure pointer */ ++ if (cif->rtype->type == FFI_TYPE_STRUCT ++#ifdef SPARC ++ && (cif->abi != FFI_V9 || cif->rtype->size > 32) ++#endif ++#ifdef X86_DARWIN ++ && (struct_on_stack(cif->rtype->size)) ++#endif ++ ) ++ bytes = STACK_ARG_SIZE(sizeof(void*)); ++#endif ++ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ /* Initialize any uninitialized aggregate type definitions */ ++ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ if ((*ptr)->alignment == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type, do this ++ check after the initialization. */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#if defined(X86_DARWIN) ++ { ++ int align = (*ptr)->alignment; ++ ++ if (align > 4) ++ align = 4; ++ ++ if ((align - 1) & bytes) ++ bytes = ALIGN(bytes, align); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#elif !defined __x86_64__ && !defined S390 && !defined PA ++#ifdef SPARC ++ if (((*ptr)->type == FFI_TYPE_STRUCT ++ && ((*ptr)->size > 16 || cif->abi != FFI_V9)) ++ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE ++ && cif->abi != FFI_V9)) ++ bytes += sizeof(void*); ++ else ++#endif ++ { ++ /* Add any padding if necessary */ ++ if (((*ptr)->alignment - 1) & bytes) ++ bytes = ALIGN(bytes, (*ptr)->alignment); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#endif ++ } ++ ++ cif->bytes = bytes; ++ ++ /* Perform machine dependent cif processing */ ++ return ffi_prep_cif_machdep(cif); ++} ++#endif /* not __CRIS__ */ +diff --git ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h +new file mode 100644 +index 0000000..c104a5c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi.h +@@ -0,0 +1,355 @@ ++/* -----------------------------------------------------------------*-C-*- ++ libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++/* ------------------------------------------------------------------- ++ The basic API is described in the README file. ++ ++ The raw API is designed to bypass some of the argument packing ++ and unpacking on architectures for which it can be avoided. ++ ++ The closure API allows interpreted functions to be packaged up ++ inside a C function pointer, so that they can be called as C functions, ++ with no understanding on the client side that they are interpreted. ++ It can also be used in other cases in which it is necessary to package ++ up a user specified parameter and a function pointer as a single ++ function pointer. ++ ++ The closure API must be implemented in order to get its functionality, ++ e.g. for use by gij. Routines are provided to emulate the raw API ++ if the underlying platform doesn't allow faster implementation. ++ ++ More details on the raw and closure API can be found in: ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html ++ ++ and ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html ++ -------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_H ++#define LIBFFI_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Specify which architecture libffi is configured for. */ ++#ifdef MACOSX ++# if defined(__i386__) || defined(__x86_64__) ++# define X86_DARWIN ++# elif defined(__ppc__) || defined(__ppc64__) ++# define POWERPC_DARWIN ++# else ++# error "Unsupported MacOS X CPU type" ++# endif ++#else ++#error "Unsupported OS type" ++#endif ++ ++/* ---- System configuration information --------------------------------- */ ++ ++#include "ffitarget.h" ++#include "fficonfig.h" ++ ++#ifndef LIBFFI_ASM ++ ++#include ++#include ++ ++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). ++ But we can find it either under the correct ANSI name, or under GNU ++ C's internal name. */ ++#ifdef LONG_LONG_MAX ++# define FFI_LONG_LONG_MAX LONG_LONG_MAX ++#else ++# ifdef LLONG_MAX ++# define FFI_LONG_LONG_MAX LLONG_MAX ++# else ++# ifdef __GNUC__ ++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ ++# endif ++# endif ++#endif ++ ++#if SCHAR_MAX == 127 ++# define ffi_type_uchar ffi_type_uint8 ++# define ffi_type_schar ffi_type_sint8 ++#else ++#error "char size not supported" ++#endif ++ ++#if SHRT_MAX == 32767 ++# define ffi_type_ushort ffi_type_uint16 ++# define ffi_type_sshort ffi_type_sint16 ++#elif SHRT_MAX == 2147483647 ++# define ffi_type_ushort ffi_type_uint32 ++# define ffi_type_sshort ffi_type_sint32 ++#else ++#error "short size not supported" ++#endif ++ ++#if INT_MAX == 32767 ++# define ffi_type_uint ffi_type_uint16 ++# define ffi_type_sint ffi_type_sint16 ++#elif INT_MAX == 2147483647 ++# define ffi_type_uint ffi_type_uint32 ++# define ffi_type_sint ffi_type_sint32 ++#elif INT_MAX == 9223372036854775807 ++# define ffi_type_uint ffi_type_uint64 ++# define ffi_type_sint ffi_type_sint64 ++#else ++#error "int size not supported" ++#endif ++ ++#define ffi_type_ulong ffi_type_uint64 ++#define ffi_type_slong ffi_type_sint64 ++ ++#if LONG_MAX == 2147483647 ++# if FFI_LONG_LONG_MAX != 9223372036854775807 ++# error "no 64-bit data type supported" ++# endif ++#elif LONG_MAX != 9223372036854775807 ++#error "long size not supported" ++#endif ++ ++/* The closure code assumes that this works on pointers, i.e. a size_t ++ can hold a pointer. */ ++ ++typedef struct _ffi_type { ++ size_t size; ++ unsigned short alignment; ++ unsigned short type; ++/*@null@*/ struct _ffi_type** elements; ++} ffi_type; ++ ++/* These are defined in types.c */ ++extern ffi_type ffi_type_void; ++extern ffi_type ffi_type_uint8; ++extern ffi_type ffi_type_sint8; ++extern ffi_type ffi_type_uint16; ++extern ffi_type ffi_type_sint16; ++extern ffi_type ffi_type_uint32; ++extern ffi_type ffi_type_sint32; ++extern ffi_type ffi_type_uint64; ++extern ffi_type ffi_type_sint64; ++extern ffi_type ffi_type_float; ++extern ffi_type ffi_type_double; ++extern ffi_type ffi_type_longdouble; ++extern ffi_type ffi_type_pointer; ++ ++typedef enum ffi_status { ++ FFI_OK = 0, ++ FFI_BAD_TYPEDEF, ++ FFI_BAD_ABI ++} ffi_status; ++ ++typedef unsigned FFI_TYPE; ++ ++typedef struct ffi_cif { ++ ffi_abi abi; ++ unsigned nargs; ++/*@dependent@*/ ffi_type** arg_types; ++/*@dependent@*/ ffi_type* rtype; ++ unsigned bytes; ++ unsigned flags; ++#ifdef FFI_EXTRA_CIF_FIELDS ++ FFI_EXTRA_CIF_FIELDS; ++#endif ++} ffi_cif; ++ ++/* ---- Definitions for the raw API -------------------------------------- */ ++ ++#ifndef FFI_SIZEOF_ARG ++# if LONG_MAX == 2147483647 ++# define FFI_SIZEOF_ARG 4 ++# elif LONG_MAX == 9223372036854775807 ++# define FFI_SIZEOF_ARG 8 ++# endif ++#endif ++ ++typedef union { ++ ffi_sarg sint; ++ ffi_arg uint; ++ float flt; ++ char data[FFI_SIZEOF_ARG]; ++ void* ptr; ++} ffi_raw; ++ ++void ++ffi_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_raw_size( ++ ffi_cif* cif); ++ ++/* This is analogous to the raw API, except it uses Java parameter ++ packing, even on 64-bit machines. I.e. on 64-bit machines ++ longs and doubles are followed by an empty 64-bit word. */ ++void ++ffi_java_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_java_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_java_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_java_raw_size( ++ ffi_cif* cif); ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#if FFI_CLOSURES ++ ++typedef struct ffi_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ void (*fun)(ffi_cif*,void*,void**,void*); ++ void* user_data; ++} ffi_closure; ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void* user_data); ++ ++void ffi_closure_free(void *); ++void *ffi_closure_alloc (size_t size, void **code); ++ ++typedef struct ffi_raw_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ ++#if !FFI_NATIVE_RAW_API ++ /* if this is enabled, then a raw closure has the same layout ++ as a regular closure. We use this to install an intermediate ++ handler to do the transaltion, void** -> ffi_raw*. */ ++ void (*translate_args)(ffi_cif*,void*,void**,void*); ++ void* this_closure; ++#endif ++ ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*); ++ void* user_data; ++} ffi_raw_closure; ++ ++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_status ++ffi_prep_java_raw_closure( ++ ffi_raw_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*), ++ void* user_data); ++ ++#endif // FFI_CLOSURES ++ ++/* ---- Public interface definition -------------------------------------- */ ++ ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes); ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ void** avalue); ++ ++/* Useful for eliminating compiler warnings */ ++#define FFI_FN(f) ((void (*)(void))f) ++ ++#endif // #ifndef LIBFFI_ASM ++/* ---- Definitions shared with assembly code ---------------------------- */ ++ ++/* If these change, update src/mips/ffitarget.h. */ ++#define FFI_TYPE_VOID 0 ++#define FFI_TYPE_INT 1 ++#define FFI_TYPE_FLOAT 2 ++#define FFI_TYPE_DOUBLE 3 ++ ++#ifdef HAVE_LONG_DOUBLE ++# define FFI_TYPE_LONGDOUBLE 4 ++#else ++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE ++#endif ++ ++#define FFI_TYPE_UINT8 5 ++#define FFI_TYPE_SINT8 6 ++#define FFI_TYPE_UINT16 7 ++#define FFI_TYPE_SINT16 8 ++#define FFI_TYPE_UINT32 9 ++#define FFI_TYPE_SINT32 10 ++#define FFI_TYPE_UINT64 11 ++#define FFI_TYPE_SINT64 12 ++#define FFI_TYPE_STRUCT 13 ++#define FFI_TYPE_POINTER 14 ++ ++/* This should always refer to the last type code (for sanity checks) */ ++#define FFI_TYPE_LAST FFI_TYPE_POINTER ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef LIBFFI_H +diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h +new file mode 100644 +index 0000000..685a358 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi_common.h +@@ -0,0 +1,102 @@ ++/* ----------------------------------------------------------------------- ++ ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ++ ++ Common internal definitions and macros. Only necessary for building ++ libffi. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef FFI_COMMON_H ++#define FFI_COMMON_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fficonfig.h" ++ ++/* Do not move this. Some versions of AIX are very picky about where ++ this is positioned. */ ++#ifdef __GNUC__ ++# define alloca __builtin_alloca ++#else ++# if HAVE_ALLOCA_H ++# include ++# else ++# ifdef _AIX ++# pragma alloca ++# else ++# ifndef alloca /* predefined by HP cc +Olibcalls */ ++char* alloca(); ++# endif ++# endif ++# endif ++#endif ++ ++/* Check for the existence of memcpy. */ ++#if STDC_HEADERS ++# include ++#else ++# ifndef HAVE_MEMCPY ++# define memcpy(d, s, n) bcopy((s), (d), (n)) ++# endif ++#endif ++ ++/*#if defined(FFI_DEBUG) ++#include ++#endif*/ ++ ++#ifdef FFI_DEBUG ++#include ++ ++/*@exits@*/ void ++ffi_assert( ++/*@temp@*/ char* expr, ++/*@temp@*/ char* file, ++ int line); ++void ++ffi_stop_here(void); ++void ++ffi_type_test( ++/*@temp@*/ /*@out@*/ ffi_type* a, ++/*@temp@*/ char* file, ++ int line); ++ ++# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) ++# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) ++# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__) ++#else ++# define FFI_ASSERT(x) ++# define FFI_ASSERT_AT(x, f, l) ++# define FFI_ASSERT_VALID_TYPE(x) ++#endif // #ifdef FFI_DEBUG ++ ++#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) ++ ++/* Perform machine dependent cif processing */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif); ++ ++/* Extended cif, used in callback from assembly routine */ ++typedef struct extended_cif { ++/*@dependent@*/ ffi_cif* cif; ++/*@dependent@*/ void* rvalue; ++/*@dependent@*/ void** avalue; ++} extended_cif; ++ ++/* Terse sized type definitions. */ ++typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); ++typedef signed int SINT8 __attribute__((__mode__(__QI__))); ++typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); ++typedef signed int SINT16 __attribute__((__mode__(__HI__))); ++typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); ++typedef signed int SINT32 __attribute__((__mode__(__SI__))); ++typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); ++typedef signed int SINT64 __attribute__((__mode__(__DI__))); ++typedef float FLOAT32; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef FFI_COMMON_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h +new file mode 100644 +index 0000000..2172490 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/fficonfig.h +@@ -0,0 +1,150 @@ ++/* Manually created fficonfig.h for Darwin on PowerPC or Intel ++ ++ This file is manually generated to do away with the need for autoconf and ++ therefore make it easier to cross-compile and build fat binaries. ++ ++ NOTE: This file was added by PyObjC. ++*/ ++ ++#ifndef MACOSX ++#error "This file is only supported on Mac OS X" ++#endif ++ ++#if defined(__i386__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__x86_64__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__ppc__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# if __GNUC__ >= 4 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++# else ++# undef HAVE_LONG_DOUBLE ++# define SIZEOF_LONG_DOUBLE 8 ++# endif ++ ++#elif defined(__ppc64__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#else ++#error "Unknown CPU type" ++#endif ++ ++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP ++ systems. This function is required for `alloca.c' support on those systems. */ ++#undef CRAY_STACKSEG_END ++ ++/* Define to 1 if using `alloca.c'. */ ++/* #undef C_ALLOCA */ ++ ++/* Define to the flags needed for the .section .eh_frame directive. */ ++#define EH_FRAME_FLAGS "aw" ++ ++/* Define this if you want extra debugging. */ ++/* #undef FFI_DEBUG */ ++ ++/* Define this is you do not want support for the raw API. */ ++#define FFI_NO_RAW_API 1 ++ ++/* Define this if you do not want support for aggregate types. */ ++/* #undef FFI_NO_STRUCTS */ ++ ++/* Define to 1 if you have `alloca', as a function or macro. */ ++#define HAVE_ALLOCA 1 ++ ++/* Define to 1 if you have and it should be used (not on Ultrix). */ ++#define HAVE_ALLOCA_H 1 ++ ++/* Define if your assembler supports .register. */ ++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ ++ ++/* Define if your assembler and linker support unaligned PC relative relocs. */ ++/* #undef HAVE_AS_SPARC_UA_PCREL */ ++ ++/* Define to 1 if you have the `memcpy' function. */ ++#define HAVE_MEMCPY 1 ++ ++/* Define if mmap with MAP_ANON(YMOUS) works. */ ++#define HAVE_MMAP_ANON 1 ++ ++/* Define if mmap of /dev/zero works. */ ++/* #undef HAVE_MMAP_DEV_ZERO */ ++ ++/* Define if read-only mmap of a plain file works. */ ++#define HAVE_MMAP_FILE 1 ++ ++/* Define if .eh_frame sections should be read-only. */ ++/* #undef HAVE_RO_EH_FRAME */ ++ ++/* Define to 1 if your C compiler doesn't accept -c and -o together. */ ++/* #undef NO_MINUS_C_MINUS_O */ ++ ++/* Name of package */ ++#define PACKAGE "libffi" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "libffi" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "libffi 2.1" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libffi" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "2.1" ++ ++/* If using the C implementation of alloca, define if you know the ++ direction of stack growth for your system; otherwise it will be ++ automatically deduced at run-time. ++ STACK_DIRECTION > 0 => grows toward higher addresses ++ STACK_DIRECTION < 0 => grows toward lower addresses ++ STACK_DIRECTION = 0 => direction of growth unknown */ ++/* #undef STACK_DIRECTION */ ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this if you are using Purify and want to suppress spurious messages. */ ++/* #undef USING_PURIFY */ ++ ++/* Version number of package */ ++#define VERSION "2.1-pyobjc" ++ ++#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) .hidden name ++# else ++# define FFI_HIDDEN __attribute__((visibility ("hidden"))) ++# endif ++#else ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) ++# else ++# define FFI_HIDDEN ++# endif ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h +new file mode 100644 +index 0000000..faaa30d +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffitarget.h +@@ -0,0 +1,13 @@ ++/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a ++ normal build, the build environment copies the file to the right location or ++ sets up the right include flags. We want to do neither because that would ++ make building fat binaries harder. ++*/ ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "x86-ffitarget.h" ++#elif defined(__ppc__) || defined(__ppc64__) ++#include "ppc-ffitarget.h" ++#else ++#error "Unsupported CPU type" ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +new file mode 100644 +index 0000000..2318421 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +@@ -0,0 +1,104 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for PowerPC. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if (defined(POWERPC) && defined(__powerpc64__)) || \ ++ (defined(POWERPC_DARWIN) && defined(__ppc64__)) ++#define POWERPC64 ++#endif ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++#ifdef POWERPC ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++# ifdef POWERPC64 ++ FFI_DEFAULT_ABI = FFI_LINUX64, ++# else ++ FFI_DEFAULT_ABI = FFI_GCC_SYSV, ++# endif ++#endif ++ ++#ifdef POWERPC_AIX ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_AIX, ++#endif ++ ++#ifdef POWERPC_DARWIN ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_DARWIN, ++#endif ++ ++#ifdef POWERPC_FREEBSD ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++#define FFI_NATIVE_RAW_API 0 ++ ++/* Needed for FFI_SYSV small structure returns. */ ++#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) ++ ++#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/ ++# define FFI_TRAMPOLINE_SIZE 48 ++#elif defined(POWERPC_AIX) ++# define FFI_TRAMPOLINE_SIZE 24 ++#else ++# define FFI_TRAMPOLINE_SIZE 40 ++#endif ++ ++#ifndef LIBFFI_ASM ++# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) ++typedef struct ffi_aix_trampoline_struct { ++ void* code_pointer; /* Pointer to ffi_closure_ASM */ ++ void* toc; /* TOC */ ++ void* static_chain; /* Pointer to closure */ ++} ffi_aix_trampoline_struct; ++# endif ++#endif // #ifndef LIBFFI_ASM ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +new file mode 100644 +index 0000000..55c2b6c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +@@ -0,0 +1,88 @@ ++/* -----------------------------------------------------------------*-C-*- ++ x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for x86 and x86-64. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if defined(X86_64) && defined(__i386__) ++# undef X86_64 ++# define X86 ++#endif ++ ++#if defined(__x86_64__) ++# ifndef X86_64 ++# define X86_64 ++# endif ++#endif ++ ++/* ---- Generic type definitions ----------------------------------------- */ ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++ /* ---- Intel x86 Win32 ---------- */ ++#ifdef X86_WIN32 ++ FFI_SYSV, ++ FFI_STDCALL, ++ /* TODO: Add fastcall support for the sake of completeness */ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ /* ---- Intel x86 and AMD x86-64 - */ ++#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) ++ FFI_SYSV, ++ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ ++# ifdef __i386__ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++# else ++ FFI_DEFAULT_ABI = FFI_UNIX64, ++# endif ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++ ++#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN)) ++# define FFI_TRAMPOLINE_SIZE 24 ++# define FFI_NATIVE_RAW_API 0 ++#else ++# define FFI_TRAMPOLINE_SIZE 10 ++# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ ++#endif ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +new file mode 100644 +index 0000000..f143dbd +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +@@ -0,0 +1,365 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist ++ Copyright (c) 2004 Free Software Foundation, Inc. ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include ++#include ++#include ++ ++.text ++ .align 2 ++.globl _ffi_prep_args ++ ++.text ++ .align 2 ++.globl _ffi_call_DARWIN ++ ++.text ++ .align 2 ++_ffi_call_DARWIN: ++LFB0: ++ mr r12,r8 /* We only need r12 until the call, ++ so it doesn't have to be saved. */ ++ ++LFB1: ++ /* Save the old stack pointer as AP. */ ++ mr r8,r1 ++ ++LCFI0: ++#if defined(__ppc64__) ++ /* Allocate the stack space we need. ++ r4 (size of input data) ++ 48 bytes (linkage area) ++ 40 bytes (saved registers) ++ 8 bytes (extra FPR) ++ r4 + 96 bytes total ++ */ ++ ++ addi r4,r4,-96 // Add our overhead. ++ li r0,-32 // Align to 32 bytes. ++ and r4,r4,r0 ++#endif ++ stgux r1,r1,r4 // Grow the stack. ++ mflr r9 ++ ++ /* Save registers we use. */ ++#if defined(__ppc64__) ++ std r27,-40(r8) ++#endif ++ stg r28,MODE_CHOICE(-16,-32)(r8) ++ stg r29,MODE_CHOICE(-12,-24)(r8) ++ stg r30,MODE_CHOICE(-8,-16)(r8) ++ stg r31,MODE_CHOICE(-4,-8)(r8) ++ stg r9,SF_RETURN(r8) /* return address */ ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ stg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++LCFI1: ++#if defined(__ppc64__) ++ mr r27,r3 // our extended_cif ++#endif ++ /* Save arguments over call. */ ++ mr r31,r5 /* flags, */ ++ mr r30,r6 /* rvalue, */ ++ mr r29,r7 /* function address, */ ++ mr r28,r8 /* our AP. */ ++ ++LCFI2: ++ /* Call ffi_prep_args. */ ++ mr r4,r1 ++ li r9,0 ++ mtctr r12 /* r12 holds address of _ffi_prep_args. */ ++ bctrl ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ lg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++ /* Now do the call. ++ Set up cr1 with bits 4-7 of the flags. */ ++ mtcrf 0x40,r31 ++ ++ /* Load all those argument registers. ++ We have set up a nice stack frame, just load it into registers. */ ++ lg r3,SF_ARG1(r1) ++ lg r4,SF_ARG2(r1) ++ lg r5,SF_ARG3(r1) ++ lg r6,SF_ARG4(r1) ++ nop ++ lg r7,SF_ARG5(r1) ++ lg r8,SF_ARG6(r1) ++ lg r9,SF_ARG7(r1) ++ lg r10,SF_ARG8(r1) ++ ++ /* Load all the FP registers. */ ++ bf 6,L2 /* No floats to load. */ ++#if defined(__ppc64__) ++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#elif defined(__ppc__) ++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#else ++#error undefined architecture ++#endif ++ ++L2: ++ mr r12,r29 // Put the target address in r12 as specified. ++ mtctr r12 // Get the address to call into CTR. ++ nop ++ nop ++ bctrl // Make the call. ++ ++ // Deal with the return value. ++#if defined(__ppc64__) ++ mtcrf 0x3,r31 // flags in cr6 and cr7 ++ bt 27,L(st_return_value) ++#elif defined(__ppc__) ++ mtcrf 0x1,r31 // flags in cr7 ++#else ++#error undefined architecture ++#endif ++ ++ bt 30,L(done_return_value) ++ bt 29,L(fp_return_value) ++ stg r3,0(r30) ++#if defined(__ppc__) ++ bf 28,L(done_return_value) // Store the second long if necessary. ++ stg r4,4(r30) ++#endif ++ // Fall through ++ ++L(done_return_value): ++ lg r1,0(r1) // Restore stack pointer. ++ // Restore the registers we used. ++ lg r9,SF_RETURN(r1) // return address ++ lg r31,MODE_CHOICE(-4,-8)(r1) ++ mtlr r9 ++ lg r30,MODE_CHOICE(-8,-16)(r1) ++ lg r29,MODE_CHOICE(-12,-24)(r1) ++ lg r28,MODE_CHOICE(-16,-32)(r1) ++#if defined(__ppc64__) ++ ld r27,-40(r1) ++#endif ++ blr ++ ++#if defined(__ppc64__) ++L(st_return_value): ++ // Grow the stack enough to fit the registers. Leave room for 8 args ++ // to trample the 1st 8 slots in param area. ++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 ++ ++ // Store GPRs ++ std r3,SF_ARG9(r1) ++ std r4,SF_ARG10(r1) ++ std r5,SF_ARG11(r1) ++ std r6,SF_ARG12(r1) ++ nop ++ std r7,SF_ARG13(r1) ++ std r8,SF_ARG14(r1) ++ std r9,SF_ARG15(r1) ++ std r10,SF_ARG16(r1) ++ ++ // Store FPRs ++ nop ++ bf 26,L(call_struct_to_ram_form) ++ stfd f1,SF_ARG17(r1) ++ stfd f2,SF_ARG18(r1) ++ stfd f3,SF_ARG19(r1) ++ stfd f4,SF_ARG20(r1) ++ nop ++ stfd f5,SF_ARG21(r1) ++ stfd f6,SF_ARG22(r1) ++ stfd f7,SF_ARG23(r1) ++ stfd f8,SF_ARG24(r1) ++ nop ++ stfd f9,SF_ARG25(r1) ++ stfd f10,SF_ARG26(r1) ++ stfd f11,SF_ARG27(r1) ++ stfd f12,SF_ARG28(r1) ++ nop ++ stfd f13,SF_ARG29(r1) ++ ++L(call_struct_to_ram_form): ++ ld r3,0(r27) // extended_cif->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ addi r4,r1,SF_ARG9 // stored GPRs ++ addi r6,r1,SF_ARG17 // stored FPRs ++ li r5,0 // GPR size ptr (NULL) ++ li r7,0 // FPR size ptr (NULL) ++ li r8,0 // FPR count ptr (NULL) ++ li r10,0 // struct offset (NULL) ++ mr r9,r30 // return area ++ bl Lffi64_struct_to_ram_form$stub ++ lg r1,0(r1) // Restore stack pointer. ++ b L(done_return_value) ++#endif ++ ++L(fp_return_value): ++ /* Do we have long double to store? */ ++ bf 31,L(fd_return_value) ++ stfd f1,0(r30) ++ stfd f2,8(r30) ++ b L(done_return_value) ++ ++L(fd_return_value): ++ /* Do we have double to store? */ ++ bf 28,L(float_return_value) ++ stfd f1,0(r30) ++ b L(done_return_value) ++ ++L(float_return_value): ++ /* We only have a float to store. */ ++ stfs f1,0(r30) ++ b L(done_return_value) ++ ++LFE1: ++/* END(_ffi_call_DARWIN) */ ++ ++/* Provide a null definition of _ffi_call_AIX. */ ++.text ++ .align 2 ++.globl _ffi_call_AIX ++.text ++ .align 2 ++_ffi_call_AIX: ++ blr ++/* END(_ffi_call_AIX) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_call_DARWIN.eh ++_ffi_call_DARWIN.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x08 ; uleb128 0x08 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$5,LCFI1-LCFI0 ++ .long L$set$5 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .byte 0x9f ; DW_CFA_offset, column 0x1f ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x9e ; DW_CFA_offset, column 0x1e ++ .byte 0x2 ; uleb128 0x2 ++ .byte 0x9d ; DW_CFA_offset, column 0x1d ++ .byte 0x3 ; uleb128 0x3 ++ .byte 0x9c ; DW_CFA_offset, column 0x1c ++ .byte 0x4 ; uleb128 0x4 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$6,LCFI2-LCFI1 ++ .long L$set$6 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x1c ; uleb128 0x1c ++ .align LOG2_GPR_BYTES ++LEFDE1: ++ ++#if defined(__ppc64__) ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_ram_form$stub: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_ram_form ++ ++LO$ffi64_struct_to_ram_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_ram_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ ++#endif // __ppc__ || __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +new file mode 100644 +index 0000000..cf4bd50 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +@@ -0,0 +1,85 @@ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define L(x) x ++ ++#define SF_ARG9 MODE_CHOICE(56,112) ++#define SF_ARG10 MODE_CHOICE(60,120) ++#define SF_ARG11 MODE_CHOICE(64,128) ++#define SF_ARG12 MODE_CHOICE(68,136) ++#define SF_ARG13 MODE_CHOICE(72,144) ++#define SF_ARG14 MODE_CHOICE(76,152) ++#define SF_ARG15 MODE_CHOICE(80,160) ++#define SF_ARG16 MODE_CHOICE(84,168) ++#define SF_ARG17 MODE_CHOICE(88,176) ++#define SF_ARG18 MODE_CHOICE(92,184) ++#define SF_ARG19 MODE_CHOICE(96,192) ++#define SF_ARG20 MODE_CHOICE(100,200) ++#define SF_ARG21 MODE_CHOICE(104,208) ++#define SF_ARG22 MODE_CHOICE(108,216) ++#define SF_ARG23 MODE_CHOICE(112,224) ++#define SF_ARG24 MODE_CHOICE(116,232) ++#define SF_ARG25 MODE_CHOICE(120,240) ++#define SF_ARG26 MODE_CHOICE(124,248) ++#define SF_ARG27 MODE_CHOICE(128,256) ++#define SF_ARG28 MODE_CHOICE(132,264) ++#define SF_ARG29 MODE_CHOICE(136,272) ++ ++#define ASM_NEEDS_REGISTERS 4 ++#define NUM_GPR_ARG_REGISTERS 8 ++#define NUM_FPR_ARG_REGISTERS 13 ++ ++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8) ++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16) ++#define FFI_TYPE_4_BYTE(x) \ ++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\ ++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT) ++ ++#if !defined(LIBFFI_ASM) ++ ++enum { ++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7 ++ FLAG_RETURNS_FP = 1 << (31 - 29), ++ FLAG_RETURNS_64BITS = 1 << (31 - 28), ++ FLAG_RETURNS_128BITS = 1 << (31 - 31), ++ ++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6 ++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26), ++ ++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7), ++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI ++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5), ++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4) ++}; ++ ++#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*); ++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*); ++#endif ++ ++#endif // !defined(LIBFFI_ASM) +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +new file mode 100644 +index 0000000..c3d30c2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +@@ -0,0 +1,308 @@ ++#if defined(__ppc__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 // Save return address ++ stg r0,SF_RETURN(r1) ++ ++LCFI0: ++ /* 24/48 bytes (Linkage Area) ++ 32/64 bytes (outgoing parameter area, always reserved) ++ 104 bytes (13*8 from FPR) ++ 16/32 bytes (result) ++ 176/232 total bytes */ ++ ++ /* skip over caller save area and keep stack aligned to 16/32. */ ++ stgu r1,-SF_ROUND(176)(r1) ++ ++LCFI1: ++ /* We want to build up an area for the parameters passed ++ in registers. (both floating point and integer) */ ++ ++ /* 176/256 bytes (callee stack frame aligned to 16/32) ++ 24/48 bytes (caller linkage area) ++ 200/304 (start of caller parameter area aligned to 4/8) ++ */ ++ ++ /* Save GPRs 3 - 10 (aligned to 4/8) ++ in the parents outgoing area. */ ++ 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,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. ++ 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. Use it to look up in a table ++ so we know how to deal with each type. */ ++ 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 ++ ++LFE1: ++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ (4 instructions). For cache effectiveness we align to a 16 byte boundary ++ first. */ ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++/* case FFI_TYPE_VOID */ ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* case FFI_TYPE_INT */ ++Lret_type1: ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_FLOAT */ ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_DOUBLE */ ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_LONGDOUBLE */ ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT8 */ ++Lret_type5: ++ lbz r3,3(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT8 */ ++Lret_type6: ++ lbz r3,3(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT16 */ ++Lret_type7: ++ lhz r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT16 */ ++Lret_type8: ++ lha r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT32 */ ++Lret_type9: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT32 */ ++Lret_type10: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT64 */ ++Lret_type11: ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_SINT64 */ ++Lret_type12: // same as Lret_type11 ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_STRUCT */ ++Lret_type13: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* End 16-byte aligned cases */ ++/* case FFI_TYPE_POINTER */ ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ // fall through ++ ++/* case done */ ++Lfinish: ++ 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) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++ ++#endif // __ppc__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +new file mode 100644 +index 0000000..8953d5f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +@@ -0,0 +1,1776 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1998 Geoffrey Keating ++ ++ PowerPC Foreign Function Interface ++ ++ Darwin ABI support (c) 2001 John Hornkvist ++ AIX ABI support (c) 2002 Free Software Foundation, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#if defined(POWERPC_DARWIN) ++#include // for sys_icache_invalidate() ++#endif ++ ++#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 ++// points to one of these. ++typedef struct aix_fd_struct { ++ void* code_pointer; ++ void* toc; ++} aix_fd; ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments. ++ ++ The stack layout we want looks like this: ++ ++ | Return address from ffi_call_DARWIN | higher addresses ++ |--------------------------------------------| ++ | Previous backchain pointer 4/8 | stack pointer here ++ |--------------------------------------------|-\ <<< on entry to ++ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN ++ |--------------------------------------------| | ++ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 ++ |--------------------------------------------| | ++ | Space for GPR2 4/8 | | ++ |--------------------------------------------| | stack | ++ | Reserved (4/8)*2 | | grows | ++ |--------------------------------------------| | down V ++ | Space for callee's LR 4/8 | | ++ |--------------------------------------------| | lower addresses ++ | Saved CR 4/8 | | ++ |--------------------------------------------| | stack pointer here ++ | Current backchain pointer 4/8 | | during ++ |--------------------------------------------|-/ <<< ffi_call_DARWIN ++ ++ Note: ppc64 CR is saved in the low word of a long on the stack. ++*/ ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args( ++ extended_cif* inEcif, ++ unsigned *const stack) ++/*@=exportheader@*/ ++{ ++ /* Copy the ecif to a local var so we can trample the arg. ++ BC note: test this with GP later for possible problems... */ ++ volatile extended_cif* ecif = inEcif; ++ ++ const unsigned bytes = ecif->cif->bytes; ++ const unsigned flags = ecif->cif->flags; ++ ++ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode ++ and 8 in 64-bit mode. */ ++ unsigned long *const longStack = (unsigned long *const)stack; ++ ++ /* 'stacktop' points at the previous backchain pointer. */ ++#if defined(__ppc64__) ++ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, ++ // saved registers, and an extra FPR. ++ unsigned long *const stacktop = ++ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); ++#elif defined(__ppc__) ++ unsigned long *const stacktop = longStack + (bytes / sizeof(long)); ++#else ++#error undefined architecture ++#endif ++ ++ /* 'fpr_base' points at the space for fpr1, and grows upwards as ++ we use FPR registers. */ ++ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - ++ NUM_FPR_ARG_REGISTERS; ++ ++#if defined(__ppc64__) ++ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base ++ // down a couple pegs. ++ fpr_base -= 2; ++#endif ++ ++ unsigned int fparg_count = 0; ++ ++ /* 'next_arg' grows up as we put parameters in it. */ ++ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ ++ ++ int i; ++ double double_tmp; ++ void** p_argv = ecif->avalue; ++ unsigned long gprvalue; ++ ffi_type** ptr = ecif->cif->arg_types; ++ ++ /* Check that everything starts aligned properly. */ ++ FFI_ASSERT(stack == SF_ROUND(stack)); ++ FFI_ASSERT(stacktop == SF_ROUND(stacktop)); ++ FFI_ASSERT(bytes == SF_ROUND(bytes)); ++ ++ /* Deal with return values that are actually pass-by-reference. ++ Rule: ++ Return values are referenced by r3, so r4 is the first parameter. */ ++ ++ if (flags & FLAG_RETVAL_REFERENCE) ++ *next_arg++ = (unsigned long)(char*)ecif->rvalue; ++ ++ /* Now for the arguments. */ ++ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) ++ { ++ switch ((*ptr)->type) ++ { ++ /* If a floating-point parameter appears before all of the general- ++ purpose registers are filled, the corresponding GPRs that match ++ the size of the floating-point parameter are shadowed for the ++ benefit of vararg and pre-ANSI functions. */ ++ case FFI_TYPE_FLOAT: ++ double_tmp = *(float*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg++; ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ double_tmp = *(double*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg += MODE_CHOICE(2,1); ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++#elif defined(__ppc__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) ++ *(double*)fpr_base = *(double*)*p_argv; ++#else ++#error undefined architecture ++#endif ++ ++ *(long double*)next_arg = *(long double*)*p_argv; ++ fparg_count += 2; ++ fpr_base += 2; ++ next_arg += MODE_CHOICE(4,2); ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++#if defined(__ppc64__) ++ gprvalue = *(long long*)*p_argv; ++ goto putgpr; ++#elif defined(__ppc__) ++ *(long long*)next_arg = *(long long*)*p_argv; ++ next_arg += 2; ++ break; ++#else ++#error undefined architecture ++#endif ++ ++ case FFI_TYPE_POINTER: ++ gprvalue = *(unsigned long*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT8: ++ gprvalue = *(unsigned char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT8: ++ gprvalue = *(signed char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT16: ++ gprvalue = *(unsigned short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT16: ++ gprvalue = *(signed short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ ++ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, ++ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); ++ next_arg += gprSize / sizeof(long); ++ fpr_base += fprSize / sizeof(double); ++ ++#elif defined(__ppc__) ++ char* dest_cpy = (char*)next_arg; ++ ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. ++ Structures with 3 byte in size are padded upwards. */ ++ unsigned size_al = (*ptr)->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++ if (ecif->cif->abi == FFI_DARWIN) ++ { ++ if (size_al < 3) ++ dest_cpy += 4 - size_al; ++ } ++ ++ memcpy((char*)dest_cpy, (char*)*p_argv, size_al); ++ next_arg += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ gprvalue = *(unsigned*)*p_argv; ++ ++putgpr: ++ *next_arg++ = gprvalue; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Check that we didn't overrun the stack... */ ++ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); ++ //FFI_ASSERT((unsigned *)fpr_base ++ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); ++ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); ++} ++ ++#if defined(__ppc64__) ++ ++bool ++ffi64_struct_contains_fp( ++ const ffi_type* inType) ++{ ++ bool containsFP = false; ++ unsigned int i; ++ ++ for (i = 0; inType->elements[i] != NULL && !containsFP; i++) ++ { ++ if (inType->elements[i]->type == FFI_TYPE_FLOAT || ++ inType->elements[i]->type == FFI_TYPE_DOUBLE || ++ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) ++ containsFP = true; ++ else if (inType->elements[i]->type == FFI_TYPE_STRUCT) ++ containsFP = ffi64_struct_contains_fp(inType->elements[i]); ++ } ++ ++ return containsFP; ++} ++ ++#endif // defined(__ppc64__) ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ /* All this is for the DARWIN ABI. */ ++ int i; ++ ffi_type** ptr; ++ int intarg_count = 0; ++ int fparg_count = 0; ++ unsigned int flags = 0; ++ unsigned int size_al = 0; ++ ++ /* All the machine-independent calculation of cif->bytes will be wrong. ++ Redo the calculation for DARWIN. */ ++ ++ /* Space for the frame pointer, callee's LR, CR, etc, and for ++ the asm's temp regs. */ ++ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); ++ ++ /* Return value handling. The rules are as follows: ++ - 32-bit (or less) integer values are returned in gpr3; ++ - Structures of size <= 4 bytes also returned in gpr3; ++ - 64-bit integer values and structures between 5 and 8 bytes are ++ returned in gpr3 and gpr4; ++ - Single/double FP values are returned in fpr1; ++ - Long double FP (if not equivalent to double) values are returned in ++ fpr1 and fpr2; ++ - Larger structures values are allocated space and a pointer is passed ++ as the first argument. */ ++ switch (cif->rtype->type) ++ { ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ flags |= FLAG_RETURNS_128BITS; ++ flags |= FLAG_RETURNS_FP; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_DOUBLE: ++ flags |= FLAG_RETURNS_64BITS; ++ /* Fall through. */ ++ case FFI_TYPE_FLOAT: ++ flags |= FLAG_RETURNS_FP; ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ flags |= FLAG_RETURNS_64BITS; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ ++ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++ { ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ } ++ else ++ { ++ flags |= FLAG_RETURNS_STRUCT; ++ ++ if (ffi64_struct_contains_fp(cif->rtype)) ++ flags |= FLAG_STRUCT_CONTAINS_FP; ++ } ++ ++#elif defined(__ppc__) ++ ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_VOID: ++ flags |= FLAG_RETURNS_NOTHING; ++ break; ++ ++ default: ++ /* Returns 32-bit integer, or similar. Nothing to do here. */ ++ break; ++ } ++ ++ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the ++ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest ++ goes on the stack. Structures are passed as a pointer to a copy of ++ the structure. Stuff on the stack needs to keep proper alignment. */ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ switch ((*ptr)->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ fparg_count++; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ fparg_count += 2; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ ++ if ( ++#if defined(__ppc64__) ++ fparg_count > NUM_FPR_ARG_REGISTERS + 1 ++#elif defined(__ppc__) ++ fparg_count > NUM_FPR_ARG_REGISTERS ++#else ++#error undefined architecture ++#endif ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ ++ intarg_count += 2; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ /* 'long long' arguments are passed as two words, but ++ either both words must fit in registers or both go ++ on the stack. If they go on the stack, they must ++ be 8-byte-aligned. */ ++ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 ++ || (intarg_count >= NUM_GPR_ARG_REGISTERS ++ && intarg_count % 2 != 0)) ++ intarg_count++; ++ ++ intarg_count += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ size_al = (*ptr)->size; ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++#if defined(__ppc64__) ++ // Look for FP struct members. ++ unsigned int j; ++ ++ for (j = 0; (*ptr)->elements[j] != NULL; j++) ++ { ++ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || ++ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) ++ { ++ fparg_count++; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS) ++ intarg_count++; ++ } ++ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) ++ { ++ fparg_count += 2; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) ++ intarg_count += 2; ++ } ++ else ++ intarg_count++; ++ } ++#elif defined(__ppc__) ++ intarg_count += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ ++ break; ++ ++ default: ++ /* Everything else is passed as a 4/8-byte word in a GPR, either ++ the object itself or a pointer to it. */ ++ intarg_count++; ++ break; ++ } ++ } ++ ++ /* Space for the FPR registers, if needed. */ ++ if (fparg_count != 0) ++ { ++ flags |= FLAG_FP_ARGUMENTS; ++#if defined(__ppc64__) ++ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); ++#elif defined(__ppc__) ++ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ /* Stack space. */ ++#if defined(__ppc64__) ++ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + fparg_count) * sizeof(long); ++#elif defined(__ppc__) ++ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + 2 * fparg_count) * sizeof(long); ++#else ++#error undefined architecture ++#endif ++ else ++ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); ++ ++ /* The stack space allocated needs to be a multiple of 16/32 bytes. */ ++ bytes = SF_ROUND(bytes); ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ ++ return FFI_OK; ++} ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ++ffi_call_AIX( ++/*@out@*/ extended_cif*, ++ unsigned, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++ ++extern void ++ffi_call_DARWIN( ++/*@out@*/ extended_cif*, ++ unsigned long, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ 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) && ++ (cif->rtype->type == FFI_TYPE_STRUCT)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ switch (cif->abi) ++ { ++ case FFI_AIX: ++ /*@-usedef@*/ ++ ffi_call_AIX(&ecif, -cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ case FFI_DARWIN: ++ /*@-usedef@*/ ++ ffi_call_DARWIN(&ecif, -(long)cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++/* here I'd like to add the stack frame layout we use in darwin_closure.S ++ and aix_clsoure.S ++ ++ SP previous -> +---------------------------------------+ <--- child frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 4 ++ | saved CR 4 | ++ +---------------------------------------+ 8 ++ | saved LR 4 | ++ +---------------------------------------+ 12 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 16 ++ | reserved for binders 4 | ++ +---------------------------------------+ 20 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 24 ++ | always reserved 8*4=32 (previous GPRs)| ++ | according to the linkage convention | ++ | from AIX | ++ +---------------------------------------+ 56 ++ | our FPR area 13*8=104 | ++ | f1 | ++ | . | ++ | f13 | ++ +---------------------------------------+ 160 ++ | result area 8 | ++ +---------------------------------------+ 168 ++ | alignement to the next multiple of 16 | ++SP current --> +---------------------------------------+ 176 <- parent frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 180 ++ | saved CR 4 | ++ +---------------------------------------+ 184 ++ | saved LR 4 | ++ +---------------------------------------+ 188 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 192 ++ | reserved for binders 4 | ++ +---------------------------------------+ 196 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 200 ++ | always reserved 8*4=32 we store our | ++ | GPRs here | ++ | r3 | ++ | . | ++ | r10 | ++ +---------------------------------------+ 232 ++ | overflow part | ++ +---------------------------------------+ xxx ++ | ???? | ++ +---------------------------------------+ xxx ++*/ ++ ++#if !defined(POWERPC_DARWIN) ++ ++#define MIN_LINE_SIZE 32 ++ ++static void ++flush_icache( ++ char* addr) ++{ ++#ifndef _AIX ++ __asm__ volatile ( ++ "dcbf 0,%0\n" ++ "sync\n" ++ "icbi 0,%0\n" ++ "sync\n" ++ "isync" ++ : : "r" (addr) : "memory"); ++#endif ++} ++ ++static void ++flush_range( ++ char* addr, ++ int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i += MIN_LINE_SIZE) ++ flush_icache(addr + i); ++ ++ flush_icache(addr + size - 1); ++} ++ ++#endif // !defined(POWERPC_DARWIN) ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ switch (cif->abi) ++ { ++ case FFI_DARWIN: ++ { ++ FFI_ASSERT (cif->abi == FFI_DARWIN); ++ ++ unsigned int* tramp = (unsigned int*)&closure->tramp[0]; ++ ++#if defined(__ppc64__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0xe98b0018; // ld r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0xe96b0020; // ld r11,32(r11) ++ tramp[7] = 0x4e800420; // bctr ++ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; ++ *(unsigned long*)&tramp[10] = (unsigned long)closure; ++#elif defined(__ppc__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0x818b0018; // lwz r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0x816b001c; // lwz r11,28(r11) ++ tramp[7] = 0x4e800420; // bctr ++ tramp[8] = (unsigned long)ffi_closure_ASM; ++ tramp[9] = (unsigned long)closure; ++#else ++#error undefined architecture ++#endif ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ // Flush the icache. Only necessary on Darwin. ++#if defined(POWERPC_DARWIN) ++ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#else ++ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#endif ++ ++ break; ++ } ++ ++ case FFI_AIX: ++ { ++ FFI_ASSERT (cif->abi == FFI_AIX); ++ ++ ffi_aix_trampoline_struct* tramp_aix = ++ (ffi_aix_trampoline_struct*)(closure->tramp); ++ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; ++ ++ tramp_aix->code_pointer = fd->code_pointer; ++ tramp_aix->toc = fd->toc; ++ tramp_aix->static_chain = closure; ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ break; ++ } ++ ++ default: ++ return FFI_BAD_ABI; ++ } ++ ++ return FFI_OK; ++} ++ ++#if defined(__ppc__) ++ typedef double ldbits[2]; ++ ++ typedef union ++ { ++ ldbits lb; ++ long double ld; ++ } 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 ++ for a return value, ffi_closure_ASM invokes the following helper function ++ to do most of the work. */ ++int ++ffi_closure_helper_DARWIN( ++ ffi_closure* closure, ++ void* rvalue, ++ unsigned long* pgr, ++ ffi_dblfl* pfr) ++{ ++ /* rvalue is the pointer to space for return value in closure assembly ++ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM ++ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ ++ ++#if defined(__ppc__) ++ ldu temp_ld; ++#endif ++ ++ double temp; ++ unsigned int i; ++ unsigned int nf = 0; /* number of FPRs already used. */ ++ unsigned int ng = 0; /* number of GPRs already used. */ ++ ffi_cif* cif = closure->cif; ++ long avn = cif->nargs; ++ void** avalue = alloca(cif->nargs * sizeof(void*)); ++ ffi_type** arg_types = cif->arg_types; ++ ++ /* Copy the caller's structure return value address so that the closure ++ returns the data directly to the caller. */ ++#if defined(__ppc64__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT && ++ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++#elif defined(__ppc__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT) ++#else ++#error undefined architecture ++#endif ++ { ++ rvalue = (void*)*pgr; ++ pgr++; ++ ng++; ++ } ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ for (i = 0; i < avn; i++) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ avalue[i] = (char*)pgr + MODE_CHOICE(3,7); ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ avalue[i] = (char*)pgr + MODE_CHOICE(2,6); ++ ng++; ++ pgr++; ++ break; ++ ++#if defined(__ppc__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ avalue[i] = (char*)pgr + MODE_CHOICE(0,4); ++ ng++; ++ pgr++; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ if (cif->abi == FFI_DARWIN) ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ unsigned int savedFPRSize = fprSize; ++ ++ avalue[i] = alloca(arg_types[i]->size); ++ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, ++ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); ++ ++ ng += gprSize / sizeof(long); ++ pgr += gprSize / sizeof(long); ++ pfr += (fprSize - savedFPRSize) / sizeof(double); ++ ++#elif defined(__ppc__) ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. */ ++ unsigned int size_al = size_al = arg_types[i]->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN(arg_types[i]->size, 8); ++ ++ if (size_al < 3) ++ avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; ++ else ++ avalue[i] = (void*)pgr; ++ ++ ng += (size_al + 3) / sizeof(long); ++ pgr += (size_al + 3) / sizeof(long); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ /* Long long ints are passed in 1 or 2 GPRs. */ ++ avalue[i] = pgr; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ /* A float value consumes a GPR. ++ There are 13 64-bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ temp = pfr->d; ++ pfr->f = (float)temp; ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ /* A double value consumes one or two GPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++#elif defined(__ppc__) ++ /* A long double value consumes 2/4 GPRs and 2 FPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS - 1) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++ /* Here we have the situation where one part of the long double ++ is stored in fpr13 and the other part is already on the stack. ++ 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(temp_ld.lb[0])); ++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); ++ avalue[i] = &temp_ld.ld; ++ } ++#else ++#error undefined architecture ++#endif ++ else ++ avalue[i] = pgr; ++ ++ nf += 2; ++ ng += MODE_CHOICE(4,2); ++ pgr += MODE_CHOICE(4,2); ++ ++ break; ++ ++#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ (closure->fun)(cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell ffi_closure_ASM to perform return type promotions. */ ++ return cif->rtype->type; ++} ++ ++#if defined(__ppc64__) ++ ++/* ffi64_struct_to_ram_form ++ ++ Rebuild a struct's natural layout from buffers of concatenated registers. ++ Return the number of registers used. ++ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_ram_form( ++ const ffi_type* inType, ++ const char* inGPRs, ++ unsigned int* ioGPRMarker, ++ const char* inFPRs, ++ unsigned int* ioFPRMarker, ++ unsigned int* ioFPRsUsed, ++ char* outStruct, // caller-allocated ++ unsigned int* ioStructMarker) ++{ ++ unsigned int srcGMarker = 0; ++ unsigned int srcFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ unsigned int destMarker = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioGPRMarker) ++ srcGMarker = *ioGPRMarker; ++ ++ if (ioFPRMarker) ++ { ++ srcFMarker = *ioFPRMarker; ++ savedFMarker = srcFMarker; ++ } ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioStructMarker) ++ destMarker = *ioStructMarker; ++ ++ size_t i; ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ srcGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ srcFMarker = ALIGN(srcFMarker, 4); ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inGPRs[srcGMarker]; ++ ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcFMarker = ALIGN(srcFMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inGPRs[srcGMarker]; ++ ++ destMarker += 8; ++ ++ // Skip next GPR ++ srcGMarker += 8; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ destMarker = ALIGN(destMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ srcFMarker = ALIGN(srcFMarker, 8); ++ srcGMarker = ALIGN(srcGMarker, 8); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inFPRs[srcFMarker]; ++ srcFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ srcFMarker = ALIGN(srcFMarker, 16); ++ srcGMarker = ALIGN(srcGMarker, 16); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inGPRs[srcGMarker]; ++ } ++ ++ destMarker += 16; ++ ++ // Skip next 2 GPRs ++ srcGMarker += 16; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ if (inType->alignment == 1) // chars only ++ { ++ if (inType->size == 1) ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ else if (inType->size == 2) ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ i++; ++ } ++ else ++ { ++ memcpy(&outStruct[destMarker], ++ &inGPRs[srcGMarker], inType->size); ++ srcGMarker += inType->size; ++ destMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // chars and other stuff ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcGMarker = ALIGN(srcGMarker, 2); ++ destMarker = ALIGN(destMarker, 2); ++ ++ *(short*)&outStruct[destMarker] = ++ *(short*)&inGPRs[srcGMarker]; ++ srcGMarker += 2; ++ destMarker += 2; ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ *(int*)&outStruct[destMarker] = ++ *(int*)&inGPRs[srcGMarker]; ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcGMarker = ALIGN(srcGMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ *(long long*)&outStruct[destMarker] = ++ *(long long*)&inGPRs[srcGMarker]; ++ srcGMarker += 8; ++ destMarker += 8; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_ram_form(inType->elements[i], inGPRs, ++ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, ++ outStruct, &destMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); // unknown element type ++ break; ++ } ++ } ++ ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && srcGMarker == 16) ++ { ++ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; ++ srcFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioGPRMarker) ++ *ioGPRMarker = ALIGN(srcGMarker, 8); ++ ++ if (ioFPRMarker) ++ *ioFPRMarker = srcFMarker; ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(destMarker, 8); ++} ++ ++/* ffi64_struct_to_reg_form ++ ++ Copy a struct's elements into buffers that can be sliced into registers. ++ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers ++ to calculate size only. ++ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_reg_form( ++ const ffi_type* inType, ++ const char* inStruct, ++ unsigned int* ioStructMarker, ++ unsigned int* ioFPRsUsed, ++ char* outGPRs, // caller-allocated ++ unsigned int* ioGPRSize, ++ char* outFPRs, // caller-allocated ++ unsigned int* ioFPRSize) ++{ ++ size_t i; ++ unsigned int srcMarker = 0; ++ unsigned int destGMarker = 0; ++ unsigned int destFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioStructMarker) ++ srcMarker = *ioStructMarker; ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioGPRSize) ++ destGMarker = *ioGPRSize; ++ ++ if (ioFPRSize) ++ { ++ destFMarker = *ioFPRSize; ++ savedFMarker = destFMarker; ++ } ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ destGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ // Shadow floating-point types in GPRs for vararg and pre-ANSI ++ // functions. ++ case FFI_TYPE_FLOAT: ++ // Nudge markers to next 4/8-byte boundary ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcMarker = ALIGN(srcMarker, 8); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ ++ // Skip next GPR ++ destGMarker += 8; ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ srcMarker = ALIGN(srcMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ destFMarker = ALIGN(destFMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outFPRs != NULL && inStruct != NULL) ++ *(long double*)&outFPRs[destFMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ destFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ destGMarker = ALIGN(destGMarker, 16); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ } ++ ++ srcMarker += 16; ++ destGMarker += 16; // Skip next 2 GPRs ++ destGMarker = ALIGN(destGMarker, 8); // was 16 ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ if (inType->alignment == 1) // bytes only ++ { ++ if (inType->size == 1) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ } ++ else if (inType->size == 2) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; ++ } ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ i++; ++ } ++ else ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ // Avoid memcpy for small chunks. ++ if (inType->size <= sizeof(long)) ++ *(long*)&outGPRs[destGMarker] = ++ *(long*)&inStruct[srcMarker]; ++ else ++ memcpy(&outGPRs[destGMarker], ++ &inStruct[srcMarker], inType->size); ++ } ++ ++ srcMarker += inType->size; ++ destGMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // bytes and other stuff ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcMarker = ALIGN(srcMarker, 2); ++ destGMarker = ALIGN(destGMarker, 2); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(short*)&outGPRs[destGMarker] = ++ *(short*)&inStruct[srcMarker]; ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(int*)&outGPRs[destGMarker] = ++ *(int*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcMarker = ALIGN(srcMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long long*)&outGPRs[destGMarker] = ++ *(long long*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ destGMarker += 8; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_reg_form(inType->elements[i], ++ inStruct, &srcMarker, &fprsUsed, outGPRs, ++ &destGMarker, outFPRs, &destFMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && destGMarker == 16) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; ++ ++ destFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(srcMarker, 8); ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioGPRSize) ++ *ioGPRSize = ALIGN(destGMarker, 8); ++ ++ if (ioFPRSize) ++ *ioFPRSize = ALIGN(destFMarker, 8); ++} ++ ++/* ffi64_stret_needs_ptr ++ ++ Determine whether a returned struct needs a pointer in r3 or can fit ++ in registers. ++*/ ++ ++bool ++ffi64_stret_needs_ptr( ++ const ffi_type* inType, ++ unsigned short* ioGPRCount, ++ unsigned short* ioFPRCount) ++{ ++ // Obvious case first- struct is larger than combined FPR size. ++ if (inType->size > 14 * 8) ++ return true; ++ ++ // Now the struct can physically fit in registers, determine if it ++ // also fits logically. ++ bool needsPtr = false; ++ unsigned short gprsUsed = 0; ++ unsigned short fprsUsed = 0; ++ size_t i; ++ ++ if (ioGPRCount) ++ gprsUsed = *ioGPRCount; ++ ++ if (ioFPRCount) ++ fprsUsed = *ioFPRCount; ++ ++ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ gprsUsed++; ++ fprsUsed++; ++ ++ if (fprsUsed > 13) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ gprsUsed += 2; ++ fprsUsed += 2; ++ ++ if (fprsUsed > 14) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ { ++ needsPtr = true; ++ break; ++ } ++ ++ if (inType->elements[i + 1] == NULL) // last byte in the struct ++ break; ++ ++ // Count possible contiguous bytes ahead, up to 8. ++ unsigned short j; ++ ++ for (j = 1; j < 8; j++) ++ { ++ if (inType->elements[i + j] == NULL || ++ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) ++ break; ++ } ++ ++ i += j - 1; // allow for i++ before the test condition ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ needsPtr = ffi64_stret_needs_ptr( ++ inType->elements[i], &gprsUsed, &fprsUsed); ++ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ if (ioGPRCount) ++ *ioGPRCount = gprsUsed; ++ ++ if (ioFPRCount) ++ *ioFPRCount = fprsUsed; ++ ++ return needsPtr; ++} ++ ++/* ffi64_data_size ++ ++ Calculate the size in bytes of an ffi type. ++*/ ++ ++unsigned int ++ffi64_data_size( ++ const ffi_type* inType) ++{ ++ unsigned int size = 0; ++ ++ switch (inType->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ size = 1; ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ size = 2; ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_FLOAT: ++ size = 4; ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_DOUBLE: ++ size = 8; ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ size = 16; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ ffi64_struct_to_reg_form( ++ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); ++ break; ++ ++ case FFI_TYPE_VOID: ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ ++ return size; ++} ++ ++#endif /* defined(__ppc64__) */ ++#endif /* __ppc__ || __ppc64__ */ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +new file mode 100644 +index 0000000..7162fa1 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +@@ -0,0 +1,418 @@ ++#if defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc64-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 ++ stg r0,SF_RETURN(r1) // save return address ++ ++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. ++ stg r3,SF_ARG1(r1) ++ stg r4,SF_ARG2(r1) ++ stg r5,SF_ARG3(r1) ++ stg r6,SF_ARG4(r1) ++ stg r7,SF_ARG5(r1) ++ stg r8,SF_ARG6(r1) ++ stg r9,SF_ARG7(r1) ++ stg r10,SF_ARG8(r1) ++ ++LCFI0: ++/* 48 bytes (Linkage Area) ++ 64 bytes (outgoing parameter area, always reserved) ++ 112 bytes (14*8 for incoming FPR) ++ ? bytes (result) ++ 112 bytes (14*8 for outgoing FPR) ++ 16 bytes (2 saved registers) ++ 352 + ? total bytes ++*/ ++ ++ std r31,-8(r1) // Save registers we use. ++ std r30,-16(r1) ++ mr r30,r1 // Save the old SP. ++ mr r31,r11 // Save the ffi_closure around ffi64_data_size. ++ ++ // Calculate the space we need. ++ stdu r1,-SF_MINSIZE(r1) ++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ bl Lffi64_data_size$stub ++ ld r1,0(r1) ++ ++ addi r3,r3,352 // Add our overhead. ++ neg r3,r3 ++ li r0,-32 // Align to 32 bytes. ++ and r3,r3,r0 ++ stdux r1,r1,r3 // Grow the stack. ++ ++ mr r11,r31 // Copy the ffi_closure back. ++ ++LCFI1: ++ // We want to build up an area for the parameters passed ++ // in registers. (both floating point and integer) ++ ++/* 320 bytes (callee stack frame aligned to 32) ++ 48 bytes (caller linkage area) ++ 368 (start of caller parameter area aligned to 8) ++*/ ++ ++ // Save FPRs 1 - 14. (aligned to 8) ++ stfd f1,112(r1) ++ stfd f2,120(r1) ++ stfd f3,128(r1) ++ stfd f4,136(r1) ++ stfd f5,144(r1) ++ stfd f6,152(r1) ++ stfd f7,160(r1) ++ stfd f8,168(r1) ++ stfd f9,176(r1) ++ stfd f10,184(r1) ++ stfd f11,192(r1) ++ stfd f12,200(r1) ++ stfd f13,208(r1) ++ stfd f14,216(r1) ++ ++ // Set up registers for the routine that actually does the work. ++ mr r3,r11 // context pointer from the trampoline ++ addi r4,r1,224 // result storage ++ addi r5,r30,SF_ARG1 // saved GPRs ++ addi r6,r1,112 // saved FPRs ++ bl Lffi_closure_helper_DARWIN$stub ++ ++ // Look the proper starting point in table ++ // by using return type as an offset. ++ addi r5,r1,224 // 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. ++ mtctr r3 ++ bctr ++ ++LFE1: ++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ // (4 instructions). For cache effectiveness we align to a 16 byte ++ // boundary first. ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++// case FFI_TYPE_VOID ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++// case FFI_TYPE_INT ++Lret_type1: ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_FLOAT ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_DOUBLE ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_LONGDOUBLE ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT8 ++Lret_type5: ++ lbz r3,7(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT8 ++Lret_type6: ++ lbz r3,7(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT16 ++Lret_type7: ++ lhz r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT16 ++Lret_type8: ++ lha r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT32 ++Lret_type9: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT32 ++Lret_type10: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT64 ++Lret_type11: ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT64 ++Lret_type12: // same as Lret_type11 ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_STRUCT ++Lret_type13: ++ b Lret_struct ++ nop ++ nop ++ nop ++ ++// ** End 16-byte aligned cases ** ++// case FFI_TYPE_POINTER ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ b Lfinish ++ ++// copy struct into registers ++Lret_struct: ++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r31) // ffi_cif->rtype* ++ ld r31,24(r31) // ffi_cif->flags ++ mr r4,r5 // copy struct* to 2nd arg ++ addi r7,r1,SF_ARG9 // GPR return area ++ addi r9,r30,-16-(14*8) // FPR return area ++ li r5,0 // struct offset ptr (NULL) ++ li r6,0 // FPR used count ptr (NULL) ++ li r8,0 // GPR return area size ptr (NULL) ++ li r10,0 // FPR return area size ptr (NULL) ++ bl Lffi64_struct_to_reg_form$stub ++ ++ // Load GPRs ++ ld r3,SF_ARG9(r1) ++ ld r4,SF_ARG10(r1) ++ ld r5,SF_ARG11(r1) ++ ld r6,SF_ARG12(r1) ++ nop ++ ld r7,SF_ARG13(r1) ++ ld r8,SF_ARG14(r1) ++ ld r9,SF_ARG15(r1) ++ ld r10,SF_ARG16(r1) ++ nop ++ ++ // Load FPRs ++ mtcrf 0x2,r31 ++ bf 26,Lfinish ++ lfd f1,-16-(14*8)(r30) ++ lfd f2,-16-(13*8)(r30) ++ lfd f3,-16-(12*8)(r30) ++ lfd f4,-16-(11*8)(r30) ++ nop ++ lfd f5,-16-(10*8)(r30) ++ lfd f6,-16-(9*8)(r30) ++ lfd f7,-16-(8*8)(r30) ++ lfd f8,-16-(7*8)(r30) ++ nop ++ lfd f9,-16-(6*8)(r30) ++ lfd f10,-16-(5*8)(r30) ++ lfd f11,-16-(4*8)(r30) ++ lfd f12,-16-(3*8)(r30) ++ nop ++ lfd f13,-16-(2*8)(r30) ++ lfd f14,-16-(1*8)(r30) ++ // Fall through ++ ++// case done ++Lfinish: ++ 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. ++ blr ++ ++// END(ffi_closure_ASM) ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_reg_form$stub: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_reg_form ++ ++LO$ffi64_struct_to_reg_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) ++ mtctr r12 ++ bctr ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_data_size$stub: ++ .indirect_symbol _ffi64_data_size ++ mflr r0 ++ bcl 20,31,LO$ffi64_data_size ++ ++LO$ffi64_data_size: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_reg_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ .g_long dyld_stub_binding_helper ++ ++L_ffi64_data_size$lazy_ptr: ++ .indirect_symbol _ffi64_data_size ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c +new file mode 100644 +index 0000000..44806ae +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/types.c +@@ -0,0 +1,115 @@ ++/* ----------------------------------------------------------------------- ++ types.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Predefined ffi_types needed by libffi. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++/* Type definitions */ ++#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \ ++ ffi_type ffi_type_##n = { s, a, t, NULL } ++#define FFI_AGGREGATE_TYPEDEF(n, e) \ ++ ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } ++ ++FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); ++FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); ++FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); ++FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); ++FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); ++FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); ++FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); ++ ++/* Size and alignment are fake here. They must not be 0. */ ++FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); ++ ++#if defined ALPHA || defined SPARC64 || defined X86_64 || \ ++ defined S390X || defined IA64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); ++#else ++FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); ++#endif ++ ++#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN) ++ ++# ifdef X86_64 ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++# else ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++# endif ++ ++#elif defined(POWERPC_DARWIN) ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#elif defined SH ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++#else ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#endif ++ ++#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN) ++ ++# if defined X86_WIN32 || defined X86_64 ++ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++# endif ++ ++# ifdef X86_DARWIN ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined ARM || defined SH || defined POWERPC_AIX ++FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); ++#elif defined POWERPC_DARWIN ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# if __GNUC__ >= 4 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined SPARC ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# ifdef SPARC64 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined X86_64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++#else ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S +new file mode 100644 +index 0000000..165d469 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S +@@ -0,0 +1,417 @@ ++/* ----------------------------------------------------------------------- ++ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. ++ derived from unix64.S ++ ++ x86-64 Foreign Function Interface for Darwin. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifdef __x86_64__ ++#define LIBFFI_ASM ++#include ++#include ++ ++ .file "darwin64.S" ++.text ++ ++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, ++ void *raddr, void (*fnaddr)()); ++ ++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame ++ for this function. This has been allocated by ffi_call. We also ++ deallocate some of the stack that has been alloca'd. */ ++ ++ .align 3 ++ .globl _ffi_call_unix64 ++ ++_ffi_call_unix64: ++LUW0: ++ movq (%rsp), %r10 /* Load return address. */ ++ movq %rdi, %r12 /* Save a copy of the register area. */ ++ leaq (%rdi, %rsi), %rax /* Find local stack base. */ ++ movq %rdx, (%rax) /* Save flags. */ ++ movq %rcx, 8(%rax) /* Save raddr. */ ++ movq %rbp, 16(%rax) /* Save old frame pointer. */ ++ movq %r10, 24(%rax) /* Relocate return address. */ ++ movq %rax, %rbp /* Finalize local stack frame. */ ++LUW1: ++ /* movq %rdi, %r10 // Save a copy of the register area. */ ++ movq %r12, %r10 ++ movq %r8, %r11 /* Save a copy of the target fn. */ ++ movl %r9d, %eax /* Set number of SSE registers. */ ++ ++ /* Load up all argument registers. */ ++ movq (%r10), %rdi ++ movq 8(%r10), %rsi ++ movq 16(%r10), %rdx ++ movq 24(%r10), %rcx ++ movq 32(%r10), %r8 ++ movq 40(%r10), %r9 ++ testl %eax, %eax ++ jnz Lload_sse ++Lret_from_load_sse: ++ ++ /* Deallocate the reg arg area. */ ++ leaq 176(%r10), %rsp ++ ++ /* Call the user function. */ ++ call *%r11 ++ ++ /* Deallocate stack arg area; local stack frame in redzone. */ ++ leaq 24(%rbp), %rsp ++ ++ movq 0(%rbp), %rcx /* Reload flags. */ ++ movq 8(%rbp), %rdi /* Reload raddr. */ ++ movq 16(%rbp), %rbp /* Reload old frame pointer. */ ++LUW2: ++ ++ /* The first byte of the flags contains the FFI_TYPE. */ ++ movzbl %cl, %r10d ++ leaq Lstore_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lstore_table: ++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ ++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ ++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ ++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ ++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ ++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ ++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ ++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ ++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lst_void: ++ ret ++ .align 3 ++Lst_uint8: ++ movzbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_sint8: ++ movsbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint16: ++ movzwq %ax, %rax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint16: ++ movswq %ax, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint32: ++ movl %eax, %eax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint32: ++ cltq ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_int64: ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_float: ++ movss %xmm0, (%rdi) ++ ret ++ .align 3 ++Lst_double: ++ movsd %xmm0, (%rdi) ++ ret ++Lst_ldouble: ++ fstpt (%rdi) ++ ret ++ .align 3 ++Lst_struct: ++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */ ++ ++ /* We have to locate the values now, and since we don't want to ++ write too much data into the user's return value, we spill the ++ value to a 16 byte scratch area first. Bits 8, 9, and 10 ++ control where the values are located. Only one of the three ++ bits will be set; see ffi_prep_cif_machdep for the pattern. */ ++ movd %xmm0, %r10 ++ movd %xmm1, %r11 ++ testl $0x100, %ecx ++ cmovnz %rax, %rdx ++ cmovnz %r10, %rax ++ testl $0x200, %ecx ++ cmovnz %r10, %rdx ++ testl $0x400, %ecx ++ cmovnz %r10, %rax ++ cmovnz %r11, %rdx ++ movq %rax, (%rsi) ++ movq %rdx, 8(%rsi) ++ ++ /* Bits 12-31 contain the true size of the structure. Copy from ++ the scratch area to the true destination. */ ++ shrl $12, %ecx ++ rep movsb ++ ret ++ ++ /* Many times we can avoid loading any SSE registers at all. ++ It's not worth an indirect jump to load the exact set of ++ SSE registers needed; zero or all is a good compromise. */ ++ .align 3 ++LUW3: ++Lload_sse: ++ movdqa 48(%r10), %xmm0 ++ movdqa 64(%r10), %xmm1 ++ movdqa 80(%r10), %xmm2 ++ movdqa 96(%r10), %xmm3 ++ movdqa 112(%r10), %xmm4 ++ movdqa 128(%r10), %xmm5 ++ movdqa 144(%r10), %xmm6 ++ movdqa 160(%r10), %xmm7 ++ jmp Lret_from_load_sse ++ ++LUW4: ++ .align 3 ++ .globl _ffi_closure_unix64 ++ ++_ffi_closure_unix64: ++LUW5: ++ /* The carry flag is set by the trampoline iff SSE registers ++ are used. Don't clobber it before the branch instruction. */ ++ leaq -200(%rsp), %rsp ++LUW6: ++ movq %rdi, (%rsp) ++ movq %rsi, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rcx, 24(%rsp) ++ movq %r8, 32(%rsp) ++ movq %r9, 40(%rsp) ++ jc Lsave_sse ++Lret_from_save_sse: ++ ++ movq %r10, %rdi ++ leaq 176(%rsp), %rsi ++ movq %rsp, %rdx ++ leaq 208(%rsp), %rcx ++ call _ffi_closure_unix64_inner ++ ++ /* Deallocate stack frame early; return value is now in redzone. */ ++ addq $200, %rsp ++LUW7: ++ ++ /* The first byte of the return value contains the FFI_TYPE. */ ++ movzbl %al, %r10d ++ leaq Lload_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lload_table: ++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */ ++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ ++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ ++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ ++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lld_void: ++ ret ++ .align 3 ++Lld_int8: ++ movzbl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int16: ++ movzwl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int32: ++ movl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int64: ++ movq -24(%rsp), %rax ++ ret ++ .align 3 ++Lld_float: ++ movss -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_double: ++ movsd -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_ldouble: ++ fldt -24(%rsp) ++ ret ++ .align 3 ++Lld_struct: ++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, ++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading ++ both rdx and xmm1 with the second word. For the remaining, ++ bit 8 set means xmm0 gets the second word, and bit 9 means ++ that rax gets the second word. */ ++ movq -24(%rsp), %rcx ++ movq -16(%rsp), %rdx ++ movq -16(%rsp), %xmm1 ++ testl $0x100, %eax ++ cmovnz %rdx, %rcx ++ movd %rcx, %xmm0 ++ testl $0x200, %eax ++ movq -24(%rsp), %rax ++ cmovnz %rdx, %rax ++ ret ++ ++ /* See the comment above Lload_sse; the same logic applies here. */ ++ .align 3 ++LUW8: ++Lsave_sse: ++ movdqa %xmm0, 48(%rsp) ++ movdqa %xmm1, 64(%rsp) ++ movdqa %xmm2, 80(%rsp) ++ movdqa %xmm3, 96(%rsp) ++ movdqa %xmm4, 112(%rsp) ++ movdqa %xmm5, 128(%rsp) ++ movdqa %xmm6, 144(%rsp) ++ movdqa %xmm7, 160(%rsp) ++ jmp Lret_from_save_sse ++ ++LUW9: ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ ++ .long L$set$0 ++LSCIE1: ++ .long 0x0 /* CIE Identifier Tag */ ++ .byte 0x1 /* CIE Version */ ++ .ascii "zR\0" /* CIE Augmentation */ ++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ ++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ ++ .byte 0x10 /* CIE RA Column */ ++ .byte 0x1 /* uleb128 0x1; Augmentation size */ ++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */ ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 /* uleb128 0x7 */ ++ .byte 0x8 /* uleb128 0x8 */ ++ .byte 0x90 /* DW_CFA_offset, column 0x10 */ ++ .byte 0x1 ++ .align 3 ++LECIE1: ++ .globl _ffi_call_unix64.eh ++_ffi_call_unix64.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ ++ .long L$set$1 ++LASFDE1: ++ .long LASFDE1-EH_frame1 /* FDE CIE offset */ ++ .quad LUW0-. /* FDE initial location */ ++ .set L$set$2,LUW4-LUW0 /* FDE address range */ ++ .quad L$set$2 ++ .byte 0x0 /* Augmentation size */ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$3,LUW1-LUW0 ++ .long L$set$3 ++ ++ /* New stack frame based off rbp. This is a itty bit of unwind ++ trickery in that the CFA *has* changed. There is no easy way ++ to describe it correctly on entry to the function. Fortunately, ++ it doesn't matter too much since at all points we can correctly ++ unwind back to ffi_call. Note that the location to which we ++ moved the return address is (the new) CFA-8, so from the ++ perspective of the unwind info, it hasn't moved. */ ++ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ ++ .byte 0x6 ++ .byte 0x20 ++ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ ++ .byte 0x2 ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$4,LUW2-LUW1 ++ .long L$set$4 ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 ++ .byte 0x8 ++ .byte 0xc0+6 /* DW_CFA_restore, %rbp */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$5,LUW3-LUW2 ++ .long L$set$5 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE1: ++ .globl _ffi_closure_unix64.eh ++_ffi_closure_unix64.eh: ++LSFDE3: ++ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ ++ .long L$set$6 ++LASFDE3: ++ .long LASFDE3-EH_frame1 /* FDE CIE offset */ ++ .quad LUW5-. /* FDE initial location */ ++ .set L$set$7,LUW9-LUW5 /* FDE address range */ ++ .quad L$set$7 ++ .byte 0x0 /* Augmentation size */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$8,LUW6-LUW5 ++ .long L$set$8 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 208,1 /* uleb128 208 */ ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$9,LUW7-LUW6 ++ .long L$set$9 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 0x8 ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$10,LUW8-LUW7 ++ .long L$set$10 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE3: ++ .subsections_via_symbols ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +new file mode 100644 +index 0000000..925a841 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +@@ -0,0 +1,422 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. ++ ++ X86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++/* ++ * This file is based on sysv.S and then hacked up by Ronald who hasn't done ++ * assembly programming in 8 years. ++ */ ++ ++#ifndef __x86_64__ ++ ++#define LIBFFI_ASM ++#include ++#include ++ ++#ifdef PyObjC_STRICT_DEBUGGING ++ /* XXX: Debugging of stack alignment, to be removed */ ++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 ++#else ++#define ASSERT_STACK_ALIGNED ++#endif ++ ++.text ++ ++.globl _ffi_prep_args ++ ++ .align 4 ++.globl _ffi_call_SYSV ++ ++_ffi_call_SYSV: ++LFB1: ++ pushl %ebp ++LCFI0: ++ movl %esp,%ebp ++LCFI1: ++ subl $8,%esp ++ /* Make room for all of the new args. */ ++ movl 16(%ebp),%ecx ++ subl %ecx,%esp ++ ++ movl %esp,%eax ++ ++ /* Place all of the ffi_prep_args in position */ ++ subl $8,%esp ++ pushl 12(%ebp) ++ pushl %eax ++ call *8(%ebp) ++ ++ /* Return stack to previous state and call the function */ ++ addl $16,%esp ++ ++ call *28(%ebp) ++ ++ /* 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 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 Lnoretval ++ fstp %st(0) ++ ++ jmp Lepilogue ++ ++Lretint: ++ cmpl $FFI_TYPE_INT,%ecx ++ jne Lretfloat ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ movl %eax,0(%ecx) ++ jmp Lepilogue ++ ++Lretfloat: ++ cmpl $FFI_TYPE_FLOAT,%ecx ++ jne Lretdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstps (%ecx) ++ jmp Lepilogue ++ ++Lretdouble: ++ cmpl $FFI_TYPE_DOUBLE,%ecx ++ jne Lretlongdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpl (%ecx) ++ jmp Lepilogue ++ ++Lretlongdouble: ++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx ++ jne Lretint64 ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpt (%ecx) ++ jmp Lepilogue ++ ++Lretint64: ++ cmpl $FFI_TYPE_SINT64,%ecx ++ 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 Lepilogue ++ ++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 ++ ++Lnoretval: ++Lepilogue: ++ addl $8,%esp ++ movl %ebp,%esp ++ popl %ebp ++ ret ++LFE1: ++.ffi_call_SYSV_end: ++ ++ .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_UINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_SINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_UINT16, %eax ++ je Lcls_retstruct2 ++ 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 ++ ++.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__ */ ++ ++#endif /* defined __i386__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +new file mode 100644 +index 0000000..06feaf2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +@@ -0,0 +1,734 @@ ++#ifdef __x86_64__ ++ ++/* ----------------------------------------------------------------------- ++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen ++ ++ x86-64 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_GPR_REGS 6 ++#define MAX_SSE_REGS 8 ++ ++typedef struct RegisterArgs { ++ /* Registers for argument passing. */ ++ UINT64 gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++} RegisterArgs; ++ ++extern void ++ffi_call_unix64( ++ void* args, ++ unsigned long bytes, ++ unsigned flags, ++ void* raddr, ++ void (*fnaddr)(), ++ unsigned ssecount); ++ ++/* All reference to register classes here is identical to the code in ++ gcc/config/i386/i386.c. Do *not* change one without the other. */ ++ ++/* 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 reformating penalties. ++ ++ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves ++ whenever possible (upper half does contain padding). */ ++enum x86_64_reg_class ++{ ++ X86_64_NO_CLASS, ++ X86_64_INTEGER_CLASS, ++ X86_64_INTEGERSI_CLASS, ++ X86_64_SSE_CLASS, ++ X86_64_SSESF_CLASS, ++ X86_64_SSEDF_CLASS, ++ X86_64_SSEUP_CLASS, ++ X86_64_X87_CLASS, ++ X86_64_X87UP_CLASS, ++ X86_64_COMPLEX_X87_CLASS, ++ X86_64_MEMORY_CLASS ++}; ++ ++#define MAX_CLASSES 4 ++#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) ++ ++/* x86-64 register passing implementation. See x86-64 ABI for details. Goal ++ of this code is to classify each 8bytes of incoming argument by the register ++ class and assign registers accordingly. */ ++ ++/* Return the union class of CLASS1 and CLASS2. ++ See the x86-64 PS ABI for details. */ ++static enum x86_64_reg_class ++merge_classes( ++ enum x86_64_reg_class class1, ++ enum x86_64_reg_class class2) ++{ ++ /* Rule #1: If both classes are equal, this is the resulting class. */ ++ if (class1 == class2) ++ return class1; ++ ++ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is ++ the other class. */ ++ if (class1 == X86_64_NO_CLASS) ++ return class2; ++ ++ if (class2 == X86_64_NO_CLASS) ++ return class1; ++ ++ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ ++ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ ++ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) ++ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) ++ return X86_64_INTEGERSI_CLASS; ++ ++ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS ++ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) ++ return X86_64_INTEGER_CLASS; ++ ++ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, ++ MEMORY is used. */ ++ if (class1 == X86_64_X87_CLASS ++ || class1 == X86_64_X87UP_CLASS ++ || class1 == X86_64_COMPLEX_X87_CLASS ++ || class2 == X86_64_X87_CLASS ++ || class2 == X86_64_X87UP_CLASS ++ || class2 == X86_64_COMPLEX_X87_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #6: Otherwise class SSE is used. */ ++ return X86_64_SSE_CLASS; ++} ++ ++/* Classify the argument of type TYPE and mode MODE. ++ CLASSES will be filled by the register class used to pass each word ++ of the operand. The number of words is returned. In case the parameter ++ should be passed in memory, 0 is returned. As a special case for zero ++ sized containers, classes[0] will be NO_CLASS and 1 is returned. ++ ++ See the x86-64 PS ABI for details. */ ++ ++static int ++classify_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[], ++ size_t byte_offset) ++{ ++ switch (type->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++#if 0 ++ if (byte_offset + type->size <= 4) ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ else ++ classes[0] = X86_64_INTEGER_CLASS; ++ ++ return 1; ++#else ++ { ++ int size = byte_offset + type->size; ++ ++ if (size <= 4) ++ { ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ return 1; ++ } ++ else if (size <= 8) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ return 1; ++ } ++ else if (size <= 12) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else if (size <= 16) ++ { ++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else ++ FFI_ASSERT (0); ++ } ++#endif ++ ++ case FFI_TYPE_FLOAT: ++ if (byte_offset == 0) ++ classes[0] = X86_64_SSESF_CLASS; ++ else ++ classes[0] = X86_64_SSE_CLASS; ++ ++ return 1; ++ ++ case FFI_TYPE_DOUBLE: ++ classes[0] = X86_64_SSEDF_CLASS; ++ return 1; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ classes[0] = X86_64_X87_CLASS; ++ classes[1] = X86_64_X87UP_CLASS; ++ return 2; ++ ++ case FFI_TYPE_STRUCT: ++ { ++ ffi_type** ptr; ++ int i; ++ enum x86_64_reg_class subclasses[MAX_CLASSES]; ++ const int UNITS_PER_WORD = 8; ++ int words = ++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ++ ++ /* If the struct is larger than 16 bytes, pass it on the stack. */ ++ if (type->size > 16) ++ return 0; ++ ++ for (i = 0; i < words; i++) ++ classes[i] = X86_64_NO_CLASS; ++ ++ /* Merge the fields of structure. */ ++ for (ptr = type->elements; *ptr != NULL; ptr++) ++ { ++ byte_offset = ALIGN(byte_offset, (*ptr)->alignment); ++ ++ int num = classify_argument(*ptr, subclasses, byte_offset % 8); ++ ++ if (num == 0) ++ return 0; ++ ++ int pos = byte_offset / 8; ++ ++ for (i = 0; i < num; i++) ++ { ++ classes[i + pos] = ++ merge_classes(subclasses[i], classes[i + pos]); ++ } ++ ++ byte_offset += (*ptr)->size; ++ } ++ ++ if (words > 2) ++ { ++ /* When size > 16 bytes, if the first one isn't ++ X86_64_SSE_CLASS or any other ones aren't ++ X86_64_SSEUP_CLASS, everything should be passed in ++ memory. */ ++ if (classes[0] != X86_64_SSE_CLASS) ++ return 0; ++ ++ for (i = 1; i < words; i++) ++ if (classes[i] != X86_64_SSEUP_CLASS) ++ return 0; ++ } ++ ++ ++ /* Final merger cleanup. */ ++ for (i = 0; i < words; i++) ++ { ++ /* If one class is MEMORY, everything should be passed in ++ memory. */ ++ if (classes[i] == X86_64_MEMORY_CLASS) ++ return 0; ++ ++ /* The X86_64_SSEUP_CLASS should be always preceded by ++ X86_64_SSE_CLASS. */ ++ if (classes[i] == X86_64_SSEUP_CLASS ++ && classes[i - 1] != X86_64_SSE_CLASS ++ && classes[i - 1] != X86_64_SSEUP_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ ++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ ++ if (classes[i] == X86_64_X87UP_CLASS ++ && classes[i - 1] != X86_64_X87_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ } ++ ++ return words; ++ } ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ return 0; /* Never reached. */ ++} ++ ++/* Examine the argument and return set number of register required in each ++ class. Return zero if parameter should be passed in memory, otherwise ++ the number of registers. */ ++static int ++examine_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[MAX_CLASSES], ++ _Bool in_return, ++ int* pngpr, ++ int* pnsse) ++{ ++ int n = classify_argument(type, classes, 0); ++ int ngpr = 0; ++ int nsse = 0; ++ int i; ++ ++ if (n == 0) ++ return 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ ngpr++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ nsse++; ++ break; ++ ++ case X86_64_NO_CLASS: ++ case X86_64_SSEUP_CLASS: ++ break; ++ ++ case X86_64_X87_CLASS: ++ case X86_64_X87UP_CLASS: ++ case X86_64_COMPLEX_X87_CLASS: ++ return in_return != 0; ++ ++ default: ++ abort(); ++ } ++ } ++ ++ *pngpr = ngpr; ++ *pnsse = nsse; ++ ++ return n; ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ int gprcount = 0; ++ int ssecount = 0; ++ int flags = cif->rtype->type; ++ int i, avn, n, ngpr, nsse; ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ size_t bytes; ++ ++ if (flags != FFI_TYPE_VOID) ++ { ++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value is passed in memory. A pointer to that ++ memory is the first argument. Allocate a register for it. */ ++ gprcount++; ++ ++ /* We don't have to do anything in asm for the return. */ ++ flags = FFI_TYPE_VOID; ++ } ++ else if (flags == FFI_TYPE_STRUCT) ++ { ++ /* Mark which registers the result appears in. */ ++ _Bool sse0 = SSE_CLASS_P(classes[0]); ++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]); ++ ++ if (sse0 && !sse1) ++ flags |= 1 << 8; ++ else if (!sse0 && sse1) ++ flags |= 1 << 9; ++ else if (sse0 && sse1) ++ flags |= 1 << 10; ++ ++ /* Mark the true size of the structure. */ ++ flags |= cif->rtype->size << 12; ++ } ++ } ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) ++ { ++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = cif->arg_types[i]->alignment; ++ ++ if (align < 8) ++ align = 8; ++ ++ bytes = ALIGN(bytes, align); ++ bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += ngpr; ++ ssecount += nsse; ++ } ++ } ++ ++ if (ssecount) ++ flags |= 1 << 11; ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ cif->bytes = ALIGN(bytes,8); ++ ++ return FFI_OK; ++} ++ ++void ++ffi_call( ++ ffi_cif* cif, ++ void (*fn)(), ++ void* rvalue, ++ void** avalue) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ char* stack; ++ char* argp; ++ ffi_type** arg_types; ++ int gprcount, ssecount, ngpr, nsse, i, avn; ++ _Bool ret_in_memory; ++ RegisterArgs* reg_args; ++ ++ /* Can't call 32-bit mode from 64-bit mode. */ ++ FFI_ASSERT(cif->abi == FFI_UNIX64); ++ ++ /* If the return value is a struct and we don't have a return value ++ address then we need to make one. Note the setting of flags to ++ VOID above in ffi_prep_cif_machdep. */ ++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT ++ && (cif->flags & 0xff) == FFI_TYPE_VOID); ++ ++ if (rvalue == NULL && ret_in_memory) ++ rvalue = alloca (cif->rtype->size); ++ ++ /* Allocate the space for the arguments, plus 4 words of temp space. */ ++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8); ++ reg_args = (RegisterArgs*)stack; ++ argp = stack + sizeof(RegisterArgs); ++ ++ gprcount = ssecount = 0; ++ ++ /* If the return value is passed in memory, add the pointer as the ++ first integer argument. */ ++ if (ret_in_memory) ++ reg_args->gpr[gprcount++] = (long) rvalue; ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ size_t size = arg_types[i]->size; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ memcpy (argp, avalue[i], size); ++ argp += size; ++ } ++ else ++ { /* The argument is passed entirely in registers. */ ++ char *a = (char *) avalue[i]; ++ int j; ++ ++ for (j = 0; j < n; j++, a += 8, size -= 8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ reg_args->gpr[gprcount] = 0; ++ switch (arg_types[i]->type) { ++ case FFI_TYPE_SINT8: ++ { ++ int8_t shortval = *(int8_t*)a; ++ int64_t actval = (int64_t)shortval; ++ reg_args->gpr[gprcount] = actval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ break; ++ } ++ ++ case FFI_TYPE_SINT16: ++ { ++ int16_t shortval = *(int16_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_SINT32: ++ { ++ int32_t shortval = *(int32_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT8: ++ { ++ u_int8_t shortval = *(u_int8_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ reg_args->gpr[gprcount] = actval; ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ { ++ u_int16_t shortval = *(u_int16_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT32: ++ { ++ u_int32_t shortval = *(u_int32_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ default: ++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); ++ reg_args->gpr[gprcount] = *(int64_t*)a; ++ } ++ gprcount++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSEDF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT64 *) a; ++ break; ++ ++ case X86_64_SSESF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT32 *) a; ++ break; ++ ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++ ++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs), ++ cif->flags, rvalue, fn, ssecount); ++} ++ ++extern void ffi_closure_unix64(void); ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ if (cif->abi != FFI_UNIX64) ++ return FFI_BAD_ABI; ++ ++ volatile unsigned short* tramp = ++ (volatile unsigned short*)&closure->tramp[0]; ++ ++ tramp[0] = 0xbb49; /* mov , %r11 */ ++ *(void* volatile*)&tramp[1] = ffi_closure_unix64; ++ tramp[5] = 0xba49; /* mov , %r10 */ ++ *(void* volatile*)&tramp[6] = closure; ++ ++ /* Set the carry bit if the function uses any sse registers. ++ This is clc or stc, together with the first byte of the jmp. */ ++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; ++ tramp[11] = 0xe3ff; /* jmp *%r11 */ ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wmissing-prototypes" ++int ++ffi_closure_unix64_inner( ++ ffi_closure* closure, ++ void* rvalue, ++ RegisterArgs* reg_args, ++ char* argp) ++#pragma clang diagnostic pop ++{ ++ ffi_cif* cif = closure->cif; ++ void** avalue = alloca(cif->nargs * sizeof(void *)); ++ ffi_type** arg_types; ++ long i, avn; ++ int gprcount = 0; ++ int ssecount = 0; ++ int ngpr, nsse; ++ int ret; ++ ++ ret = cif->rtype->type; ++ ++ if (ret != FFI_TYPE_VOID) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value goes in memory. Arrange for the closure ++ return value to go directly back to the original caller. */ ++ rvalue = (void *) reg_args->gpr[gprcount++]; ++ ++ /* We don't have to do anything in asm for the return. */ ++ ret = FFI_TYPE_VOID; ++ } ++ else if (ret == FFI_TYPE_STRUCT && n == 2) ++ { ++ /* Mark which register the second word of the structure goes in. */ ++ _Bool sse0 = SSE_CLASS_P (classes[0]); ++ _Bool sse1 = SSE_CLASS_P (classes[1]); ++ ++ if (!sse0 && sse1) ++ ret |= 1 << 8; ++ else if (sse0 && !sse1) ++ ret |= 1 << 9; ++ } ++ } ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ avalue[i] = argp; ++ argp += arg_types[i]->size; ++ } ++ ++#if !defined(X86_DARWIN) ++ /* If the argument is in a single register, or two consecutive ++ registers, then we can use that address directly. */ ++ else if (n == 1 || (n == 2 && ++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1]))) ++ { ++ // The argument is in a single register. ++ if (SSE_CLASS_P (classes[0])) ++ { ++ avalue[i] = ®_args->sse[ssecount]; ++ ssecount += n; ++ } ++ else ++ { ++ avalue[i] = ®_args->gpr[gprcount]; ++ gprcount += n; ++ } ++ } ++#endif ++ ++ /* Otherwise, allocate space to make them consecutive. */ ++ else ++ { ++ char *a = alloca (16); ++ int j; ++ ++ avalue[i] = a; ++ ++ for (j = 0; j < n; j++, a += 8) ++ { ++ if (SSE_CLASS_P (classes[j])) ++ memcpy (a, ®_args->sse[ssecount++], 8); ++ else ++ memcpy (a, ®_args->gpr[gprcount++], 8); ++ } ++ } ++ } ++ ++ /* Invoke the closure. */ ++ closure->fun (cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell assembly how to perform return type promotions. */ ++ return ret; ++} ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +new file mode 100644 +index 0000000..706ea0f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +@@ -0,0 +1,438 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ++ Copyright (c) 2002 Ranjit Mathew ++ Copyright (c) 2002 Bo Thorsen ++ Copyright (c) 2002 Roger Sayle ++ ++ x86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments */ ++ ++void ffi_prep_args(char *stack, extended_cif *ecif); ++ ++void ffi_prep_args(char *stack, extended_cif *ecif) ++{ ++ 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) ++ { ++ *(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) ++{ ++ /* 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_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; ++ } ++ ++#ifdef X86_DARWIN ++ cif->bytes = (cif->bytes + 15) & ~0xF; ++#endif ++ ++ return FFI_OK; ++} ++ ++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 *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); ++ ++#endif /* X86_WIN32 */ ++ ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++ ++/** private members **/ ++ ++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 */ ++ ++unsigned int FFI_HIDDEN ++ffi_closure_SYSV_inner (closure, respp, args) ++ffi_closure *closure; ++void **respp; ++void *args; ++{ ++ // 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 - (__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) ++{ ++ if (cif->abi != FFI_SYSV) ++ return FFI_BAD_ABI; ++ ++ 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 ++ ++ffi_status ++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) ++{ ++ 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) ++{ ++ 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 *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++ ++#ifdef X86_WIN32 ++extern void ++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++#endif /* X86_WIN32 */ ++ ++void ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++#endif ++#endif // __i386__ +diff --git ./setup.py ./setup.py +index 46b92fe..2bf6b4b 100644 +--- ./setup.py ++++ ./setup.py +@@ -98,8 +98,14 @@ class PyBuildExt(build_ext): + self.detect_modules() + + # Remove modules that are present on the disabled list +- self.extensions = [ext for ext in self.extensions +- if ext.name not in disabled_module_list] ++ extensions = [ext for ext in self.extensions ++ if ext.name not in disabled_module_list] ++ # move ctypes to the end, it depends on other modules ++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) ++ if "_ctypes" in ext_map: ++ ctypes = extensions.pop(ext_map["_ctypes"]) ++ extensions.append(ctypes) ++ self.extensions = extensions + + # Fix up the autodetected modules, prefixing all the source files + # with Modules/ and adding Python's include directory to the path. +@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext): + # *** Uncomment these for TOGL extension only: + # -lGL -lGLU -lXext -lXmu \ + ++ def configure_ctypes_darwin(self, ext): ++ # Darwin (OS X) uses preconfigured files, in ++ # the Modules/_ctypes/libffi_osx directory. ++ srcdir = sysconfig.get_config_var('srcdir') ++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', ++ '_ctypes', 'libffi_osx')) ++ sources = [os.path.join(ffi_srcdir, p) ++ for p in ['ffi.c', ++ 'x86/darwin64.S', ++ 'x86/x86-darwin.S', ++ 'x86/x86-ffi_darwin.c', ++ 'x86/x86-ffi64.c', ++ 'powerpc/ppc-darwin.S', ++ 'powerpc/ppc-darwin_closure.S', ++ 'powerpc/ppc-ffi_darwin.c', ++ 'powerpc/ppc64-darwin_closure.S', ++ ]] ++ ++ # Add .S (preprocessed assembly) to C compiler source extensions. ++ self.compiler.src_extensions.append('.S') ++ ++ include_dirs = [os.path.join(ffi_srcdir, 'include'), ++ os.path.join(ffi_srcdir, 'powerpc')] ++ ext.include_dirs.extend(include_dirs) ++ ext.sources.extend(sources) ++ return True ++ + def configure_ctypes(self, ext): + if not self.use_system_libffi: +- (srcdir,) = sysconfig.get_config_vars('srcdir') ++ if sys.platform == 'darwin': ++ return self.configure_ctypes_darwin(ext) ++ ++ srcdir = sysconfig.get_config_var('srcdir') + ffi_builddir = os.path.join(self.build_temp, 'libffi') + ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + '_ctypes', 'libffi')) +@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext): + ffi_configfile): + from distutils.dir_util import mkpath + mkpath(ffi_builddir) +- config_args = [] ++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() ++ if (('--host=' in arg) or ('--build=' in arg))] ++ if not self.verbose: ++ config_args.append("-q") + + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. +@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext): + self.compiler.src_extensions.append('.S') + + include_dirs = [os.path.join(ffi_builddir, 'include'), +- ffi_builddir, ffi_srcdir] ++ ffi_builddir, ++ os.path.join(ffi_srcdir, 'src')] + extra_compile_args = fficonfig['ffi_cflags'].split() + +- ext.sources.extend(fficonfig['ffi_sources']) ++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in ++ fficonfig['ffi_sources']) + ext.include_dirs.extend(include_dirs) + ext.extra_compile_args.extend(extra_compile_args) + return True +@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext): + + if sys.platform == 'darwin': + sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + # XXX Is this still needed? + ## extra_link_args.extend(['-read_only_relocs', 'warning']) +@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext): + if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = find_file('ffi.h', [], inc_dirs) ++ if sys.platform == 'darwin': ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') ++ ++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] ++ if not ffi_inc or ffi_inc[0] == '': ++ ffi_inc = find_file('ffi.h', [], inc_dirs) + if ffi_inc is not None: + ffi_h = ffi_inc[0] + '/ffi.h' + fp = open(ffi_h) diff --git a/plugins/python-build/share/python-build/patches/2.5.5/Python-2.5.5/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.5/Python-2.5.5/004_osx_libffi.patch new file mode 100644 index 00000000..cd500771 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/2.5.5/Python-2.5.5/004_osx_libffi.patch @@ -0,0 +1,6881 @@ +diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE +new file mode 100644 +index 0000000..f591795 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/LICENSE +@@ -0,0 +1,20 @@ ++libffi - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++``Software''), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice shall be included ++in all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++OTHER DEALINGS IN THE SOFTWARE. +diff --git ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README +new file mode 100644 +index 0000000..1fc2747 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README +@@ -0,0 +1,500 @@ ++This directory contains the libffi package, which is not part of GCC but ++shipped with GCC as convenience. ++ ++Status ++====== ++ ++libffi-2.00 has not been released yet! This is a development snapshot! ++ ++libffi-1.20 was released on October 5, 1998. Check the libffi web ++page for updates: . ++ ++ ++What is libffi? ++=============== ++ ++Compilers for high level languages generate code that follow certain ++conventions. These conventions are necessary, in part, for separate ++compilation to work. One such convention is the "calling ++convention". The "calling convention" is essentially a set of ++assumptions made by the compiler about where function arguments will ++be found on entry to a function. A "calling convention" also specifies ++where the return value for a function is found. ++ ++Some programs may not know at the time of compilation what arguments ++are to be passed to a function. For instance, an interpreter may be ++told at run-time about the number and types of arguments used to call ++a given function. Libffi can be used in such programs to provide a ++bridge from the interpreter program to compiled code. ++ ++The libffi library provides a portable, high level programming ++interface to various calling conventions. This allows a programmer to ++call any function specified by a call interface description at run ++time. ++ ++Ffi stands for Foreign Function Interface. A foreign function ++interface is the popular name for the interface that allows code ++written in one language to call code written in another language. The ++libffi library really only provides the lowest, machine dependent ++layer of a fully featured foreign function interface. A layer must ++exist above libffi that handles type conversions for values passed ++between the two languages. ++ ++ ++Supported Platforms and Prerequisites ++===================================== ++ ++Libffi has been ported to: ++ ++ SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) ++ ++ Irix 5.3 & 6.2 (System V/o32 & n32) ++ ++ Intel x86 - Linux (System V ABI) ++ ++ Alpha - Linux and OSF/1 ++ ++ m68k - Linux (System V ABI) ++ ++ PowerPC - Linux (System V ABI, Darwin, AIX) ++ ++ ARM - Linux (System V ABI) ++ ++Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are ++that other versions will work. Libffi has also been built and tested ++with the SGI compiler tools. ++ ++On PowerPC, the tests failed (see the note below). ++ ++You must use GNU make to build libffi. SGI's make will not work. ++Sun's probably won't either. ++ ++If you port libffi to another platform, please let me know! I assume ++that some will be easy (x86 NetBSD), and others will be more difficult ++(HP). ++ ++ ++Installing libffi ++================= ++ ++[Note: before actually performing any of these installation steps, ++ you may wish to read the "Platform Specific Notes" below.] ++ ++First you must configure the distribution for your particular ++system. Go to the directory you wish to build libffi in and run the ++"configure" program found in the root directory of the libffi source ++distribution. ++ ++You may want to tell configure where to install the libffi library and ++header files. To do that, use the --prefix configure switch. Libffi ++will install under /usr/local by default. ++ ++If you want to enable extra run-time debugging checks use the the ++--enable-debug configure switch. This is useful when your program dies ++mysteriously while using libffi. ++ ++Another useful configure switch is --enable-purify-safety. Using this ++will add some extra code which will suppress certain warnings when you ++are using Purify with libffi. Only use this switch when using ++Purify, as it will slow down the library. ++ ++Configure has many other options. Use "configure --help" to see them all. ++ ++Once configure has finished, type "make". Note that you must be using ++GNU make. SGI's make will not work. Sun's probably won't either. ++You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. ++ ++To ensure that libffi is working as advertised, type "make test". ++ ++To install the library and header files, type "make install". ++ ++ ++Using libffi ++============ ++ ++ The Basics ++ ---------- ++ ++Libffi assumes that you have a pointer to the function you wish to ++call and that you know the number and types of arguments to pass it, ++as well as the return type of the function. ++ ++The first thing you must do is create an ffi_cif object that matches ++the signature of the function you wish to call. The cif in ffi_cif ++stands for Call InterFace. To prepare a call interface object, use the ++following function: ++ ++ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, ++ unsigned int nargs, ++ ffi_type *rtype, ffi_type **atypes); ++ ++ CIF is a pointer to the call interface object you wish ++ to initialize. ++ ++ ABI is an enum that specifies the calling convention ++ to use for the call. FFI_DEFAULT_ABI defaults ++ to the system's native calling convention. Other ++ ABI's may be used with care. They are system ++ specific. ++ ++ NARGS is the number of arguments this function accepts. ++ libffi does not yet support vararg functions. ++ ++ RTYPE is a pointer to an ffi_type structure that represents ++ the return type of the function. Ffi_type objects ++ describe the types of values. libffi provides ++ ffi_type objects for many of the native C types: ++ signed int, unsigned int, signed char, unsigned char, ++ etc. There is also a pointer ffi_type object and ++ a void ffi_type. Use &ffi_type_void for functions that ++ don't return values. ++ ++ ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. ++ If NARGS is 0, this is ignored. ++ ++ ++ffi_prep_cif will return a status code that you are responsible ++for checking. It will be one of the following: ++ ++ FFI_OK - All is good. ++ ++ FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif ++ came across is bad. ++ ++ ++Before making the call, the VALUES vector should be initialized ++with pointers to the appropriate argument values. ++ ++To call the the function using the initialized ffi_cif, use the ++ffi_call function: ++ ++void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); ++ ++ CIF is a pointer to the ffi_cif initialized specifically ++ for this function. ++ ++ FN is a pointer to the function you want to call. ++ ++ RVALUE is a pointer to a chunk of memory that is to hold the ++ result of the function call. Currently, it must be ++ at least one word in size (except for the n32 version ++ under Irix 6.x, which must be a pointer to an 8 byte ++ aligned value (a long long). It must also be at least ++ word aligned (depending on the return type, and the ++ system's alignment requirements). If RTYPE is ++ &ffi_type_void, this is ignored. If RVALUE is NULL, ++ the return value is discarded. ++ ++ AVALUES is a vector of void* that point to the memory locations ++ holding the argument values for a call. ++ If NARGS is 0, this is ignored. ++ ++ ++If you are expecting a return value from FN it will have been stored ++at RVALUE. ++ ++ ++ ++ An Example ++ ---------- ++ ++Here is a trivial example that calls puts() a few times. ++ ++ #include ++ #include ++ ++ int main() ++ { ++ ffi_cif cif; ++ ffi_type *args[1]; ++ void *values[1]; ++ char *s; ++ int rc; ++ ++ /* Initialize the argument info vectors */ ++ args[0] = &ffi_type_uint; ++ values[0] = &s; ++ ++ /* Initialize the cif */ ++ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, ++ &ffi_type_uint, args) == FFI_OK) ++ { ++ s = "Hello World!"; ++ ffi_call(&cif, puts, &rc, values); ++ /* rc now holds the result of the call to puts */ ++ ++ /* values holds a pointer to the function's arg, so to ++ call puts() again all we need to do is change the ++ value of s */ ++ s = "This is cool!"; ++ ffi_call(&cif, puts, &rc, values); ++ } ++ ++ return 0; ++ } ++ ++ ++ ++ Aggregate Types ++ --------------- ++ ++Although libffi has no special support for unions or bit-fields, it is ++perfectly happy passing structures back and forth. You must first ++describe the structure to libffi by creating a new ffi_type object ++for it. Here is the definition of ffi_type: ++ ++ typedef struct _ffi_type ++ { ++ unsigned size; ++ short alignment; ++ short type; ++ struct _ffi_type **elements; ++ } ffi_type; ++ ++All structures must have type set to FFI_TYPE_STRUCT. You may set ++size and alignment to 0. These will be calculated and reset to the ++appropriate values by ffi_prep_cif(). ++ ++elements is a NULL terminated array of pointers to ffi_type objects ++that describe the type of the structure elements. These may, in turn, ++be structure elements. ++ ++The following example initializes a ffi_type object representing the ++tm struct from Linux's time.h: ++ ++ struct tm { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++ /* Those are for future use. */ ++ long int __tm_gmtoff__; ++ __const char *__tm_zone__; ++ }; ++ ++ { ++ ffi_type tm_type; ++ ffi_type *tm_type_elements[12]; ++ int i; ++ ++ tm_type.size = tm_type.alignment = 0; ++ tm_type.elements = &tm_type_elements; ++ ++ for (i = 0; i < 9; i++) ++ tm_type_elements[i] = &ffi_type_sint; ++ ++ tm_type_elements[9] = &ffi_type_slong; ++ tm_type_elements[10] = &ffi_type_pointer; ++ tm_type_elements[11] = NULL; ++ ++ /* tm_type can now be used to represent tm argument types and ++ return types for ffi_prep_cif() */ ++ } ++ ++ ++ ++Platform Specific Notes ++======================= ++ ++ Intel x86 ++ --------- ++ ++There are no known problems with the x86 port. ++ ++ Sun SPARC - SunOS 4.1.3 & Solaris 2.x ++ ------------------------------------- ++ ++You must use GNU Make to build libffi on Sun platforms. ++ ++ MIPS - Irix 5.3 & 6.x ++ --------------------- ++ ++Irix 6.2 and better supports three different calling conventions: o32, ++n32 and n64. Currently, libffi only supports both o32 and n32 under ++Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be ++configured for whichever calling convention it was built for. ++ ++By default, the configure script will try to build libffi with the GNU ++development tools. To build libffi with the SGI development tools, set ++the environment variable CC to either "cc -32" or "cc -n32" before ++running configure under Irix 6.x (depending on whether you want an o32 ++or n32 library), or just "cc" for Irix 5.3. ++ ++With the n32 calling convention, when returning structures smaller ++than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. ++Here's one way of forcing this: ++ ++ double struct_storage[2]; ++ my_small_struct *s = (my_small_struct *) struct_storage; ++ /* Use s for RVALUE */ ++ ++If you don't do this you are liable to get spurious bus errors. ++ ++"long long" values are not supported yet. ++ ++You must use GNU Make to build libffi on SGI platforms. ++ ++ ARM - System V ABI ++ ------------------ ++ ++The ARM port was performed on a NetWinder running ARM Linux ELF ++(2.0.31) and gcc 2.8.1. ++ ++ ++ ++ PowerPC System V ABI ++ -------------------- ++ ++There are two `System V ABI's which libffi implements for PowerPC. ++They differ only in how small structures are returned from functions. ++ ++In the FFI_SYSV version, structures that are 8 bytes or smaller are ++returned in registers. This is what GCC does when it is configured ++for solaris, and is what the System V ABI I have (dated September ++1995) says. ++ ++In the FFI_GCC_SYSV version, all structures are returned the same way: ++by passing a pointer as the first argument to the function. This is ++what GCC does when it is configured for linux or a generic sysv ++target. ++ ++EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a ++inconsistency with the SysV ABI: When a procedure is called with many ++floating-point arguments, some of them get put on the stack. They are ++all supposed to be stored in double-precision format, even if they are ++only single-precision, but EGCS stores single-precision arguments as ++single-precision anyway. This causes one test to fail (the `many ++arguments' test). ++ ++ ++What's With The Crazy Comments? ++=============================== ++ ++You might notice a number of cryptic comments in the code, delimited ++by /*@ and @*/. These are annotations read by the program LCLint, a ++tool for statically checking C programs. You can read all about it at ++. ++ ++ ++History ++======= ++ ++1.20 Oct-5-98 ++ Raffaele Sena produces ARM port. ++ ++1.19 Oct-5-98 ++ Fixed x86 long double and long long return support. ++ m68k bug fixes from Andreas Schwab. ++ Patch for DU assembler compatibility for the Alpha from Richard ++ Henderson. ++ ++1.18 Apr-17-98 ++ Bug fixes and MIPS configuration changes. ++ ++1.17 Feb-24-98 ++ Bug fixes and m68k port from Andreas Schwab. PowerPC port from ++ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. ++ ++1.16 Feb-11-98 ++ Richard Henderson produces Alpha port. ++ ++1.15 Dec-4-97 ++ Fixed an n32 ABI bug. New libtool, auto* support. ++ ++1.14 May-13-97 ++ libtool is now used to generate shared and static libraries. ++ Fixed a minor portability problem reported by Russ McManus ++ . ++ ++1.13 Dec-2-96 ++ Added --enable-purify-safety to keep Purify from complaining ++ about certain low level code. ++ Sparc fix for calling functions with < 6 args. ++ Linux x86 a.out fix. ++ ++1.12 Nov-22-96 ++ Added missing ffi_type_void, needed for supporting void return ++ types. Fixed test case for non MIPS machines. Cygnus Support ++ is now Cygnus Solutions. ++ ++1.11 Oct-30-96 ++ Added notes about GNU make. ++ ++1.10 Oct-29-96 ++ Added configuration fix for non GNU compilers. ++ ++1.09 Oct-29-96 ++ Added --enable-debug configure switch. Clean-ups based on LCLint ++ feedback. ffi_mips.h is always installed. Many configuration ++ fixes. Fixed ffitest.c for sparc builds. ++ ++1.08 Oct-15-96 ++ Fixed n32 problem. Many clean-ups. ++ ++1.07 Oct-14-96 ++ Gordon Irlam rewrites v8.S again. Bug fixes. ++ ++1.06 Oct-14-96 ++ Gordon Irlam improved the sparc port. ++ ++1.05 Oct-14-96 ++ Interface changes based on feedback. ++ ++1.04 Oct-11-96 ++ Sparc port complete (modulo struct passing bug). ++ ++1.03 Oct-10-96 ++ Passing struct args, and returning struct values works for ++ all architectures/calling conventions. Expanded tests. ++ ++1.02 Oct-9-96 ++ Added SGI n32 support. Fixed bugs in both o32 and Linux support. ++ Added "make test". ++ ++1.01 Oct-8-96 ++ Fixed float passing bug in mips version. Restructured some ++ of the code. Builds cleanly with SGI tools. ++ ++1.00 Oct-7-96 ++ First release. No public announcement. ++ ++ ++Authors & Credits ++================= ++ ++libffi was written by Anthony Green . ++ ++Portions of libffi were derived from Gianni Mariani's free gencall ++library for Silicon Graphics machines. ++ ++The closure mechanism was designed and implemented by Kresten Krab ++Thorup. ++ ++The Sparc port was derived from code contributed by the fine folks at ++Visible Decisions Inc . Further enhancements were ++made by Gordon Irlam at Cygnus Solutions . ++ ++The Alpha port was written by Richard Henderson at Cygnus Solutions. ++ ++Andreas Schwab ported libffi to m68k Linux and provided a number of ++bug fixes. ++ ++Geoffrey Keating ported libffi to the PowerPC. ++ ++Raffaele Sena ported libffi to the ARM. ++ ++Jesper Skov and Andrew Haley both did more than their fair share of ++stepping through the code and tracking down bugs. ++ ++Thanks also to Tom Tromey for bug fixes and configuration help. ++ ++Thanks to Jim Blandy, who provided some useful feedback on the libffi ++interface. ++ ++If you have a problem, or have found a bug, please send a note to ++green@cygnus.com. +diff --git ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc +new file mode 100644 +index 0000000..405d85f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README.pyobjc +@@ -0,0 +1,5 @@ ++This directory contains a slightly modified version of libffi, extracted from ++the GCC source-tree. ++ ++The only modifications are those that are necessary to compile libffi using ++the Apple provided compiler and outside of the GCC source tree. +diff --git ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c +new file mode 100644 +index 0000000..bf42093 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/ffi.c +@@ -0,0 +1,226 @@ ++/* ----------------------------------------------------------------------- ++ prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++/* Round up to FFI_SIZEOF_ARG. */ ++#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) ++ ++/* Perform machine independent initialization of aggregate type ++ specifications. */ ++ ++static ffi_status ++initialize_aggregate( ++/*@out@*/ ffi_type* arg) ++{ ++/*@-usedef@*/ ++ ++ if (arg == NULL || arg->elements == NULL || ++ arg->size != 0 || arg->alignment != 0) ++ return FFI_BAD_TYPEDEF; ++ ++ ffi_type** ptr = &(arg->elements[0]); ++ ++ while ((*ptr) != NULL) ++ { ++ if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#ifdef POWERPC_DARWIN ++ int curalign = (*ptr)->alignment; ++ ++ if (ptr != &(arg->elements[0])) ++ { ++ if (curalign > 4 && curalign != 16) ++ curalign = 4; ++ } ++ ++ arg->size = ALIGN(arg->size, curalign); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > curalign) ? ++ arg->alignment : curalign; ++#else ++ arg->size = ALIGN(arg->size, (*ptr)->alignment); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > (*ptr)->alignment) ? ++ arg->alignment : (*ptr)->alignment; ++#endif ++ ++ ptr++; ++ } ++ ++ /* Structure size includes tail padding. This is important for ++ structures that fit in one register on ABIs like the PowerPC64 ++ Linux ABI that right justify small structs in a register. ++ It's also needed for nested structure layout, for example ++ struct A { long a; char b; }; struct B { struct A x; char y; }; ++ should find y at an offset of 2*sizeof(long) and result in a ++ total size of 3*sizeof(long). */ ++ arg->size = ALIGN(arg->size, arg->alignment); ++ ++ if (arg->size == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ return FFI_OK; ++ ++/*@=usedef@*/ ++} ++ ++#ifndef __CRIS__ ++/* The CRIS ABI specifies structure elements to have byte ++ alignment only, so it completely overrides this functions, ++ which assumes "natural" alignment and padding. */ ++ ++/* Perform machine independent ffi_cif preparation, then call ++ machine dependent routine. */ ++ ++#if defined(X86_DARWIN) ++ ++static inline bool ++struct_on_stack( ++ int size) ++{ ++ if (size > 8) ++ return true; ++ ++ /* This is not what the ABI says, but is what is really implemented */ ++ switch (size) ++ { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ return false; ++ ++ default: ++ return true; ++ } ++} ++ ++#endif // defined(X86_DARWIN) ++ ++// Arguments' ffi_type->alignment must be nonzero. ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes) ++{ ++ if (cif == NULL) ++ return FFI_BAD_TYPEDEF; ++ ++ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI) ++ return FFI_BAD_ABI; ++ ++ unsigned int bytes = 0; ++ unsigned int i; ++ ffi_type** ptr; ++ ++ cif->abi = abi; ++ cif->arg_types = atypes; ++ cif->nargs = nargs; ++ cif->rtype = rtype; ++ cif->flags = 0; ++ ++ /* Initialize the return type if necessary */ ++ /*@-usedef@*/ ++ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ /*@=usedef@*/ ++ ++ /* Perform a sanity check on the return type */ ++ FFI_ASSERT_VALID_TYPE(cif->rtype); ++ ++ /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ ++#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA ++ /* Make space for the return structure pointer */ ++ if (cif->rtype->type == FFI_TYPE_STRUCT ++#ifdef SPARC ++ && (cif->abi != FFI_V9 || cif->rtype->size > 32) ++#endif ++#ifdef X86_DARWIN ++ && (struct_on_stack(cif->rtype->size)) ++#endif ++ ) ++ bytes = STACK_ARG_SIZE(sizeof(void*)); ++#endif ++ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ /* Initialize any uninitialized aggregate type definitions */ ++ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ if ((*ptr)->alignment == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type, do this ++ check after the initialization. */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#if defined(X86_DARWIN) ++ { ++ int align = (*ptr)->alignment; ++ ++ if (align > 4) ++ align = 4; ++ ++ if ((align - 1) & bytes) ++ bytes = ALIGN(bytes, align); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#elif !defined __x86_64__ && !defined S390 && !defined PA ++#ifdef SPARC ++ if (((*ptr)->type == FFI_TYPE_STRUCT ++ && ((*ptr)->size > 16 || cif->abi != FFI_V9)) ++ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE ++ && cif->abi != FFI_V9)) ++ bytes += sizeof(void*); ++ else ++#endif ++ { ++ /* Add any padding if necessary */ ++ if (((*ptr)->alignment - 1) & bytes) ++ bytes = ALIGN(bytes, (*ptr)->alignment); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#endif ++ } ++ ++ cif->bytes = bytes; ++ ++ /* Perform machine dependent cif processing */ ++ return ffi_prep_cif_machdep(cif); ++} ++#endif /* not __CRIS__ */ +diff --git ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h +new file mode 100644 +index 0000000..c104a5c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi.h +@@ -0,0 +1,355 @@ ++/* -----------------------------------------------------------------*-C-*- ++ libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++/* ------------------------------------------------------------------- ++ The basic API is described in the README file. ++ ++ The raw API is designed to bypass some of the argument packing ++ and unpacking on architectures for which it can be avoided. ++ ++ The closure API allows interpreted functions to be packaged up ++ inside a C function pointer, so that they can be called as C functions, ++ with no understanding on the client side that they are interpreted. ++ It can also be used in other cases in which it is necessary to package ++ up a user specified parameter and a function pointer as a single ++ function pointer. ++ ++ The closure API must be implemented in order to get its functionality, ++ e.g. for use by gij. Routines are provided to emulate the raw API ++ if the underlying platform doesn't allow faster implementation. ++ ++ More details on the raw and closure API can be found in: ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html ++ ++ and ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html ++ -------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_H ++#define LIBFFI_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Specify which architecture libffi is configured for. */ ++#ifdef MACOSX ++# if defined(__i386__) || defined(__x86_64__) ++# define X86_DARWIN ++# elif defined(__ppc__) || defined(__ppc64__) ++# define POWERPC_DARWIN ++# else ++# error "Unsupported MacOS X CPU type" ++# endif ++#else ++#error "Unsupported OS type" ++#endif ++ ++/* ---- System configuration information --------------------------------- */ ++ ++#include "ffitarget.h" ++#include "fficonfig.h" ++ ++#ifndef LIBFFI_ASM ++ ++#include ++#include ++ ++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). ++ But we can find it either under the correct ANSI name, or under GNU ++ C's internal name. */ ++#ifdef LONG_LONG_MAX ++# define FFI_LONG_LONG_MAX LONG_LONG_MAX ++#else ++# ifdef LLONG_MAX ++# define FFI_LONG_LONG_MAX LLONG_MAX ++# else ++# ifdef __GNUC__ ++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ ++# endif ++# endif ++#endif ++ ++#if SCHAR_MAX == 127 ++# define ffi_type_uchar ffi_type_uint8 ++# define ffi_type_schar ffi_type_sint8 ++#else ++#error "char size not supported" ++#endif ++ ++#if SHRT_MAX == 32767 ++# define ffi_type_ushort ffi_type_uint16 ++# define ffi_type_sshort ffi_type_sint16 ++#elif SHRT_MAX == 2147483647 ++# define ffi_type_ushort ffi_type_uint32 ++# define ffi_type_sshort ffi_type_sint32 ++#else ++#error "short size not supported" ++#endif ++ ++#if INT_MAX == 32767 ++# define ffi_type_uint ffi_type_uint16 ++# define ffi_type_sint ffi_type_sint16 ++#elif INT_MAX == 2147483647 ++# define ffi_type_uint ffi_type_uint32 ++# define ffi_type_sint ffi_type_sint32 ++#elif INT_MAX == 9223372036854775807 ++# define ffi_type_uint ffi_type_uint64 ++# define ffi_type_sint ffi_type_sint64 ++#else ++#error "int size not supported" ++#endif ++ ++#define ffi_type_ulong ffi_type_uint64 ++#define ffi_type_slong ffi_type_sint64 ++ ++#if LONG_MAX == 2147483647 ++# if FFI_LONG_LONG_MAX != 9223372036854775807 ++# error "no 64-bit data type supported" ++# endif ++#elif LONG_MAX != 9223372036854775807 ++#error "long size not supported" ++#endif ++ ++/* The closure code assumes that this works on pointers, i.e. a size_t ++ can hold a pointer. */ ++ ++typedef struct _ffi_type { ++ size_t size; ++ unsigned short alignment; ++ unsigned short type; ++/*@null@*/ struct _ffi_type** elements; ++} ffi_type; ++ ++/* These are defined in types.c */ ++extern ffi_type ffi_type_void; ++extern ffi_type ffi_type_uint8; ++extern ffi_type ffi_type_sint8; ++extern ffi_type ffi_type_uint16; ++extern ffi_type ffi_type_sint16; ++extern ffi_type ffi_type_uint32; ++extern ffi_type ffi_type_sint32; ++extern ffi_type ffi_type_uint64; ++extern ffi_type ffi_type_sint64; ++extern ffi_type ffi_type_float; ++extern ffi_type ffi_type_double; ++extern ffi_type ffi_type_longdouble; ++extern ffi_type ffi_type_pointer; ++ ++typedef enum ffi_status { ++ FFI_OK = 0, ++ FFI_BAD_TYPEDEF, ++ FFI_BAD_ABI ++} ffi_status; ++ ++typedef unsigned FFI_TYPE; ++ ++typedef struct ffi_cif { ++ ffi_abi abi; ++ unsigned nargs; ++/*@dependent@*/ ffi_type** arg_types; ++/*@dependent@*/ ffi_type* rtype; ++ unsigned bytes; ++ unsigned flags; ++#ifdef FFI_EXTRA_CIF_FIELDS ++ FFI_EXTRA_CIF_FIELDS; ++#endif ++} ffi_cif; ++ ++/* ---- Definitions for the raw API -------------------------------------- */ ++ ++#ifndef FFI_SIZEOF_ARG ++# if LONG_MAX == 2147483647 ++# define FFI_SIZEOF_ARG 4 ++# elif LONG_MAX == 9223372036854775807 ++# define FFI_SIZEOF_ARG 8 ++# endif ++#endif ++ ++typedef union { ++ ffi_sarg sint; ++ ffi_arg uint; ++ float flt; ++ char data[FFI_SIZEOF_ARG]; ++ void* ptr; ++} ffi_raw; ++ ++void ++ffi_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_raw_size( ++ ffi_cif* cif); ++ ++/* This is analogous to the raw API, except it uses Java parameter ++ packing, even on 64-bit machines. I.e. on 64-bit machines ++ longs and doubles are followed by an empty 64-bit word. */ ++void ++ffi_java_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_java_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_java_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_java_raw_size( ++ ffi_cif* cif); ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#if FFI_CLOSURES ++ ++typedef struct ffi_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ void (*fun)(ffi_cif*,void*,void**,void*); ++ void* user_data; ++} ffi_closure; ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void* user_data); ++ ++void ffi_closure_free(void *); ++void *ffi_closure_alloc (size_t size, void **code); ++ ++typedef struct ffi_raw_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ ++#if !FFI_NATIVE_RAW_API ++ /* if this is enabled, then a raw closure has the same layout ++ as a regular closure. We use this to install an intermediate ++ handler to do the transaltion, void** -> ffi_raw*. */ ++ void (*translate_args)(ffi_cif*,void*,void**,void*); ++ void* this_closure; ++#endif ++ ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*); ++ void* user_data; ++} ffi_raw_closure; ++ ++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_status ++ffi_prep_java_raw_closure( ++ ffi_raw_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*), ++ void* user_data); ++ ++#endif // FFI_CLOSURES ++ ++/* ---- Public interface definition -------------------------------------- */ ++ ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes); ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ void** avalue); ++ ++/* Useful for eliminating compiler warnings */ ++#define FFI_FN(f) ((void (*)(void))f) ++ ++#endif // #ifndef LIBFFI_ASM ++/* ---- Definitions shared with assembly code ---------------------------- */ ++ ++/* If these change, update src/mips/ffitarget.h. */ ++#define FFI_TYPE_VOID 0 ++#define FFI_TYPE_INT 1 ++#define FFI_TYPE_FLOAT 2 ++#define FFI_TYPE_DOUBLE 3 ++ ++#ifdef HAVE_LONG_DOUBLE ++# define FFI_TYPE_LONGDOUBLE 4 ++#else ++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE ++#endif ++ ++#define FFI_TYPE_UINT8 5 ++#define FFI_TYPE_SINT8 6 ++#define FFI_TYPE_UINT16 7 ++#define FFI_TYPE_SINT16 8 ++#define FFI_TYPE_UINT32 9 ++#define FFI_TYPE_SINT32 10 ++#define FFI_TYPE_UINT64 11 ++#define FFI_TYPE_SINT64 12 ++#define FFI_TYPE_STRUCT 13 ++#define FFI_TYPE_POINTER 14 ++ ++/* This should always refer to the last type code (for sanity checks) */ ++#define FFI_TYPE_LAST FFI_TYPE_POINTER ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef LIBFFI_H +diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h +new file mode 100644 +index 0000000..685a358 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi_common.h +@@ -0,0 +1,102 @@ ++/* ----------------------------------------------------------------------- ++ ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ++ ++ Common internal definitions and macros. Only necessary for building ++ libffi. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef FFI_COMMON_H ++#define FFI_COMMON_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fficonfig.h" ++ ++/* Do not move this. Some versions of AIX are very picky about where ++ this is positioned. */ ++#ifdef __GNUC__ ++# define alloca __builtin_alloca ++#else ++# if HAVE_ALLOCA_H ++# include ++# else ++# ifdef _AIX ++# pragma alloca ++# else ++# ifndef alloca /* predefined by HP cc +Olibcalls */ ++char* alloca(); ++# endif ++# endif ++# endif ++#endif ++ ++/* Check for the existence of memcpy. */ ++#if STDC_HEADERS ++# include ++#else ++# ifndef HAVE_MEMCPY ++# define memcpy(d, s, n) bcopy((s), (d), (n)) ++# endif ++#endif ++ ++/*#if defined(FFI_DEBUG) ++#include ++#endif*/ ++ ++#ifdef FFI_DEBUG ++#include ++ ++/*@exits@*/ void ++ffi_assert( ++/*@temp@*/ char* expr, ++/*@temp@*/ char* file, ++ int line); ++void ++ffi_stop_here(void); ++void ++ffi_type_test( ++/*@temp@*/ /*@out@*/ ffi_type* a, ++/*@temp@*/ char* file, ++ int line); ++ ++# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) ++# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) ++# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__) ++#else ++# define FFI_ASSERT(x) ++# define FFI_ASSERT_AT(x, f, l) ++# define FFI_ASSERT_VALID_TYPE(x) ++#endif // #ifdef FFI_DEBUG ++ ++#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) ++ ++/* Perform machine dependent cif processing */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif); ++ ++/* Extended cif, used in callback from assembly routine */ ++typedef struct extended_cif { ++/*@dependent@*/ ffi_cif* cif; ++/*@dependent@*/ void* rvalue; ++/*@dependent@*/ void** avalue; ++} extended_cif; ++ ++/* Terse sized type definitions. */ ++typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); ++typedef signed int SINT8 __attribute__((__mode__(__QI__))); ++typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); ++typedef signed int SINT16 __attribute__((__mode__(__HI__))); ++typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); ++typedef signed int SINT32 __attribute__((__mode__(__SI__))); ++typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); ++typedef signed int SINT64 __attribute__((__mode__(__DI__))); ++typedef float FLOAT32; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef FFI_COMMON_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h +new file mode 100644 +index 0000000..2172490 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/fficonfig.h +@@ -0,0 +1,150 @@ ++/* Manually created fficonfig.h for Darwin on PowerPC or Intel ++ ++ This file is manually generated to do away with the need for autoconf and ++ therefore make it easier to cross-compile and build fat binaries. ++ ++ NOTE: This file was added by PyObjC. ++*/ ++ ++#ifndef MACOSX ++#error "This file is only supported on Mac OS X" ++#endif ++ ++#if defined(__i386__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__x86_64__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__ppc__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# if __GNUC__ >= 4 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++# else ++# undef HAVE_LONG_DOUBLE ++# define SIZEOF_LONG_DOUBLE 8 ++# endif ++ ++#elif defined(__ppc64__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#else ++#error "Unknown CPU type" ++#endif ++ ++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP ++ systems. This function is required for `alloca.c' support on those systems. */ ++#undef CRAY_STACKSEG_END ++ ++/* Define to 1 if using `alloca.c'. */ ++/* #undef C_ALLOCA */ ++ ++/* Define to the flags needed for the .section .eh_frame directive. */ ++#define EH_FRAME_FLAGS "aw" ++ ++/* Define this if you want extra debugging. */ ++/* #undef FFI_DEBUG */ ++ ++/* Define this is you do not want support for the raw API. */ ++#define FFI_NO_RAW_API 1 ++ ++/* Define this if you do not want support for aggregate types. */ ++/* #undef FFI_NO_STRUCTS */ ++ ++/* Define to 1 if you have `alloca', as a function or macro. */ ++#define HAVE_ALLOCA 1 ++ ++/* Define to 1 if you have and it should be used (not on Ultrix). */ ++#define HAVE_ALLOCA_H 1 ++ ++/* Define if your assembler supports .register. */ ++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ ++ ++/* Define if your assembler and linker support unaligned PC relative relocs. */ ++/* #undef HAVE_AS_SPARC_UA_PCREL */ ++ ++/* Define to 1 if you have the `memcpy' function. */ ++#define HAVE_MEMCPY 1 ++ ++/* Define if mmap with MAP_ANON(YMOUS) works. */ ++#define HAVE_MMAP_ANON 1 ++ ++/* Define if mmap of /dev/zero works. */ ++/* #undef HAVE_MMAP_DEV_ZERO */ ++ ++/* Define if read-only mmap of a plain file works. */ ++#define HAVE_MMAP_FILE 1 ++ ++/* Define if .eh_frame sections should be read-only. */ ++/* #undef HAVE_RO_EH_FRAME */ ++ ++/* Define to 1 if your C compiler doesn't accept -c and -o together. */ ++/* #undef NO_MINUS_C_MINUS_O */ ++ ++/* Name of package */ ++#define PACKAGE "libffi" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "libffi" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "libffi 2.1" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libffi" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "2.1" ++ ++/* If using the C implementation of alloca, define if you know the ++ direction of stack growth for your system; otherwise it will be ++ automatically deduced at run-time. ++ STACK_DIRECTION > 0 => grows toward higher addresses ++ STACK_DIRECTION < 0 => grows toward lower addresses ++ STACK_DIRECTION = 0 => direction of growth unknown */ ++/* #undef STACK_DIRECTION */ ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this if you are using Purify and want to suppress spurious messages. */ ++/* #undef USING_PURIFY */ ++ ++/* Version number of package */ ++#define VERSION "2.1-pyobjc" ++ ++#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) .hidden name ++# else ++# define FFI_HIDDEN __attribute__((visibility ("hidden"))) ++# endif ++#else ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) ++# else ++# define FFI_HIDDEN ++# endif ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h +new file mode 100644 +index 0000000..faaa30d +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffitarget.h +@@ -0,0 +1,13 @@ ++/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a ++ normal build, the build environment copies the file to the right location or ++ sets up the right include flags. We want to do neither because that would ++ make building fat binaries harder. ++*/ ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "x86-ffitarget.h" ++#elif defined(__ppc__) || defined(__ppc64__) ++#include "ppc-ffitarget.h" ++#else ++#error "Unsupported CPU type" ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +new file mode 100644 +index 0000000..2318421 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +@@ -0,0 +1,104 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for PowerPC. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if (defined(POWERPC) && defined(__powerpc64__)) || \ ++ (defined(POWERPC_DARWIN) && defined(__ppc64__)) ++#define POWERPC64 ++#endif ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++#ifdef POWERPC ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++# ifdef POWERPC64 ++ FFI_DEFAULT_ABI = FFI_LINUX64, ++# else ++ FFI_DEFAULT_ABI = FFI_GCC_SYSV, ++# endif ++#endif ++ ++#ifdef POWERPC_AIX ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_AIX, ++#endif ++ ++#ifdef POWERPC_DARWIN ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_DARWIN, ++#endif ++ ++#ifdef POWERPC_FREEBSD ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++#define FFI_NATIVE_RAW_API 0 ++ ++/* Needed for FFI_SYSV small structure returns. */ ++#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) ++ ++#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/ ++# define FFI_TRAMPOLINE_SIZE 48 ++#elif defined(POWERPC_AIX) ++# define FFI_TRAMPOLINE_SIZE 24 ++#else ++# define FFI_TRAMPOLINE_SIZE 40 ++#endif ++ ++#ifndef LIBFFI_ASM ++# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) ++typedef struct ffi_aix_trampoline_struct { ++ void* code_pointer; /* Pointer to ffi_closure_ASM */ ++ void* toc; /* TOC */ ++ void* static_chain; /* Pointer to closure */ ++} ffi_aix_trampoline_struct; ++# endif ++#endif // #ifndef LIBFFI_ASM ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +new file mode 100644 +index 0000000..55c2b6c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +@@ -0,0 +1,88 @@ ++/* -----------------------------------------------------------------*-C-*- ++ x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for x86 and x86-64. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if defined(X86_64) && defined(__i386__) ++# undef X86_64 ++# define X86 ++#endif ++ ++#if defined(__x86_64__) ++# ifndef X86_64 ++# define X86_64 ++# endif ++#endif ++ ++/* ---- Generic type definitions ----------------------------------------- */ ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++ /* ---- Intel x86 Win32 ---------- */ ++#ifdef X86_WIN32 ++ FFI_SYSV, ++ FFI_STDCALL, ++ /* TODO: Add fastcall support for the sake of completeness */ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ /* ---- Intel x86 and AMD x86-64 - */ ++#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) ++ FFI_SYSV, ++ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ ++# ifdef __i386__ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++# else ++ FFI_DEFAULT_ABI = FFI_UNIX64, ++# endif ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++ ++#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN)) ++# define FFI_TRAMPOLINE_SIZE 24 ++# define FFI_NATIVE_RAW_API 0 ++#else ++# define FFI_TRAMPOLINE_SIZE 10 ++# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ ++#endif ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +new file mode 100644 +index 0000000..f143dbd +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +@@ -0,0 +1,365 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist ++ Copyright (c) 2004 Free Software Foundation, Inc. ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include ++#include ++#include ++ ++.text ++ .align 2 ++.globl _ffi_prep_args ++ ++.text ++ .align 2 ++.globl _ffi_call_DARWIN ++ ++.text ++ .align 2 ++_ffi_call_DARWIN: ++LFB0: ++ mr r12,r8 /* We only need r12 until the call, ++ so it doesn't have to be saved. */ ++ ++LFB1: ++ /* Save the old stack pointer as AP. */ ++ mr r8,r1 ++ ++LCFI0: ++#if defined(__ppc64__) ++ /* Allocate the stack space we need. ++ r4 (size of input data) ++ 48 bytes (linkage area) ++ 40 bytes (saved registers) ++ 8 bytes (extra FPR) ++ r4 + 96 bytes total ++ */ ++ ++ addi r4,r4,-96 // Add our overhead. ++ li r0,-32 // Align to 32 bytes. ++ and r4,r4,r0 ++#endif ++ stgux r1,r1,r4 // Grow the stack. ++ mflr r9 ++ ++ /* Save registers we use. */ ++#if defined(__ppc64__) ++ std r27,-40(r8) ++#endif ++ stg r28,MODE_CHOICE(-16,-32)(r8) ++ stg r29,MODE_CHOICE(-12,-24)(r8) ++ stg r30,MODE_CHOICE(-8,-16)(r8) ++ stg r31,MODE_CHOICE(-4,-8)(r8) ++ stg r9,SF_RETURN(r8) /* return address */ ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ stg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++LCFI1: ++#if defined(__ppc64__) ++ mr r27,r3 // our extended_cif ++#endif ++ /* Save arguments over call. */ ++ mr r31,r5 /* flags, */ ++ mr r30,r6 /* rvalue, */ ++ mr r29,r7 /* function address, */ ++ mr r28,r8 /* our AP. */ ++ ++LCFI2: ++ /* Call ffi_prep_args. */ ++ mr r4,r1 ++ li r9,0 ++ mtctr r12 /* r12 holds address of _ffi_prep_args. */ ++ bctrl ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ lg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++ /* Now do the call. ++ Set up cr1 with bits 4-7 of the flags. */ ++ mtcrf 0x40,r31 ++ ++ /* Load all those argument registers. ++ We have set up a nice stack frame, just load it into registers. */ ++ lg r3,SF_ARG1(r1) ++ lg r4,SF_ARG2(r1) ++ lg r5,SF_ARG3(r1) ++ lg r6,SF_ARG4(r1) ++ nop ++ lg r7,SF_ARG5(r1) ++ lg r8,SF_ARG6(r1) ++ lg r9,SF_ARG7(r1) ++ lg r10,SF_ARG8(r1) ++ ++ /* Load all the FP registers. */ ++ bf 6,L2 /* No floats to load. */ ++#if defined(__ppc64__) ++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#elif defined(__ppc__) ++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#else ++#error undefined architecture ++#endif ++ ++L2: ++ mr r12,r29 // Put the target address in r12 as specified. ++ mtctr r12 // Get the address to call into CTR. ++ nop ++ nop ++ bctrl // Make the call. ++ ++ // Deal with the return value. ++#if defined(__ppc64__) ++ mtcrf 0x3,r31 // flags in cr6 and cr7 ++ bt 27,L(st_return_value) ++#elif defined(__ppc__) ++ mtcrf 0x1,r31 // flags in cr7 ++#else ++#error undefined architecture ++#endif ++ ++ bt 30,L(done_return_value) ++ bt 29,L(fp_return_value) ++ stg r3,0(r30) ++#if defined(__ppc__) ++ bf 28,L(done_return_value) // Store the second long if necessary. ++ stg r4,4(r30) ++#endif ++ // Fall through ++ ++L(done_return_value): ++ lg r1,0(r1) // Restore stack pointer. ++ // Restore the registers we used. ++ lg r9,SF_RETURN(r1) // return address ++ lg r31,MODE_CHOICE(-4,-8)(r1) ++ mtlr r9 ++ lg r30,MODE_CHOICE(-8,-16)(r1) ++ lg r29,MODE_CHOICE(-12,-24)(r1) ++ lg r28,MODE_CHOICE(-16,-32)(r1) ++#if defined(__ppc64__) ++ ld r27,-40(r1) ++#endif ++ blr ++ ++#if defined(__ppc64__) ++L(st_return_value): ++ // Grow the stack enough to fit the registers. Leave room for 8 args ++ // to trample the 1st 8 slots in param area. ++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 ++ ++ // Store GPRs ++ std r3,SF_ARG9(r1) ++ std r4,SF_ARG10(r1) ++ std r5,SF_ARG11(r1) ++ std r6,SF_ARG12(r1) ++ nop ++ std r7,SF_ARG13(r1) ++ std r8,SF_ARG14(r1) ++ std r9,SF_ARG15(r1) ++ std r10,SF_ARG16(r1) ++ ++ // Store FPRs ++ nop ++ bf 26,L(call_struct_to_ram_form) ++ stfd f1,SF_ARG17(r1) ++ stfd f2,SF_ARG18(r1) ++ stfd f3,SF_ARG19(r1) ++ stfd f4,SF_ARG20(r1) ++ nop ++ stfd f5,SF_ARG21(r1) ++ stfd f6,SF_ARG22(r1) ++ stfd f7,SF_ARG23(r1) ++ stfd f8,SF_ARG24(r1) ++ nop ++ stfd f9,SF_ARG25(r1) ++ stfd f10,SF_ARG26(r1) ++ stfd f11,SF_ARG27(r1) ++ stfd f12,SF_ARG28(r1) ++ nop ++ stfd f13,SF_ARG29(r1) ++ ++L(call_struct_to_ram_form): ++ ld r3,0(r27) // extended_cif->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ addi r4,r1,SF_ARG9 // stored GPRs ++ addi r6,r1,SF_ARG17 // stored FPRs ++ li r5,0 // GPR size ptr (NULL) ++ li r7,0 // FPR size ptr (NULL) ++ li r8,0 // FPR count ptr (NULL) ++ li r10,0 // struct offset (NULL) ++ mr r9,r30 // return area ++ bl Lffi64_struct_to_ram_form$stub ++ lg r1,0(r1) // Restore stack pointer. ++ b L(done_return_value) ++#endif ++ ++L(fp_return_value): ++ /* Do we have long double to store? */ ++ bf 31,L(fd_return_value) ++ stfd f1,0(r30) ++ stfd f2,8(r30) ++ b L(done_return_value) ++ ++L(fd_return_value): ++ /* Do we have double to store? */ ++ bf 28,L(float_return_value) ++ stfd f1,0(r30) ++ b L(done_return_value) ++ ++L(float_return_value): ++ /* We only have a float to store. */ ++ stfs f1,0(r30) ++ b L(done_return_value) ++ ++LFE1: ++/* END(_ffi_call_DARWIN) */ ++ ++/* Provide a null definition of _ffi_call_AIX. */ ++.text ++ .align 2 ++.globl _ffi_call_AIX ++.text ++ .align 2 ++_ffi_call_AIX: ++ blr ++/* END(_ffi_call_AIX) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_call_DARWIN.eh ++_ffi_call_DARWIN.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x08 ; uleb128 0x08 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$5,LCFI1-LCFI0 ++ .long L$set$5 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .byte 0x9f ; DW_CFA_offset, column 0x1f ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x9e ; DW_CFA_offset, column 0x1e ++ .byte 0x2 ; uleb128 0x2 ++ .byte 0x9d ; DW_CFA_offset, column 0x1d ++ .byte 0x3 ; uleb128 0x3 ++ .byte 0x9c ; DW_CFA_offset, column 0x1c ++ .byte 0x4 ; uleb128 0x4 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$6,LCFI2-LCFI1 ++ .long L$set$6 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x1c ; uleb128 0x1c ++ .align LOG2_GPR_BYTES ++LEFDE1: ++ ++#if defined(__ppc64__) ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_ram_form$stub: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_ram_form ++ ++LO$ffi64_struct_to_ram_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_ram_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ ++#endif // __ppc__ || __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +new file mode 100644 +index 0000000..cf4bd50 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +@@ -0,0 +1,85 @@ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define L(x) x ++ ++#define SF_ARG9 MODE_CHOICE(56,112) ++#define SF_ARG10 MODE_CHOICE(60,120) ++#define SF_ARG11 MODE_CHOICE(64,128) ++#define SF_ARG12 MODE_CHOICE(68,136) ++#define SF_ARG13 MODE_CHOICE(72,144) ++#define SF_ARG14 MODE_CHOICE(76,152) ++#define SF_ARG15 MODE_CHOICE(80,160) ++#define SF_ARG16 MODE_CHOICE(84,168) ++#define SF_ARG17 MODE_CHOICE(88,176) ++#define SF_ARG18 MODE_CHOICE(92,184) ++#define SF_ARG19 MODE_CHOICE(96,192) ++#define SF_ARG20 MODE_CHOICE(100,200) ++#define SF_ARG21 MODE_CHOICE(104,208) ++#define SF_ARG22 MODE_CHOICE(108,216) ++#define SF_ARG23 MODE_CHOICE(112,224) ++#define SF_ARG24 MODE_CHOICE(116,232) ++#define SF_ARG25 MODE_CHOICE(120,240) ++#define SF_ARG26 MODE_CHOICE(124,248) ++#define SF_ARG27 MODE_CHOICE(128,256) ++#define SF_ARG28 MODE_CHOICE(132,264) ++#define SF_ARG29 MODE_CHOICE(136,272) ++ ++#define ASM_NEEDS_REGISTERS 4 ++#define NUM_GPR_ARG_REGISTERS 8 ++#define NUM_FPR_ARG_REGISTERS 13 ++ ++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8) ++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16) ++#define FFI_TYPE_4_BYTE(x) \ ++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\ ++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT) ++ ++#if !defined(LIBFFI_ASM) ++ ++enum { ++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7 ++ FLAG_RETURNS_FP = 1 << (31 - 29), ++ FLAG_RETURNS_64BITS = 1 << (31 - 28), ++ FLAG_RETURNS_128BITS = 1 << (31 - 31), ++ ++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6 ++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26), ++ ++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7), ++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI ++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5), ++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4) ++}; ++ ++#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*); ++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*); ++#endif ++ ++#endif // !defined(LIBFFI_ASM) +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +new file mode 100644 +index 0000000..c3d30c2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +@@ -0,0 +1,308 @@ ++#if defined(__ppc__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 // Save return address ++ stg r0,SF_RETURN(r1) ++ ++LCFI0: ++ /* 24/48 bytes (Linkage Area) ++ 32/64 bytes (outgoing parameter area, always reserved) ++ 104 bytes (13*8 from FPR) ++ 16/32 bytes (result) ++ 176/232 total bytes */ ++ ++ /* skip over caller save area and keep stack aligned to 16/32. */ ++ stgu r1,-SF_ROUND(176)(r1) ++ ++LCFI1: ++ /* We want to build up an area for the parameters passed ++ in registers. (both floating point and integer) */ ++ ++ /* 176/256 bytes (callee stack frame aligned to 16/32) ++ 24/48 bytes (caller linkage area) ++ 200/304 (start of caller parameter area aligned to 4/8) ++ */ ++ ++ /* Save GPRs 3 - 10 (aligned to 4/8) ++ in the parents outgoing area. */ ++ 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,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. ++ 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. Use it to look up in a table ++ so we know how to deal with each type. */ ++ 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 ++ ++LFE1: ++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ (4 instructions). For cache effectiveness we align to a 16 byte boundary ++ first. */ ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++/* case FFI_TYPE_VOID */ ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* case FFI_TYPE_INT */ ++Lret_type1: ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_FLOAT */ ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_DOUBLE */ ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_LONGDOUBLE */ ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT8 */ ++Lret_type5: ++ lbz r3,3(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT8 */ ++Lret_type6: ++ lbz r3,3(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT16 */ ++Lret_type7: ++ lhz r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT16 */ ++Lret_type8: ++ lha r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT32 */ ++Lret_type9: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT32 */ ++Lret_type10: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT64 */ ++Lret_type11: ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_SINT64 */ ++Lret_type12: // same as Lret_type11 ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_STRUCT */ ++Lret_type13: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* End 16-byte aligned cases */ ++/* case FFI_TYPE_POINTER */ ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ // fall through ++ ++/* case done */ ++Lfinish: ++ 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) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++ ++#endif // __ppc__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +new file mode 100644 +index 0000000..8953d5f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +@@ -0,0 +1,1776 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1998 Geoffrey Keating ++ ++ PowerPC Foreign Function Interface ++ ++ Darwin ABI support (c) 2001 John Hornkvist ++ AIX ABI support (c) 2002 Free Software Foundation, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#if defined(POWERPC_DARWIN) ++#include // for sys_icache_invalidate() ++#endif ++ ++#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 ++// points to one of these. ++typedef struct aix_fd_struct { ++ void* code_pointer; ++ void* toc; ++} aix_fd; ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments. ++ ++ The stack layout we want looks like this: ++ ++ | Return address from ffi_call_DARWIN | higher addresses ++ |--------------------------------------------| ++ | Previous backchain pointer 4/8 | stack pointer here ++ |--------------------------------------------|-\ <<< on entry to ++ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN ++ |--------------------------------------------| | ++ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 ++ |--------------------------------------------| | ++ | Space for GPR2 4/8 | | ++ |--------------------------------------------| | stack | ++ | Reserved (4/8)*2 | | grows | ++ |--------------------------------------------| | down V ++ | Space for callee's LR 4/8 | | ++ |--------------------------------------------| | lower addresses ++ | Saved CR 4/8 | | ++ |--------------------------------------------| | stack pointer here ++ | Current backchain pointer 4/8 | | during ++ |--------------------------------------------|-/ <<< ffi_call_DARWIN ++ ++ Note: ppc64 CR is saved in the low word of a long on the stack. ++*/ ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args( ++ extended_cif* inEcif, ++ unsigned *const stack) ++/*@=exportheader@*/ ++{ ++ /* Copy the ecif to a local var so we can trample the arg. ++ BC note: test this with GP later for possible problems... */ ++ volatile extended_cif* ecif = inEcif; ++ ++ const unsigned bytes = ecif->cif->bytes; ++ const unsigned flags = ecif->cif->flags; ++ ++ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode ++ and 8 in 64-bit mode. */ ++ unsigned long *const longStack = (unsigned long *const)stack; ++ ++ /* 'stacktop' points at the previous backchain pointer. */ ++#if defined(__ppc64__) ++ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, ++ // saved registers, and an extra FPR. ++ unsigned long *const stacktop = ++ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); ++#elif defined(__ppc__) ++ unsigned long *const stacktop = longStack + (bytes / sizeof(long)); ++#else ++#error undefined architecture ++#endif ++ ++ /* 'fpr_base' points at the space for fpr1, and grows upwards as ++ we use FPR registers. */ ++ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - ++ NUM_FPR_ARG_REGISTERS; ++ ++#if defined(__ppc64__) ++ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base ++ // down a couple pegs. ++ fpr_base -= 2; ++#endif ++ ++ unsigned int fparg_count = 0; ++ ++ /* 'next_arg' grows up as we put parameters in it. */ ++ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ ++ ++ int i; ++ double double_tmp; ++ void** p_argv = ecif->avalue; ++ unsigned long gprvalue; ++ ffi_type** ptr = ecif->cif->arg_types; ++ ++ /* Check that everything starts aligned properly. */ ++ FFI_ASSERT(stack == SF_ROUND(stack)); ++ FFI_ASSERT(stacktop == SF_ROUND(stacktop)); ++ FFI_ASSERT(bytes == SF_ROUND(bytes)); ++ ++ /* Deal with return values that are actually pass-by-reference. ++ Rule: ++ Return values are referenced by r3, so r4 is the first parameter. */ ++ ++ if (flags & FLAG_RETVAL_REFERENCE) ++ *next_arg++ = (unsigned long)(char*)ecif->rvalue; ++ ++ /* Now for the arguments. */ ++ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) ++ { ++ switch ((*ptr)->type) ++ { ++ /* If a floating-point parameter appears before all of the general- ++ purpose registers are filled, the corresponding GPRs that match ++ the size of the floating-point parameter are shadowed for the ++ benefit of vararg and pre-ANSI functions. */ ++ case FFI_TYPE_FLOAT: ++ double_tmp = *(float*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg++; ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ double_tmp = *(double*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg += MODE_CHOICE(2,1); ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++#elif defined(__ppc__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) ++ *(double*)fpr_base = *(double*)*p_argv; ++#else ++#error undefined architecture ++#endif ++ ++ *(long double*)next_arg = *(long double*)*p_argv; ++ fparg_count += 2; ++ fpr_base += 2; ++ next_arg += MODE_CHOICE(4,2); ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++#if defined(__ppc64__) ++ gprvalue = *(long long*)*p_argv; ++ goto putgpr; ++#elif defined(__ppc__) ++ *(long long*)next_arg = *(long long*)*p_argv; ++ next_arg += 2; ++ break; ++#else ++#error undefined architecture ++#endif ++ ++ case FFI_TYPE_POINTER: ++ gprvalue = *(unsigned long*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT8: ++ gprvalue = *(unsigned char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT8: ++ gprvalue = *(signed char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT16: ++ gprvalue = *(unsigned short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT16: ++ gprvalue = *(signed short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ ++ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, ++ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); ++ next_arg += gprSize / sizeof(long); ++ fpr_base += fprSize / sizeof(double); ++ ++#elif defined(__ppc__) ++ char* dest_cpy = (char*)next_arg; ++ ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. ++ Structures with 3 byte in size are padded upwards. */ ++ unsigned size_al = (*ptr)->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++ if (ecif->cif->abi == FFI_DARWIN) ++ { ++ if (size_al < 3) ++ dest_cpy += 4 - size_al; ++ } ++ ++ memcpy((char*)dest_cpy, (char*)*p_argv, size_al); ++ next_arg += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ gprvalue = *(unsigned*)*p_argv; ++ ++putgpr: ++ *next_arg++ = gprvalue; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Check that we didn't overrun the stack... */ ++ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); ++ //FFI_ASSERT((unsigned *)fpr_base ++ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); ++ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); ++} ++ ++#if defined(__ppc64__) ++ ++bool ++ffi64_struct_contains_fp( ++ const ffi_type* inType) ++{ ++ bool containsFP = false; ++ unsigned int i; ++ ++ for (i = 0; inType->elements[i] != NULL && !containsFP; i++) ++ { ++ if (inType->elements[i]->type == FFI_TYPE_FLOAT || ++ inType->elements[i]->type == FFI_TYPE_DOUBLE || ++ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) ++ containsFP = true; ++ else if (inType->elements[i]->type == FFI_TYPE_STRUCT) ++ containsFP = ffi64_struct_contains_fp(inType->elements[i]); ++ } ++ ++ return containsFP; ++} ++ ++#endif // defined(__ppc64__) ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ /* All this is for the DARWIN ABI. */ ++ int i; ++ ffi_type** ptr; ++ int intarg_count = 0; ++ int fparg_count = 0; ++ unsigned int flags = 0; ++ unsigned int size_al = 0; ++ ++ /* All the machine-independent calculation of cif->bytes will be wrong. ++ Redo the calculation for DARWIN. */ ++ ++ /* Space for the frame pointer, callee's LR, CR, etc, and for ++ the asm's temp regs. */ ++ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); ++ ++ /* Return value handling. The rules are as follows: ++ - 32-bit (or less) integer values are returned in gpr3; ++ - Structures of size <= 4 bytes also returned in gpr3; ++ - 64-bit integer values and structures between 5 and 8 bytes are ++ returned in gpr3 and gpr4; ++ - Single/double FP values are returned in fpr1; ++ - Long double FP (if not equivalent to double) values are returned in ++ fpr1 and fpr2; ++ - Larger structures values are allocated space and a pointer is passed ++ as the first argument. */ ++ switch (cif->rtype->type) ++ { ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ flags |= FLAG_RETURNS_128BITS; ++ flags |= FLAG_RETURNS_FP; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_DOUBLE: ++ flags |= FLAG_RETURNS_64BITS; ++ /* Fall through. */ ++ case FFI_TYPE_FLOAT: ++ flags |= FLAG_RETURNS_FP; ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ flags |= FLAG_RETURNS_64BITS; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ ++ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++ { ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ } ++ else ++ { ++ flags |= FLAG_RETURNS_STRUCT; ++ ++ if (ffi64_struct_contains_fp(cif->rtype)) ++ flags |= FLAG_STRUCT_CONTAINS_FP; ++ } ++ ++#elif defined(__ppc__) ++ ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_VOID: ++ flags |= FLAG_RETURNS_NOTHING; ++ break; ++ ++ default: ++ /* Returns 32-bit integer, or similar. Nothing to do here. */ ++ break; ++ } ++ ++ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the ++ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest ++ goes on the stack. Structures are passed as a pointer to a copy of ++ the structure. Stuff on the stack needs to keep proper alignment. */ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ switch ((*ptr)->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ fparg_count++; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ fparg_count += 2; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ ++ if ( ++#if defined(__ppc64__) ++ fparg_count > NUM_FPR_ARG_REGISTERS + 1 ++#elif defined(__ppc__) ++ fparg_count > NUM_FPR_ARG_REGISTERS ++#else ++#error undefined architecture ++#endif ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ ++ intarg_count += 2; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ /* 'long long' arguments are passed as two words, but ++ either both words must fit in registers or both go ++ on the stack. If they go on the stack, they must ++ be 8-byte-aligned. */ ++ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 ++ || (intarg_count >= NUM_GPR_ARG_REGISTERS ++ && intarg_count % 2 != 0)) ++ intarg_count++; ++ ++ intarg_count += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ size_al = (*ptr)->size; ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++#if defined(__ppc64__) ++ // Look for FP struct members. ++ unsigned int j; ++ ++ for (j = 0; (*ptr)->elements[j] != NULL; j++) ++ { ++ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || ++ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) ++ { ++ fparg_count++; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS) ++ intarg_count++; ++ } ++ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) ++ { ++ fparg_count += 2; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) ++ intarg_count += 2; ++ } ++ else ++ intarg_count++; ++ } ++#elif defined(__ppc__) ++ intarg_count += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ ++ break; ++ ++ default: ++ /* Everything else is passed as a 4/8-byte word in a GPR, either ++ the object itself or a pointer to it. */ ++ intarg_count++; ++ break; ++ } ++ } ++ ++ /* Space for the FPR registers, if needed. */ ++ if (fparg_count != 0) ++ { ++ flags |= FLAG_FP_ARGUMENTS; ++#if defined(__ppc64__) ++ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); ++#elif defined(__ppc__) ++ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ /* Stack space. */ ++#if defined(__ppc64__) ++ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + fparg_count) * sizeof(long); ++#elif defined(__ppc__) ++ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + 2 * fparg_count) * sizeof(long); ++#else ++#error undefined architecture ++#endif ++ else ++ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); ++ ++ /* The stack space allocated needs to be a multiple of 16/32 bytes. */ ++ bytes = SF_ROUND(bytes); ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ ++ return FFI_OK; ++} ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ++ffi_call_AIX( ++/*@out@*/ extended_cif*, ++ unsigned, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++ ++extern void ++ffi_call_DARWIN( ++/*@out@*/ extended_cif*, ++ unsigned long, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ 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) && ++ (cif->rtype->type == FFI_TYPE_STRUCT)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ switch (cif->abi) ++ { ++ case FFI_AIX: ++ /*@-usedef@*/ ++ ffi_call_AIX(&ecif, -cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ case FFI_DARWIN: ++ /*@-usedef@*/ ++ ffi_call_DARWIN(&ecif, -(long)cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++/* here I'd like to add the stack frame layout we use in darwin_closure.S ++ and aix_clsoure.S ++ ++ SP previous -> +---------------------------------------+ <--- child frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 4 ++ | saved CR 4 | ++ +---------------------------------------+ 8 ++ | saved LR 4 | ++ +---------------------------------------+ 12 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 16 ++ | reserved for binders 4 | ++ +---------------------------------------+ 20 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 24 ++ | always reserved 8*4=32 (previous GPRs)| ++ | according to the linkage convention | ++ | from AIX | ++ +---------------------------------------+ 56 ++ | our FPR area 13*8=104 | ++ | f1 | ++ | . | ++ | f13 | ++ +---------------------------------------+ 160 ++ | result area 8 | ++ +---------------------------------------+ 168 ++ | alignement to the next multiple of 16 | ++SP current --> +---------------------------------------+ 176 <- parent frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 180 ++ | saved CR 4 | ++ +---------------------------------------+ 184 ++ | saved LR 4 | ++ +---------------------------------------+ 188 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 192 ++ | reserved for binders 4 | ++ +---------------------------------------+ 196 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 200 ++ | always reserved 8*4=32 we store our | ++ | GPRs here | ++ | r3 | ++ | . | ++ | r10 | ++ +---------------------------------------+ 232 ++ | overflow part | ++ +---------------------------------------+ xxx ++ | ???? | ++ +---------------------------------------+ xxx ++*/ ++ ++#if !defined(POWERPC_DARWIN) ++ ++#define MIN_LINE_SIZE 32 ++ ++static void ++flush_icache( ++ char* addr) ++{ ++#ifndef _AIX ++ __asm__ volatile ( ++ "dcbf 0,%0\n" ++ "sync\n" ++ "icbi 0,%0\n" ++ "sync\n" ++ "isync" ++ : : "r" (addr) : "memory"); ++#endif ++} ++ ++static void ++flush_range( ++ char* addr, ++ int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i += MIN_LINE_SIZE) ++ flush_icache(addr + i); ++ ++ flush_icache(addr + size - 1); ++} ++ ++#endif // !defined(POWERPC_DARWIN) ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ switch (cif->abi) ++ { ++ case FFI_DARWIN: ++ { ++ FFI_ASSERT (cif->abi == FFI_DARWIN); ++ ++ unsigned int* tramp = (unsigned int*)&closure->tramp[0]; ++ ++#if defined(__ppc64__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0xe98b0018; // ld r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0xe96b0020; // ld r11,32(r11) ++ tramp[7] = 0x4e800420; // bctr ++ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; ++ *(unsigned long*)&tramp[10] = (unsigned long)closure; ++#elif defined(__ppc__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0x818b0018; // lwz r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0x816b001c; // lwz r11,28(r11) ++ tramp[7] = 0x4e800420; // bctr ++ tramp[8] = (unsigned long)ffi_closure_ASM; ++ tramp[9] = (unsigned long)closure; ++#else ++#error undefined architecture ++#endif ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ // Flush the icache. Only necessary on Darwin. ++#if defined(POWERPC_DARWIN) ++ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#else ++ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#endif ++ ++ break; ++ } ++ ++ case FFI_AIX: ++ { ++ FFI_ASSERT (cif->abi == FFI_AIX); ++ ++ ffi_aix_trampoline_struct* tramp_aix = ++ (ffi_aix_trampoline_struct*)(closure->tramp); ++ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; ++ ++ tramp_aix->code_pointer = fd->code_pointer; ++ tramp_aix->toc = fd->toc; ++ tramp_aix->static_chain = closure; ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ break; ++ } ++ ++ default: ++ return FFI_BAD_ABI; ++ } ++ ++ return FFI_OK; ++} ++ ++#if defined(__ppc__) ++ typedef double ldbits[2]; ++ ++ typedef union ++ { ++ ldbits lb; ++ long double ld; ++ } 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 ++ for a return value, ffi_closure_ASM invokes the following helper function ++ to do most of the work. */ ++int ++ffi_closure_helper_DARWIN( ++ ffi_closure* closure, ++ void* rvalue, ++ unsigned long* pgr, ++ ffi_dblfl* pfr) ++{ ++ /* rvalue is the pointer to space for return value in closure assembly ++ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM ++ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ ++ ++#if defined(__ppc__) ++ ldu temp_ld; ++#endif ++ ++ double temp; ++ unsigned int i; ++ unsigned int nf = 0; /* number of FPRs already used. */ ++ unsigned int ng = 0; /* number of GPRs already used. */ ++ ffi_cif* cif = closure->cif; ++ long avn = cif->nargs; ++ void** avalue = alloca(cif->nargs * sizeof(void*)); ++ ffi_type** arg_types = cif->arg_types; ++ ++ /* Copy the caller's structure return value address so that the closure ++ returns the data directly to the caller. */ ++#if defined(__ppc64__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT && ++ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++#elif defined(__ppc__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT) ++#else ++#error undefined architecture ++#endif ++ { ++ rvalue = (void*)*pgr; ++ pgr++; ++ ng++; ++ } ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ for (i = 0; i < avn; i++) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ avalue[i] = (char*)pgr + MODE_CHOICE(3,7); ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ avalue[i] = (char*)pgr + MODE_CHOICE(2,6); ++ ng++; ++ pgr++; ++ break; ++ ++#if defined(__ppc__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ avalue[i] = (char*)pgr + MODE_CHOICE(0,4); ++ ng++; ++ pgr++; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ if (cif->abi == FFI_DARWIN) ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ unsigned int savedFPRSize = fprSize; ++ ++ avalue[i] = alloca(arg_types[i]->size); ++ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, ++ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); ++ ++ ng += gprSize / sizeof(long); ++ pgr += gprSize / sizeof(long); ++ pfr += (fprSize - savedFPRSize) / sizeof(double); ++ ++#elif defined(__ppc__) ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. */ ++ unsigned int size_al = size_al = arg_types[i]->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN(arg_types[i]->size, 8); ++ ++ if (size_al < 3) ++ avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; ++ else ++ avalue[i] = (void*)pgr; ++ ++ ng += (size_al + 3) / sizeof(long); ++ pgr += (size_al + 3) / sizeof(long); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ /* Long long ints are passed in 1 or 2 GPRs. */ ++ avalue[i] = pgr; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ /* A float value consumes a GPR. ++ There are 13 64-bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ temp = pfr->d; ++ pfr->f = (float)temp; ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ /* A double value consumes one or two GPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++#elif defined(__ppc__) ++ /* A long double value consumes 2/4 GPRs and 2 FPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS - 1) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++ /* Here we have the situation where one part of the long double ++ is stored in fpr13 and the other part is already on the stack. ++ 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(temp_ld.lb[0])); ++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); ++ avalue[i] = &temp_ld.ld; ++ } ++#else ++#error undefined architecture ++#endif ++ else ++ avalue[i] = pgr; ++ ++ nf += 2; ++ ng += MODE_CHOICE(4,2); ++ pgr += MODE_CHOICE(4,2); ++ ++ break; ++ ++#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ (closure->fun)(cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell ffi_closure_ASM to perform return type promotions. */ ++ return cif->rtype->type; ++} ++ ++#if defined(__ppc64__) ++ ++/* ffi64_struct_to_ram_form ++ ++ Rebuild a struct's natural layout from buffers of concatenated registers. ++ Return the number of registers used. ++ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_ram_form( ++ const ffi_type* inType, ++ const char* inGPRs, ++ unsigned int* ioGPRMarker, ++ const char* inFPRs, ++ unsigned int* ioFPRMarker, ++ unsigned int* ioFPRsUsed, ++ char* outStruct, // caller-allocated ++ unsigned int* ioStructMarker) ++{ ++ unsigned int srcGMarker = 0; ++ unsigned int srcFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ unsigned int destMarker = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioGPRMarker) ++ srcGMarker = *ioGPRMarker; ++ ++ if (ioFPRMarker) ++ { ++ srcFMarker = *ioFPRMarker; ++ savedFMarker = srcFMarker; ++ } ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioStructMarker) ++ destMarker = *ioStructMarker; ++ ++ size_t i; ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ srcGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ srcFMarker = ALIGN(srcFMarker, 4); ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inGPRs[srcGMarker]; ++ ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcFMarker = ALIGN(srcFMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inGPRs[srcGMarker]; ++ ++ destMarker += 8; ++ ++ // Skip next GPR ++ srcGMarker += 8; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ destMarker = ALIGN(destMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ srcFMarker = ALIGN(srcFMarker, 8); ++ srcGMarker = ALIGN(srcGMarker, 8); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inFPRs[srcFMarker]; ++ srcFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ srcFMarker = ALIGN(srcFMarker, 16); ++ srcGMarker = ALIGN(srcGMarker, 16); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inGPRs[srcGMarker]; ++ } ++ ++ destMarker += 16; ++ ++ // Skip next 2 GPRs ++ srcGMarker += 16; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ if (inType->alignment == 1) // chars only ++ { ++ if (inType->size == 1) ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ else if (inType->size == 2) ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ i++; ++ } ++ else ++ { ++ memcpy(&outStruct[destMarker], ++ &inGPRs[srcGMarker], inType->size); ++ srcGMarker += inType->size; ++ destMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // chars and other stuff ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcGMarker = ALIGN(srcGMarker, 2); ++ destMarker = ALIGN(destMarker, 2); ++ ++ *(short*)&outStruct[destMarker] = ++ *(short*)&inGPRs[srcGMarker]; ++ srcGMarker += 2; ++ destMarker += 2; ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ *(int*)&outStruct[destMarker] = ++ *(int*)&inGPRs[srcGMarker]; ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcGMarker = ALIGN(srcGMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ *(long long*)&outStruct[destMarker] = ++ *(long long*)&inGPRs[srcGMarker]; ++ srcGMarker += 8; ++ destMarker += 8; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_ram_form(inType->elements[i], inGPRs, ++ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, ++ outStruct, &destMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); // unknown element type ++ break; ++ } ++ } ++ ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && srcGMarker == 16) ++ { ++ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; ++ srcFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioGPRMarker) ++ *ioGPRMarker = ALIGN(srcGMarker, 8); ++ ++ if (ioFPRMarker) ++ *ioFPRMarker = srcFMarker; ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(destMarker, 8); ++} ++ ++/* ffi64_struct_to_reg_form ++ ++ Copy a struct's elements into buffers that can be sliced into registers. ++ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers ++ to calculate size only. ++ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_reg_form( ++ const ffi_type* inType, ++ const char* inStruct, ++ unsigned int* ioStructMarker, ++ unsigned int* ioFPRsUsed, ++ char* outGPRs, // caller-allocated ++ unsigned int* ioGPRSize, ++ char* outFPRs, // caller-allocated ++ unsigned int* ioFPRSize) ++{ ++ size_t i; ++ unsigned int srcMarker = 0; ++ unsigned int destGMarker = 0; ++ unsigned int destFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioStructMarker) ++ srcMarker = *ioStructMarker; ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioGPRSize) ++ destGMarker = *ioGPRSize; ++ ++ if (ioFPRSize) ++ { ++ destFMarker = *ioFPRSize; ++ savedFMarker = destFMarker; ++ } ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ destGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ // Shadow floating-point types in GPRs for vararg and pre-ANSI ++ // functions. ++ case FFI_TYPE_FLOAT: ++ // Nudge markers to next 4/8-byte boundary ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcMarker = ALIGN(srcMarker, 8); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ ++ // Skip next GPR ++ destGMarker += 8; ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ srcMarker = ALIGN(srcMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ destFMarker = ALIGN(destFMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outFPRs != NULL && inStruct != NULL) ++ *(long double*)&outFPRs[destFMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ destFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ destGMarker = ALIGN(destGMarker, 16); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ } ++ ++ srcMarker += 16; ++ destGMarker += 16; // Skip next 2 GPRs ++ destGMarker = ALIGN(destGMarker, 8); // was 16 ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ if (inType->alignment == 1) // bytes only ++ { ++ if (inType->size == 1) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ } ++ else if (inType->size == 2) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; ++ } ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ i++; ++ } ++ else ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ // Avoid memcpy for small chunks. ++ if (inType->size <= sizeof(long)) ++ *(long*)&outGPRs[destGMarker] = ++ *(long*)&inStruct[srcMarker]; ++ else ++ memcpy(&outGPRs[destGMarker], ++ &inStruct[srcMarker], inType->size); ++ } ++ ++ srcMarker += inType->size; ++ destGMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // bytes and other stuff ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcMarker = ALIGN(srcMarker, 2); ++ destGMarker = ALIGN(destGMarker, 2); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(short*)&outGPRs[destGMarker] = ++ *(short*)&inStruct[srcMarker]; ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(int*)&outGPRs[destGMarker] = ++ *(int*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcMarker = ALIGN(srcMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long long*)&outGPRs[destGMarker] = ++ *(long long*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ destGMarker += 8; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_reg_form(inType->elements[i], ++ inStruct, &srcMarker, &fprsUsed, outGPRs, ++ &destGMarker, outFPRs, &destFMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && destGMarker == 16) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; ++ ++ destFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(srcMarker, 8); ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioGPRSize) ++ *ioGPRSize = ALIGN(destGMarker, 8); ++ ++ if (ioFPRSize) ++ *ioFPRSize = ALIGN(destFMarker, 8); ++} ++ ++/* ffi64_stret_needs_ptr ++ ++ Determine whether a returned struct needs a pointer in r3 or can fit ++ in registers. ++*/ ++ ++bool ++ffi64_stret_needs_ptr( ++ const ffi_type* inType, ++ unsigned short* ioGPRCount, ++ unsigned short* ioFPRCount) ++{ ++ // Obvious case first- struct is larger than combined FPR size. ++ if (inType->size > 14 * 8) ++ return true; ++ ++ // Now the struct can physically fit in registers, determine if it ++ // also fits logically. ++ bool needsPtr = false; ++ unsigned short gprsUsed = 0; ++ unsigned short fprsUsed = 0; ++ size_t i; ++ ++ if (ioGPRCount) ++ gprsUsed = *ioGPRCount; ++ ++ if (ioFPRCount) ++ fprsUsed = *ioFPRCount; ++ ++ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ gprsUsed++; ++ fprsUsed++; ++ ++ if (fprsUsed > 13) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ gprsUsed += 2; ++ fprsUsed += 2; ++ ++ if (fprsUsed > 14) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ { ++ needsPtr = true; ++ break; ++ } ++ ++ if (inType->elements[i + 1] == NULL) // last byte in the struct ++ break; ++ ++ // Count possible contiguous bytes ahead, up to 8. ++ unsigned short j; ++ ++ for (j = 1; j < 8; j++) ++ { ++ if (inType->elements[i + j] == NULL || ++ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) ++ break; ++ } ++ ++ i += j - 1; // allow for i++ before the test condition ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ needsPtr = ffi64_stret_needs_ptr( ++ inType->elements[i], &gprsUsed, &fprsUsed); ++ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ if (ioGPRCount) ++ *ioGPRCount = gprsUsed; ++ ++ if (ioFPRCount) ++ *ioFPRCount = fprsUsed; ++ ++ return needsPtr; ++} ++ ++/* ffi64_data_size ++ ++ Calculate the size in bytes of an ffi type. ++*/ ++ ++unsigned int ++ffi64_data_size( ++ const ffi_type* inType) ++{ ++ unsigned int size = 0; ++ ++ switch (inType->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ size = 1; ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ size = 2; ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_FLOAT: ++ size = 4; ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_DOUBLE: ++ size = 8; ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ size = 16; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ ffi64_struct_to_reg_form( ++ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); ++ break; ++ ++ case FFI_TYPE_VOID: ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ ++ return size; ++} ++ ++#endif /* defined(__ppc64__) */ ++#endif /* __ppc__ || __ppc64__ */ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +new file mode 100644 +index 0000000..7162fa1 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +@@ -0,0 +1,418 @@ ++#if defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc64-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 ++ stg r0,SF_RETURN(r1) // save return address ++ ++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. ++ stg r3,SF_ARG1(r1) ++ stg r4,SF_ARG2(r1) ++ stg r5,SF_ARG3(r1) ++ stg r6,SF_ARG4(r1) ++ stg r7,SF_ARG5(r1) ++ stg r8,SF_ARG6(r1) ++ stg r9,SF_ARG7(r1) ++ stg r10,SF_ARG8(r1) ++ ++LCFI0: ++/* 48 bytes (Linkage Area) ++ 64 bytes (outgoing parameter area, always reserved) ++ 112 bytes (14*8 for incoming FPR) ++ ? bytes (result) ++ 112 bytes (14*8 for outgoing FPR) ++ 16 bytes (2 saved registers) ++ 352 + ? total bytes ++*/ ++ ++ std r31,-8(r1) // Save registers we use. ++ std r30,-16(r1) ++ mr r30,r1 // Save the old SP. ++ mr r31,r11 // Save the ffi_closure around ffi64_data_size. ++ ++ // Calculate the space we need. ++ stdu r1,-SF_MINSIZE(r1) ++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ bl Lffi64_data_size$stub ++ ld r1,0(r1) ++ ++ addi r3,r3,352 // Add our overhead. ++ neg r3,r3 ++ li r0,-32 // Align to 32 bytes. ++ and r3,r3,r0 ++ stdux r1,r1,r3 // Grow the stack. ++ ++ mr r11,r31 // Copy the ffi_closure back. ++ ++LCFI1: ++ // We want to build up an area for the parameters passed ++ // in registers. (both floating point and integer) ++ ++/* 320 bytes (callee stack frame aligned to 32) ++ 48 bytes (caller linkage area) ++ 368 (start of caller parameter area aligned to 8) ++*/ ++ ++ // Save FPRs 1 - 14. (aligned to 8) ++ stfd f1,112(r1) ++ stfd f2,120(r1) ++ stfd f3,128(r1) ++ stfd f4,136(r1) ++ stfd f5,144(r1) ++ stfd f6,152(r1) ++ stfd f7,160(r1) ++ stfd f8,168(r1) ++ stfd f9,176(r1) ++ stfd f10,184(r1) ++ stfd f11,192(r1) ++ stfd f12,200(r1) ++ stfd f13,208(r1) ++ stfd f14,216(r1) ++ ++ // Set up registers for the routine that actually does the work. ++ mr r3,r11 // context pointer from the trampoline ++ addi r4,r1,224 // result storage ++ addi r5,r30,SF_ARG1 // saved GPRs ++ addi r6,r1,112 // saved FPRs ++ bl Lffi_closure_helper_DARWIN$stub ++ ++ // Look the proper starting point in table ++ // by using return type as an offset. ++ addi r5,r1,224 // 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. ++ mtctr r3 ++ bctr ++ ++LFE1: ++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ // (4 instructions). For cache effectiveness we align to a 16 byte ++ // boundary first. ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++// case FFI_TYPE_VOID ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++// case FFI_TYPE_INT ++Lret_type1: ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_FLOAT ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_DOUBLE ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_LONGDOUBLE ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT8 ++Lret_type5: ++ lbz r3,7(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT8 ++Lret_type6: ++ lbz r3,7(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT16 ++Lret_type7: ++ lhz r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT16 ++Lret_type8: ++ lha r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT32 ++Lret_type9: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT32 ++Lret_type10: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT64 ++Lret_type11: ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT64 ++Lret_type12: // same as Lret_type11 ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_STRUCT ++Lret_type13: ++ b Lret_struct ++ nop ++ nop ++ nop ++ ++// ** End 16-byte aligned cases ** ++// case FFI_TYPE_POINTER ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ b Lfinish ++ ++// copy struct into registers ++Lret_struct: ++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r31) // ffi_cif->rtype* ++ ld r31,24(r31) // ffi_cif->flags ++ mr r4,r5 // copy struct* to 2nd arg ++ addi r7,r1,SF_ARG9 // GPR return area ++ addi r9,r30,-16-(14*8) // FPR return area ++ li r5,0 // struct offset ptr (NULL) ++ li r6,0 // FPR used count ptr (NULL) ++ li r8,0 // GPR return area size ptr (NULL) ++ li r10,0 // FPR return area size ptr (NULL) ++ bl Lffi64_struct_to_reg_form$stub ++ ++ // Load GPRs ++ ld r3,SF_ARG9(r1) ++ ld r4,SF_ARG10(r1) ++ ld r5,SF_ARG11(r1) ++ ld r6,SF_ARG12(r1) ++ nop ++ ld r7,SF_ARG13(r1) ++ ld r8,SF_ARG14(r1) ++ ld r9,SF_ARG15(r1) ++ ld r10,SF_ARG16(r1) ++ nop ++ ++ // Load FPRs ++ mtcrf 0x2,r31 ++ bf 26,Lfinish ++ lfd f1,-16-(14*8)(r30) ++ lfd f2,-16-(13*8)(r30) ++ lfd f3,-16-(12*8)(r30) ++ lfd f4,-16-(11*8)(r30) ++ nop ++ lfd f5,-16-(10*8)(r30) ++ lfd f6,-16-(9*8)(r30) ++ lfd f7,-16-(8*8)(r30) ++ lfd f8,-16-(7*8)(r30) ++ nop ++ lfd f9,-16-(6*8)(r30) ++ lfd f10,-16-(5*8)(r30) ++ lfd f11,-16-(4*8)(r30) ++ lfd f12,-16-(3*8)(r30) ++ nop ++ lfd f13,-16-(2*8)(r30) ++ lfd f14,-16-(1*8)(r30) ++ // Fall through ++ ++// case done ++Lfinish: ++ 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. ++ blr ++ ++// END(ffi_closure_ASM) ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_reg_form$stub: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_reg_form ++ ++LO$ffi64_struct_to_reg_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) ++ mtctr r12 ++ bctr ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_data_size$stub: ++ .indirect_symbol _ffi64_data_size ++ mflr r0 ++ bcl 20,31,LO$ffi64_data_size ++ ++LO$ffi64_data_size: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_reg_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ .g_long dyld_stub_binding_helper ++ ++L_ffi64_data_size$lazy_ptr: ++ .indirect_symbol _ffi64_data_size ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c +new file mode 100644 +index 0000000..44806ae +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/types.c +@@ -0,0 +1,115 @@ ++/* ----------------------------------------------------------------------- ++ types.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Predefined ffi_types needed by libffi. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++/* Type definitions */ ++#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \ ++ ffi_type ffi_type_##n = { s, a, t, NULL } ++#define FFI_AGGREGATE_TYPEDEF(n, e) \ ++ ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } ++ ++FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); ++FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); ++FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); ++FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); ++FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); ++FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); ++FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); ++ ++/* Size and alignment are fake here. They must not be 0. */ ++FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); ++ ++#if defined ALPHA || defined SPARC64 || defined X86_64 || \ ++ defined S390X || defined IA64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); ++#else ++FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); ++#endif ++ ++#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN) ++ ++# ifdef X86_64 ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++# else ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++# endif ++ ++#elif defined(POWERPC_DARWIN) ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#elif defined SH ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++#else ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#endif ++ ++#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN) ++ ++# if defined X86_WIN32 || defined X86_64 ++ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++# endif ++ ++# ifdef X86_DARWIN ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined ARM || defined SH || defined POWERPC_AIX ++FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); ++#elif defined POWERPC_DARWIN ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# if __GNUC__ >= 4 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined SPARC ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# ifdef SPARC64 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined X86_64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++#else ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S +new file mode 100644 +index 0000000..165d469 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S +@@ -0,0 +1,417 @@ ++/* ----------------------------------------------------------------------- ++ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. ++ derived from unix64.S ++ ++ x86-64 Foreign Function Interface for Darwin. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifdef __x86_64__ ++#define LIBFFI_ASM ++#include ++#include ++ ++ .file "darwin64.S" ++.text ++ ++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, ++ void *raddr, void (*fnaddr)()); ++ ++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame ++ for this function. This has been allocated by ffi_call. We also ++ deallocate some of the stack that has been alloca'd. */ ++ ++ .align 3 ++ .globl _ffi_call_unix64 ++ ++_ffi_call_unix64: ++LUW0: ++ movq (%rsp), %r10 /* Load return address. */ ++ movq %rdi, %r12 /* Save a copy of the register area. */ ++ leaq (%rdi, %rsi), %rax /* Find local stack base. */ ++ movq %rdx, (%rax) /* Save flags. */ ++ movq %rcx, 8(%rax) /* Save raddr. */ ++ movq %rbp, 16(%rax) /* Save old frame pointer. */ ++ movq %r10, 24(%rax) /* Relocate return address. */ ++ movq %rax, %rbp /* Finalize local stack frame. */ ++LUW1: ++ /* movq %rdi, %r10 // Save a copy of the register area. */ ++ movq %r12, %r10 ++ movq %r8, %r11 /* Save a copy of the target fn. */ ++ movl %r9d, %eax /* Set number of SSE registers. */ ++ ++ /* Load up all argument registers. */ ++ movq (%r10), %rdi ++ movq 8(%r10), %rsi ++ movq 16(%r10), %rdx ++ movq 24(%r10), %rcx ++ movq 32(%r10), %r8 ++ movq 40(%r10), %r9 ++ testl %eax, %eax ++ jnz Lload_sse ++Lret_from_load_sse: ++ ++ /* Deallocate the reg arg area. */ ++ leaq 176(%r10), %rsp ++ ++ /* Call the user function. */ ++ call *%r11 ++ ++ /* Deallocate stack arg area; local stack frame in redzone. */ ++ leaq 24(%rbp), %rsp ++ ++ movq 0(%rbp), %rcx /* Reload flags. */ ++ movq 8(%rbp), %rdi /* Reload raddr. */ ++ movq 16(%rbp), %rbp /* Reload old frame pointer. */ ++LUW2: ++ ++ /* The first byte of the flags contains the FFI_TYPE. */ ++ movzbl %cl, %r10d ++ leaq Lstore_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lstore_table: ++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ ++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ ++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ ++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ ++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ ++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ ++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ ++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ ++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lst_void: ++ ret ++ .align 3 ++Lst_uint8: ++ movzbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_sint8: ++ movsbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint16: ++ movzwq %ax, %rax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint16: ++ movswq %ax, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint32: ++ movl %eax, %eax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint32: ++ cltq ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_int64: ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_float: ++ movss %xmm0, (%rdi) ++ ret ++ .align 3 ++Lst_double: ++ movsd %xmm0, (%rdi) ++ ret ++Lst_ldouble: ++ fstpt (%rdi) ++ ret ++ .align 3 ++Lst_struct: ++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */ ++ ++ /* We have to locate the values now, and since we don't want to ++ write too much data into the user's return value, we spill the ++ value to a 16 byte scratch area first. Bits 8, 9, and 10 ++ control where the values are located. Only one of the three ++ bits will be set; see ffi_prep_cif_machdep for the pattern. */ ++ movd %xmm0, %r10 ++ movd %xmm1, %r11 ++ testl $0x100, %ecx ++ cmovnz %rax, %rdx ++ cmovnz %r10, %rax ++ testl $0x200, %ecx ++ cmovnz %r10, %rdx ++ testl $0x400, %ecx ++ cmovnz %r10, %rax ++ cmovnz %r11, %rdx ++ movq %rax, (%rsi) ++ movq %rdx, 8(%rsi) ++ ++ /* Bits 12-31 contain the true size of the structure. Copy from ++ the scratch area to the true destination. */ ++ shrl $12, %ecx ++ rep movsb ++ ret ++ ++ /* Many times we can avoid loading any SSE registers at all. ++ It's not worth an indirect jump to load the exact set of ++ SSE registers needed; zero or all is a good compromise. */ ++ .align 3 ++LUW3: ++Lload_sse: ++ movdqa 48(%r10), %xmm0 ++ movdqa 64(%r10), %xmm1 ++ movdqa 80(%r10), %xmm2 ++ movdqa 96(%r10), %xmm3 ++ movdqa 112(%r10), %xmm4 ++ movdqa 128(%r10), %xmm5 ++ movdqa 144(%r10), %xmm6 ++ movdqa 160(%r10), %xmm7 ++ jmp Lret_from_load_sse ++ ++LUW4: ++ .align 3 ++ .globl _ffi_closure_unix64 ++ ++_ffi_closure_unix64: ++LUW5: ++ /* The carry flag is set by the trampoline iff SSE registers ++ are used. Don't clobber it before the branch instruction. */ ++ leaq -200(%rsp), %rsp ++LUW6: ++ movq %rdi, (%rsp) ++ movq %rsi, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rcx, 24(%rsp) ++ movq %r8, 32(%rsp) ++ movq %r9, 40(%rsp) ++ jc Lsave_sse ++Lret_from_save_sse: ++ ++ movq %r10, %rdi ++ leaq 176(%rsp), %rsi ++ movq %rsp, %rdx ++ leaq 208(%rsp), %rcx ++ call _ffi_closure_unix64_inner ++ ++ /* Deallocate stack frame early; return value is now in redzone. */ ++ addq $200, %rsp ++LUW7: ++ ++ /* The first byte of the return value contains the FFI_TYPE. */ ++ movzbl %al, %r10d ++ leaq Lload_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lload_table: ++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */ ++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ ++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ ++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ ++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lld_void: ++ ret ++ .align 3 ++Lld_int8: ++ movzbl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int16: ++ movzwl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int32: ++ movl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int64: ++ movq -24(%rsp), %rax ++ ret ++ .align 3 ++Lld_float: ++ movss -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_double: ++ movsd -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_ldouble: ++ fldt -24(%rsp) ++ ret ++ .align 3 ++Lld_struct: ++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, ++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading ++ both rdx and xmm1 with the second word. For the remaining, ++ bit 8 set means xmm0 gets the second word, and bit 9 means ++ that rax gets the second word. */ ++ movq -24(%rsp), %rcx ++ movq -16(%rsp), %rdx ++ movq -16(%rsp), %xmm1 ++ testl $0x100, %eax ++ cmovnz %rdx, %rcx ++ movd %rcx, %xmm0 ++ testl $0x200, %eax ++ movq -24(%rsp), %rax ++ cmovnz %rdx, %rax ++ ret ++ ++ /* See the comment above Lload_sse; the same logic applies here. */ ++ .align 3 ++LUW8: ++Lsave_sse: ++ movdqa %xmm0, 48(%rsp) ++ movdqa %xmm1, 64(%rsp) ++ movdqa %xmm2, 80(%rsp) ++ movdqa %xmm3, 96(%rsp) ++ movdqa %xmm4, 112(%rsp) ++ movdqa %xmm5, 128(%rsp) ++ movdqa %xmm6, 144(%rsp) ++ movdqa %xmm7, 160(%rsp) ++ jmp Lret_from_save_sse ++ ++LUW9: ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ ++ .long L$set$0 ++LSCIE1: ++ .long 0x0 /* CIE Identifier Tag */ ++ .byte 0x1 /* CIE Version */ ++ .ascii "zR\0" /* CIE Augmentation */ ++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ ++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ ++ .byte 0x10 /* CIE RA Column */ ++ .byte 0x1 /* uleb128 0x1; Augmentation size */ ++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */ ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 /* uleb128 0x7 */ ++ .byte 0x8 /* uleb128 0x8 */ ++ .byte 0x90 /* DW_CFA_offset, column 0x10 */ ++ .byte 0x1 ++ .align 3 ++LECIE1: ++ .globl _ffi_call_unix64.eh ++_ffi_call_unix64.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ ++ .long L$set$1 ++LASFDE1: ++ .long LASFDE1-EH_frame1 /* FDE CIE offset */ ++ .quad LUW0-. /* FDE initial location */ ++ .set L$set$2,LUW4-LUW0 /* FDE address range */ ++ .quad L$set$2 ++ .byte 0x0 /* Augmentation size */ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$3,LUW1-LUW0 ++ .long L$set$3 ++ ++ /* New stack frame based off rbp. This is a itty bit of unwind ++ trickery in that the CFA *has* changed. There is no easy way ++ to describe it correctly on entry to the function. Fortunately, ++ it doesn't matter too much since at all points we can correctly ++ unwind back to ffi_call. Note that the location to which we ++ moved the return address is (the new) CFA-8, so from the ++ perspective of the unwind info, it hasn't moved. */ ++ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ ++ .byte 0x6 ++ .byte 0x20 ++ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ ++ .byte 0x2 ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$4,LUW2-LUW1 ++ .long L$set$4 ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 ++ .byte 0x8 ++ .byte 0xc0+6 /* DW_CFA_restore, %rbp */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$5,LUW3-LUW2 ++ .long L$set$5 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE1: ++ .globl _ffi_closure_unix64.eh ++_ffi_closure_unix64.eh: ++LSFDE3: ++ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ ++ .long L$set$6 ++LASFDE3: ++ .long LASFDE3-EH_frame1 /* FDE CIE offset */ ++ .quad LUW5-. /* FDE initial location */ ++ .set L$set$7,LUW9-LUW5 /* FDE address range */ ++ .quad L$set$7 ++ .byte 0x0 /* Augmentation size */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$8,LUW6-LUW5 ++ .long L$set$8 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 208,1 /* uleb128 208 */ ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$9,LUW7-LUW6 ++ .long L$set$9 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 0x8 ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$10,LUW8-LUW7 ++ .long L$set$10 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE3: ++ .subsections_via_symbols ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +new file mode 100644 +index 0000000..925a841 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +@@ -0,0 +1,422 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. ++ ++ X86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++/* ++ * This file is based on sysv.S and then hacked up by Ronald who hasn't done ++ * assembly programming in 8 years. ++ */ ++ ++#ifndef __x86_64__ ++ ++#define LIBFFI_ASM ++#include ++#include ++ ++#ifdef PyObjC_STRICT_DEBUGGING ++ /* XXX: Debugging of stack alignment, to be removed */ ++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 ++#else ++#define ASSERT_STACK_ALIGNED ++#endif ++ ++.text ++ ++.globl _ffi_prep_args ++ ++ .align 4 ++.globl _ffi_call_SYSV ++ ++_ffi_call_SYSV: ++LFB1: ++ pushl %ebp ++LCFI0: ++ movl %esp,%ebp ++LCFI1: ++ subl $8,%esp ++ /* Make room for all of the new args. */ ++ movl 16(%ebp),%ecx ++ subl %ecx,%esp ++ ++ movl %esp,%eax ++ ++ /* Place all of the ffi_prep_args in position */ ++ subl $8,%esp ++ pushl 12(%ebp) ++ pushl %eax ++ call *8(%ebp) ++ ++ /* Return stack to previous state and call the function */ ++ addl $16,%esp ++ ++ call *28(%ebp) ++ ++ /* 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 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 Lnoretval ++ fstp %st(0) ++ ++ jmp Lepilogue ++ ++Lretint: ++ cmpl $FFI_TYPE_INT,%ecx ++ jne Lretfloat ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ movl %eax,0(%ecx) ++ jmp Lepilogue ++ ++Lretfloat: ++ cmpl $FFI_TYPE_FLOAT,%ecx ++ jne Lretdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstps (%ecx) ++ jmp Lepilogue ++ ++Lretdouble: ++ cmpl $FFI_TYPE_DOUBLE,%ecx ++ jne Lretlongdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpl (%ecx) ++ jmp Lepilogue ++ ++Lretlongdouble: ++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx ++ jne Lretint64 ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpt (%ecx) ++ jmp Lepilogue ++ ++Lretint64: ++ cmpl $FFI_TYPE_SINT64,%ecx ++ 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 Lepilogue ++ ++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 ++ ++Lnoretval: ++Lepilogue: ++ addl $8,%esp ++ movl %ebp,%esp ++ popl %ebp ++ ret ++LFE1: ++.ffi_call_SYSV_end: ++ ++ .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_UINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_SINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_UINT16, %eax ++ je Lcls_retstruct2 ++ 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 ++ ++.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__ */ ++ ++#endif /* defined __i386__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +new file mode 100644 +index 0000000..06feaf2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +@@ -0,0 +1,734 @@ ++#ifdef __x86_64__ ++ ++/* ----------------------------------------------------------------------- ++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen ++ ++ x86-64 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_GPR_REGS 6 ++#define MAX_SSE_REGS 8 ++ ++typedef struct RegisterArgs { ++ /* Registers for argument passing. */ ++ UINT64 gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++} RegisterArgs; ++ ++extern void ++ffi_call_unix64( ++ void* args, ++ unsigned long bytes, ++ unsigned flags, ++ void* raddr, ++ void (*fnaddr)(), ++ unsigned ssecount); ++ ++/* All reference to register classes here is identical to the code in ++ gcc/config/i386/i386.c. Do *not* change one without the other. */ ++ ++/* 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 reformating penalties. ++ ++ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves ++ whenever possible (upper half does contain padding). */ ++enum x86_64_reg_class ++{ ++ X86_64_NO_CLASS, ++ X86_64_INTEGER_CLASS, ++ X86_64_INTEGERSI_CLASS, ++ X86_64_SSE_CLASS, ++ X86_64_SSESF_CLASS, ++ X86_64_SSEDF_CLASS, ++ X86_64_SSEUP_CLASS, ++ X86_64_X87_CLASS, ++ X86_64_X87UP_CLASS, ++ X86_64_COMPLEX_X87_CLASS, ++ X86_64_MEMORY_CLASS ++}; ++ ++#define MAX_CLASSES 4 ++#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) ++ ++/* x86-64 register passing implementation. See x86-64 ABI for details. Goal ++ of this code is to classify each 8bytes of incoming argument by the register ++ class and assign registers accordingly. */ ++ ++/* Return the union class of CLASS1 and CLASS2. ++ See the x86-64 PS ABI for details. */ ++static enum x86_64_reg_class ++merge_classes( ++ enum x86_64_reg_class class1, ++ enum x86_64_reg_class class2) ++{ ++ /* Rule #1: If both classes are equal, this is the resulting class. */ ++ if (class1 == class2) ++ return class1; ++ ++ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is ++ the other class. */ ++ if (class1 == X86_64_NO_CLASS) ++ return class2; ++ ++ if (class2 == X86_64_NO_CLASS) ++ return class1; ++ ++ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ ++ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ ++ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) ++ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) ++ return X86_64_INTEGERSI_CLASS; ++ ++ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS ++ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) ++ return X86_64_INTEGER_CLASS; ++ ++ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, ++ MEMORY is used. */ ++ if (class1 == X86_64_X87_CLASS ++ || class1 == X86_64_X87UP_CLASS ++ || class1 == X86_64_COMPLEX_X87_CLASS ++ || class2 == X86_64_X87_CLASS ++ || class2 == X86_64_X87UP_CLASS ++ || class2 == X86_64_COMPLEX_X87_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #6: Otherwise class SSE is used. */ ++ return X86_64_SSE_CLASS; ++} ++ ++/* Classify the argument of type TYPE and mode MODE. ++ CLASSES will be filled by the register class used to pass each word ++ of the operand. The number of words is returned. In case the parameter ++ should be passed in memory, 0 is returned. As a special case for zero ++ sized containers, classes[0] will be NO_CLASS and 1 is returned. ++ ++ See the x86-64 PS ABI for details. */ ++ ++static int ++classify_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[], ++ size_t byte_offset) ++{ ++ switch (type->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++#if 0 ++ if (byte_offset + type->size <= 4) ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ else ++ classes[0] = X86_64_INTEGER_CLASS; ++ ++ return 1; ++#else ++ { ++ int size = byte_offset + type->size; ++ ++ if (size <= 4) ++ { ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ return 1; ++ } ++ else if (size <= 8) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ return 1; ++ } ++ else if (size <= 12) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else if (size <= 16) ++ { ++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else ++ FFI_ASSERT (0); ++ } ++#endif ++ ++ case FFI_TYPE_FLOAT: ++ if (byte_offset == 0) ++ classes[0] = X86_64_SSESF_CLASS; ++ else ++ classes[0] = X86_64_SSE_CLASS; ++ ++ return 1; ++ ++ case FFI_TYPE_DOUBLE: ++ classes[0] = X86_64_SSEDF_CLASS; ++ return 1; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ classes[0] = X86_64_X87_CLASS; ++ classes[1] = X86_64_X87UP_CLASS; ++ return 2; ++ ++ case FFI_TYPE_STRUCT: ++ { ++ ffi_type** ptr; ++ int i; ++ enum x86_64_reg_class subclasses[MAX_CLASSES]; ++ const int UNITS_PER_WORD = 8; ++ int words = ++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ++ ++ /* If the struct is larger than 16 bytes, pass it on the stack. */ ++ if (type->size > 16) ++ return 0; ++ ++ for (i = 0; i < words; i++) ++ classes[i] = X86_64_NO_CLASS; ++ ++ /* Merge the fields of structure. */ ++ for (ptr = type->elements; *ptr != NULL; ptr++) ++ { ++ byte_offset = ALIGN(byte_offset, (*ptr)->alignment); ++ ++ int num = classify_argument(*ptr, subclasses, byte_offset % 8); ++ ++ if (num == 0) ++ return 0; ++ ++ int pos = byte_offset / 8; ++ ++ for (i = 0; i < num; i++) ++ { ++ classes[i + pos] = ++ merge_classes(subclasses[i], classes[i + pos]); ++ } ++ ++ byte_offset += (*ptr)->size; ++ } ++ ++ if (words > 2) ++ { ++ /* When size > 16 bytes, if the first one isn't ++ X86_64_SSE_CLASS or any other ones aren't ++ X86_64_SSEUP_CLASS, everything should be passed in ++ memory. */ ++ if (classes[0] != X86_64_SSE_CLASS) ++ return 0; ++ ++ for (i = 1; i < words; i++) ++ if (classes[i] != X86_64_SSEUP_CLASS) ++ return 0; ++ } ++ ++ ++ /* Final merger cleanup. */ ++ for (i = 0; i < words; i++) ++ { ++ /* If one class is MEMORY, everything should be passed in ++ memory. */ ++ if (classes[i] == X86_64_MEMORY_CLASS) ++ return 0; ++ ++ /* The X86_64_SSEUP_CLASS should be always preceded by ++ X86_64_SSE_CLASS. */ ++ if (classes[i] == X86_64_SSEUP_CLASS ++ && classes[i - 1] != X86_64_SSE_CLASS ++ && classes[i - 1] != X86_64_SSEUP_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ ++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ ++ if (classes[i] == X86_64_X87UP_CLASS ++ && classes[i - 1] != X86_64_X87_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ } ++ ++ return words; ++ } ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ return 0; /* Never reached. */ ++} ++ ++/* Examine the argument and return set number of register required in each ++ class. Return zero if parameter should be passed in memory, otherwise ++ the number of registers. */ ++static int ++examine_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[MAX_CLASSES], ++ _Bool in_return, ++ int* pngpr, ++ int* pnsse) ++{ ++ int n = classify_argument(type, classes, 0); ++ int ngpr = 0; ++ int nsse = 0; ++ int i; ++ ++ if (n == 0) ++ return 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ ngpr++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ nsse++; ++ break; ++ ++ case X86_64_NO_CLASS: ++ case X86_64_SSEUP_CLASS: ++ break; ++ ++ case X86_64_X87_CLASS: ++ case X86_64_X87UP_CLASS: ++ case X86_64_COMPLEX_X87_CLASS: ++ return in_return != 0; ++ ++ default: ++ abort(); ++ } ++ } ++ ++ *pngpr = ngpr; ++ *pnsse = nsse; ++ ++ return n; ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ int gprcount = 0; ++ int ssecount = 0; ++ int flags = cif->rtype->type; ++ int i, avn, n, ngpr, nsse; ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ size_t bytes; ++ ++ if (flags != FFI_TYPE_VOID) ++ { ++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value is passed in memory. A pointer to that ++ memory is the first argument. Allocate a register for it. */ ++ gprcount++; ++ ++ /* We don't have to do anything in asm for the return. */ ++ flags = FFI_TYPE_VOID; ++ } ++ else if (flags == FFI_TYPE_STRUCT) ++ { ++ /* Mark which registers the result appears in. */ ++ _Bool sse0 = SSE_CLASS_P(classes[0]); ++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]); ++ ++ if (sse0 && !sse1) ++ flags |= 1 << 8; ++ else if (!sse0 && sse1) ++ flags |= 1 << 9; ++ else if (sse0 && sse1) ++ flags |= 1 << 10; ++ ++ /* Mark the true size of the structure. */ ++ flags |= cif->rtype->size << 12; ++ } ++ } ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) ++ { ++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = cif->arg_types[i]->alignment; ++ ++ if (align < 8) ++ align = 8; ++ ++ bytes = ALIGN(bytes, align); ++ bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += ngpr; ++ ssecount += nsse; ++ } ++ } ++ ++ if (ssecount) ++ flags |= 1 << 11; ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ cif->bytes = ALIGN(bytes,8); ++ ++ return FFI_OK; ++} ++ ++void ++ffi_call( ++ ffi_cif* cif, ++ void (*fn)(), ++ void* rvalue, ++ void** avalue) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ char* stack; ++ char* argp; ++ ffi_type** arg_types; ++ int gprcount, ssecount, ngpr, nsse, i, avn; ++ _Bool ret_in_memory; ++ RegisterArgs* reg_args; ++ ++ /* Can't call 32-bit mode from 64-bit mode. */ ++ FFI_ASSERT(cif->abi == FFI_UNIX64); ++ ++ /* If the return value is a struct and we don't have a return value ++ address then we need to make one. Note the setting of flags to ++ VOID above in ffi_prep_cif_machdep. */ ++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT ++ && (cif->flags & 0xff) == FFI_TYPE_VOID); ++ ++ if (rvalue == NULL && ret_in_memory) ++ rvalue = alloca (cif->rtype->size); ++ ++ /* Allocate the space for the arguments, plus 4 words of temp space. */ ++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8); ++ reg_args = (RegisterArgs*)stack; ++ argp = stack + sizeof(RegisterArgs); ++ ++ gprcount = ssecount = 0; ++ ++ /* If the return value is passed in memory, add the pointer as the ++ first integer argument. */ ++ if (ret_in_memory) ++ reg_args->gpr[gprcount++] = (long) rvalue; ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ size_t size = arg_types[i]->size; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ memcpy (argp, avalue[i], size); ++ argp += size; ++ } ++ else ++ { /* The argument is passed entirely in registers. */ ++ char *a = (char *) avalue[i]; ++ int j; ++ ++ for (j = 0; j < n; j++, a += 8, size -= 8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ reg_args->gpr[gprcount] = 0; ++ switch (arg_types[i]->type) { ++ case FFI_TYPE_SINT8: ++ { ++ int8_t shortval = *(int8_t*)a; ++ int64_t actval = (int64_t)shortval; ++ reg_args->gpr[gprcount] = actval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ break; ++ } ++ ++ case FFI_TYPE_SINT16: ++ { ++ int16_t shortval = *(int16_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_SINT32: ++ { ++ int32_t shortval = *(int32_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT8: ++ { ++ u_int8_t shortval = *(u_int8_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ reg_args->gpr[gprcount] = actval; ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ { ++ u_int16_t shortval = *(u_int16_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT32: ++ { ++ u_int32_t shortval = *(u_int32_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ default: ++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); ++ reg_args->gpr[gprcount] = *(int64_t*)a; ++ } ++ gprcount++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSEDF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT64 *) a; ++ break; ++ ++ case X86_64_SSESF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT32 *) a; ++ break; ++ ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++ ++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs), ++ cif->flags, rvalue, fn, ssecount); ++} ++ ++extern void ffi_closure_unix64(void); ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ if (cif->abi != FFI_UNIX64) ++ return FFI_BAD_ABI; ++ ++ volatile unsigned short* tramp = ++ (volatile unsigned short*)&closure->tramp[0]; ++ ++ tramp[0] = 0xbb49; /* mov , %r11 */ ++ *(void* volatile*)&tramp[1] = ffi_closure_unix64; ++ tramp[5] = 0xba49; /* mov , %r10 */ ++ *(void* volatile*)&tramp[6] = closure; ++ ++ /* Set the carry bit if the function uses any sse registers. ++ This is clc or stc, together with the first byte of the jmp. */ ++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; ++ tramp[11] = 0xe3ff; /* jmp *%r11 */ ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wmissing-prototypes" ++int ++ffi_closure_unix64_inner( ++ ffi_closure* closure, ++ void* rvalue, ++ RegisterArgs* reg_args, ++ char* argp) ++#pragma clang diagnostic pop ++{ ++ ffi_cif* cif = closure->cif; ++ void** avalue = alloca(cif->nargs * sizeof(void *)); ++ ffi_type** arg_types; ++ long i, avn; ++ int gprcount = 0; ++ int ssecount = 0; ++ int ngpr, nsse; ++ int ret; ++ ++ ret = cif->rtype->type; ++ ++ if (ret != FFI_TYPE_VOID) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value goes in memory. Arrange for the closure ++ return value to go directly back to the original caller. */ ++ rvalue = (void *) reg_args->gpr[gprcount++]; ++ ++ /* We don't have to do anything in asm for the return. */ ++ ret = FFI_TYPE_VOID; ++ } ++ else if (ret == FFI_TYPE_STRUCT && n == 2) ++ { ++ /* Mark which register the second word of the structure goes in. */ ++ _Bool sse0 = SSE_CLASS_P (classes[0]); ++ _Bool sse1 = SSE_CLASS_P (classes[1]); ++ ++ if (!sse0 && sse1) ++ ret |= 1 << 8; ++ else if (sse0 && !sse1) ++ ret |= 1 << 9; ++ } ++ } ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ avalue[i] = argp; ++ argp += arg_types[i]->size; ++ } ++ ++#if !defined(X86_DARWIN) ++ /* If the argument is in a single register, or two consecutive ++ registers, then we can use that address directly. */ ++ else if (n == 1 || (n == 2 && ++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1]))) ++ { ++ // The argument is in a single register. ++ if (SSE_CLASS_P (classes[0])) ++ { ++ avalue[i] = ®_args->sse[ssecount]; ++ ssecount += n; ++ } ++ else ++ { ++ avalue[i] = ®_args->gpr[gprcount]; ++ gprcount += n; ++ } ++ } ++#endif ++ ++ /* Otherwise, allocate space to make them consecutive. */ ++ else ++ { ++ char *a = alloca (16); ++ int j; ++ ++ avalue[i] = a; ++ ++ for (j = 0; j < n; j++, a += 8) ++ { ++ if (SSE_CLASS_P (classes[j])) ++ memcpy (a, ®_args->sse[ssecount++], 8); ++ else ++ memcpy (a, ®_args->gpr[gprcount++], 8); ++ } ++ } ++ } ++ ++ /* Invoke the closure. */ ++ closure->fun (cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell assembly how to perform return type promotions. */ ++ return ret; ++} ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +new file mode 100644 +index 0000000..706ea0f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +@@ -0,0 +1,438 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ++ Copyright (c) 2002 Ranjit Mathew ++ Copyright (c) 2002 Bo Thorsen ++ Copyright (c) 2002 Roger Sayle ++ ++ x86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments */ ++ ++void ffi_prep_args(char *stack, extended_cif *ecif); ++ ++void ffi_prep_args(char *stack, extended_cif *ecif) ++{ ++ 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) ++ { ++ *(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) ++{ ++ /* 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_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; ++ } ++ ++#ifdef X86_DARWIN ++ cif->bytes = (cif->bytes + 15) & ~0xF; ++#endif ++ ++ return FFI_OK; ++} ++ ++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 *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); ++ ++#endif /* X86_WIN32 */ ++ ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++ ++/** private members **/ ++ ++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 */ ++ ++unsigned int FFI_HIDDEN ++ffi_closure_SYSV_inner (closure, respp, args) ++ffi_closure *closure; ++void **respp; ++void *args; ++{ ++ // 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 - (__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) ++{ ++ if (cif->abi != FFI_SYSV) ++ return FFI_BAD_ABI; ++ ++ 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 ++ ++ffi_status ++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) ++{ ++ 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) ++{ ++ 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 *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++ ++#ifdef X86_WIN32 ++extern void ++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++#endif /* X86_WIN32 */ ++ ++void ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++#endif ++#endif // __i386__ +diff --git ./setup.py ./setup.py +index 46b92fe..2bf6b4b 100644 +--- ./setup.py ++++ ./setup.py +@@ -98,8 +98,14 @@ class PyBuildExt(build_ext): + self.detect_modules() + + # Remove modules that are present on the disabled list +- self.extensions = [ext for ext in self.extensions +- if ext.name not in disabled_module_list] ++ extensions = [ext for ext in self.extensions ++ if ext.name not in disabled_module_list] ++ # move ctypes to the end, it depends on other modules ++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) ++ if "_ctypes" in ext_map: ++ ctypes = extensions.pop(ext_map["_ctypes"]) ++ extensions.append(ctypes) ++ self.extensions = extensions + + # Fix up the autodetected modules, prefixing all the source files + # with Modules/ and adding Python's include directory to the path. +@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext): + # *** Uncomment these for TOGL extension only: + # -lGL -lGLU -lXext -lXmu \ + ++ def configure_ctypes_darwin(self, ext): ++ # Darwin (OS X) uses preconfigured files, in ++ # the Modules/_ctypes/libffi_osx directory. ++ srcdir = sysconfig.get_config_var('srcdir') ++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', ++ '_ctypes', 'libffi_osx')) ++ sources = [os.path.join(ffi_srcdir, p) ++ for p in ['ffi.c', ++ 'x86/darwin64.S', ++ 'x86/x86-darwin.S', ++ 'x86/x86-ffi_darwin.c', ++ 'x86/x86-ffi64.c', ++ 'powerpc/ppc-darwin.S', ++ 'powerpc/ppc-darwin_closure.S', ++ 'powerpc/ppc-ffi_darwin.c', ++ 'powerpc/ppc64-darwin_closure.S', ++ ]] ++ ++ # Add .S (preprocessed assembly) to C compiler source extensions. ++ self.compiler.src_extensions.append('.S') ++ ++ include_dirs = [os.path.join(ffi_srcdir, 'include'), ++ os.path.join(ffi_srcdir, 'powerpc')] ++ ext.include_dirs.extend(include_dirs) ++ ext.sources.extend(sources) ++ return True ++ + def configure_ctypes(self, ext): + if not self.use_system_libffi: +- (srcdir,) = sysconfig.get_config_vars('srcdir') ++ if sys.platform == 'darwin': ++ return self.configure_ctypes_darwin(ext) ++ ++ srcdir = sysconfig.get_config_var('srcdir') + ffi_builddir = os.path.join(self.build_temp, 'libffi') + ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + '_ctypes', 'libffi')) +@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext): + ffi_configfile): + from distutils.dir_util import mkpath + mkpath(ffi_builddir) +- config_args = [] ++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() ++ if (('--host=' in arg) or ('--build=' in arg))] ++ if not self.verbose: ++ config_args.append("-q") + + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. +@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext): + self.compiler.src_extensions.append('.S') + + include_dirs = [os.path.join(ffi_builddir, 'include'), +- ffi_builddir, ffi_srcdir] ++ ffi_builddir, ++ os.path.join(ffi_srcdir, 'src')] + extra_compile_args = fficonfig['ffi_cflags'].split() + +- ext.sources.extend(fficonfig['ffi_sources']) ++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in ++ fficonfig['ffi_sources']) + ext.include_dirs.extend(include_dirs) + ext.extra_compile_args.extend(extra_compile_args) + return True +@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext): + + if sys.platform == 'darwin': + sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + # XXX Is this still needed? + ## extra_link_args.extend(['-read_only_relocs', 'warning']) +@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext): + if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = find_file('ffi.h', [], inc_dirs) ++ if sys.platform == 'darwin': ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') ++ ++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] ++ if not ffi_inc or ffi_inc[0] == '': ++ ffi_inc = find_file('ffi.h', [], inc_dirs) + if ffi_inc is not None: + ffi_h = ffi_inc[0] + '/ffi.h' + fp = open(ffi_h) diff --git a/plugins/python-build/share/python-build/patches/2.5.6/Python-2.5.6/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5.6/Python-2.5.6/004_osx_libffi.patch new file mode 100644 index 00000000..cd500771 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/2.5.6/Python-2.5.6/004_osx_libffi.patch @@ -0,0 +1,6881 @@ +diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE +new file mode 100644 +index 0000000..f591795 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/LICENSE +@@ -0,0 +1,20 @@ ++libffi - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++``Software''), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice shall be included ++in all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++OTHER DEALINGS IN THE SOFTWARE. +diff --git ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README +new file mode 100644 +index 0000000..1fc2747 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README +@@ -0,0 +1,500 @@ ++This directory contains the libffi package, which is not part of GCC but ++shipped with GCC as convenience. ++ ++Status ++====== ++ ++libffi-2.00 has not been released yet! This is a development snapshot! ++ ++libffi-1.20 was released on October 5, 1998. Check the libffi web ++page for updates: . ++ ++ ++What is libffi? ++=============== ++ ++Compilers for high level languages generate code that follow certain ++conventions. These conventions are necessary, in part, for separate ++compilation to work. One such convention is the "calling ++convention". The "calling convention" is essentially a set of ++assumptions made by the compiler about where function arguments will ++be found on entry to a function. A "calling convention" also specifies ++where the return value for a function is found. ++ ++Some programs may not know at the time of compilation what arguments ++are to be passed to a function. For instance, an interpreter may be ++told at run-time about the number and types of arguments used to call ++a given function. Libffi can be used in such programs to provide a ++bridge from the interpreter program to compiled code. ++ ++The libffi library provides a portable, high level programming ++interface to various calling conventions. This allows a programmer to ++call any function specified by a call interface description at run ++time. ++ ++Ffi stands for Foreign Function Interface. A foreign function ++interface is the popular name for the interface that allows code ++written in one language to call code written in another language. The ++libffi library really only provides the lowest, machine dependent ++layer of a fully featured foreign function interface. A layer must ++exist above libffi that handles type conversions for values passed ++between the two languages. ++ ++ ++Supported Platforms and Prerequisites ++===================================== ++ ++Libffi has been ported to: ++ ++ SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) ++ ++ Irix 5.3 & 6.2 (System V/o32 & n32) ++ ++ Intel x86 - Linux (System V ABI) ++ ++ Alpha - Linux and OSF/1 ++ ++ m68k - Linux (System V ABI) ++ ++ PowerPC - Linux (System V ABI, Darwin, AIX) ++ ++ ARM - Linux (System V ABI) ++ ++Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are ++that other versions will work. Libffi has also been built and tested ++with the SGI compiler tools. ++ ++On PowerPC, the tests failed (see the note below). ++ ++You must use GNU make to build libffi. SGI's make will not work. ++Sun's probably won't either. ++ ++If you port libffi to another platform, please let me know! I assume ++that some will be easy (x86 NetBSD), and others will be more difficult ++(HP). ++ ++ ++Installing libffi ++================= ++ ++[Note: before actually performing any of these installation steps, ++ you may wish to read the "Platform Specific Notes" below.] ++ ++First you must configure the distribution for your particular ++system. Go to the directory you wish to build libffi in and run the ++"configure" program found in the root directory of the libffi source ++distribution. ++ ++You may want to tell configure where to install the libffi library and ++header files. To do that, use the --prefix configure switch. Libffi ++will install under /usr/local by default. ++ ++If you want to enable extra run-time debugging checks use the the ++--enable-debug configure switch. This is useful when your program dies ++mysteriously while using libffi. ++ ++Another useful configure switch is --enable-purify-safety. Using this ++will add some extra code which will suppress certain warnings when you ++are using Purify with libffi. Only use this switch when using ++Purify, as it will slow down the library. ++ ++Configure has many other options. Use "configure --help" to see them all. ++ ++Once configure has finished, type "make". Note that you must be using ++GNU make. SGI's make will not work. Sun's probably won't either. ++You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. ++ ++To ensure that libffi is working as advertised, type "make test". ++ ++To install the library and header files, type "make install". ++ ++ ++Using libffi ++============ ++ ++ The Basics ++ ---------- ++ ++Libffi assumes that you have a pointer to the function you wish to ++call and that you know the number and types of arguments to pass it, ++as well as the return type of the function. ++ ++The first thing you must do is create an ffi_cif object that matches ++the signature of the function you wish to call. The cif in ffi_cif ++stands for Call InterFace. To prepare a call interface object, use the ++following function: ++ ++ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, ++ unsigned int nargs, ++ ffi_type *rtype, ffi_type **atypes); ++ ++ CIF is a pointer to the call interface object you wish ++ to initialize. ++ ++ ABI is an enum that specifies the calling convention ++ to use for the call. FFI_DEFAULT_ABI defaults ++ to the system's native calling convention. Other ++ ABI's may be used with care. They are system ++ specific. ++ ++ NARGS is the number of arguments this function accepts. ++ libffi does not yet support vararg functions. ++ ++ RTYPE is a pointer to an ffi_type structure that represents ++ the return type of the function. Ffi_type objects ++ describe the types of values. libffi provides ++ ffi_type objects for many of the native C types: ++ signed int, unsigned int, signed char, unsigned char, ++ etc. There is also a pointer ffi_type object and ++ a void ffi_type. Use &ffi_type_void for functions that ++ don't return values. ++ ++ ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. ++ If NARGS is 0, this is ignored. ++ ++ ++ffi_prep_cif will return a status code that you are responsible ++for checking. It will be one of the following: ++ ++ FFI_OK - All is good. ++ ++ FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif ++ came across is bad. ++ ++ ++Before making the call, the VALUES vector should be initialized ++with pointers to the appropriate argument values. ++ ++To call the the function using the initialized ffi_cif, use the ++ffi_call function: ++ ++void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); ++ ++ CIF is a pointer to the ffi_cif initialized specifically ++ for this function. ++ ++ FN is a pointer to the function you want to call. ++ ++ RVALUE is a pointer to a chunk of memory that is to hold the ++ result of the function call. Currently, it must be ++ at least one word in size (except for the n32 version ++ under Irix 6.x, which must be a pointer to an 8 byte ++ aligned value (a long long). It must also be at least ++ word aligned (depending on the return type, and the ++ system's alignment requirements). If RTYPE is ++ &ffi_type_void, this is ignored. If RVALUE is NULL, ++ the return value is discarded. ++ ++ AVALUES is a vector of void* that point to the memory locations ++ holding the argument values for a call. ++ If NARGS is 0, this is ignored. ++ ++ ++If you are expecting a return value from FN it will have been stored ++at RVALUE. ++ ++ ++ ++ An Example ++ ---------- ++ ++Here is a trivial example that calls puts() a few times. ++ ++ #include ++ #include ++ ++ int main() ++ { ++ ffi_cif cif; ++ ffi_type *args[1]; ++ void *values[1]; ++ char *s; ++ int rc; ++ ++ /* Initialize the argument info vectors */ ++ args[0] = &ffi_type_uint; ++ values[0] = &s; ++ ++ /* Initialize the cif */ ++ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, ++ &ffi_type_uint, args) == FFI_OK) ++ { ++ s = "Hello World!"; ++ ffi_call(&cif, puts, &rc, values); ++ /* rc now holds the result of the call to puts */ ++ ++ /* values holds a pointer to the function's arg, so to ++ call puts() again all we need to do is change the ++ value of s */ ++ s = "This is cool!"; ++ ffi_call(&cif, puts, &rc, values); ++ } ++ ++ return 0; ++ } ++ ++ ++ ++ Aggregate Types ++ --------------- ++ ++Although libffi has no special support for unions or bit-fields, it is ++perfectly happy passing structures back and forth. You must first ++describe the structure to libffi by creating a new ffi_type object ++for it. Here is the definition of ffi_type: ++ ++ typedef struct _ffi_type ++ { ++ unsigned size; ++ short alignment; ++ short type; ++ struct _ffi_type **elements; ++ } ffi_type; ++ ++All structures must have type set to FFI_TYPE_STRUCT. You may set ++size and alignment to 0. These will be calculated and reset to the ++appropriate values by ffi_prep_cif(). ++ ++elements is a NULL terminated array of pointers to ffi_type objects ++that describe the type of the structure elements. These may, in turn, ++be structure elements. ++ ++The following example initializes a ffi_type object representing the ++tm struct from Linux's time.h: ++ ++ struct tm { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++ /* Those are for future use. */ ++ long int __tm_gmtoff__; ++ __const char *__tm_zone__; ++ }; ++ ++ { ++ ffi_type tm_type; ++ ffi_type *tm_type_elements[12]; ++ int i; ++ ++ tm_type.size = tm_type.alignment = 0; ++ tm_type.elements = &tm_type_elements; ++ ++ for (i = 0; i < 9; i++) ++ tm_type_elements[i] = &ffi_type_sint; ++ ++ tm_type_elements[9] = &ffi_type_slong; ++ tm_type_elements[10] = &ffi_type_pointer; ++ tm_type_elements[11] = NULL; ++ ++ /* tm_type can now be used to represent tm argument types and ++ return types for ffi_prep_cif() */ ++ } ++ ++ ++ ++Platform Specific Notes ++======================= ++ ++ Intel x86 ++ --------- ++ ++There are no known problems with the x86 port. ++ ++ Sun SPARC - SunOS 4.1.3 & Solaris 2.x ++ ------------------------------------- ++ ++You must use GNU Make to build libffi on Sun platforms. ++ ++ MIPS - Irix 5.3 & 6.x ++ --------------------- ++ ++Irix 6.2 and better supports three different calling conventions: o32, ++n32 and n64. Currently, libffi only supports both o32 and n32 under ++Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be ++configured for whichever calling convention it was built for. ++ ++By default, the configure script will try to build libffi with the GNU ++development tools. To build libffi with the SGI development tools, set ++the environment variable CC to either "cc -32" or "cc -n32" before ++running configure under Irix 6.x (depending on whether you want an o32 ++or n32 library), or just "cc" for Irix 5.3. ++ ++With the n32 calling convention, when returning structures smaller ++than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. ++Here's one way of forcing this: ++ ++ double struct_storage[2]; ++ my_small_struct *s = (my_small_struct *) struct_storage; ++ /* Use s for RVALUE */ ++ ++If you don't do this you are liable to get spurious bus errors. ++ ++"long long" values are not supported yet. ++ ++You must use GNU Make to build libffi on SGI platforms. ++ ++ ARM - System V ABI ++ ------------------ ++ ++The ARM port was performed on a NetWinder running ARM Linux ELF ++(2.0.31) and gcc 2.8.1. ++ ++ ++ ++ PowerPC System V ABI ++ -------------------- ++ ++There are two `System V ABI's which libffi implements for PowerPC. ++They differ only in how small structures are returned from functions. ++ ++In the FFI_SYSV version, structures that are 8 bytes or smaller are ++returned in registers. This is what GCC does when it is configured ++for solaris, and is what the System V ABI I have (dated September ++1995) says. ++ ++In the FFI_GCC_SYSV version, all structures are returned the same way: ++by passing a pointer as the first argument to the function. This is ++what GCC does when it is configured for linux or a generic sysv ++target. ++ ++EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a ++inconsistency with the SysV ABI: When a procedure is called with many ++floating-point arguments, some of them get put on the stack. They are ++all supposed to be stored in double-precision format, even if they are ++only single-precision, but EGCS stores single-precision arguments as ++single-precision anyway. This causes one test to fail (the `many ++arguments' test). ++ ++ ++What's With The Crazy Comments? ++=============================== ++ ++You might notice a number of cryptic comments in the code, delimited ++by /*@ and @*/. These are annotations read by the program LCLint, a ++tool for statically checking C programs. You can read all about it at ++. ++ ++ ++History ++======= ++ ++1.20 Oct-5-98 ++ Raffaele Sena produces ARM port. ++ ++1.19 Oct-5-98 ++ Fixed x86 long double and long long return support. ++ m68k bug fixes from Andreas Schwab. ++ Patch for DU assembler compatibility for the Alpha from Richard ++ Henderson. ++ ++1.18 Apr-17-98 ++ Bug fixes and MIPS configuration changes. ++ ++1.17 Feb-24-98 ++ Bug fixes and m68k port from Andreas Schwab. PowerPC port from ++ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. ++ ++1.16 Feb-11-98 ++ Richard Henderson produces Alpha port. ++ ++1.15 Dec-4-97 ++ Fixed an n32 ABI bug. New libtool, auto* support. ++ ++1.14 May-13-97 ++ libtool is now used to generate shared and static libraries. ++ Fixed a minor portability problem reported by Russ McManus ++ . ++ ++1.13 Dec-2-96 ++ Added --enable-purify-safety to keep Purify from complaining ++ about certain low level code. ++ Sparc fix for calling functions with < 6 args. ++ Linux x86 a.out fix. ++ ++1.12 Nov-22-96 ++ Added missing ffi_type_void, needed for supporting void return ++ types. Fixed test case for non MIPS machines. Cygnus Support ++ is now Cygnus Solutions. ++ ++1.11 Oct-30-96 ++ Added notes about GNU make. ++ ++1.10 Oct-29-96 ++ Added configuration fix for non GNU compilers. ++ ++1.09 Oct-29-96 ++ Added --enable-debug configure switch. Clean-ups based on LCLint ++ feedback. ffi_mips.h is always installed. Many configuration ++ fixes. Fixed ffitest.c for sparc builds. ++ ++1.08 Oct-15-96 ++ Fixed n32 problem. Many clean-ups. ++ ++1.07 Oct-14-96 ++ Gordon Irlam rewrites v8.S again. Bug fixes. ++ ++1.06 Oct-14-96 ++ Gordon Irlam improved the sparc port. ++ ++1.05 Oct-14-96 ++ Interface changes based on feedback. ++ ++1.04 Oct-11-96 ++ Sparc port complete (modulo struct passing bug). ++ ++1.03 Oct-10-96 ++ Passing struct args, and returning struct values works for ++ all architectures/calling conventions. Expanded tests. ++ ++1.02 Oct-9-96 ++ Added SGI n32 support. Fixed bugs in both o32 and Linux support. ++ Added "make test". ++ ++1.01 Oct-8-96 ++ Fixed float passing bug in mips version. Restructured some ++ of the code. Builds cleanly with SGI tools. ++ ++1.00 Oct-7-96 ++ First release. No public announcement. ++ ++ ++Authors & Credits ++================= ++ ++libffi was written by Anthony Green . ++ ++Portions of libffi were derived from Gianni Mariani's free gencall ++library for Silicon Graphics machines. ++ ++The closure mechanism was designed and implemented by Kresten Krab ++Thorup. ++ ++The Sparc port was derived from code contributed by the fine folks at ++Visible Decisions Inc . Further enhancements were ++made by Gordon Irlam at Cygnus Solutions . ++ ++The Alpha port was written by Richard Henderson at Cygnus Solutions. ++ ++Andreas Schwab ported libffi to m68k Linux and provided a number of ++bug fixes. ++ ++Geoffrey Keating ported libffi to the PowerPC. ++ ++Raffaele Sena ported libffi to the ARM. ++ ++Jesper Skov and Andrew Haley both did more than their fair share of ++stepping through the code and tracking down bugs. ++ ++Thanks also to Tom Tromey for bug fixes and configuration help. ++ ++Thanks to Jim Blandy, who provided some useful feedback on the libffi ++interface. ++ ++If you have a problem, or have found a bug, please send a note to ++green@cygnus.com. +diff --git ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc +new file mode 100644 +index 0000000..405d85f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README.pyobjc +@@ -0,0 +1,5 @@ ++This directory contains a slightly modified version of libffi, extracted from ++the GCC source-tree. ++ ++The only modifications are those that are necessary to compile libffi using ++the Apple provided compiler and outside of the GCC source tree. +diff --git ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c +new file mode 100644 +index 0000000..bf42093 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/ffi.c +@@ -0,0 +1,226 @@ ++/* ----------------------------------------------------------------------- ++ prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++/* Round up to FFI_SIZEOF_ARG. */ ++#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) ++ ++/* Perform machine independent initialization of aggregate type ++ specifications. */ ++ ++static ffi_status ++initialize_aggregate( ++/*@out@*/ ffi_type* arg) ++{ ++/*@-usedef@*/ ++ ++ if (arg == NULL || arg->elements == NULL || ++ arg->size != 0 || arg->alignment != 0) ++ return FFI_BAD_TYPEDEF; ++ ++ ffi_type** ptr = &(arg->elements[0]); ++ ++ while ((*ptr) != NULL) ++ { ++ if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#ifdef POWERPC_DARWIN ++ int curalign = (*ptr)->alignment; ++ ++ if (ptr != &(arg->elements[0])) ++ { ++ if (curalign > 4 && curalign != 16) ++ curalign = 4; ++ } ++ ++ arg->size = ALIGN(arg->size, curalign); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > curalign) ? ++ arg->alignment : curalign; ++#else ++ arg->size = ALIGN(arg->size, (*ptr)->alignment); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > (*ptr)->alignment) ? ++ arg->alignment : (*ptr)->alignment; ++#endif ++ ++ ptr++; ++ } ++ ++ /* Structure size includes tail padding. This is important for ++ structures that fit in one register on ABIs like the PowerPC64 ++ Linux ABI that right justify small structs in a register. ++ It's also needed for nested structure layout, for example ++ struct A { long a; char b; }; struct B { struct A x; char y; }; ++ should find y at an offset of 2*sizeof(long) and result in a ++ total size of 3*sizeof(long). */ ++ arg->size = ALIGN(arg->size, arg->alignment); ++ ++ if (arg->size == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ return FFI_OK; ++ ++/*@=usedef@*/ ++} ++ ++#ifndef __CRIS__ ++/* The CRIS ABI specifies structure elements to have byte ++ alignment only, so it completely overrides this functions, ++ which assumes "natural" alignment and padding. */ ++ ++/* Perform machine independent ffi_cif preparation, then call ++ machine dependent routine. */ ++ ++#if defined(X86_DARWIN) ++ ++static inline bool ++struct_on_stack( ++ int size) ++{ ++ if (size > 8) ++ return true; ++ ++ /* This is not what the ABI says, but is what is really implemented */ ++ switch (size) ++ { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ return false; ++ ++ default: ++ return true; ++ } ++} ++ ++#endif // defined(X86_DARWIN) ++ ++// Arguments' ffi_type->alignment must be nonzero. ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes) ++{ ++ if (cif == NULL) ++ return FFI_BAD_TYPEDEF; ++ ++ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI) ++ return FFI_BAD_ABI; ++ ++ unsigned int bytes = 0; ++ unsigned int i; ++ ffi_type** ptr; ++ ++ cif->abi = abi; ++ cif->arg_types = atypes; ++ cif->nargs = nargs; ++ cif->rtype = rtype; ++ cif->flags = 0; ++ ++ /* Initialize the return type if necessary */ ++ /*@-usedef@*/ ++ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ /*@=usedef@*/ ++ ++ /* Perform a sanity check on the return type */ ++ FFI_ASSERT_VALID_TYPE(cif->rtype); ++ ++ /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ ++#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA ++ /* Make space for the return structure pointer */ ++ if (cif->rtype->type == FFI_TYPE_STRUCT ++#ifdef SPARC ++ && (cif->abi != FFI_V9 || cif->rtype->size > 32) ++#endif ++#ifdef X86_DARWIN ++ && (struct_on_stack(cif->rtype->size)) ++#endif ++ ) ++ bytes = STACK_ARG_SIZE(sizeof(void*)); ++#endif ++ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ /* Initialize any uninitialized aggregate type definitions */ ++ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ if ((*ptr)->alignment == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type, do this ++ check after the initialization. */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#if defined(X86_DARWIN) ++ { ++ int align = (*ptr)->alignment; ++ ++ if (align > 4) ++ align = 4; ++ ++ if ((align - 1) & bytes) ++ bytes = ALIGN(bytes, align); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#elif !defined __x86_64__ && !defined S390 && !defined PA ++#ifdef SPARC ++ if (((*ptr)->type == FFI_TYPE_STRUCT ++ && ((*ptr)->size > 16 || cif->abi != FFI_V9)) ++ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE ++ && cif->abi != FFI_V9)) ++ bytes += sizeof(void*); ++ else ++#endif ++ { ++ /* Add any padding if necessary */ ++ if (((*ptr)->alignment - 1) & bytes) ++ bytes = ALIGN(bytes, (*ptr)->alignment); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#endif ++ } ++ ++ cif->bytes = bytes; ++ ++ /* Perform machine dependent cif processing */ ++ return ffi_prep_cif_machdep(cif); ++} ++#endif /* not __CRIS__ */ +diff --git ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h +new file mode 100644 +index 0000000..c104a5c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi.h +@@ -0,0 +1,355 @@ ++/* -----------------------------------------------------------------*-C-*- ++ libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++/* ------------------------------------------------------------------- ++ The basic API is described in the README file. ++ ++ The raw API is designed to bypass some of the argument packing ++ and unpacking on architectures for which it can be avoided. ++ ++ The closure API allows interpreted functions to be packaged up ++ inside a C function pointer, so that they can be called as C functions, ++ with no understanding on the client side that they are interpreted. ++ It can also be used in other cases in which it is necessary to package ++ up a user specified parameter and a function pointer as a single ++ function pointer. ++ ++ The closure API must be implemented in order to get its functionality, ++ e.g. for use by gij. Routines are provided to emulate the raw API ++ if the underlying platform doesn't allow faster implementation. ++ ++ More details on the raw and closure API can be found in: ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html ++ ++ and ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html ++ -------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_H ++#define LIBFFI_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Specify which architecture libffi is configured for. */ ++#ifdef MACOSX ++# if defined(__i386__) || defined(__x86_64__) ++# define X86_DARWIN ++# elif defined(__ppc__) || defined(__ppc64__) ++# define POWERPC_DARWIN ++# else ++# error "Unsupported MacOS X CPU type" ++# endif ++#else ++#error "Unsupported OS type" ++#endif ++ ++/* ---- System configuration information --------------------------------- */ ++ ++#include "ffitarget.h" ++#include "fficonfig.h" ++ ++#ifndef LIBFFI_ASM ++ ++#include ++#include ++ ++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). ++ But we can find it either under the correct ANSI name, or under GNU ++ C's internal name. */ ++#ifdef LONG_LONG_MAX ++# define FFI_LONG_LONG_MAX LONG_LONG_MAX ++#else ++# ifdef LLONG_MAX ++# define FFI_LONG_LONG_MAX LLONG_MAX ++# else ++# ifdef __GNUC__ ++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ ++# endif ++# endif ++#endif ++ ++#if SCHAR_MAX == 127 ++# define ffi_type_uchar ffi_type_uint8 ++# define ffi_type_schar ffi_type_sint8 ++#else ++#error "char size not supported" ++#endif ++ ++#if SHRT_MAX == 32767 ++# define ffi_type_ushort ffi_type_uint16 ++# define ffi_type_sshort ffi_type_sint16 ++#elif SHRT_MAX == 2147483647 ++# define ffi_type_ushort ffi_type_uint32 ++# define ffi_type_sshort ffi_type_sint32 ++#else ++#error "short size not supported" ++#endif ++ ++#if INT_MAX == 32767 ++# define ffi_type_uint ffi_type_uint16 ++# define ffi_type_sint ffi_type_sint16 ++#elif INT_MAX == 2147483647 ++# define ffi_type_uint ffi_type_uint32 ++# define ffi_type_sint ffi_type_sint32 ++#elif INT_MAX == 9223372036854775807 ++# define ffi_type_uint ffi_type_uint64 ++# define ffi_type_sint ffi_type_sint64 ++#else ++#error "int size not supported" ++#endif ++ ++#define ffi_type_ulong ffi_type_uint64 ++#define ffi_type_slong ffi_type_sint64 ++ ++#if LONG_MAX == 2147483647 ++# if FFI_LONG_LONG_MAX != 9223372036854775807 ++# error "no 64-bit data type supported" ++# endif ++#elif LONG_MAX != 9223372036854775807 ++#error "long size not supported" ++#endif ++ ++/* The closure code assumes that this works on pointers, i.e. a size_t ++ can hold a pointer. */ ++ ++typedef struct _ffi_type { ++ size_t size; ++ unsigned short alignment; ++ unsigned short type; ++/*@null@*/ struct _ffi_type** elements; ++} ffi_type; ++ ++/* These are defined in types.c */ ++extern ffi_type ffi_type_void; ++extern ffi_type ffi_type_uint8; ++extern ffi_type ffi_type_sint8; ++extern ffi_type ffi_type_uint16; ++extern ffi_type ffi_type_sint16; ++extern ffi_type ffi_type_uint32; ++extern ffi_type ffi_type_sint32; ++extern ffi_type ffi_type_uint64; ++extern ffi_type ffi_type_sint64; ++extern ffi_type ffi_type_float; ++extern ffi_type ffi_type_double; ++extern ffi_type ffi_type_longdouble; ++extern ffi_type ffi_type_pointer; ++ ++typedef enum ffi_status { ++ FFI_OK = 0, ++ FFI_BAD_TYPEDEF, ++ FFI_BAD_ABI ++} ffi_status; ++ ++typedef unsigned FFI_TYPE; ++ ++typedef struct ffi_cif { ++ ffi_abi abi; ++ unsigned nargs; ++/*@dependent@*/ ffi_type** arg_types; ++/*@dependent@*/ ffi_type* rtype; ++ unsigned bytes; ++ unsigned flags; ++#ifdef FFI_EXTRA_CIF_FIELDS ++ FFI_EXTRA_CIF_FIELDS; ++#endif ++} ffi_cif; ++ ++/* ---- Definitions for the raw API -------------------------------------- */ ++ ++#ifndef FFI_SIZEOF_ARG ++# if LONG_MAX == 2147483647 ++# define FFI_SIZEOF_ARG 4 ++# elif LONG_MAX == 9223372036854775807 ++# define FFI_SIZEOF_ARG 8 ++# endif ++#endif ++ ++typedef union { ++ ffi_sarg sint; ++ ffi_arg uint; ++ float flt; ++ char data[FFI_SIZEOF_ARG]; ++ void* ptr; ++} ffi_raw; ++ ++void ++ffi_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_raw_size( ++ ffi_cif* cif); ++ ++/* This is analogous to the raw API, except it uses Java parameter ++ packing, even on 64-bit machines. I.e. on 64-bit machines ++ longs and doubles are followed by an empty 64-bit word. */ ++void ++ffi_java_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_java_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_java_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_java_raw_size( ++ ffi_cif* cif); ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#if FFI_CLOSURES ++ ++typedef struct ffi_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ void (*fun)(ffi_cif*,void*,void**,void*); ++ void* user_data; ++} ffi_closure; ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void* user_data); ++ ++void ffi_closure_free(void *); ++void *ffi_closure_alloc (size_t size, void **code); ++ ++typedef struct ffi_raw_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ ++#if !FFI_NATIVE_RAW_API ++ /* if this is enabled, then a raw closure has the same layout ++ as a regular closure. We use this to install an intermediate ++ handler to do the transaltion, void** -> ffi_raw*. */ ++ void (*translate_args)(ffi_cif*,void*,void**,void*); ++ void* this_closure; ++#endif ++ ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*); ++ void* user_data; ++} ffi_raw_closure; ++ ++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_status ++ffi_prep_java_raw_closure( ++ ffi_raw_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*), ++ void* user_data); ++ ++#endif // FFI_CLOSURES ++ ++/* ---- Public interface definition -------------------------------------- */ ++ ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes); ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ void** avalue); ++ ++/* Useful for eliminating compiler warnings */ ++#define FFI_FN(f) ((void (*)(void))f) ++ ++#endif // #ifndef LIBFFI_ASM ++/* ---- Definitions shared with assembly code ---------------------------- */ ++ ++/* If these change, update src/mips/ffitarget.h. */ ++#define FFI_TYPE_VOID 0 ++#define FFI_TYPE_INT 1 ++#define FFI_TYPE_FLOAT 2 ++#define FFI_TYPE_DOUBLE 3 ++ ++#ifdef HAVE_LONG_DOUBLE ++# define FFI_TYPE_LONGDOUBLE 4 ++#else ++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE ++#endif ++ ++#define FFI_TYPE_UINT8 5 ++#define FFI_TYPE_SINT8 6 ++#define FFI_TYPE_UINT16 7 ++#define FFI_TYPE_SINT16 8 ++#define FFI_TYPE_UINT32 9 ++#define FFI_TYPE_SINT32 10 ++#define FFI_TYPE_UINT64 11 ++#define FFI_TYPE_SINT64 12 ++#define FFI_TYPE_STRUCT 13 ++#define FFI_TYPE_POINTER 14 ++ ++/* This should always refer to the last type code (for sanity checks) */ ++#define FFI_TYPE_LAST FFI_TYPE_POINTER ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef LIBFFI_H +diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h +new file mode 100644 +index 0000000..685a358 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi_common.h +@@ -0,0 +1,102 @@ ++/* ----------------------------------------------------------------------- ++ ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ++ ++ Common internal definitions and macros. Only necessary for building ++ libffi. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef FFI_COMMON_H ++#define FFI_COMMON_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fficonfig.h" ++ ++/* Do not move this. Some versions of AIX are very picky about where ++ this is positioned. */ ++#ifdef __GNUC__ ++# define alloca __builtin_alloca ++#else ++# if HAVE_ALLOCA_H ++# include ++# else ++# ifdef _AIX ++# pragma alloca ++# else ++# ifndef alloca /* predefined by HP cc +Olibcalls */ ++char* alloca(); ++# endif ++# endif ++# endif ++#endif ++ ++/* Check for the existence of memcpy. */ ++#if STDC_HEADERS ++# include ++#else ++# ifndef HAVE_MEMCPY ++# define memcpy(d, s, n) bcopy((s), (d), (n)) ++# endif ++#endif ++ ++/*#if defined(FFI_DEBUG) ++#include ++#endif*/ ++ ++#ifdef FFI_DEBUG ++#include ++ ++/*@exits@*/ void ++ffi_assert( ++/*@temp@*/ char* expr, ++/*@temp@*/ char* file, ++ int line); ++void ++ffi_stop_here(void); ++void ++ffi_type_test( ++/*@temp@*/ /*@out@*/ ffi_type* a, ++/*@temp@*/ char* file, ++ int line); ++ ++# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) ++# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) ++# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__) ++#else ++# define FFI_ASSERT(x) ++# define FFI_ASSERT_AT(x, f, l) ++# define FFI_ASSERT_VALID_TYPE(x) ++#endif // #ifdef FFI_DEBUG ++ ++#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) ++ ++/* Perform machine dependent cif processing */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif); ++ ++/* Extended cif, used in callback from assembly routine */ ++typedef struct extended_cif { ++/*@dependent@*/ ffi_cif* cif; ++/*@dependent@*/ void* rvalue; ++/*@dependent@*/ void** avalue; ++} extended_cif; ++ ++/* Terse sized type definitions. */ ++typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); ++typedef signed int SINT8 __attribute__((__mode__(__QI__))); ++typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); ++typedef signed int SINT16 __attribute__((__mode__(__HI__))); ++typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); ++typedef signed int SINT32 __attribute__((__mode__(__SI__))); ++typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); ++typedef signed int SINT64 __attribute__((__mode__(__DI__))); ++typedef float FLOAT32; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef FFI_COMMON_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h +new file mode 100644 +index 0000000..2172490 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/fficonfig.h +@@ -0,0 +1,150 @@ ++/* Manually created fficonfig.h for Darwin on PowerPC or Intel ++ ++ This file is manually generated to do away with the need for autoconf and ++ therefore make it easier to cross-compile and build fat binaries. ++ ++ NOTE: This file was added by PyObjC. ++*/ ++ ++#ifndef MACOSX ++#error "This file is only supported on Mac OS X" ++#endif ++ ++#if defined(__i386__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__x86_64__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__ppc__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# if __GNUC__ >= 4 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++# else ++# undef HAVE_LONG_DOUBLE ++# define SIZEOF_LONG_DOUBLE 8 ++# endif ++ ++#elif defined(__ppc64__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#else ++#error "Unknown CPU type" ++#endif ++ ++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP ++ systems. This function is required for `alloca.c' support on those systems. */ ++#undef CRAY_STACKSEG_END ++ ++/* Define to 1 if using `alloca.c'. */ ++/* #undef C_ALLOCA */ ++ ++/* Define to the flags needed for the .section .eh_frame directive. */ ++#define EH_FRAME_FLAGS "aw" ++ ++/* Define this if you want extra debugging. */ ++/* #undef FFI_DEBUG */ ++ ++/* Define this is you do not want support for the raw API. */ ++#define FFI_NO_RAW_API 1 ++ ++/* Define this if you do not want support for aggregate types. */ ++/* #undef FFI_NO_STRUCTS */ ++ ++/* Define to 1 if you have `alloca', as a function or macro. */ ++#define HAVE_ALLOCA 1 ++ ++/* Define to 1 if you have and it should be used (not on Ultrix). */ ++#define HAVE_ALLOCA_H 1 ++ ++/* Define if your assembler supports .register. */ ++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ ++ ++/* Define if your assembler and linker support unaligned PC relative relocs. */ ++/* #undef HAVE_AS_SPARC_UA_PCREL */ ++ ++/* Define to 1 if you have the `memcpy' function. */ ++#define HAVE_MEMCPY 1 ++ ++/* Define if mmap with MAP_ANON(YMOUS) works. */ ++#define HAVE_MMAP_ANON 1 ++ ++/* Define if mmap of /dev/zero works. */ ++/* #undef HAVE_MMAP_DEV_ZERO */ ++ ++/* Define if read-only mmap of a plain file works. */ ++#define HAVE_MMAP_FILE 1 ++ ++/* Define if .eh_frame sections should be read-only. */ ++/* #undef HAVE_RO_EH_FRAME */ ++ ++/* Define to 1 if your C compiler doesn't accept -c and -o together. */ ++/* #undef NO_MINUS_C_MINUS_O */ ++ ++/* Name of package */ ++#define PACKAGE "libffi" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "libffi" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "libffi 2.1" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libffi" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "2.1" ++ ++/* If using the C implementation of alloca, define if you know the ++ direction of stack growth for your system; otherwise it will be ++ automatically deduced at run-time. ++ STACK_DIRECTION > 0 => grows toward higher addresses ++ STACK_DIRECTION < 0 => grows toward lower addresses ++ STACK_DIRECTION = 0 => direction of growth unknown */ ++/* #undef STACK_DIRECTION */ ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this if you are using Purify and want to suppress spurious messages. */ ++/* #undef USING_PURIFY */ ++ ++/* Version number of package */ ++#define VERSION "2.1-pyobjc" ++ ++#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) .hidden name ++# else ++# define FFI_HIDDEN __attribute__((visibility ("hidden"))) ++# endif ++#else ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) ++# else ++# define FFI_HIDDEN ++# endif ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h +new file mode 100644 +index 0000000..faaa30d +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffitarget.h +@@ -0,0 +1,13 @@ ++/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a ++ normal build, the build environment copies the file to the right location or ++ sets up the right include flags. We want to do neither because that would ++ make building fat binaries harder. ++*/ ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "x86-ffitarget.h" ++#elif defined(__ppc__) || defined(__ppc64__) ++#include "ppc-ffitarget.h" ++#else ++#error "Unsupported CPU type" ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +new file mode 100644 +index 0000000..2318421 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +@@ -0,0 +1,104 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for PowerPC. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if (defined(POWERPC) && defined(__powerpc64__)) || \ ++ (defined(POWERPC_DARWIN) && defined(__ppc64__)) ++#define POWERPC64 ++#endif ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++#ifdef POWERPC ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++# ifdef POWERPC64 ++ FFI_DEFAULT_ABI = FFI_LINUX64, ++# else ++ FFI_DEFAULT_ABI = FFI_GCC_SYSV, ++# endif ++#endif ++ ++#ifdef POWERPC_AIX ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_AIX, ++#endif ++ ++#ifdef POWERPC_DARWIN ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_DARWIN, ++#endif ++ ++#ifdef POWERPC_FREEBSD ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++#define FFI_NATIVE_RAW_API 0 ++ ++/* Needed for FFI_SYSV small structure returns. */ ++#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) ++ ++#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/ ++# define FFI_TRAMPOLINE_SIZE 48 ++#elif defined(POWERPC_AIX) ++# define FFI_TRAMPOLINE_SIZE 24 ++#else ++# define FFI_TRAMPOLINE_SIZE 40 ++#endif ++ ++#ifndef LIBFFI_ASM ++# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) ++typedef struct ffi_aix_trampoline_struct { ++ void* code_pointer; /* Pointer to ffi_closure_ASM */ ++ void* toc; /* TOC */ ++ void* static_chain; /* Pointer to closure */ ++} ffi_aix_trampoline_struct; ++# endif ++#endif // #ifndef LIBFFI_ASM ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +new file mode 100644 +index 0000000..55c2b6c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +@@ -0,0 +1,88 @@ ++/* -----------------------------------------------------------------*-C-*- ++ x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for x86 and x86-64. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if defined(X86_64) && defined(__i386__) ++# undef X86_64 ++# define X86 ++#endif ++ ++#if defined(__x86_64__) ++# ifndef X86_64 ++# define X86_64 ++# endif ++#endif ++ ++/* ---- Generic type definitions ----------------------------------------- */ ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++ /* ---- Intel x86 Win32 ---------- */ ++#ifdef X86_WIN32 ++ FFI_SYSV, ++ FFI_STDCALL, ++ /* TODO: Add fastcall support for the sake of completeness */ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ /* ---- Intel x86 and AMD x86-64 - */ ++#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) ++ FFI_SYSV, ++ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ ++# ifdef __i386__ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++# else ++ FFI_DEFAULT_ABI = FFI_UNIX64, ++# endif ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++ ++#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN)) ++# define FFI_TRAMPOLINE_SIZE 24 ++# define FFI_NATIVE_RAW_API 0 ++#else ++# define FFI_TRAMPOLINE_SIZE 10 ++# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ ++#endif ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +new file mode 100644 +index 0000000..f143dbd +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +@@ -0,0 +1,365 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist ++ Copyright (c) 2004 Free Software Foundation, Inc. ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include ++#include ++#include ++ ++.text ++ .align 2 ++.globl _ffi_prep_args ++ ++.text ++ .align 2 ++.globl _ffi_call_DARWIN ++ ++.text ++ .align 2 ++_ffi_call_DARWIN: ++LFB0: ++ mr r12,r8 /* We only need r12 until the call, ++ so it doesn't have to be saved. */ ++ ++LFB1: ++ /* Save the old stack pointer as AP. */ ++ mr r8,r1 ++ ++LCFI0: ++#if defined(__ppc64__) ++ /* Allocate the stack space we need. ++ r4 (size of input data) ++ 48 bytes (linkage area) ++ 40 bytes (saved registers) ++ 8 bytes (extra FPR) ++ r4 + 96 bytes total ++ */ ++ ++ addi r4,r4,-96 // Add our overhead. ++ li r0,-32 // Align to 32 bytes. ++ and r4,r4,r0 ++#endif ++ stgux r1,r1,r4 // Grow the stack. ++ mflr r9 ++ ++ /* Save registers we use. */ ++#if defined(__ppc64__) ++ std r27,-40(r8) ++#endif ++ stg r28,MODE_CHOICE(-16,-32)(r8) ++ stg r29,MODE_CHOICE(-12,-24)(r8) ++ stg r30,MODE_CHOICE(-8,-16)(r8) ++ stg r31,MODE_CHOICE(-4,-8)(r8) ++ stg r9,SF_RETURN(r8) /* return address */ ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ stg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++LCFI1: ++#if defined(__ppc64__) ++ mr r27,r3 // our extended_cif ++#endif ++ /* Save arguments over call. */ ++ mr r31,r5 /* flags, */ ++ mr r30,r6 /* rvalue, */ ++ mr r29,r7 /* function address, */ ++ mr r28,r8 /* our AP. */ ++ ++LCFI2: ++ /* Call ffi_prep_args. */ ++ mr r4,r1 ++ li r9,0 ++ mtctr r12 /* r12 holds address of _ffi_prep_args. */ ++ bctrl ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ lg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++ /* Now do the call. ++ Set up cr1 with bits 4-7 of the flags. */ ++ mtcrf 0x40,r31 ++ ++ /* Load all those argument registers. ++ We have set up a nice stack frame, just load it into registers. */ ++ lg r3,SF_ARG1(r1) ++ lg r4,SF_ARG2(r1) ++ lg r5,SF_ARG3(r1) ++ lg r6,SF_ARG4(r1) ++ nop ++ lg r7,SF_ARG5(r1) ++ lg r8,SF_ARG6(r1) ++ lg r9,SF_ARG7(r1) ++ lg r10,SF_ARG8(r1) ++ ++ /* Load all the FP registers. */ ++ bf 6,L2 /* No floats to load. */ ++#if defined(__ppc64__) ++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#elif defined(__ppc__) ++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#else ++#error undefined architecture ++#endif ++ ++L2: ++ mr r12,r29 // Put the target address in r12 as specified. ++ mtctr r12 // Get the address to call into CTR. ++ nop ++ nop ++ bctrl // Make the call. ++ ++ // Deal with the return value. ++#if defined(__ppc64__) ++ mtcrf 0x3,r31 // flags in cr6 and cr7 ++ bt 27,L(st_return_value) ++#elif defined(__ppc__) ++ mtcrf 0x1,r31 // flags in cr7 ++#else ++#error undefined architecture ++#endif ++ ++ bt 30,L(done_return_value) ++ bt 29,L(fp_return_value) ++ stg r3,0(r30) ++#if defined(__ppc__) ++ bf 28,L(done_return_value) // Store the second long if necessary. ++ stg r4,4(r30) ++#endif ++ // Fall through ++ ++L(done_return_value): ++ lg r1,0(r1) // Restore stack pointer. ++ // Restore the registers we used. ++ lg r9,SF_RETURN(r1) // return address ++ lg r31,MODE_CHOICE(-4,-8)(r1) ++ mtlr r9 ++ lg r30,MODE_CHOICE(-8,-16)(r1) ++ lg r29,MODE_CHOICE(-12,-24)(r1) ++ lg r28,MODE_CHOICE(-16,-32)(r1) ++#if defined(__ppc64__) ++ ld r27,-40(r1) ++#endif ++ blr ++ ++#if defined(__ppc64__) ++L(st_return_value): ++ // Grow the stack enough to fit the registers. Leave room for 8 args ++ // to trample the 1st 8 slots in param area. ++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 ++ ++ // Store GPRs ++ std r3,SF_ARG9(r1) ++ std r4,SF_ARG10(r1) ++ std r5,SF_ARG11(r1) ++ std r6,SF_ARG12(r1) ++ nop ++ std r7,SF_ARG13(r1) ++ std r8,SF_ARG14(r1) ++ std r9,SF_ARG15(r1) ++ std r10,SF_ARG16(r1) ++ ++ // Store FPRs ++ nop ++ bf 26,L(call_struct_to_ram_form) ++ stfd f1,SF_ARG17(r1) ++ stfd f2,SF_ARG18(r1) ++ stfd f3,SF_ARG19(r1) ++ stfd f4,SF_ARG20(r1) ++ nop ++ stfd f5,SF_ARG21(r1) ++ stfd f6,SF_ARG22(r1) ++ stfd f7,SF_ARG23(r1) ++ stfd f8,SF_ARG24(r1) ++ nop ++ stfd f9,SF_ARG25(r1) ++ stfd f10,SF_ARG26(r1) ++ stfd f11,SF_ARG27(r1) ++ stfd f12,SF_ARG28(r1) ++ nop ++ stfd f13,SF_ARG29(r1) ++ ++L(call_struct_to_ram_form): ++ ld r3,0(r27) // extended_cif->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ addi r4,r1,SF_ARG9 // stored GPRs ++ addi r6,r1,SF_ARG17 // stored FPRs ++ li r5,0 // GPR size ptr (NULL) ++ li r7,0 // FPR size ptr (NULL) ++ li r8,0 // FPR count ptr (NULL) ++ li r10,0 // struct offset (NULL) ++ mr r9,r30 // return area ++ bl Lffi64_struct_to_ram_form$stub ++ lg r1,0(r1) // Restore stack pointer. ++ b L(done_return_value) ++#endif ++ ++L(fp_return_value): ++ /* Do we have long double to store? */ ++ bf 31,L(fd_return_value) ++ stfd f1,0(r30) ++ stfd f2,8(r30) ++ b L(done_return_value) ++ ++L(fd_return_value): ++ /* Do we have double to store? */ ++ bf 28,L(float_return_value) ++ stfd f1,0(r30) ++ b L(done_return_value) ++ ++L(float_return_value): ++ /* We only have a float to store. */ ++ stfs f1,0(r30) ++ b L(done_return_value) ++ ++LFE1: ++/* END(_ffi_call_DARWIN) */ ++ ++/* Provide a null definition of _ffi_call_AIX. */ ++.text ++ .align 2 ++.globl _ffi_call_AIX ++.text ++ .align 2 ++_ffi_call_AIX: ++ blr ++/* END(_ffi_call_AIX) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_call_DARWIN.eh ++_ffi_call_DARWIN.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x08 ; uleb128 0x08 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$5,LCFI1-LCFI0 ++ .long L$set$5 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .byte 0x9f ; DW_CFA_offset, column 0x1f ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x9e ; DW_CFA_offset, column 0x1e ++ .byte 0x2 ; uleb128 0x2 ++ .byte 0x9d ; DW_CFA_offset, column 0x1d ++ .byte 0x3 ; uleb128 0x3 ++ .byte 0x9c ; DW_CFA_offset, column 0x1c ++ .byte 0x4 ; uleb128 0x4 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$6,LCFI2-LCFI1 ++ .long L$set$6 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x1c ; uleb128 0x1c ++ .align LOG2_GPR_BYTES ++LEFDE1: ++ ++#if defined(__ppc64__) ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_ram_form$stub: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_ram_form ++ ++LO$ffi64_struct_to_ram_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_ram_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ ++#endif // __ppc__ || __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +new file mode 100644 +index 0000000..cf4bd50 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +@@ -0,0 +1,85 @@ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define L(x) x ++ ++#define SF_ARG9 MODE_CHOICE(56,112) ++#define SF_ARG10 MODE_CHOICE(60,120) ++#define SF_ARG11 MODE_CHOICE(64,128) ++#define SF_ARG12 MODE_CHOICE(68,136) ++#define SF_ARG13 MODE_CHOICE(72,144) ++#define SF_ARG14 MODE_CHOICE(76,152) ++#define SF_ARG15 MODE_CHOICE(80,160) ++#define SF_ARG16 MODE_CHOICE(84,168) ++#define SF_ARG17 MODE_CHOICE(88,176) ++#define SF_ARG18 MODE_CHOICE(92,184) ++#define SF_ARG19 MODE_CHOICE(96,192) ++#define SF_ARG20 MODE_CHOICE(100,200) ++#define SF_ARG21 MODE_CHOICE(104,208) ++#define SF_ARG22 MODE_CHOICE(108,216) ++#define SF_ARG23 MODE_CHOICE(112,224) ++#define SF_ARG24 MODE_CHOICE(116,232) ++#define SF_ARG25 MODE_CHOICE(120,240) ++#define SF_ARG26 MODE_CHOICE(124,248) ++#define SF_ARG27 MODE_CHOICE(128,256) ++#define SF_ARG28 MODE_CHOICE(132,264) ++#define SF_ARG29 MODE_CHOICE(136,272) ++ ++#define ASM_NEEDS_REGISTERS 4 ++#define NUM_GPR_ARG_REGISTERS 8 ++#define NUM_FPR_ARG_REGISTERS 13 ++ ++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8) ++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16) ++#define FFI_TYPE_4_BYTE(x) \ ++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\ ++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT) ++ ++#if !defined(LIBFFI_ASM) ++ ++enum { ++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7 ++ FLAG_RETURNS_FP = 1 << (31 - 29), ++ FLAG_RETURNS_64BITS = 1 << (31 - 28), ++ FLAG_RETURNS_128BITS = 1 << (31 - 31), ++ ++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6 ++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26), ++ ++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7), ++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI ++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5), ++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4) ++}; ++ ++#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*); ++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*); ++#endif ++ ++#endif // !defined(LIBFFI_ASM) +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +new file mode 100644 +index 0000000..c3d30c2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +@@ -0,0 +1,308 @@ ++#if defined(__ppc__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 // Save return address ++ stg r0,SF_RETURN(r1) ++ ++LCFI0: ++ /* 24/48 bytes (Linkage Area) ++ 32/64 bytes (outgoing parameter area, always reserved) ++ 104 bytes (13*8 from FPR) ++ 16/32 bytes (result) ++ 176/232 total bytes */ ++ ++ /* skip over caller save area and keep stack aligned to 16/32. */ ++ stgu r1,-SF_ROUND(176)(r1) ++ ++LCFI1: ++ /* We want to build up an area for the parameters passed ++ in registers. (both floating point and integer) */ ++ ++ /* 176/256 bytes (callee stack frame aligned to 16/32) ++ 24/48 bytes (caller linkage area) ++ 200/304 (start of caller parameter area aligned to 4/8) ++ */ ++ ++ /* Save GPRs 3 - 10 (aligned to 4/8) ++ in the parents outgoing area. */ ++ 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,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. ++ 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. Use it to look up in a table ++ so we know how to deal with each type. */ ++ 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 ++ ++LFE1: ++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ (4 instructions). For cache effectiveness we align to a 16 byte boundary ++ first. */ ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++/* case FFI_TYPE_VOID */ ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* case FFI_TYPE_INT */ ++Lret_type1: ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_FLOAT */ ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_DOUBLE */ ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_LONGDOUBLE */ ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT8 */ ++Lret_type5: ++ lbz r3,3(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT8 */ ++Lret_type6: ++ lbz r3,3(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT16 */ ++Lret_type7: ++ lhz r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT16 */ ++Lret_type8: ++ lha r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT32 */ ++Lret_type9: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT32 */ ++Lret_type10: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT64 */ ++Lret_type11: ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_SINT64 */ ++Lret_type12: // same as Lret_type11 ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_STRUCT */ ++Lret_type13: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* End 16-byte aligned cases */ ++/* case FFI_TYPE_POINTER */ ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ // fall through ++ ++/* case done */ ++Lfinish: ++ 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) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++ ++#endif // __ppc__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +new file mode 100644 +index 0000000..8953d5f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +@@ -0,0 +1,1776 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1998 Geoffrey Keating ++ ++ PowerPC Foreign Function Interface ++ ++ Darwin ABI support (c) 2001 John Hornkvist ++ AIX ABI support (c) 2002 Free Software Foundation, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#if defined(POWERPC_DARWIN) ++#include // for sys_icache_invalidate() ++#endif ++ ++#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 ++// points to one of these. ++typedef struct aix_fd_struct { ++ void* code_pointer; ++ void* toc; ++} aix_fd; ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments. ++ ++ The stack layout we want looks like this: ++ ++ | Return address from ffi_call_DARWIN | higher addresses ++ |--------------------------------------------| ++ | Previous backchain pointer 4/8 | stack pointer here ++ |--------------------------------------------|-\ <<< on entry to ++ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN ++ |--------------------------------------------| | ++ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 ++ |--------------------------------------------| | ++ | Space for GPR2 4/8 | | ++ |--------------------------------------------| | stack | ++ | Reserved (4/8)*2 | | grows | ++ |--------------------------------------------| | down V ++ | Space for callee's LR 4/8 | | ++ |--------------------------------------------| | lower addresses ++ | Saved CR 4/8 | | ++ |--------------------------------------------| | stack pointer here ++ | Current backchain pointer 4/8 | | during ++ |--------------------------------------------|-/ <<< ffi_call_DARWIN ++ ++ Note: ppc64 CR is saved in the low word of a long on the stack. ++*/ ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args( ++ extended_cif* inEcif, ++ unsigned *const stack) ++/*@=exportheader@*/ ++{ ++ /* Copy the ecif to a local var so we can trample the arg. ++ BC note: test this with GP later for possible problems... */ ++ volatile extended_cif* ecif = inEcif; ++ ++ const unsigned bytes = ecif->cif->bytes; ++ const unsigned flags = ecif->cif->flags; ++ ++ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode ++ and 8 in 64-bit mode. */ ++ unsigned long *const longStack = (unsigned long *const)stack; ++ ++ /* 'stacktop' points at the previous backchain pointer. */ ++#if defined(__ppc64__) ++ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, ++ // saved registers, and an extra FPR. ++ unsigned long *const stacktop = ++ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); ++#elif defined(__ppc__) ++ unsigned long *const stacktop = longStack + (bytes / sizeof(long)); ++#else ++#error undefined architecture ++#endif ++ ++ /* 'fpr_base' points at the space for fpr1, and grows upwards as ++ we use FPR registers. */ ++ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - ++ NUM_FPR_ARG_REGISTERS; ++ ++#if defined(__ppc64__) ++ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base ++ // down a couple pegs. ++ fpr_base -= 2; ++#endif ++ ++ unsigned int fparg_count = 0; ++ ++ /* 'next_arg' grows up as we put parameters in it. */ ++ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ ++ ++ int i; ++ double double_tmp; ++ void** p_argv = ecif->avalue; ++ unsigned long gprvalue; ++ ffi_type** ptr = ecif->cif->arg_types; ++ ++ /* Check that everything starts aligned properly. */ ++ FFI_ASSERT(stack == SF_ROUND(stack)); ++ FFI_ASSERT(stacktop == SF_ROUND(stacktop)); ++ FFI_ASSERT(bytes == SF_ROUND(bytes)); ++ ++ /* Deal with return values that are actually pass-by-reference. ++ Rule: ++ Return values are referenced by r3, so r4 is the first parameter. */ ++ ++ if (flags & FLAG_RETVAL_REFERENCE) ++ *next_arg++ = (unsigned long)(char*)ecif->rvalue; ++ ++ /* Now for the arguments. */ ++ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) ++ { ++ switch ((*ptr)->type) ++ { ++ /* If a floating-point parameter appears before all of the general- ++ purpose registers are filled, the corresponding GPRs that match ++ the size of the floating-point parameter are shadowed for the ++ benefit of vararg and pre-ANSI functions. */ ++ case FFI_TYPE_FLOAT: ++ double_tmp = *(float*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg++; ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ double_tmp = *(double*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg += MODE_CHOICE(2,1); ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++#elif defined(__ppc__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) ++ *(double*)fpr_base = *(double*)*p_argv; ++#else ++#error undefined architecture ++#endif ++ ++ *(long double*)next_arg = *(long double*)*p_argv; ++ fparg_count += 2; ++ fpr_base += 2; ++ next_arg += MODE_CHOICE(4,2); ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++#if defined(__ppc64__) ++ gprvalue = *(long long*)*p_argv; ++ goto putgpr; ++#elif defined(__ppc__) ++ *(long long*)next_arg = *(long long*)*p_argv; ++ next_arg += 2; ++ break; ++#else ++#error undefined architecture ++#endif ++ ++ case FFI_TYPE_POINTER: ++ gprvalue = *(unsigned long*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT8: ++ gprvalue = *(unsigned char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT8: ++ gprvalue = *(signed char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT16: ++ gprvalue = *(unsigned short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT16: ++ gprvalue = *(signed short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ ++ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, ++ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); ++ next_arg += gprSize / sizeof(long); ++ fpr_base += fprSize / sizeof(double); ++ ++#elif defined(__ppc__) ++ char* dest_cpy = (char*)next_arg; ++ ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. ++ Structures with 3 byte in size are padded upwards. */ ++ unsigned size_al = (*ptr)->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++ if (ecif->cif->abi == FFI_DARWIN) ++ { ++ if (size_al < 3) ++ dest_cpy += 4 - size_al; ++ } ++ ++ memcpy((char*)dest_cpy, (char*)*p_argv, size_al); ++ next_arg += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ gprvalue = *(unsigned*)*p_argv; ++ ++putgpr: ++ *next_arg++ = gprvalue; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Check that we didn't overrun the stack... */ ++ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); ++ //FFI_ASSERT((unsigned *)fpr_base ++ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); ++ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); ++} ++ ++#if defined(__ppc64__) ++ ++bool ++ffi64_struct_contains_fp( ++ const ffi_type* inType) ++{ ++ bool containsFP = false; ++ unsigned int i; ++ ++ for (i = 0; inType->elements[i] != NULL && !containsFP; i++) ++ { ++ if (inType->elements[i]->type == FFI_TYPE_FLOAT || ++ inType->elements[i]->type == FFI_TYPE_DOUBLE || ++ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) ++ containsFP = true; ++ else if (inType->elements[i]->type == FFI_TYPE_STRUCT) ++ containsFP = ffi64_struct_contains_fp(inType->elements[i]); ++ } ++ ++ return containsFP; ++} ++ ++#endif // defined(__ppc64__) ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ /* All this is for the DARWIN ABI. */ ++ int i; ++ ffi_type** ptr; ++ int intarg_count = 0; ++ int fparg_count = 0; ++ unsigned int flags = 0; ++ unsigned int size_al = 0; ++ ++ /* All the machine-independent calculation of cif->bytes will be wrong. ++ Redo the calculation for DARWIN. */ ++ ++ /* Space for the frame pointer, callee's LR, CR, etc, and for ++ the asm's temp regs. */ ++ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); ++ ++ /* Return value handling. The rules are as follows: ++ - 32-bit (or less) integer values are returned in gpr3; ++ - Structures of size <= 4 bytes also returned in gpr3; ++ - 64-bit integer values and structures between 5 and 8 bytes are ++ returned in gpr3 and gpr4; ++ - Single/double FP values are returned in fpr1; ++ - Long double FP (if not equivalent to double) values are returned in ++ fpr1 and fpr2; ++ - Larger structures values are allocated space and a pointer is passed ++ as the first argument. */ ++ switch (cif->rtype->type) ++ { ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ flags |= FLAG_RETURNS_128BITS; ++ flags |= FLAG_RETURNS_FP; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_DOUBLE: ++ flags |= FLAG_RETURNS_64BITS; ++ /* Fall through. */ ++ case FFI_TYPE_FLOAT: ++ flags |= FLAG_RETURNS_FP; ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ flags |= FLAG_RETURNS_64BITS; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ ++ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++ { ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ } ++ else ++ { ++ flags |= FLAG_RETURNS_STRUCT; ++ ++ if (ffi64_struct_contains_fp(cif->rtype)) ++ flags |= FLAG_STRUCT_CONTAINS_FP; ++ } ++ ++#elif defined(__ppc__) ++ ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_VOID: ++ flags |= FLAG_RETURNS_NOTHING; ++ break; ++ ++ default: ++ /* Returns 32-bit integer, or similar. Nothing to do here. */ ++ break; ++ } ++ ++ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the ++ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest ++ goes on the stack. Structures are passed as a pointer to a copy of ++ the structure. Stuff on the stack needs to keep proper alignment. */ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ switch ((*ptr)->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ fparg_count++; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ fparg_count += 2; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ ++ if ( ++#if defined(__ppc64__) ++ fparg_count > NUM_FPR_ARG_REGISTERS + 1 ++#elif defined(__ppc__) ++ fparg_count > NUM_FPR_ARG_REGISTERS ++#else ++#error undefined architecture ++#endif ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ ++ intarg_count += 2; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ /* 'long long' arguments are passed as two words, but ++ either both words must fit in registers or both go ++ on the stack. If they go on the stack, they must ++ be 8-byte-aligned. */ ++ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 ++ || (intarg_count >= NUM_GPR_ARG_REGISTERS ++ && intarg_count % 2 != 0)) ++ intarg_count++; ++ ++ intarg_count += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ size_al = (*ptr)->size; ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++#if defined(__ppc64__) ++ // Look for FP struct members. ++ unsigned int j; ++ ++ for (j = 0; (*ptr)->elements[j] != NULL; j++) ++ { ++ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || ++ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) ++ { ++ fparg_count++; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS) ++ intarg_count++; ++ } ++ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) ++ { ++ fparg_count += 2; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) ++ intarg_count += 2; ++ } ++ else ++ intarg_count++; ++ } ++#elif defined(__ppc__) ++ intarg_count += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ ++ break; ++ ++ default: ++ /* Everything else is passed as a 4/8-byte word in a GPR, either ++ the object itself or a pointer to it. */ ++ intarg_count++; ++ break; ++ } ++ } ++ ++ /* Space for the FPR registers, if needed. */ ++ if (fparg_count != 0) ++ { ++ flags |= FLAG_FP_ARGUMENTS; ++#if defined(__ppc64__) ++ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); ++#elif defined(__ppc__) ++ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ /* Stack space. */ ++#if defined(__ppc64__) ++ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + fparg_count) * sizeof(long); ++#elif defined(__ppc__) ++ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + 2 * fparg_count) * sizeof(long); ++#else ++#error undefined architecture ++#endif ++ else ++ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); ++ ++ /* The stack space allocated needs to be a multiple of 16/32 bytes. */ ++ bytes = SF_ROUND(bytes); ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ ++ return FFI_OK; ++} ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ++ffi_call_AIX( ++/*@out@*/ extended_cif*, ++ unsigned, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++ ++extern void ++ffi_call_DARWIN( ++/*@out@*/ extended_cif*, ++ unsigned long, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ 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) && ++ (cif->rtype->type == FFI_TYPE_STRUCT)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ switch (cif->abi) ++ { ++ case FFI_AIX: ++ /*@-usedef@*/ ++ ffi_call_AIX(&ecif, -cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ case FFI_DARWIN: ++ /*@-usedef@*/ ++ ffi_call_DARWIN(&ecif, -(long)cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++/* here I'd like to add the stack frame layout we use in darwin_closure.S ++ and aix_clsoure.S ++ ++ SP previous -> +---------------------------------------+ <--- child frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 4 ++ | saved CR 4 | ++ +---------------------------------------+ 8 ++ | saved LR 4 | ++ +---------------------------------------+ 12 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 16 ++ | reserved for binders 4 | ++ +---------------------------------------+ 20 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 24 ++ | always reserved 8*4=32 (previous GPRs)| ++ | according to the linkage convention | ++ | from AIX | ++ +---------------------------------------+ 56 ++ | our FPR area 13*8=104 | ++ | f1 | ++ | . | ++ | f13 | ++ +---------------------------------------+ 160 ++ | result area 8 | ++ +---------------------------------------+ 168 ++ | alignement to the next multiple of 16 | ++SP current --> +---------------------------------------+ 176 <- parent frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 180 ++ | saved CR 4 | ++ +---------------------------------------+ 184 ++ | saved LR 4 | ++ +---------------------------------------+ 188 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 192 ++ | reserved for binders 4 | ++ +---------------------------------------+ 196 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 200 ++ | always reserved 8*4=32 we store our | ++ | GPRs here | ++ | r3 | ++ | . | ++ | r10 | ++ +---------------------------------------+ 232 ++ | overflow part | ++ +---------------------------------------+ xxx ++ | ???? | ++ +---------------------------------------+ xxx ++*/ ++ ++#if !defined(POWERPC_DARWIN) ++ ++#define MIN_LINE_SIZE 32 ++ ++static void ++flush_icache( ++ char* addr) ++{ ++#ifndef _AIX ++ __asm__ volatile ( ++ "dcbf 0,%0\n" ++ "sync\n" ++ "icbi 0,%0\n" ++ "sync\n" ++ "isync" ++ : : "r" (addr) : "memory"); ++#endif ++} ++ ++static void ++flush_range( ++ char* addr, ++ int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i += MIN_LINE_SIZE) ++ flush_icache(addr + i); ++ ++ flush_icache(addr + size - 1); ++} ++ ++#endif // !defined(POWERPC_DARWIN) ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ switch (cif->abi) ++ { ++ case FFI_DARWIN: ++ { ++ FFI_ASSERT (cif->abi == FFI_DARWIN); ++ ++ unsigned int* tramp = (unsigned int*)&closure->tramp[0]; ++ ++#if defined(__ppc64__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0xe98b0018; // ld r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0xe96b0020; // ld r11,32(r11) ++ tramp[7] = 0x4e800420; // bctr ++ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; ++ *(unsigned long*)&tramp[10] = (unsigned long)closure; ++#elif defined(__ppc__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0x818b0018; // lwz r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0x816b001c; // lwz r11,28(r11) ++ tramp[7] = 0x4e800420; // bctr ++ tramp[8] = (unsigned long)ffi_closure_ASM; ++ tramp[9] = (unsigned long)closure; ++#else ++#error undefined architecture ++#endif ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ // Flush the icache. Only necessary on Darwin. ++#if defined(POWERPC_DARWIN) ++ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#else ++ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#endif ++ ++ break; ++ } ++ ++ case FFI_AIX: ++ { ++ FFI_ASSERT (cif->abi == FFI_AIX); ++ ++ ffi_aix_trampoline_struct* tramp_aix = ++ (ffi_aix_trampoline_struct*)(closure->tramp); ++ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; ++ ++ tramp_aix->code_pointer = fd->code_pointer; ++ tramp_aix->toc = fd->toc; ++ tramp_aix->static_chain = closure; ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ break; ++ } ++ ++ default: ++ return FFI_BAD_ABI; ++ } ++ ++ return FFI_OK; ++} ++ ++#if defined(__ppc__) ++ typedef double ldbits[2]; ++ ++ typedef union ++ { ++ ldbits lb; ++ long double ld; ++ } 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 ++ for a return value, ffi_closure_ASM invokes the following helper function ++ to do most of the work. */ ++int ++ffi_closure_helper_DARWIN( ++ ffi_closure* closure, ++ void* rvalue, ++ unsigned long* pgr, ++ ffi_dblfl* pfr) ++{ ++ /* rvalue is the pointer to space for return value in closure assembly ++ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM ++ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ ++ ++#if defined(__ppc__) ++ ldu temp_ld; ++#endif ++ ++ double temp; ++ unsigned int i; ++ unsigned int nf = 0; /* number of FPRs already used. */ ++ unsigned int ng = 0; /* number of GPRs already used. */ ++ ffi_cif* cif = closure->cif; ++ long avn = cif->nargs; ++ void** avalue = alloca(cif->nargs * sizeof(void*)); ++ ffi_type** arg_types = cif->arg_types; ++ ++ /* Copy the caller's structure return value address so that the closure ++ returns the data directly to the caller. */ ++#if defined(__ppc64__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT && ++ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++#elif defined(__ppc__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT) ++#else ++#error undefined architecture ++#endif ++ { ++ rvalue = (void*)*pgr; ++ pgr++; ++ ng++; ++ } ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ for (i = 0; i < avn; i++) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ avalue[i] = (char*)pgr + MODE_CHOICE(3,7); ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ avalue[i] = (char*)pgr + MODE_CHOICE(2,6); ++ ng++; ++ pgr++; ++ break; ++ ++#if defined(__ppc__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ avalue[i] = (char*)pgr + MODE_CHOICE(0,4); ++ ng++; ++ pgr++; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ if (cif->abi == FFI_DARWIN) ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ unsigned int savedFPRSize = fprSize; ++ ++ avalue[i] = alloca(arg_types[i]->size); ++ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, ++ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); ++ ++ ng += gprSize / sizeof(long); ++ pgr += gprSize / sizeof(long); ++ pfr += (fprSize - savedFPRSize) / sizeof(double); ++ ++#elif defined(__ppc__) ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. */ ++ unsigned int size_al = size_al = arg_types[i]->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN(arg_types[i]->size, 8); ++ ++ if (size_al < 3) ++ avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; ++ else ++ avalue[i] = (void*)pgr; ++ ++ ng += (size_al + 3) / sizeof(long); ++ pgr += (size_al + 3) / sizeof(long); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ /* Long long ints are passed in 1 or 2 GPRs. */ ++ avalue[i] = pgr; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ /* A float value consumes a GPR. ++ There are 13 64-bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ temp = pfr->d; ++ pfr->f = (float)temp; ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ /* A double value consumes one or two GPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++#elif defined(__ppc__) ++ /* A long double value consumes 2/4 GPRs and 2 FPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS - 1) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++ /* Here we have the situation where one part of the long double ++ is stored in fpr13 and the other part is already on the stack. ++ 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(temp_ld.lb[0])); ++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); ++ avalue[i] = &temp_ld.ld; ++ } ++#else ++#error undefined architecture ++#endif ++ else ++ avalue[i] = pgr; ++ ++ nf += 2; ++ ng += MODE_CHOICE(4,2); ++ pgr += MODE_CHOICE(4,2); ++ ++ break; ++ ++#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ (closure->fun)(cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell ffi_closure_ASM to perform return type promotions. */ ++ return cif->rtype->type; ++} ++ ++#if defined(__ppc64__) ++ ++/* ffi64_struct_to_ram_form ++ ++ Rebuild a struct's natural layout from buffers of concatenated registers. ++ Return the number of registers used. ++ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_ram_form( ++ const ffi_type* inType, ++ const char* inGPRs, ++ unsigned int* ioGPRMarker, ++ const char* inFPRs, ++ unsigned int* ioFPRMarker, ++ unsigned int* ioFPRsUsed, ++ char* outStruct, // caller-allocated ++ unsigned int* ioStructMarker) ++{ ++ unsigned int srcGMarker = 0; ++ unsigned int srcFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ unsigned int destMarker = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioGPRMarker) ++ srcGMarker = *ioGPRMarker; ++ ++ if (ioFPRMarker) ++ { ++ srcFMarker = *ioFPRMarker; ++ savedFMarker = srcFMarker; ++ } ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioStructMarker) ++ destMarker = *ioStructMarker; ++ ++ size_t i; ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ srcGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ srcFMarker = ALIGN(srcFMarker, 4); ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inGPRs[srcGMarker]; ++ ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcFMarker = ALIGN(srcFMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inGPRs[srcGMarker]; ++ ++ destMarker += 8; ++ ++ // Skip next GPR ++ srcGMarker += 8; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ destMarker = ALIGN(destMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ srcFMarker = ALIGN(srcFMarker, 8); ++ srcGMarker = ALIGN(srcGMarker, 8); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inFPRs[srcFMarker]; ++ srcFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ srcFMarker = ALIGN(srcFMarker, 16); ++ srcGMarker = ALIGN(srcGMarker, 16); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inGPRs[srcGMarker]; ++ } ++ ++ destMarker += 16; ++ ++ // Skip next 2 GPRs ++ srcGMarker += 16; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ if (inType->alignment == 1) // chars only ++ { ++ if (inType->size == 1) ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ else if (inType->size == 2) ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ i++; ++ } ++ else ++ { ++ memcpy(&outStruct[destMarker], ++ &inGPRs[srcGMarker], inType->size); ++ srcGMarker += inType->size; ++ destMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // chars and other stuff ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcGMarker = ALIGN(srcGMarker, 2); ++ destMarker = ALIGN(destMarker, 2); ++ ++ *(short*)&outStruct[destMarker] = ++ *(short*)&inGPRs[srcGMarker]; ++ srcGMarker += 2; ++ destMarker += 2; ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ *(int*)&outStruct[destMarker] = ++ *(int*)&inGPRs[srcGMarker]; ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcGMarker = ALIGN(srcGMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ *(long long*)&outStruct[destMarker] = ++ *(long long*)&inGPRs[srcGMarker]; ++ srcGMarker += 8; ++ destMarker += 8; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_ram_form(inType->elements[i], inGPRs, ++ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, ++ outStruct, &destMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); // unknown element type ++ break; ++ } ++ } ++ ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && srcGMarker == 16) ++ { ++ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; ++ srcFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioGPRMarker) ++ *ioGPRMarker = ALIGN(srcGMarker, 8); ++ ++ if (ioFPRMarker) ++ *ioFPRMarker = srcFMarker; ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(destMarker, 8); ++} ++ ++/* ffi64_struct_to_reg_form ++ ++ Copy a struct's elements into buffers that can be sliced into registers. ++ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers ++ to calculate size only. ++ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_reg_form( ++ const ffi_type* inType, ++ const char* inStruct, ++ unsigned int* ioStructMarker, ++ unsigned int* ioFPRsUsed, ++ char* outGPRs, // caller-allocated ++ unsigned int* ioGPRSize, ++ char* outFPRs, // caller-allocated ++ unsigned int* ioFPRSize) ++{ ++ size_t i; ++ unsigned int srcMarker = 0; ++ unsigned int destGMarker = 0; ++ unsigned int destFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioStructMarker) ++ srcMarker = *ioStructMarker; ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioGPRSize) ++ destGMarker = *ioGPRSize; ++ ++ if (ioFPRSize) ++ { ++ destFMarker = *ioFPRSize; ++ savedFMarker = destFMarker; ++ } ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ destGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ // Shadow floating-point types in GPRs for vararg and pre-ANSI ++ // functions. ++ case FFI_TYPE_FLOAT: ++ // Nudge markers to next 4/8-byte boundary ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcMarker = ALIGN(srcMarker, 8); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ ++ // Skip next GPR ++ destGMarker += 8; ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ srcMarker = ALIGN(srcMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ destFMarker = ALIGN(destFMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outFPRs != NULL && inStruct != NULL) ++ *(long double*)&outFPRs[destFMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ destFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ destGMarker = ALIGN(destGMarker, 16); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ } ++ ++ srcMarker += 16; ++ destGMarker += 16; // Skip next 2 GPRs ++ destGMarker = ALIGN(destGMarker, 8); // was 16 ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ if (inType->alignment == 1) // bytes only ++ { ++ if (inType->size == 1) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ } ++ else if (inType->size == 2) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; ++ } ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ i++; ++ } ++ else ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ // Avoid memcpy for small chunks. ++ if (inType->size <= sizeof(long)) ++ *(long*)&outGPRs[destGMarker] = ++ *(long*)&inStruct[srcMarker]; ++ else ++ memcpy(&outGPRs[destGMarker], ++ &inStruct[srcMarker], inType->size); ++ } ++ ++ srcMarker += inType->size; ++ destGMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // bytes and other stuff ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcMarker = ALIGN(srcMarker, 2); ++ destGMarker = ALIGN(destGMarker, 2); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(short*)&outGPRs[destGMarker] = ++ *(short*)&inStruct[srcMarker]; ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(int*)&outGPRs[destGMarker] = ++ *(int*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcMarker = ALIGN(srcMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long long*)&outGPRs[destGMarker] = ++ *(long long*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ destGMarker += 8; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_reg_form(inType->elements[i], ++ inStruct, &srcMarker, &fprsUsed, outGPRs, ++ &destGMarker, outFPRs, &destFMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && destGMarker == 16) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; ++ ++ destFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(srcMarker, 8); ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioGPRSize) ++ *ioGPRSize = ALIGN(destGMarker, 8); ++ ++ if (ioFPRSize) ++ *ioFPRSize = ALIGN(destFMarker, 8); ++} ++ ++/* ffi64_stret_needs_ptr ++ ++ Determine whether a returned struct needs a pointer in r3 or can fit ++ in registers. ++*/ ++ ++bool ++ffi64_stret_needs_ptr( ++ const ffi_type* inType, ++ unsigned short* ioGPRCount, ++ unsigned short* ioFPRCount) ++{ ++ // Obvious case first- struct is larger than combined FPR size. ++ if (inType->size > 14 * 8) ++ return true; ++ ++ // Now the struct can physically fit in registers, determine if it ++ // also fits logically. ++ bool needsPtr = false; ++ unsigned short gprsUsed = 0; ++ unsigned short fprsUsed = 0; ++ size_t i; ++ ++ if (ioGPRCount) ++ gprsUsed = *ioGPRCount; ++ ++ if (ioFPRCount) ++ fprsUsed = *ioFPRCount; ++ ++ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ gprsUsed++; ++ fprsUsed++; ++ ++ if (fprsUsed > 13) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ gprsUsed += 2; ++ fprsUsed += 2; ++ ++ if (fprsUsed > 14) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ { ++ needsPtr = true; ++ break; ++ } ++ ++ if (inType->elements[i + 1] == NULL) // last byte in the struct ++ break; ++ ++ // Count possible contiguous bytes ahead, up to 8. ++ unsigned short j; ++ ++ for (j = 1; j < 8; j++) ++ { ++ if (inType->elements[i + j] == NULL || ++ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) ++ break; ++ } ++ ++ i += j - 1; // allow for i++ before the test condition ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ needsPtr = ffi64_stret_needs_ptr( ++ inType->elements[i], &gprsUsed, &fprsUsed); ++ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ if (ioGPRCount) ++ *ioGPRCount = gprsUsed; ++ ++ if (ioFPRCount) ++ *ioFPRCount = fprsUsed; ++ ++ return needsPtr; ++} ++ ++/* ffi64_data_size ++ ++ Calculate the size in bytes of an ffi type. ++*/ ++ ++unsigned int ++ffi64_data_size( ++ const ffi_type* inType) ++{ ++ unsigned int size = 0; ++ ++ switch (inType->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ size = 1; ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ size = 2; ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_FLOAT: ++ size = 4; ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_DOUBLE: ++ size = 8; ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ size = 16; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ ffi64_struct_to_reg_form( ++ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); ++ break; ++ ++ case FFI_TYPE_VOID: ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ ++ return size; ++} ++ ++#endif /* defined(__ppc64__) */ ++#endif /* __ppc__ || __ppc64__ */ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +new file mode 100644 +index 0000000..7162fa1 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +@@ -0,0 +1,418 @@ ++#if defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc64-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 ++ stg r0,SF_RETURN(r1) // save return address ++ ++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. ++ stg r3,SF_ARG1(r1) ++ stg r4,SF_ARG2(r1) ++ stg r5,SF_ARG3(r1) ++ stg r6,SF_ARG4(r1) ++ stg r7,SF_ARG5(r1) ++ stg r8,SF_ARG6(r1) ++ stg r9,SF_ARG7(r1) ++ stg r10,SF_ARG8(r1) ++ ++LCFI0: ++/* 48 bytes (Linkage Area) ++ 64 bytes (outgoing parameter area, always reserved) ++ 112 bytes (14*8 for incoming FPR) ++ ? bytes (result) ++ 112 bytes (14*8 for outgoing FPR) ++ 16 bytes (2 saved registers) ++ 352 + ? total bytes ++*/ ++ ++ std r31,-8(r1) // Save registers we use. ++ std r30,-16(r1) ++ mr r30,r1 // Save the old SP. ++ mr r31,r11 // Save the ffi_closure around ffi64_data_size. ++ ++ // Calculate the space we need. ++ stdu r1,-SF_MINSIZE(r1) ++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ bl Lffi64_data_size$stub ++ ld r1,0(r1) ++ ++ addi r3,r3,352 // Add our overhead. ++ neg r3,r3 ++ li r0,-32 // Align to 32 bytes. ++ and r3,r3,r0 ++ stdux r1,r1,r3 // Grow the stack. ++ ++ mr r11,r31 // Copy the ffi_closure back. ++ ++LCFI1: ++ // We want to build up an area for the parameters passed ++ // in registers. (both floating point and integer) ++ ++/* 320 bytes (callee stack frame aligned to 32) ++ 48 bytes (caller linkage area) ++ 368 (start of caller parameter area aligned to 8) ++*/ ++ ++ // Save FPRs 1 - 14. (aligned to 8) ++ stfd f1,112(r1) ++ stfd f2,120(r1) ++ stfd f3,128(r1) ++ stfd f4,136(r1) ++ stfd f5,144(r1) ++ stfd f6,152(r1) ++ stfd f7,160(r1) ++ stfd f8,168(r1) ++ stfd f9,176(r1) ++ stfd f10,184(r1) ++ stfd f11,192(r1) ++ stfd f12,200(r1) ++ stfd f13,208(r1) ++ stfd f14,216(r1) ++ ++ // Set up registers for the routine that actually does the work. ++ mr r3,r11 // context pointer from the trampoline ++ addi r4,r1,224 // result storage ++ addi r5,r30,SF_ARG1 // saved GPRs ++ addi r6,r1,112 // saved FPRs ++ bl Lffi_closure_helper_DARWIN$stub ++ ++ // Look the proper starting point in table ++ // by using return type as an offset. ++ addi r5,r1,224 // 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. ++ mtctr r3 ++ bctr ++ ++LFE1: ++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ // (4 instructions). For cache effectiveness we align to a 16 byte ++ // boundary first. ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++// case FFI_TYPE_VOID ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++// case FFI_TYPE_INT ++Lret_type1: ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_FLOAT ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_DOUBLE ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_LONGDOUBLE ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT8 ++Lret_type5: ++ lbz r3,7(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT8 ++Lret_type6: ++ lbz r3,7(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT16 ++Lret_type7: ++ lhz r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT16 ++Lret_type8: ++ lha r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT32 ++Lret_type9: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT32 ++Lret_type10: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT64 ++Lret_type11: ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT64 ++Lret_type12: // same as Lret_type11 ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_STRUCT ++Lret_type13: ++ b Lret_struct ++ nop ++ nop ++ nop ++ ++// ** End 16-byte aligned cases ** ++// case FFI_TYPE_POINTER ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ b Lfinish ++ ++// copy struct into registers ++Lret_struct: ++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r31) // ffi_cif->rtype* ++ ld r31,24(r31) // ffi_cif->flags ++ mr r4,r5 // copy struct* to 2nd arg ++ addi r7,r1,SF_ARG9 // GPR return area ++ addi r9,r30,-16-(14*8) // FPR return area ++ li r5,0 // struct offset ptr (NULL) ++ li r6,0 // FPR used count ptr (NULL) ++ li r8,0 // GPR return area size ptr (NULL) ++ li r10,0 // FPR return area size ptr (NULL) ++ bl Lffi64_struct_to_reg_form$stub ++ ++ // Load GPRs ++ ld r3,SF_ARG9(r1) ++ ld r4,SF_ARG10(r1) ++ ld r5,SF_ARG11(r1) ++ ld r6,SF_ARG12(r1) ++ nop ++ ld r7,SF_ARG13(r1) ++ ld r8,SF_ARG14(r1) ++ ld r9,SF_ARG15(r1) ++ ld r10,SF_ARG16(r1) ++ nop ++ ++ // Load FPRs ++ mtcrf 0x2,r31 ++ bf 26,Lfinish ++ lfd f1,-16-(14*8)(r30) ++ lfd f2,-16-(13*8)(r30) ++ lfd f3,-16-(12*8)(r30) ++ lfd f4,-16-(11*8)(r30) ++ nop ++ lfd f5,-16-(10*8)(r30) ++ lfd f6,-16-(9*8)(r30) ++ lfd f7,-16-(8*8)(r30) ++ lfd f8,-16-(7*8)(r30) ++ nop ++ lfd f9,-16-(6*8)(r30) ++ lfd f10,-16-(5*8)(r30) ++ lfd f11,-16-(4*8)(r30) ++ lfd f12,-16-(3*8)(r30) ++ nop ++ lfd f13,-16-(2*8)(r30) ++ lfd f14,-16-(1*8)(r30) ++ // Fall through ++ ++// case done ++Lfinish: ++ 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. ++ blr ++ ++// END(ffi_closure_ASM) ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_reg_form$stub: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_reg_form ++ ++LO$ffi64_struct_to_reg_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) ++ mtctr r12 ++ bctr ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_data_size$stub: ++ .indirect_symbol _ffi64_data_size ++ mflr r0 ++ bcl 20,31,LO$ffi64_data_size ++ ++LO$ffi64_data_size: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_reg_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ .g_long dyld_stub_binding_helper ++ ++L_ffi64_data_size$lazy_ptr: ++ .indirect_symbol _ffi64_data_size ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c +new file mode 100644 +index 0000000..44806ae +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/types.c +@@ -0,0 +1,115 @@ ++/* ----------------------------------------------------------------------- ++ types.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Predefined ffi_types needed by libffi. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++/* Type definitions */ ++#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \ ++ ffi_type ffi_type_##n = { s, a, t, NULL } ++#define FFI_AGGREGATE_TYPEDEF(n, e) \ ++ ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } ++ ++FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); ++FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); ++FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); ++FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); ++FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); ++FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); ++FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); ++ ++/* Size and alignment are fake here. They must not be 0. */ ++FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); ++ ++#if defined ALPHA || defined SPARC64 || defined X86_64 || \ ++ defined S390X || defined IA64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); ++#else ++FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); ++#endif ++ ++#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN) ++ ++# ifdef X86_64 ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++# else ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++# endif ++ ++#elif defined(POWERPC_DARWIN) ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#elif defined SH ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++#else ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#endif ++ ++#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN) ++ ++# if defined X86_WIN32 || defined X86_64 ++ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++# endif ++ ++# ifdef X86_DARWIN ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined ARM || defined SH || defined POWERPC_AIX ++FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); ++#elif defined POWERPC_DARWIN ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# if __GNUC__ >= 4 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined SPARC ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# ifdef SPARC64 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined X86_64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++#else ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S +new file mode 100644 +index 0000000..165d469 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S +@@ -0,0 +1,417 @@ ++/* ----------------------------------------------------------------------- ++ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. ++ derived from unix64.S ++ ++ x86-64 Foreign Function Interface for Darwin. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifdef __x86_64__ ++#define LIBFFI_ASM ++#include ++#include ++ ++ .file "darwin64.S" ++.text ++ ++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, ++ void *raddr, void (*fnaddr)()); ++ ++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame ++ for this function. This has been allocated by ffi_call. We also ++ deallocate some of the stack that has been alloca'd. */ ++ ++ .align 3 ++ .globl _ffi_call_unix64 ++ ++_ffi_call_unix64: ++LUW0: ++ movq (%rsp), %r10 /* Load return address. */ ++ movq %rdi, %r12 /* Save a copy of the register area. */ ++ leaq (%rdi, %rsi), %rax /* Find local stack base. */ ++ movq %rdx, (%rax) /* Save flags. */ ++ movq %rcx, 8(%rax) /* Save raddr. */ ++ movq %rbp, 16(%rax) /* Save old frame pointer. */ ++ movq %r10, 24(%rax) /* Relocate return address. */ ++ movq %rax, %rbp /* Finalize local stack frame. */ ++LUW1: ++ /* movq %rdi, %r10 // Save a copy of the register area. */ ++ movq %r12, %r10 ++ movq %r8, %r11 /* Save a copy of the target fn. */ ++ movl %r9d, %eax /* Set number of SSE registers. */ ++ ++ /* Load up all argument registers. */ ++ movq (%r10), %rdi ++ movq 8(%r10), %rsi ++ movq 16(%r10), %rdx ++ movq 24(%r10), %rcx ++ movq 32(%r10), %r8 ++ movq 40(%r10), %r9 ++ testl %eax, %eax ++ jnz Lload_sse ++Lret_from_load_sse: ++ ++ /* Deallocate the reg arg area. */ ++ leaq 176(%r10), %rsp ++ ++ /* Call the user function. */ ++ call *%r11 ++ ++ /* Deallocate stack arg area; local stack frame in redzone. */ ++ leaq 24(%rbp), %rsp ++ ++ movq 0(%rbp), %rcx /* Reload flags. */ ++ movq 8(%rbp), %rdi /* Reload raddr. */ ++ movq 16(%rbp), %rbp /* Reload old frame pointer. */ ++LUW2: ++ ++ /* The first byte of the flags contains the FFI_TYPE. */ ++ movzbl %cl, %r10d ++ leaq Lstore_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lstore_table: ++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ ++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ ++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ ++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ ++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ ++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ ++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ ++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ ++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lst_void: ++ ret ++ .align 3 ++Lst_uint8: ++ movzbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_sint8: ++ movsbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint16: ++ movzwq %ax, %rax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint16: ++ movswq %ax, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint32: ++ movl %eax, %eax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint32: ++ cltq ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_int64: ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_float: ++ movss %xmm0, (%rdi) ++ ret ++ .align 3 ++Lst_double: ++ movsd %xmm0, (%rdi) ++ ret ++Lst_ldouble: ++ fstpt (%rdi) ++ ret ++ .align 3 ++Lst_struct: ++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */ ++ ++ /* We have to locate the values now, and since we don't want to ++ write too much data into the user's return value, we spill the ++ value to a 16 byte scratch area first. Bits 8, 9, and 10 ++ control where the values are located. Only one of the three ++ bits will be set; see ffi_prep_cif_machdep for the pattern. */ ++ movd %xmm0, %r10 ++ movd %xmm1, %r11 ++ testl $0x100, %ecx ++ cmovnz %rax, %rdx ++ cmovnz %r10, %rax ++ testl $0x200, %ecx ++ cmovnz %r10, %rdx ++ testl $0x400, %ecx ++ cmovnz %r10, %rax ++ cmovnz %r11, %rdx ++ movq %rax, (%rsi) ++ movq %rdx, 8(%rsi) ++ ++ /* Bits 12-31 contain the true size of the structure. Copy from ++ the scratch area to the true destination. */ ++ shrl $12, %ecx ++ rep movsb ++ ret ++ ++ /* Many times we can avoid loading any SSE registers at all. ++ It's not worth an indirect jump to load the exact set of ++ SSE registers needed; zero or all is a good compromise. */ ++ .align 3 ++LUW3: ++Lload_sse: ++ movdqa 48(%r10), %xmm0 ++ movdqa 64(%r10), %xmm1 ++ movdqa 80(%r10), %xmm2 ++ movdqa 96(%r10), %xmm3 ++ movdqa 112(%r10), %xmm4 ++ movdqa 128(%r10), %xmm5 ++ movdqa 144(%r10), %xmm6 ++ movdqa 160(%r10), %xmm7 ++ jmp Lret_from_load_sse ++ ++LUW4: ++ .align 3 ++ .globl _ffi_closure_unix64 ++ ++_ffi_closure_unix64: ++LUW5: ++ /* The carry flag is set by the trampoline iff SSE registers ++ are used. Don't clobber it before the branch instruction. */ ++ leaq -200(%rsp), %rsp ++LUW6: ++ movq %rdi, (%rsp) ++ movq %rsi, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rcx, 24(%rsp) ++ movq %r8, 32(%rsp) ++ movq %r9, 40(%rsp) ++ jc Lsave_sse ++Lret_from_save_sse: ++ ++ movq %r10, %rdi ++ leaq 176(%rsp), %rsi ++ movq %rsp, %rdx ++ leaq 208(%rsp), %rcx ++ call _ffi_closure_unix64_inner ++ ++ /* Deallocate stack frame early; return value is now in redzone. */ ++ addq $200, %rsp ++LUW7: ++ ++ /* The first byte of the return value contains the FFI_TYPE. */ ++ movzbl %al, %r10d ++ leaq Lload_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lload_table: ++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */ ++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ ++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ ++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ ++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lld_void: ++ ret ++ .align 3 ++Lld_int8: ++ movzbl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int16: ++ movzwl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int32: ++ movl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int64: ++ movq -24(%rsp), %rax ++ ret ++ .align 3 ++Lld_float: ++ movss -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_double: ++ movsd -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_ldouble: ++ fldt -24(%rsp) ++ ret ++ .align 3 ++Lld_struct: ++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, ++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading ++ both rdx and xmm1 with the second word. For the remaining, ++ bit 8 set means xmm0 gets the second word, and bit 9 means ++ that rax gets the second word. */ ++ movq -24(%rsp), %rcx ++ movq -16(%rsp), %rdx ++ movq -16(%rsp), %xmm1 ++ testl $0x100, %eax ++ cmovnz %rdx, %rcx ++ movd %rcx, %xmm0 ++ testl $0x200, %eax ++ movq -24(%rsp), %rax ++ cmovnz %rdx, %rax ++ ret ++ ++ /* See the comment above Lload_sse; the same logic applies here. */ ++ .align 3 ++LUW8: ++Lsave_sse: ++ movdqa %xmm0, 48(%rsp) ++ movdqa %xmm1, 64(%rsp) ++ movdqa %xmm2, 80(%rsp) ++ movdqa %xmm3, 96(%rsp) ++ movdqa %xmm4, 112(%rsp) ++ movdqa %xmm5, 128(%rsp) ++ movdqa %xmm6, 144(%rsp) ++ movdqa %xmm7, 160(%rsp) ++ jmp Lret_from_save_sse ++ ++LUW9: ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ ++ .long L$set$0 ++LSCIE1: ++ .long 0x0 /* CIE Identifier Tag */ ++ .byte 0x1 /* CIE Version */ ++ .ascii "zR\0" /* CIE Augmentation */ ++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ ++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ ++ .byte 0x10 /* CIE RA Column */ ++ .byte 0x1 /* uleb128 0x1; Augmentation size */ ++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */ ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 /* uleb128 0x7 */ ++ .byte 0x8 /* uleb128 0x8 */ ++ .byte 0x90 /* DW_CFA_offset, column 0x10 */ ++ .byte 0x1 ++ .align 3 ++LECIE1: ++ .globl _ffi_call_unix64.eh ++_ffi_call_unix64.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ ++ .long L$set$1 ++LASFDE1: ++ .long LASFDE1-EH_frame1 /* FDE CIE offset */ ++ .quad LUW0-. /* FDE initial location */ ++ .set L$set$2,LUW4-LUW0 /* FDE address range */ ++ .quad L$set$2 ++ .byte 0x0 /* Augmentation size */ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$3,LUW1-LUW0 ++ .long L$set$3 ++ ++ /* New stack frame based off rbp. This is a itty bit of unwind ++ trickery in that the CFA *has* changed. There is no easy way ++ to describe it correctly on entry to the function. Fortunately, ++ it doesn't matter too much since at all points we can correctly ++ unwind back to ffi_call. Note that the location to which we ++ moved the return address is (the new) CFA-8, so from the ++ perspective of the unwind info, it hasn't moved. */ ++ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ ++ .byte 0x6 ++ .byte 0x20 ++ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ ++ .byte 0x2 ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$4,LUW2-LUW1 ++ .long L$set$4 ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 ++ .byte 0x8 ++ .byte 0xc0+6 /* DW_CFA_restore, %rbp */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$5,LUW3-LUW2 ++ .long L$set$5 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE1: ++ .globl _ffi_closure_unix64.eh ++_ffi_closure_unix64.eh: ++LSFDE3: ++ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ ++ .long L$set$6 ++LASFDE3: ++ .long LASFDE3-EH_frame1 /* FDE CIE offset */ ++ .quad LUW5-. /* FDE initial location */ ++ .set L$set$7,LUW9-LUW5 /* FDE address range */ ++ .quad L$set$7 ++ .byte 0x0 /* Augmentation size */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$8,LUW6-LUW5 ++ .long L$set$8 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 208,1 /* uleb128 208 */ ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$9,LUW7-LUW6 ++ .long L$set$9 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 0x8 ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$10,LUW8-LUW7 ++ .long L$set$10 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE3: ++ .subsections_via_symbols ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +new file mode 100644 +index 0000000..925a841 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +@@ -0,0 +1,422 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. ++ ++ X86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++/* ++ * This file is based on sysv.S and then hacked up by Ronald who hasn't done ++ * assembly programming in 8 years. ++ */ ++ ++#ifndef __x86_64__ ++ ++#define LIBFFI_ASM ++#include ++#include ++ ++#ifdef PyObjC_STRICT_DEBUGGING ++ /* XXX: Debugging of stack alignment, to be removed */ ++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 ++#else ++#define ASSERT_STACK_ALIGNED ++#endif ++ ++.text ++ ++.globl _ffi_prep_args ++ ++ .align 4 ++.globl _ffi_call_SYSV ++ ++_ffi_call_SYSV: ++LFB1: ++ pushl %ebp ++LCFI0: ++ movl %esp,%ebp ++LCFI1: ++ subl $8,%esp ++ /* Make room for all of the new args. */ ++ movl 16(%ebp),%ecx ++ subl %ecx,%esp ++ ++ movl %esp,%eax ++ ++ /* Place all of the ffi_prep_args in position */ ++ subl $8,%esp ++ pushl 12(%ebp) ++ pushl %eax ++ call *8(%ebp) ++ ++ /* Return stack to previous state and call the function */ ++ addl $16,%esp ++ ++ call *28(%ebp) ++ ++ /* 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 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 Lnoretval ++ fstp %st(0) ++ ++ jmp Lepilogue ++ ++Lretint: ++ cmpl $FFI_TYPE_INT,%ecx ++ jne Lretfloat ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ movl %eax,0(%ecx) ++ jmp Lepilogue ++ ++Lretfloat: ++ cmpl $FFI_TYPE_FLOAT,%ecx ++ jne Lretdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstps (%ecx) ++ jmp Lepilogue ++ ++Lretdouble: ++ cmpl $FFI_TYPE_DOUBLE,%ecx ++ jne Lretlongdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpl (%ecx) ++ jmp Lepilogue ++ ++Lretlongdouble: ++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx ++ jne Lretint64 ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpt (%ecx) ++ jmp Lepilogue ++ ++Lretint64: ++ cmpl $FFI_TYPE_SINT64,%ecx ++ 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 Lepilogue ++ ++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 ++ ++Lnoretval: ++Lepilogue: ++ addl $8,%esp ++ movl %ebp,%esp ++ popl %ebp ++ ret ++LFE1: ++.ffi_call_SYSV_end: ++ ++ .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_UINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_SINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_UINT16, %eax ++ je Lcls_retstruct2 ++ 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 ++ ++.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__ */ ++ ++#endif /* defined __i386__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +new file mode 100644 +index 0000000..06feaf2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +@@ -0,0 +1,734 @@ ++#ifdef __x86_64__ ++ ++/* ----------------------------------------------------------------------- ++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen ++ ++ x86-64 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_GPR_REGS 6 ++#define MAX_SSE_REGS 8 ++ ++typedef struct RegisterArgs { ++ /* Registers for argument passing. */ ++ UINT64 gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++} RegisterArgs; ++ ++extern void ++ffi_call_unix64( ++ void* args, ++ unsigned long bytes, ++ unsigned flags, ++ void* raddr, ++ void (*fnaddr)(), ++ unsigned ssecount); ++ ++/* All reference to register classes here is identical to the code in ++ gcc/config/i386/i386.c. Do *not* change one without the other. */ ++ ++/* 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 reformating penalties. ++ ++ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves ++ whenever possible (upper half does contain padding). */ ++enum x86_64_reg_class ++{ ++ X86_64_NO_CLASS, ++ X86_64_INTEGER_CLASS, ++ X86_64_INTEGERSI_CLASS, ++ X86_64_SSE_CLASS, ++ X86_64_SSESF_CLASS, ++ X86_64_SSEDF_CLASS, ++ X86_64_SSEUP_CLASS, ++ X86_64_X87_CLASS, ++ X86_64_X87UP_CLASS, ++ X86_64_COMPLEX_X87_CLASS, ++ X86_64_MEMORY_CLASS ++}; ++ ++#define MAX_CLASSES 4 ++#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) ++ ++/* x86-64 register passing implementation. See x86-64 ABI for details. Goal ++ of this code is to classify each 8bytes of incoming argument by the register ++ class and assign registers accordingly. */ ++ ++/* Return the union class of CLASS1 and CLASS2. ++ See the x86-64 PS ABI for details. */ ++static enum x86_64_reg_class ++merge_classes( ++ enum x86_64_reg_class class1, ++ enum x86_64_reg_class class2) ++{ ++ /* Rule #1: If both classes are equal, this is the resulting class. */ ++ if (class1 == class2) ++ return class1; ++ ++ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is ++ the other class. */ ++ if (class1 == X86_64_NO_CLASS) ++ return class2; ++ ++ if (class2 == X86_64_NO_CLASS) ++ return class1; ++ ++ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ ++ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ ++ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) ++ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) ++ return X86_64_INTEGERSI_CLASS; ++ ++ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS ++ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) ++ return X86_64_INTEGER_CLASS; ++ ++ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, ++ MEMORY is used. */ ++ if (class1 == X86_64_X87_CLASS ++ || class1 == X86_64_X87UP_CLASS ++ || class1 == X86_64_COMPLEX_X87_CLASS ++ || class2 == X86_64_X87_CLASS ++ || class2 == X86_64_X87UP_CLASS ++ || class2 == X86_64_COMPLEX_X87_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #6: Otherwise class SSE is used. */ ++ return X86_64_SSE_CLASS; ++} ++ ++/* Classify the argument of type TYPE and mode MODE. ++ CLASSES will be filled by the register class used to pass each word ++ of the operand. The number of words is returned. In case the parameter ++ should be passed in memory, 0 is returned. As a special case for zero ++ sized containers, classes[0] will be NO_CLASS and 1 is returned. ++ ++ See the x86-64 PS ABI for details. */ ++ ++static int ++classify_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[], ++ size_t byte_offset) ++{ ++ switch (type->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++#if 0 ++ if (byte_offset + type->size <= 4) ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ else ++ classes[0] = X86_64_INTEGER_CLASS; ++ ++ return 1; ++#else ++ { ++ int size = byte_offset + type->size; ++ ++ if (size <= 4) ++ { ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ return 1; ++ } ++ else if (size <= 8) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ return 1; ++ } ++ else if (size <= 12) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else if (size <= 16) ++ { ++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else ++ FFI_ASSERT (0); ++ } ++#endif ++ ++ case FFI_TYPE_FLOAT: ++ if (byte_offset == 0) ++ classes[0] = X86_64_SSESF_CLASS; ++ else ++ classes[0] = X86_64_SSE_CLASS; ++ ++ return 1; ++ ++ case FFI_TYPE_DOUBLE: ++ classes[0] = X86_64_SSEDF_CLASS; ++ return 1; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ classes[0] = X86_64_X87_CLASS; ++ classes[1] = X86_64_X87UP_CLASS; ++ return 2; ++ ++ case FFI_TYPE_STRUCT: ++ { ++ ffi_type** ptr; ++ int i; ++ enum x86_64_reg_class subclasses[MAX_CLASSES]; ++ const int UNITS_PER_WORD = 8; ++ int words = ++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ++ ++ /* If the struct is larger than 16 bytes, pass it on the stack. */ ++ if (type->size > 16) ++ return 0; ++ ++ for (i = 0; i < words; i++) ++ classes[i] = X86_64_NO_CLASS; ++ ++ /* Merge the fields of structure. */ ++ for (ptr = type->elements; *ptr != NULL; ptr++) ++ { ++ byte_offset = ALIGN(byte_offset, (*ptr)->alignment); ++ ++ int num = classify_argument(*ptr, subclasses, byte_offset % 8); ++ ++ if (num == 0) ++ return 0; ++ ++ int pos = byte_offset / 8; ++ ++ for (i = 0; i < num; i++) ++ { ++ classes[i + pos] = ++ merge_classes(subclasses[i], classes[i + pos]); ++ } ++ ++ byte_offset += (*ptr)->size; ++ } ++ ++ if (words > 2) ++ { ++ /* When size > 16 bytes, if the first one isn't ++ X86_64_SSE_CLASS or any other ones aren't ++ X86_64_SSEUP_CLASS, everything should be passed in ++ memory. */ ++ if (classes[0] != X86_64_SSE_CLASS) ++ return 0; ++ ++ for (i = 1; i < words; i++) ++ if (classes[i] != X86_64_SSEUP_CLASS) ++ return 0; ++ } ++ ++ ++ /* Final merger cleanup. */ ++ for (i = 0; i < words; i++) ++ { ++ /* If one class is MEMORY, everything should be passed in ++ memory. */ ++ if (classes[i] == X86_64_MEMORY_CLASS) ++ return 0; ++ ++ /* The X86_64_SSEUP_CLASS should be always preceded by ++ X86_64_SSE_CLASS. */ ++ if (classes[i] == X86_64_SSEUP_CLASS ++ && classes[i - 1] != X86_64_SSE_CLASS ++ && classes[i - 1] != X86_64_SSEUP_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ ++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ ++ if (classes[i] == X86_64_X87UP_CLASS ++ && classes[i - 1] != X86_64_X87_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ } ++ ++ return words; ++ } ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ return 0; /* Never reached. */ ++} ++ ++/* Examine the argument and return set number of register required in each ++ class. Return zero if parameter should be passed in memory, otherwise ++ the number of registers. */ ++static int ++examine_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[MAX_CLASSES], ++ _Bool in_return, ++ int* pngpr, ++ int* pnsse) ++{ ++ int n = classify_argument(type, classes, 0); ++ int ngpr = 0; ++ int nsse = 0; ++ int i; ++ ++ if (n == 0) ++ return 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ ngpr++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ nsse++; ++ break; ++ ++ case X86_64_NO_CLASS: ++ case X86_64_SSEUP_CLASS: ++ break; ++ ++ case X86_64_X87_CLASS: ++ case X86_64_X87UP_CLASS: ++ case X86_64_COMPLEX_X87_CLASS: ++ return in_return != 0; ++ ++ default: ++ abort(); ++ } ++ } ++ ++ *pngpr = ngpr; ++ *pnsse = nsse; ++ ++ return n; ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ int gprcount = 0; ++ int ssecount = 0; ++ int flags = cif->rtype->type; ++ int i, avn, n, ngpr, nsse; ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ size_t bytes; ++ ++ if (flags != FFI_TYPE_VOID) ++ { ++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value is passed in memory. A pointer to that ++ memory is the first argument. Allocate a register for it. */ ++ gprcount++; ++ ++ /* We don't have to do anything in asm for the return. */ ++ flags = FFI_TYPE_VOID; ++ } ++ else if (flags == FFI_TYPE_STRUCT) ++ { ++ /* Mark which registers the result appears in. */ ++ _Bool sse0 = SSE_CLASS_P(classes[0]); ++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]); ++ ++ if (sse0 && !sse1) ++ flags |= 1 << 8; ++ else if (!sse0 && sse1) ++ flags |= 1 << 9; ++ else if (sse0 && sse1) ++ flags |= 1 << 10; ++ ++ /* Mark the true size of the structure. */ ++ flags |= cif->rtype->size << 12; ++ } ++ } ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) ++ { ++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = cif->arg_types[i]->alignment; ++ ++ if (align < 8) ++ align = 8; ++ ++ bytes = ALIGN(bytes, align); ++ bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += ngpr; ++ ssecount += nsse; ++ } ++ } ++ ++ if (ssecount) ++ flags |= 1 << 11; ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ cif->bytes = ALIGN(bytes,8); ++ ++ return FFI_OK; ++} ++ ++void ++ffi_call( ++ ffi_cif* cif, ++ void (*fn)(), ++ void* rvalue, ++ void** avalue) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ char* stack; ++ char* argp; ++ ffi_type** arg_types; ++ int gprcount, ssecount, ngpr, nsse, i, avn; ++ _Bool ret_in_memory; ++ RegisterArgs* reg_args; ++ ++ /* Can't call 32-bit mode from 64-bit mode. */ ++ FFI_ASSERT(cif->abi == FFI_UNIX64); ++ ++ /* If the return value is a struct and we don't have a return value ++ address then we need to make one. Note the setting of flags to ++ VOID above in ffi_prep_cif_machdep. */ ++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT ++ && (cif->flags & 0xff) == FFI_TYPE_VOID); ++ ++ if (rvalue == NULL && ret_in_memory) ++ rvalue = alloca (cif->rtype->size); ++ ++ /* Allocate the space for the arguments, plus 4 words of temp space. */ ++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8); ++ reg_args = (RegisterArgs*)stack; ++ argp = stack + sizeof(RegisterArgs); ++ ++ gprcount = ssecount = 0; ++ ++ /* If the return value is passed in memory, add the pointer as the ++ first integer argument. */ ++ if (ret_in_memory) ++ reg_args->gpr[gprcount++] = (long) rvalue; ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ size_t size = arg_types[i]->size; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ memcpy (argp, avalue[i], size); ++ argp += size; ++ } ++ else ++ { /* The argument is passed entirely in registers. */ ++ char *a = (char *) avalue[i]; ++ int j; ++ ++ for (j = 0; j < n; j++, a += 8, size -= 8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ reg_args->gpr[gprcount] = 0; ++ switch (arg_types[i]->type) { ++ case FFI_TYPE_SINT8: ++ { ++ int8_t shortval = *(int8_t*)a; ++ int64_t actval = (int64_t)shortval; ++ reg_args->gpr[gprcount] = actval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ break; ++ } ++ ++ case FFI_TYPE_SINT16: ++ { ++ int16_t shortval = *(int16_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_SINT32: ++ { ++ int32_t shortval = *(int32_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT8: ++ { ++ u_int8_t shortval = *(u_int8_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ reg_args->gpr[gprcount] = actval; ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ { ++ u_int16_t shortval = *(u_int16_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT32: ++ { ++ u_int32_t shortval = *(u_int32_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ default: ++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); ++ reg_args->gpr[gprcount] = *(int64_t*)a; ++ } ++ gprcount++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSEDF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT64 *) a; ++ break; ++ ++ case X86_64_SSESF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT32 *) a; ++ break; ++ ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++ ++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs), ++ cif->flags, rvalue, fn, ssecount); ++} ++ ++extern void ffi_closure_unix64(void); ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ if (cif->abi != FFI_UNIX64) ++ return FFI_BAD_ABI; ++ ++ volatile unsigned short* tramp = ++ (volatile unsigned short*)&closure->tramp[0]; ++ ++ tramp[0] = 0xbb49; /* mov , %r11 */ ++ *(void* volatile*)&tramp[1] = ffi_closure_unix64; ++ tramp[5] = 0xba49; /* mov , %r10 */ ++ *(void* volatile*)&tramp[6] = closure; ++ ++ /* Set the carry bit if the function uses any sse registers. ++ This is clc or stc, together with the first byte of the jmp. */ ++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; ++ tramp[11] = 0xe3ff; /* jmp *%r11 */ ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wmissing-prototypes" ++int ++ffi_closure_unix64_inner( ++ ffi_closure* closure, ++ void* rvalue, ++ RegisterArgs* reg_args, ++ char* argp) ++#pragma clang diagnostic pop ++{ ++ ffi_cif* cif = closure->cif; ++ void** avalue = alloca(cif->nargs * sizeof(void *)); ++ ffi_type** arg_types; ++ long i, avn; ++ int gprcount = 0; ++ int ssecount = 0; ++ int ngpr, nsse; ++ int ret; ++ ++ ret = cif->rtype->type; ++ ++ if (ret != FFI_TYPE_VOID) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value goes in memory. Arrange for the closure ++ return value to go directly back to the original caller. */ ++ rvalue = (void *) reg_args->gpr[gprcount++]; ++ ++ /* We don't have to do anything in asm for the return. */ ++ ret = FFI_TYPE_VOID; ++ } ++ else if (ret == FFI_TYPE_STRUCT && n == 2) ++ { ++ /* Mark which register the second word of the structure goes in. */ ++ _Bool sse0 = SSE_CLASS_P (classes[0]); ++ _Bool sse1 = SSE_CLASS_P (classes[1]); ++ ++ if (!sse0 && sse1) ++ ret |= 1 << 8; ++ else if (sse0 && !sse1) ++ ret |= 1 << 9; ++ } ++ } ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ avalue[i] = argp; ++ argp += arg_types[i]->size; ++ } ++ ++#if !defined(X86_DARWIN) ++ /* If the argument is in a single register, or two consecutive ++ registers, then we can use that address directly. */ ++ else if (n == 1 || (n == 2 && ++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1]))) ++ { ++ // The argument is in a single register. ++ if (SSE_CLASS_P (classes[0])) ++ { ++ avalue[i] = ®_args->sse[ssecount]; ++ ssecount += n; ++ } ++ else ++ { ++ avalue[i] = ®_args->gpr[gprcount]; ++ gprcount += n; ++ } ++ } ++#endif ++ ++ /* Otherwise, allocate space to make them consecutive. */ ++ else ++ { ++ char *a = alloca (16); ++ int j; ++ ++ avalue[i] = a; ++ ++ for (j = 0; j < n; j++, a += 8) ++ { ++ if (SSE_CLASS_P (classes[j])) ++ memcpy (a, ®_args->sse[ssecount++], 8); ++ else ++ memcpy (a, ®_args->gpr[gprcount++], 8); ++ } ++ } ++ } ++ ++ /* Invoke the closure. */ ++ closure->fun (cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell assembly how to perform return type promotions. */ ++ return ret; ++} ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +new file mode 100644 +index 0000000..706ea0f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +@@ -0,0 +1,438 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ++ Copyright (c) 2002 Ranjit Mathew ++ Copyright (c) 2002 Bo Thorsen ++ Copyright (c) 2002 Roger Sayle ++ ++ x86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments */ ++ ++void ffi_prep_args(char *stack, extended_cif *ecif); ++ ++void ffi_prep_args(char *stack, extended_cif *ecif) ++{ ++ 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) ++ { ++ *(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) ++{ ++ /* 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_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; ++ } ++ ++#ifdef X86_DARWIN ++ cif->bytes = (cif->bytes + 15) & ~0xF; ++#endif ++ ++ return FFI_OK; ++} ++ ++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 *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); ++ ++#endif /* X86_WIN32 */ ++ ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++ ++/** private members **/ ++ ++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 */ ++ ++unsigned int FFI_HIDDEN ++ffi_closure_SYSV_inner (closure, respp, args) ++ffi_closure *closure; ++void **respp; ++void *args; ++{ ++ // 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 - (__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) ++{ ++ if (cif->abi != FFI_SYSV) ++ return FFI_BAD_ABI; ++ ++ 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 ++ ++ffi_status ++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) ++{ ++ 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) ++{ ++ 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 *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++ ++#ifdef X86_WIN32 ++extern void ++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++#endif /* X86_WIN32 */ ++ ++void ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++#endif ++#endif // __i386__ +diff --git ./setup.py ./setup.py +index 46b92fe..2bf6b4b 100644 +--- ./setup.py ++++ ./setup.py +@@ -98,8 +98,14 @@ class PyBuildExt(build_ext): + self.detect_modules() + + # Remove modules that are present on the disabled list +- self.extensions = [ext for ext in self.extensions +- if ext.name not in disabled_module_list] ++ extensions = [ext for ext in self.extensions ++ if ext.name not in disabled_module_list] ++ # move ctypes to the end, it depends on other modules ++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) ++ if "_ctypes" in ext_map: ++ ctypes = extensions.pop(ext_map["_ctypes"]) ++ extensions.append(ctypes) ++ self.extensions = extensions + + # Fix up the autodetected modules, prefixing all the source files + # with Modules/ and adding Python's include directory to the path. +@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext): + # *** Uncomment these for TOGL extension only: + # -lGL -lGLU -lXext -lXmu \ + ++ def configure_ctypes_darwin(self, ext): ++ # Darwin (OS X) uses preconfigured files, in ++ # the Modules/_ctypes/libffi_osx directory. ++ srcdir = sysconfig.get_config_var('srcdir') ++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', ++ '_ctypes', 'libffi_osx')) ++ sources = [os.path.join(ffi_srcdir, p) ++ for p in ['ffi.c', ++ 'x86/darwin64.S', ++ 'x86/x86-darwin.S', ++ 'x86/x86-ffi_darwin.c', ++ 'x86/x86-ffi64.c', ++ 'powerpc/ppc-darwin.S', ++ 'powerpc/ppc-darwin_closure.S', ++ 'powerpc/ppc-ffi_darwin.c', ++ 'powerpc/ppc64-darwin_closure.S', ++ ]] ++ ++ # Add .S (preprocessed assembly) to C compiler source extensions. ++ self.compiler.src_extensions.append('.S') ++ ++ include_dirs = [os.path.join(ffi_srcdir, 'include'), ++ os.path.join(ffi_srcdir, 'powerpc')] ++ ext.include_dirs.extend(include_dirs) ++ ext.sources.extend(sources) ++ return True ++ + def configure_ctypes(self, ext): + if not self.use_system_libffi: +- (srcdir,) = sysconfig.get_config_vars('srcdir') ++ if sys.platform == 'darwin': ++ return self.configure_ctypes_darwin(ext) ++ ++ srcdir = sysconfig.get_config_var('srcdir') + ffi_builddir = os.path.join(self.build_temp, 'libffi') + ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + '_ctypes', 'libffi')) +@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext): + ffi_configfile): + from distutils.dir_util import mkpath + mkpath(ffi_builddir) +- config_args = [] ++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() ++ if (('--host=' in arg) or ('--build=' in arg))] ++ if not self.verbose: ++ config_args.append("-q") + + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. +@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext): + self.compiler.src_extensions.append('.S') + + include_dirs = [os.path.join(ffi_builddir, 'include'), +- ffi_builddir, ffi_srcdir] ++ ffi_builddir, ++ os.path.join(ffi_srcdir, 'src')] + extra_compile_args = fficonfig['ffi_cflags'].split() + +- ext.sources.extend(fficonfig['ffi_sources']) ++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in ++ fficonfig['ffi_sources']) + ext.include_dirs.extend(include_dirs) + ext.extra_compile_args.extend(extra_compile_args) + return True +@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext): + + if sys.platform == 'darwin': + sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + # XXX Is this still needed? + ## extra_link_args.extend(['-read_only_relocs', 'warning']) +@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext): + if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = find_file('ffi.h', [], inc_dirs) ++ if sys.platform == 'darwin': ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') ++ ++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] ++ if not ffi_inc or ffi_inc[0] == '': ++ ffi_inc = find_file('ffi.h', [], inc_dirs) + if ffi_inc is not None: + ffi_h = ffi_inc[0] + '/ffi.h' + fp = open(ffi_h) diff --git a/plugins/python-build/share/python-build/patches/2.5/Python-2.5/004_osx_libffi.patch b/plugins/python-build/share/python-build/patches/2.5/Python-2.5/004_osx_libffi.patch new file mode 100644 index 00000000..cd500771 --- /dev/null +++ b/plugins/python-build/share/python-build/patches/2.5/Python-2.5/004_osx_libffi.patch @@ -0,0 +1,6881 @@ +diff --git ./Modules/_ctypes/libffi_osx/LICENSE ./Modules/_ctypes/libffi_osx/LICENSE +new file mode 100644 +index 0000000..f591795 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/LICENSE +@@ -0,0 +1,20 @@ ++libffi - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++Permission is hereby granted, free of charge, to any person obtaining ++a copy of this software and associated documentation files (the ++``Software''), to deal in the Software without restriction, including ++without limitation the rights to use, copy, modify, merge, publish, ++distribute, sublicense, and/or sell copies of the Software, and to ++permit persons to whom the Software is furnished to do so, subject to ++the following conditions: ++ ++The above copyright notice and this permission notice shall be included ++in all copies or substantial portions of the Software. ++ ++THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++OTHER DEALINGS IN THE SOFTWARE. +diff --git ./Modules/_ctypes/libffi_osx/README ./Modules/_ctypes/libffi_osx/README +new file mode 100644 +index 0000000..1fc2747 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README +@@ -0,0 +1,500 @@ ++This directory contains the libffi package, which is not part of GCC but ++shipped with GCC as convenience. ++ ++Status ++====== ++ ++libffi-2.00 has not been released yet! This is a development snapshot! ++ ++libffi-1.20 was released on October 5, 1998. Check the libffi web ++page for updates: . ++ ++ ++What is libffi? ++=============== ++ ++Compilers for high level languages generate code that follow certain ++conventions. These conventions are necessary, in part, for separate ++compilation to work. One such convention is the "calling ++convention". The "calling convention" is essentially a set of ++assumptions made by the compiler about where function arguments will ++be found on entry to a function. A "calling convention" also specifies ++where the return value for a function is found. ++ ++Some programs may not know at the time of compilation what arguments ++are to be passed to a function. For instance, an interpreter may be ++told at run-time about the number and types of arguments used to call ++a given function. Libffi can be used in such programs to provide a ++bridge from the interpreter program to compiled code. ++ ++The libffi library provides a portable, high level programming ++interface to various calling conventions. This allows a programmer to ++call any function specified by a call interface description at run ++time. ++ ++Ffi stands for Foreign Function Interface. A foreign function ++interface is the popular name for the interface that allows code ++written in one language to call code written in another language. The ++libffi library really only provides the lowest, machine dependent ++layer of a fully featured foreign function interface. A layer must ++exist above libffi that handles type conversions for values passed ++between the two languages. ++ ++ ++Supported Platforms and Prerequisites ++===================================== ++ ++Libffi has been ported to: ++ ++ SunOS 4.1.3 & Solaris 2.x (SPARC-V8, SPARC-V9) ++ ++ Irix 5.3 & 6.2 (System V/o32 & n32) ++ ++ Intel x86 - Linux (System V ABI) ++ ++ Alpha - Linux and OSF/1 ++ ++ m68k - Linux (System V ABI) ++ ++ PowerPC - Linux (System V ABI, Darwin, AIX) ++ ++ ARM - Linux (System V ABI) ++ ++Libffi has been tested with the egcs 1.0.2 gcc compiler. Chances are ++that other versions will work. Libffi has also been built and tested ++with the SGI compiler tools. ++ ++On PowerPC, the tests failed (see the note below). ++ ++You must use GNU make to build libffi. SGI's make will not work. ++Sun's probably won't either. ++ ++If you port libffi to another platform, please let me know! I assume ++that some will be easy (x86 NetBSD), and others will be more difficult ++(HP). ++ ++ ++Installing libffi ++================= ++ ++[Note: before actually performing any of these installation steps, ++ you may wish to read the "Platform Specific Notes" below.] ++ ++First you must configure the distribution for your particular ++system. Go to the directory you wish to build libffi in and run the ++"configure" program found in the root directory of the libffi source ++distribution. ++ ++You may want to tell configure where to install the libffi library and ++header files. To do that, use the --prefix configure switch. Libffi ++will install under /usr/local by default. ++ ++If you want to enable extra run-time debugging checks use the the ++--enable-debug configure switch. This is useful when your program dies ++mysteriously while using libffi. ++ ++Another useful configure switch is --enable-purify-safety. Using this ++will add some extra code which will suppress certain warnings when you ++are using Purify with libffi. Only use this switch when using ++Purify, as it will slow down the library. ++ ++Configure has many other options. Use "configure --help" to see them all. ++ ++Once configure has finished, type "make". Note that you must be using ++GNU make. SGI's make will not work. Sun's probably won't either. ++You can ftp GNU make from prep.ai.mit.edu:/pub/gnu. ++ ++To ensure that libffi is working as advertised, type "make test". ++ ++To install the library and header files, type "make install". ++ ++ ++Using libffi ++============ ++ ++ The Basics ++ ---------- ++ ++Libffi assumes that you have a pointer to the function you wish to ++call and that you know the number and types of arguments to pass it, ++as well as the return type of the function. ++ ++The first thing you must do is create an ffi_cif object that matches ++the signature of the function you wish to call. The cif in ffi_cif ++stands for Call InterFace. To prepare a call interface object, use the ++following function: ++ ++ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, ++ unsigned int nargs, ++ ffi_type *rtype, ffi_type **atypes); ++ ++ CIF is a pointer to the call interface object you wish ++ to initialize. ++ ++ ABI is an enum that specifies the calling convention ++ to use for the call. FFI_DEFAULT_ABI defaults ++ to the system's native calling convention. Other ++ ABI's may be used with care. They are system ++ specific. ++ ++ NARGS is the number of arguments this function accepts. ++ libffi does not yet support vararg functions. ++ ++ RTYPE is a pointer to an ffi_type structure that represents ++ the return type of the function. Ffi_type objects ++ describe the types of values. libffi provides ++ ffi_type objects for many of the native C types: ++ signed int, unsigned int, signed char, unsigned char, ++ etc. There is also a pointer ffi_type object and ++ a void ffi_type. Use &ffi_type_void for functions that ++ don't return values. ++ ++ ATYPES is a vector of ffi_type pointers. ARGS must be NARGS long. ++ If NARGS is 0, this is ignored. ++ ++ ++ffi_prep_cif will return a status code that you are responsible ++for checking. It will be one of the following: ++ ++ FFI_OK - All is good. ++ ++ FFI_BAD_TYPEDEF - One of the ffi_type objects that ffi_prep_cif ++ came across is bad. ++ ++ ++Before making the call, the VALUES vector should be initialized ++with pointers to the appropriate argument values. ++ ++To call the the function using the initialized ffi_cif, use the ++ffi_call function: ++ ++void ffi_call(ffi_cif *cif, void *fn, void *rvalue, void **avalues); ++ ++ CIF is a pointer to the ffi_cif initialized specifically ++ for this function. ++ ++ FN is a pointer to the function you want to call. ++ ++ RVALUE is a pointer to a chunk of memory that is to hold the ++ result of the function call. Currently, it must be ++ at least one word in size (except for the n32 version ++ under Irix 6.x, which must be a pointer to an 8 byte ++ aligned value (a long long). It must also be at least ++ word aligned (depending on the return type, and the ++ system's alignment requirements). If RTYPE is ++ &ffi_type_void, this is ignored. If RVALUE is NULL, ++ the return value is discarded. ++ ++ AVALUES is a vector of void* that point to the memory locations ++ holding the argument values for a call. ++ If NARGS is 0, this is ignored. ++ ++ ++If you are expecting a return value from FN it will have been stored ++at RVALUE. ++ ++ ++ ++ An Example ++ ---------- ++ ++Here is a trivial example that calls puts() a few times. ++ ++ #include ++ #include ++ ++ int main() ++ { ++ ffi_cif cif; ++ ffi_type *args[1]; ++ void *values[1]; ++ char *s; ++ int rc; ++ ++ /* Initialize the argument info vectors */ ++ args[0] = &ffi_type_uint; ++ values[0] = &s; ++ ++ /* Initialize the cif */ ++ if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, ++ &ffi_type_uint, args) == FFI_OK) ++ { ++ s = "Hello World!"; ++ ffi_call(&cif, puts, &rc, values); ++ /* rc now holds the result of the call to puts */ ++ ++ /* values holds a pointer to the function's arg, so to ++ call puts() again all we need to do is change the ++ value of s */ ++ s = "This is cool!"; ++ ffi_call(&cif, puts, &rc, values); ++ } ++ ++ return 0; ++ } ++ ++ ++ ++ Aggregate Types ++ --------------- ++ ++Although libffi has no special support for unions or bit-fields, it is ++perfectly happy passing structures back and forth. You must first ++describe the structure to libffi by creating a new ffi_type object ++for it. Here is the definition of ffi_type: ++ ++ typedef struct _ffi_type ++ { ++ unsigned size; ++ short alignment; ++ short type; ++ struct _ffi_type **elements; ++ } ffi_type; ++ ++All structures must have type set to FFI_TYPE_STRUCT. You may set ++size and alignment to 0. These will be calculated and reset to the ++appropriate values by ffi_prep_cif(). ++ ++elements is a NULL terminated array of pointers to ffi_type objects ++that describe the type of the structure elements. These may, in turn, ++be structure elements. ++ ++The following example initializes a ffi_type object representing the ++tm struct from Linux's time.h: ++ ++ struct tm { ++ int tm_sec; ++ int tm_min; ++ int tm_hour; ++ int tm_mday; ++ int tm_mon; ++ int tm_year; ++ int tm_wday; ++ int tm_yday; ++ int tm_isdst; ++ /* Those are for future use. */ ++ long int __tm_gmtoff__; ++ __const char *__tm_zone__; ++ }; ++ ++ { ++ ffi_type tm_type; ++ ffi_type *tm_type_elements[12]; ++ int i; ++ ++ tm_type.size = tm_type.alignment = 0; ++ tm_type.elements = &tm_type_elements; ++ ++ for (i = 0; i < 9; i++) ++ tm_type_elements[i] = &ffi_type_sint; ++ ++ tm_type_elements[9] = &ffi_type_slong; ++ tm_type_elements[10] = &ffi_type_pointer; ++ tm_type_elements[11] = NULL; ++ ++ /* tm_type can now be used to represent tm argument types and ++ return types for ffi_prep_cif() */ ++ } ++ ++ ++ ++Platform Specific Notes ++======================= ++ ++ Intel x86 ++ --------- ++ ++There are no known problems with the x86 port. ++ ++ Sun SPARC - SunOS 4.1.3 & Solaris 2.x ++ ------------------------------------- ++ ++You must use GNU Make to build libffi on Sun platforms. ++ ++ MIPS - Irix 5.3 & 6.x ++ --------------------- ++ ++Irix 6.2 and better supports three different calling conventions: o32, ++n32 and n64. Currently, libffi only supports both o32 and n32 under ++Irix 6.x, but only o32 under Irix 5.3. Libffi will automatically be ++configured for whichever calling convention it was built for. ++ ++By default, the configure script will try to build libffi with the GNU ++development tools. To build libffi with the SGI development tools, set ++the environment variable CC to either "cc -32" or "cc -n32" before ++running configure under Irix 6.x (depending on whether you want an o32 ++or n32 library), or just "cc" for Irix 5.3. ++ ++With the n32 calling convention, when returning structures smaller ++than 16 bytes, be sure to provide an RVALUE that is 8 byte aligned. ++Here's one way of forcing this: ++ ++ double struct_storage[2]; ++ my_small_struct *s = (my_small_struct *) struct_storage; ++ /* Use s for RVALUE */ ++ ++If you don't do this you are liable to get spurious bus errors. ++ ++"long long" values are not supported yet. ++ ++You must use GNU Make to build libffi on SGI platforms. ++ ++ ARM - System V ABI ++ ------------------ ++ ++The ARM port was performed on a NetWinder running ARM Linux ELF ++(2.0.31) and gcc 2.8.1. ++ ++ ++ ++ PowerPC System V ABI ++ -------------------- ++ ++There are two `System V ABI's which libffi implements for PowerPC. ++They differ only in how small structures are returned from functions. ++ ++In the FFI_SYSV version, structures that are 8 bytes or smaller are ++returned in registers. This is what GCC does when it is configured ++for solaris, and is what the System V ABI I have (dated September ++1995) says. ++ ++In the FFI_GCC_SYSV version, all structures are returned the same way: ++by passing a pointer as the first argument to the function. This is ++what GCC does when it is configured for linux or a generic sysv ++target. ++ ++EGCS 1.0.1 (and probably other versions of EGCS/GCC) also has a ++inconsistency with the SysV ABI: When a procedure is called with many ++floating-point arguments, some of them get put on the stack. They are ++all supposed to be stored in double-precision format, even if they are ++only single-precision, but EGCS stores single-precision arguments as ++single-precision anyway. This causes one test to fail (the `many ++arguments' test). ++ ++ ++What's With The Crazy Comments? ++=============================== ++ ++You might notice a number of cryptic comments in the code, delimited ++by /*@ and @*/. These are annotations read by the program LCLint, a ++tool for statically checking C programs. You can read all about it at ++. ++ ++ ++History ++======= ++ ++1.20 Oct-5-98 ++ Raffaele Sena produces ARM port. ++ ++1.19 Oct-5-98 ++ Fixed x86 long double and long long return support. ++ m68k bug fixes from Andreas Schwab. ++ Patch for DU assembler compatibility for the Alpha from Richard ++ Henderson. ++ ++1.18 Apr-17-98 ++ Bug fixes and MIPS configuration changes. ++ ++1.17 Feb-24-98 ++ Bug fixes and m68k port from Andreas Schwab. PowerPC port from ++ Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. ++ ++1.16 Feb-11-98 ++ Richard Henderson produces Alpha port. ++ ++1.15 Dec-4-97 ++ Fixed an n32 ABI bug. New libtool, auto* support. ++ ++1.14 May-13-97 ++ libtool is now used to generate shared and static libraries. ++ Fixed a minor portability problem reported by Russ McManus ++ . ++ ++1.13 Dec-2-96 ++ Added --enable-purify-safety to keep Purify from complaining ++ about certain low level code. ++ Sparc fix for calling functions with < 6 args. ++ Linux x86 a.out fix. ++ ++1.12 Nov-22-96 ++ Added missing ffi_type_void, needed for supporting void return ++ types. Fixed test case for non MIPS machines. Cygnus Support ++ is now Cygnus Solutions. ++ ++1.11 Oct-30-96 ++ Added notes about GNU make. ++ ++1.10 Oct-29-96 ++ Added configuration fix for non GNU compilers. ++ ++1.09 Oct-29-96 ++ Added --enable-debug configure switch. Clean-ups based on LCLint ++ feedback. ffi_mips.h is always installed. Many configuration ++ fixes. Fixed ffitest.c for sparc builds. ++ ++1.08 Oct-15-96 ++ Fixed n32 problem. Many clean-ups. ++ ++1.07 Oct-14-96 ++ Gordon Irlam rewrites v8.S again. Bug fixes. ++ ++1.06 Oct-14-96 ++ Gordon Irlam improved the sparc port. ++ ++1.05 Oct-14-96 ++ Interface changes based on feedback. ++ ++1.04 Oct-11-96 ++ Sparc port complete (modulo struct passing bug). ++ ++1.03 Oct-10-96 ++ Passing struct args, and returning struct values works for ++ all architectures/calling conventions. Expanded tests. ++ ++1.02 Oct-9-96 ++ Added SGI n32 support. Fixed bugs in both o32 and Linux support. ++ Added "make test". ++ ++1.01 Oct-8-96 ++ Fixed float passing bug in mips version. Restructured some ++ of the code. Builds cleanly with SGI tools. ++ ++1.00 Oct-7-96 ++ First release. No public announcement. ++ ++ ++Authors & Credits ++================= ++ ++libffi was written by Anthony Green . ++ ++Portions of libffi were derived from Gianni Mariani's free gencall ++library for Silicon Graphics machines. ++ ++The closure mechanism was designed and implemented by Kresten Krab ++Thorup. ++ ++The Sparc port was derived from code contributed by the fine folks at ++Visible Decisions Inc . Further enhancements were ++made by Gordon Irlam at Cygnus Solutions . ++ ++The Alpha port was written by Richard Henderson at Cygnus Solutions. ++ ++Andreas Schwab ported libffi to m68k Linux and provided a number of ++bug fixes. ++ ++Geoffrey Keating ported libffi to the PowerPC. ++ ++Raffaele Sena ported libffi to the ARM. ++ ++Jesper Skov and Andrew Haley both did more than their fair share of ++stepping through the code and tracking down bugs. ++ ++Thanks also to Tom Tromey for bug fixes and configuration help. ++ ++Thanks to Jim Blandy, who provided some useful feedback on the libffi ++interface. ++ ++If you have a problem, or have found a bug, please send a note to ++green@cygnus.com. +diff --git ./Modules/_ctypes/libffi_osx/README.pyobjc ./Modules/_ctypes/libffi_osx/README.pyobjc +new file mode 100644 +index 0000000..405d85f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/README.pyobjc +@@ -0,0 +1,5 @@ ++This directory contains a slightly modified version of libffi, extracted from ++the GCC source-tree. ++ ++The only modifications are those that are necessary to compile libffi using ++the Apple provided compiler and outside of the GCC source tree. +diff --git ./Modules/_ctypes/libffi_osx/ffi.c ./Modules/_ctypes/libffi_osx/ffi.c +new file mode 100644 +index 0000000..bf42093 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/ffi.c +@@ -0,0 +1,226 @@ ++/* ----------------------------------------------------------------------- ++ prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++/* Round up to FFI_SIZEOF_ARG. */ ++#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) ++ ++/* Perform machine independent initialization of aggregate type ++ specifications. */ ++ ++static ffi_status ++initialize_aggregate( ++/*@out@*/ ffi_type* arg) ++{ ++/*@-usedef@*/ ++ ++ if (arg == NULL || arg->elements == NULL || ++ arg->size != 0 || arg->alignment != 0) ++ return FFI_BAD_TYPEDEF; ++ ++ ffi_type** ptr = &(arg->elements[0]); ++ ++ while ((*ptr) != NULL) ++ { ++ if (((*ptr)->size == 0) && (initialize_aggregate(*ptr) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#ifdef POWERPC_DARWIN ++ int curalign = (*ptr)->alignment; ++ ++ if (ptr != &(arg->elements[0])) ++ { ++ if (curalign > 4 && curalign != 16) ++ curalign = 4; ++ } ++ ++ arg->size = ALIGN(arg->size, curalign); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > curalign) ? ++ arg->alignment : curalign; ++#else ++ arg->size = ALIGN(arg->size, (*ptr)->alignment); ++ arg->size += (*ptr)->size; ++ arg->alignment = (arg->alignment > (*ptr)->alignment) ? ++ arg->alignment : (*ptr)->alignment; ++#endif ++ ++ ptr++; ++ } ++ ++ /* Structure size includes tail padding. This is important for ++ structures that fit in one register on ABIs like the PowerPC64 ++ Linux ABI that right justify small structs in a register. ++ It's also needed for nested structure layout, for example ++ struct A { long a; char b; }; struct B { struct A x; char y; }; ++ should find y at an offset of 2*sizeof(long) and result in a ++ total size of 3*sizeof(long). */ ++ arg->size = ALIGN(arg->size, arg->alignment); ++ ++ if (arg->size == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ return FFI_OK; ++ ++/*@=usedef@*/ ++} ++ ++#ifndef __CRIS__ ++/* The CRIS ABI specifies structure elements to have byte ++ alignment only, so it completely overrides this functions, ++ which assumes "natural" alignment and padding. */ ++ ++/* Perform machine independent ffi_cif preparation, then call ++ machine dependent routine. */ ++ ++#if defined(X86_DARWIN) ++ ++static inline bool ++struct_on_stack( ++ int size) ++{ ++ if (size > 8) ++ return true; ++ ++ /* This is not what the ABI says, but is what is really implemented */ ++ switch (size) ++ { ++ case 1: ++ case 2: ++ case 4: ++ case 8: ++ return false; ++ ++ default: ++ return true; ++ } ++} ++ ++#endif // defined(X86_DARWIN) ++ ++// Arguments' ffi_type->alignment must be nonzero. ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes) ++{ ++ if (cif == NULL) ++ return FFI_BAD_TYPEDEF; ++ ++ if (abi <= FFI_FIRST_ABI || abi > FFI_DEFAULT_ABI) ++ return FFI_BAD_ABI; ++ ++ unsigned int bytes = 0; ++ unsigned int i; ++ ffi_type** ptr; ++ ++ cif->abi = abi; ++ cif->arg_types = atypes; ++ cif->nargs = nargs; ++ cif->rtype = rtype; ++ cif->flags = 0; ++ ++ /* Initialize the return type if necessary */ ++ /*@-usedef@*/ ++ if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ /*@=usedef@*/ ++ ++ /* Perform a sanity check on the return type */ ++ FFI_ASSERT_VALID_TYPE(cif->rtype); ++ ++ /* x86-64 and s390 stack space allocation is handled in prep_machdep. */ ++#if !defined M68K && !defined __x86_64__ && !defined S390 && !defined PA ++ /* Make space for the return structure pointer */ ++ if (cif->rtype->type == FFI_TYPE_STRUCT ++#ifdef SPARC ++ && (cif->abi != FFI_V9 || cif->rtype->size > 32) ++#endif ++#ifdef X86_DARWIN ++ && (struct_on_stack(cif->rtype->size)) ++#endif ++ ) ++ bytes = STACK_ARG_SIZE(sizeof(void*)); ++#endif ++ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ /* Initialize any uninitialized aggregate type definitions */ ++ if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) ++ return FFI_BAD_TYPEDEF; ++ ++ if ((*ptr)->alignment == 0) ++ return FFI_BAD_TYPEDEF; ++ ++ /* Perform a sanity check on the argument type, do this ++ check after the initialization. */ ++ FFI_ASSERT_VALID_TYPE(*ptr); ++ ++#if defined(X86_DARWIN) ++ { ++ int align = (*ptr)->alignment; ++ ++ if (align > 4) ++ align = 4; ++ ++ if ((align - 1) & bytes) ++ bytes = ALIGN(bytes, align); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#elif !defined __x86_64__ && !defined S390 && !defined PA ++#ifdef SPARC ++ if (((*ptr)->type == FFI_TYPE_STRUCT ++ && ((*ptr)->size > 16 || cif->abi != FFI_V9)) ++ || ((*ptr)->type == FFI_TYPE_LONGDOUBLE ++ && cif->abi != FFI_V9)) ++ bytes += sizeof(void*); ++ else ++#endif ++ { ++ /* Add any padding if necessary */ ++ if (((*ptr)->alignment - 1) & bytes) ++ bytes = ALIGN(bytes, (*ptr)->alignment); ++ ++ bytes += STACK_ARG_SIZE((*ptr)->size); ++ } ++#endif ++ } ++ ++ cif->bytes = bytes; ++ ++ /* Perform machine dependent cif processing */ ++ return ffi_prep_cif_machdep(cif); ++} ++#endif /* not __CRIS__ */ +diff --git ./Modules/_ctypes/libffi_osx/include/ffi.h ./Modules/_ctypes/libffi_osx/include/ffi.h +new file mode 100644 +index 0000000..c104a5c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi.h +@@ -0,0 +1,355 @@ ++/* -----------------------------------------------------------------*-C-*- ++ libffi PyOBJC - Copyright (c) 1996-2003 Red Hat, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++/* ------------------------------------------------------------------- ++ The basic API is described in the README file. ++ ++ The raw API is designed to bypass some of the argument packing ++ and unpacking on architectures for which it can be avoided. ++ ++ The closure API allows interpreted functions to be packaged up ++ inside a C function pointer, so that they can be called as C functions, ++ with no understanding on the client side that they are interpreted. ++ It can also be used in other cases in which it is necessary to package ++ up a user specified parameter and a function pointer as a single ++ function pointer. ++ ++ The closure API must be implemented in order to get its functionality, ++ e.g. for use by gij. Routines are provided to emulate the raw API ++ if the underlying platform doesn't allow faster implementation. ++ ++ More details on the raw and closure API can be found in: ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00138.html ++ ++ and ++ ++ http://gcc.gnu.org/ml/java/1999-q3/msg00174.html ++ -------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_H ++#define LIBFFI_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* Specify which architecture libffi is configured for. */ ++#ifdef MACOSX ++# if defined(__i386__) || defined(__x86_64__) ++# define X86_DARWIN ++# elif defined(__ppc__) || defined(__ppc64__) ++# define POWERPC_DARWIN ++# else ++# error "Unsupported MacOS X CPU type" ++# endif ++#else ++#error "Unsupported OS type" ++#endif ++ ++/* ---- System configuration information --------------------------------- */ ++ ++#include "ffitarget.h" ++#include "fficonfig.h" ++ ++#ifndef LIBFFI_ASM ++ ++#include ++#include ++ ++/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). ++ But we can find it either under the correct ANSI name, or under GNU ++ C's internal name. */ ++#ifdef LONG_LONG_MAX ++# define FFI_LONG_LONG_MAX LONG_LONG_MAX ++#else ++# ifdef LLONG_MAX ++# define FFI_LONG_LONG_MAX LLONG_MAX ++# else ++# ifdef __GNUC__ ++# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ ++# endif ++# endif ++#endif ++ ++#if SCHAR_MAX == 127 ++# define ffi_type_uchar ffi_type_uint8 ++# define ffi_type_schar ffi_type_sint8 ++#else ++#error "char size not supported" ++#endif ++ ++#if SHRT_MAX == 32767 ++# define ffi_type_ushort ffi_type_uint16 ++# define ffi_type_sshort ffi_type_sint16 ++#elif SHRT_MAX == 2147483647 ++# define ffi_type_ushort ffi_type_uint32 ++# define ffi_type_sshort ffi_type_sint32 ++#else ++#error "short size not supported" ++#endif ++ ++#if INT_MAX == 32767 ++# define ffi_type_uint ffi_type_uint16 ++# define ffi_type_sint ffi_type_sint16 ++#elif INT_MAX == 2147483647 ++# define ffi_type_uint ffi_type_uint32 ++# define ffi_type_sint ffi_type_sint32 ++#elif INT_MAX == 9223372036854775807 ++# define ffi_type_uint ffi_type_uint64 ++# define ffi_type_sint ffi_type_sint64 ++#else ++#error "int size not supported" ++#endif ++ ++#define ffi_type_ulong ffi_type_uint64 ++#define ffi_type_slong ffi_type_sint64 ++ ++#if LONG_MAX == 2147483647 ++# if FFI_LONG_LONG_MAX != 9223372036854775807 ++# error "no 64-bit data type supported" ++# endif ++#elif LONG_MAX != 9223372036854775807 ++#error "long size not supported" ++#endif ++ ++/* The closure code assumes that this works on pointers, i.e. a size_t ++ can hold a pointer. */ ++ ++typedef struct _ffi_type { ++ size_t size; ++ unsigned short alignment; ++ unsigned short type; ++/*@null@*/ struct _ffi_type** elements; ++} ffi_type; ++ ++/* These are defined in types.c */ ++extern ffi_type ffi_type_void; ++extern ffi_type ffi_type_uint8; ++extern ffi_type ffi_type_sint8; ++extern ffi_type ffi_type_uint16; ++extern ffi_type ffi_type_sint16; ++extern ffi_type ffi_type_uint32; ++extern ffi_type ffi_type_sint32; ++extern ffi_type ffi_type_uint64; ++extern ffi_type ffi_type_sint64; ++extern ffi_type ffi_type_float; ++extern ffi_type ffi_type_double; ++extern ffi_type ffi_type_longdouble; ++extern ffi_type ffi_type_pointer; ++ ++typedef enum ffi_status { ++ FFI_OK = 0, ++ FFI_BAD_TYPEDEF, ++ FFI_BAD_ABI ++} ffi_status; ++ ++typedef unsigned FFI_TYPE; ++ ++typedef struct ffi_cif { ++ ffi_abi abi; ++ unsigned nargs; ++/*@dependent@*/ ffi_type** arg_types; ++/*@dependent@*/ ffi_type* rtype; ++ unsigned bytes; ++ unsigned flags; ++#ifdef FFI_EXTRA_CIF_FIELDS ++ FFI_EXTRA_CIF_FIELDS; ++#endif ++} ffi_cif; ++ ++/* ---- Definitions for the raw API -------------------------------------- */ ++ ++#ifndef FFI_SIZEOF_ARG ++# if LONG_MAX == 2147483647 ++# define FFI_SIZEOF_ARG 4 ++# elif LONG_MAX == 9223372036854775807 ++# define FFI_SIZEOF_ARG 8 ++# endif ++#endif ++ ++typedef union { ++ ffi_sarg sint; ++ ffi_arg uint; ++ float flt; ++ char data[FFI_SIZEOF_ARG]; ++ void* ptr; ++} ffi_raw; ++ ++void ++ffi_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_raw_size( ++ ffi_cif* cif); ++ ++/* This is analogous to the raw API, except it uses Java parameter ++ packing, even on 64-bit machines. I.e. on 64-bit machines ++ longs and doubles are followed by an empty 64-bit word. */ ++void ++ffi_java_raw_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ ffi_raw* avalue); ++ ++void ++ffi_java_ptrarray_to_raw( ++ ffi_cif* cif, ++ void** args, ++ ffi_raw* raw); ++ ++void ++ffi_java_raw_to_ptrarray( ++ ffi_cif* cif, ++ ffi_raw* raw, ++ void** args); ++ ++size_t ++ffi_java_raw_size( ++ ffi_cif* cif); ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#if FFI_CLOSURES ++ ++typedef struct ffi_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ void (*fun)(ffi_cif*,void*,void**,void*); ++ void* user_data; ++} ffi_closure; ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,void**,void*), ++ void* user_data); ++ ++void ffi_closure_free(void *); ++void *ffi_closure_alloc (size_t size, void **code); ++ ++typedef struct ffi_raw_closure { ++ char tramp[FFI_TRAMPOLINE_SIZE]; ++ ffi_cif* cif; ++ ++#if !FFI_NATIVE_RAW_API ++ /* if this is enabled, then a raw closure has the same layout ++ as a regular closure. We use this to install an intermediate ++ handler to do the transaltion, void** -> ffi_raw*. */ ++ void (*translate_args)(ffi_cif*,void*,void**,void*); ++ void* this_closure; ++#endif ++ ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*); ++ void* user_data; ++} ffi_raw_closure; ++ ++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_status ++ffi_prep_java_raw_closure( ++ ffi_raw_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*,void*,ffi_raw*,void*), ++ void* user_data); ++ ++#endif // FFI_CLOSURES ++ ++/* ---- Public interface definition -------------------------------------- */ ++ ++ffi_status ++ffi_prep_cif( ++/*@out@*/ /*@partial@*/ ffi_cif* cif, ++ ffi_abi abi, ++ unsigned int nargs, ++/*@dependent@*/ /*@out@*/ /*@partial@*/ ffi_type* rtype, ++/*@dependent@*/ ffi_type** atypes); ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ void** avalue); ++ ++/* Useful for eliminating compiler warnings */ ++#define FFI_FN(f) ((void (*)(void))f) ++ ++#endif // #ifndef LIBFFI_ASM ++/* ---- Definitions shared with assembly code ---------------------------- */ ++ ++/* If these change, update src/mips/ffitarget.h. */ ++#define FFI_TYPE_VOID 0 ++#define FFI_TYPE_INT 1 ++#define FFI_TYPE_FLOAT 2 ++#define FFI_TYPE_DOUBLE 3 ++ ++#ifdef HAVE_LONG_DOUBLE ++# define FFI_TYPE_LONGDOUBLE 4 ++#else ++# define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE ++#endif ++ ++#define FFI_TYPE_UINT8 5 ++#define FFI_TYPE_SINT8 6 ++#define FFI_TYPE_UINT16 7 ++#define FFI_TYPE_SINT16 8 ++#define FFI_TYPE_UINT32 9 ++#define FFI_TYPE_SINT32 10 ++#define FFI_TYPE_UINT64 11 ++#define FFI_TYPE_SINT64 12 ++#define FFI_TYPE_STRUCT 13 ++#define FFI_TYPE_POINTER 14 ++ ++/* This should always refer to the last type code (for sanity checks) */ ++#define FFI_TYPE_LAST FFI_TYPE_POINTER ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef LIBFFI_H +diff --git ./Modules/_ctypes/libffi_osx/include/ffi_common.h ./Modules/_ctypes/libffi_osx/include/ffi_common.h +new file mode 100644 +index 0000000..685a358 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffi_common.h +@@ -0,0 +1,102 @@ ++/* ----------------------------------------------------------------------- ++ ffi_common.h - Copyright (c) 1996 Red Hat, Inc. ++ ++ Common internal definitions and macros. Only necessary for building ++ libffi. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef FFI_COMMON_H ++#define FFI_COMMON_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "fficonfig.h" ++ ++/* Do not move this. Some versions of AIX are very picky about where ++ this is positioned. */ ++#ifdef __GNUC__ ++# define alloca __builtin_alloca ++#else ++# if HAVE_ALLOCA_H ++# include ++# else ++# ifdef _AIX ++# pragma alloca ++# else ++# ifndef alloca /* predefined by HP cc +Olibcalls */ ++char* alloca(); ++# endif ++# endif ++# endif ++#endif ++ ++/* Check for the existence of memcpy. */ ++#if STDC_HEADERS ++# include ++#else ++# ifndef HAVE_MEMCPY ++# define memcpy(d, s, n) bcopy((s), (d), (n)) ++# endif ++#endif ++ ++/*#if defined(FFI_DEBUG) ++#include ++#endif*/ ++ ++#ifdef FFI_DEBUG ++#include ++ ++/*@exits@*/ void ++ffi_assert( ++/*@temp@*/ char* expr, ++/*@temp@*/ char* file, ++ int line); ++void ++ffi_stop_here(void); ++void ++ffi_type_test( ++/*@temp@*/ /*@out@*/ ffi_type* a, ++/*@temp@*/ char* file, ++ int line); ++ ++# define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__)) ++# define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l))) ++# define FFI_ASSERT_VALID_TYPE(x) ffi_type_test(x, __FILE__, __LINE__) ++#else ++# define FFI_ASSERT(x) ++# define FFI_ASSERT_AT(x, f, l) ++# define FFI_ASSERT_VALID_TYPE(x) ++#endif // #ifdef FFI_DEBUG ++ ++#define ALIGN(v, a) (((size_t)(v) + (a) - 1) & ~((a) - 1)) ++ ++/* Perform machine dependent cif processing */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif); ++ ++/* Extended cif, used in callback from assembly routine */ ++typedef struct extended_cif { ++/*@dependent@*/ ffi_cif* cif; ++/*@dependent@*/ void* rvalue; ++/*@dependent@*/ void** avalue; ++} extended_cif; ++ ++/* Terse sized type definitions. */ ++typedef unsigned int UINT8 __attribute__((__mode__(__QI__))); ++typedef signed int SINT8 __attribute__((__mode__(__QI__))); ++typedef unsigned int UINT16 __attribute__((__mode__(__HI__))); ++typedef signed int SINT16 __attribute__((__mode__(__HI__))); ++typedef unsigned int UINT32 __attribute__((__mode__(__SI__))); ++typedef signed int SINT32 __attribute__((__mode__(__SI__))); ++typedef unsigned int UINT64 __attribute__((__mode__(__DI__))); ++typedef signed int SINT64 __attribute__((__mode__(__DI__))); ++typedef float FLOAT32; ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // #ifndef FFI_COMMON_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/fficonfig.h ./Modules/_ctypes/libffi_osx/include/fficonfig.h +new file mode 100644 +index 0000000..2172490 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/fficonfig.h +@@ -0,0 +1,150 @@ ++/* Manually created fficonfig.h for Darwin on PowerPC or Intel ++ ++ This file is manually generated to do away with the need for autoconf and ++ therefore make it easier to cross-compile and build fat binaries. ++ ++ NOTE: This file was added by PyObjC. ++*/ ++ ++#ifndef MACOSX ++#error "This file is only supported on Mac OS X" ++#endif ++ ++#if defined(__i386__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__x86_64__) ++# define BYTEORDER 1234 ++# undef HOST_WORDS_BIG_ENDIAN ++# undef WORDS_BIGENDIAN ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#elif defined(__ppc__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# if __GNUC__ >= 4 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++# else ++# undef HAVE_LONG_DOUBLE ++# define SIZEOF_LONG_DOUBLE 8 ++# endif ++ ++#elif defined(__ppc64__) ++# define BYTEORDER 4321 ++# define HOST_WORDS_BIG_ENDIAN 1 ++# define WORDS_BIGENDIAN 1 ++# define SIZEOF_DOUBLE 8 ++# define HAVE_LONG_DOUBLE 1 ++# define SIZEOF_LONG_DOUBLE 16 ++ ++#else ++#error "Unknown CPU type" ++#endif ++ ++/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP ++ systems. This function is required for `alloca.c' support on those systems. */ ++#undef CRAY_STACKSEG_END ++ ++/* Define to 1 if using `alloca.c'. */ ++/* #undef C_ALLOCA */ ++ ++/* Define to the flags needed for the .section .eh_frame directive. */ ++#define EH_FRAME_FLAGS "aw" ++ ++/* Define this if you want extra debugging. */ ++/* #undef FFI_DEBUG */ ++ ++/* Define this is you do not want support for the raw API. */ ++#define FFI_NO_RAW_API 1 ++ ++/* Define this if you do not want support for aggregate types. */ ++/* #undef FFI_NO_STRUCTS */ ++ ++/* Define to 1 if you have `alloca', as a function or macro. */ ++#define HAVE_ALLOCA 1 ++ ++/* Define to 1 if you have and it should be used (not on Ultrix). */ ++#define HAVE_ALLOCA_H 1 ++ ++/* Define if your assembler supports .register. */ ++/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ ++ ++/* Define if your assembler and linker support unaligned PC relative relocs. */ ++/* #undef HAVE_AS_SPARC_UA_PCREL */ ++ ++/* Define to 1 if you have the `memcpy' function. */ ++#define HAVE_MEMCPY 1 ++ ++/* Define if mmap with MAP_ANON(YMOUS) works. */ ++#define HAVE_MMAP_ANON 1 ++ ++/* Define if mmap of /dev/zero works. */ ++/* #undef HAVE_MMAP_DEV_ZERO */ ++ ++/* Define if read-only mmap of a plain file works. */ ++#define HAVE_MMAP_FILE 1 ++ ++/* Define if .eh_frame sections should be read-only. */ ++/* #undef HAVE_RO_EH_FRAME */ ++ ++/* Define to 1 if your C compiler doesn't accept -c and -o together. */ ++/* #undef NO_MINUS_C_MINUS_O */ ++ ++/* Name of package */ ++#define PACKAGE "libffi" ++ ++/* Define to the address where bug reports for this package should be sent. */ ++#define PACKAGE_BUGREPORT "http://gcc.gnu.org/bugs.html" ++ ++/* Define to the full name of this package. */ ++#define PACKAGE_NAME "libffi" ++ ++/* Define to the full name and version of this package. */ ++#define PACKAGE_STRING "libffi 2.1" ++ ++/* Define to the one symbol short name of this package. */ ++#define PACKAGE_TARNAME "libffi" ++ ++/* Define to the version of this package. */ ++#define PACKAGE_VERSION "2.1" ++ ++/* If using the C implementation of alloca, define if you know the ++ direction of stack growth for your system; otherwise it will be ++ automatically deduced at run-time. ++ STACK_DIRECTION > 0 => grows toward higher addresses ++ STACK_DIRECTION < 0 => grows toward lower addresses ++ STACK_DIRECTION = 0 => direction of growth unknown */ ++/* #undef STACK_DIRECTION */ ++ ++/* Define to 1 if you have the ANSI C header files. */ ++#define STDC_HEADERS 1 ++ ++/* Define this if you are using Purify and want to suppress spurious messages. */ ++/* #undef USING_PURIFY */ ++ ++/* Version number of package */ ++#define VERSION "2.1-pyobjc" ++ ++#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) .hidden name ++# else ++# define FFI_HIDDEN __attribute__((visibility ("hidden"))) ++# endif ++#else ++# ifdef LIBFFI_ASM ++# define FFI_HIDDEN(name) ++# else ++# define FFI_HIDDEN ++# endif ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ffitarget.h ./Modules/_ctypes/libffi_osx/include/ffitarget.h +new file mode 100644 +index 0000000..faaa30d +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ffitarget.h +@@ -0,0 +1,13 @@ ++/* Dispatch to the right ffitarget file. This file is PyObjC specific; in a ++ normal build, the build environment copies the file to the right location or ++ sets up the right include flags. We want to do neither because that would ++ make building fat binaries harder. ++*/ ++ ++#if defined(__i386__) || defined(__x86_64__) ++#include "x86-ffitarget.h" ++#elif defined(__ppc__) || defined(__ppc64__) ++#include "ppc-ffitarget.h" ++#else ++#error "Unsupported CPU type" ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +new file mode 100644 +index 0000000..2318421 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/ppc-ffitarget.h +@@ -0,0 +1,104 @@ ++/* -----------------------------------------------------------------*-C-*- ++ ppc-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for PowerPC. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if (defined(POWERPC) && defined(__powerpc64__)) || \ ++ (defined(POWERPC_DARWIN) && defined(__ppc64__)) ++#define POWERPC64 ++#endif ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++#ifdef POWERPC ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++# ifdef POWERPC64 ++ FFI_DEFAULT_ABI = FFI_LINUX64, ++# else ++ FFI_DEFAULT_ABI = FFI_GCC_SYSV, ++# endif ++#endif ++ ++#ifdef POWERPC_AIX ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_AIX, ++#endif ++ ++#ifdef POWERPC_DARWIN ++ FFI_AIX, ++ FFI_DARWIN, ++ FFI_DEFAULT_ABI = FFI_DARWIN, ++#endif ++ ++#ifdef POWERPC_FREEBSD ++ FFI_SYSV, ++ FFI_GCC_SYSV, ++ FFI_LINUX64, ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++#define FFI_NATIVE_RAW_API 0 ++ ++/* Needed for FFI_SYSV small structure returns. */ ++#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST) ++ ++#if defined(POWERPC64) /*|| defined(POWERPC_AIX)*/ ++# define FFI_TRAMPOLINE_SIZE 48 ++#elif defined(POWERPC_AIX) ++# define FFI_TRAMPOLINE_SIZE 24 ++#else ++# define FFI_TRAMPOLINE_SIZE 40 ++#endif ++ ++#ifndef LIBFFI_ASM ++# if defined(POWERPC_DARWIN) || defined(POWERPC_AIX) ++typedef struct ffi_aix_trampoline_struct { ++ void* code_pointer; /* Pointer to ffi_closure_ASM */ ++ void* toc; /* TOC */ ++ void* static_chain; /* Pointer to closure */ ++} ffi_aix_trampoline_struct; ++# endif ++#endif // #ifndef LIBFFI_ASM ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +new file mode 100644 +index 0000000..55c2b6c +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/include/x86-ffitarget.h +@@ -0,0 +1,88 @@ ++/* -----------------------------------------------------------------*-C-*- ++ x86-ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc. ++ Target configuration macros for x86 and x86-64. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ++ ----------------------------------------------------------------------- */ ++ ++#ifndef LIBFFI_TARGET_H ++#define LIBFFI_TARGET_H ++ ++/* ---- System specific configurations ----------------------------------- */ ++ ++#if defined(X86_64) && defined(__i386__) ++# undef X86_64 ++# define X86 ++#endif ++ ++#if defined(__x86_64__) ++# ifndef X86_64 ++# define X86_64 ++# endif ++#endif ++ ++/* ---- Generic type definitions ----------------------------------------- */ ++ ++#ifndef LIBFFI_ASM ++ ++typedef unsigned long ffi_arg; ++typedef signed long ffi_sarg; ++ ++typedef enum ffi_abi { ++ FFI_FIRST_ABI = 0, ++ ++ /* ---- Intel x86 Win32 ---------- */ ++#ifdef X86_WIN32 ++ FFI_SYSV, ++ FFI_STDCALL, ++ /* TODO: Add fastcall support for the sake of completeness */ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++#endif ++ ++ /* ---- Intel x86 and AMD x86-64 - */ ++#if !defined(X86_WIN32) && (defined(__i386__) || defined(__x86_64__)) ++ FFI_SYSV, ++ FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ ++# ifdef __i386__ ++ FFI_DEFAULT_ABI = FFI_SYSV, ++# else ++ FFI_DEFAULT_ABI = FFI_UNIX64, ++# endif ++#endif ++ ++ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1 ++} ffi_abi; ++ ++#endif // #ifndef LIBFFI_ASM ++ ++/* ---- Definitions for closures ----------------------------------------- */ ++ ++#define FFI_CLOSURES 1 ++ ++#if defined(X86_64) || (defined(__x86_64__) && defined(X86_DARWIN)) ++# define FFI_TRAMPOLINE_SIZE 24 ++# define FFI_NATIVE_RAW_API 0 ++#else ++# define FFI_TRAMPOLINE_SIZE 10 ++# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ ++#endif ++ ++#endif // #ifndef LIBFFI_TARGET_H +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +new file mode 100644 +index 0000000..f143dbd +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.S +@@ -0,0 +1,365 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.S - Copyright (c) 2000 John Hornkvist ++ Copyright (c) 2004 Free Software Foundation, Inc. ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include ++#include ++#include ++ ++.text ++ .align 2 ++.globl _ffi_prep_args ++ ++.text ++ .align 2 ++.globl _ffi_call_DARWIN ++ ++.text ++ .align 2 ++_ffi_call_DARWIN: ++LFB0: ++ mr r12,r8 /* We only need r12 until the call, ++ so it doesn't have to be saved. */ ++ ++LFB1: ++ /* Save the old stack pointer as AP. */ ++ mr r8,r1 ++ ++LCFI0: ++#if defined(__ppc64__) ++ /* Allocate the stack space we need. ++ r4 (size of input data) ++ 48 bytes (linkage area) ++ 40 bytes (saved registers) ++ 8 bytes (extra FPR) ++ r4 + 96 bytes total ++ */ ++ ++ addi r4,r4,-96 // Add our overhead. ++ li r0,-32 // Align to 32 bytes. ++ and r4,r4,r0 ++#endif ++ stgux r1,r1,r4 // Grow the stack. ++ mflr r9 ++ ++ /* Save registers we use. */ ++#if defined(__ppc64__) ++ std r27,-40(r8) ++#endif ++ stg r28,MODE_CHOICE(-16,-32)(r8) ++ stg r29,MODE_CHOICE(-12,-24)(r8) ++ stg r30,MODE_CHOICE(-8,-16)(r8) ++ stg r31,MODE_CHOICE(-4,-8)(r8) ++ stg r9,SF_RETURN(r8) /* return address */ ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ stg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++LCFI1: ++#if defined(__ppc64__) ++ mr r27,r3 // our extended_cif ++#endif ++ /* Save arguments over call. */ ++ mr r31,r5 /* flags, */ ++ mr r30,r6 /* rvalue, */ ++ mr r29,r7 /* function address, */ ++ mr r28,r8 /* our AP. */ ++ ++LCFI2: ++ /* Call ffi_prep_args. */ ++ mr r4,r1 ++ li r9,0 ++ mtctr r12 /* r12 holds address of _ffi_prep_args. */ ++ bctrl ++#if !defined(POWERPC_DARWIN) /* TOC unused in OS X */ ++ lg r2,MODE_CHOICE(20,40)(r1) ++#endif ++ ++ /* Now do the call. ++ Set up cr1 with bits 4-7 of the flags. */ ++ mtcrf 0x40,r31 ++ ++ /* Load all those argument registers. ++ We have set up a nice stack frame, just load it into registers. */ ++ lg r3,SF_ARG1(r1) ++ lg r4,SF_ARG2(r1) ++ lg r5,SF_ARG3(r1) ++ lg r6,SF_ARG4(r1) ++ nop ++ lg r7,SF_ARG5(r1) ++ lg r8,SF_ARG6(r1) ++ lg r9,SF_ARG7(r1) ++ lg r10,SF_ARG8(r1) ++ ++ /* Load all the FP registers. */ ++ bf 6,L2 /* No floats to load. */ ++#if defined(__ppc64__) ++ lfd f1,MODE_CHOICE(-16,-40)-(14*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ lfd f14,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#elif defined(__ppc__) ++ lfd f1,MODE_CHOICE(-16,-40)-(13*8)(r28) ++ lfd f2,MODE_CHOICE(-16,-40)-(12*8)(r28) ++ lfd f3,MODE_CHOICE(-16,-40)-(11*8)(r28) ++ lfd f4,MODE_CHOICE(-16,-40)-(10*8)(r28) ++ nop ++ lfd f5,MODE_CHOICE(-16,-40)-(9*8)(r28) ++ lfd f6,MODE_CHOICE(-16,-40)-(8*8)(r28) ++ lfd f7,MODE_CHOICE(-16,-40)-(7*8)(r28) ++ lfd f8,MODE_CHOICE(-16,-40)-(6*8)(r28) ++ nop ++ lfd f9,MODE_CHOICE(-16,-40)-(5*8)(r28) ++ lfd f10,MODE_CHOICE(-16,-40)-(4*8)(r28) ++ lfd f11,MODE_CHOICE(-16,-40)-(3*8)(r28) ++ lfd f12,MODE_CHOICE(-16,-40)-(2*8)(r28) ++ nop ++ lfd f13,MODE_CHOICE(-16,-40)-(1*8)(r28) ++#else ++#error undefined architecture ++#endif ++ ++L2: ++ mr r12,r29 // Put the target address in r12 as specified. ++ mtctr r12 // Get the address to call into CTR. ++ nop ++ nop ++ bctrl // Make the call. ++ ++ // Deal with the return value. ++#if defined(__ppc64__) ++ mtcrf 0x3,r31 // flags in cr6 and cr7 ++ bt 27,L(st_return_value) ++#elif defined(__ppc__) ++ mtcrf 0x1,r31 // flags in cr7 ++#else ++#error undefined architecture ++#endif ++ ++ bt 30,L(done_return_value) ++ bt 29,L(fp_return_value) ++ stg r3,0(r30) ++#if defined(__ppc__) ++ bf 28,L(done_return_value) // Store the second long if necessary. ++ stg r4,4(r30) ++#endif ++ // Fall through ++ ++L(done_return_value): ++ lg r1,0(r1) // Restore stack pointer. ++ // Restore the registers we used. ++ lg r9,SF_RETURN(r1) // return address ++ lg r31,MODE_CHOICE(-4,-8)(r1) ++ mtlr r9 ++ lg r30,MODE_CHOICE(-8,-16)(r1) ++ lg r29,MODE_CHOICE(-12,-24)(r1) ++ lg r28,MODE_CHOICE(-16,-32)(r1) ++#if defined(__ppc64__) ++ ld r27,-40(r1) ++#endif ++ blr ++ ++#if defined(__ppc64__) ++L(st_return_value): ++ // Grow the stack enough to fit the registers. Leave room for 8 args ++ // to trample the 1st 8 slots in param area. ++ stgu r1,-SF_ROUND(280)(r1) // 64 + 104 + 48 + 64 ++ ++ // Store GPRs ++ std r3,SF_ARG9(r1) ++ std r4,SF_ARG10(r1) ++ std r5,SF_ARG11(r1) ++ std r6,SF_ARG12(r1) ++ nop ++ std r7,SF_ARG13(r1) ++ std r8,SF_ARG14(r1) ++ std r9,SF_ARG15(r1) ++ std r10,SF_ARG16(r1) ++ ++ // Store FPRs ++ nop ++ bf 26,L(call_struct_to_ram_form) ++ stfd f1,SF_ARG17(r1) ++ stfd f2,SF_ARG18(r1) ++ stfd f3,SF_ARG19(r1) ++ stfd f4,SF_ARG20(r1) ++ nop ++ stfd f5,SF_ARG21(r1) ++ stfd f6,SF_ARG22(r1) ++ stfd f7,SF_ARG23(r1) ++ stfd f8,SF_ARG24(r1) ++ nop ++ stfd f9,SF_ARG25(r1) ++ stfd f10,SF_ARG26(r1) ++ stfd f11,SF_ARG27(r1) ++ stfd f12,SF_ARG28(r1) ++ nop ++ stfd f13,SF_ARG29(r1) ++ ++L(call_struct_to_ram_form): ++ ld r3,0(r27) // extended_cif->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ addi r4,r1,SF_ARG9 // stored GPRs ++ addi r6,r1,SF_ARG17 // stored FPRs ++ li r5,0 // GPR size ptr (NULL) ++ li r7,0 // FPR size ptr (NULL) ++ li r8,0 // FPR count ptr (NULL) ++ li r10,0 // struct offset (NULL) ++ mr r9,r30 // return area ++ bl Lffi64_struct_to_ram_form$stub ++ lg r1,0(r1) // Restore stack pointer. ++ b L(done_return_value) ++#endif ++ ++L(fp_return_value): ++ /* Do we have long double to store? */ ++ bf 31,L(fd_return_value) ++ stfd f1,0(r30) ++ stfd f2,8(r30) ++ b L(done_return_value) ++ ++L(fd_return_value): ++ /* Do we have double to store? */ ++ bf 28,L(float_return_value) ++ stfd f1,0(r30) ++ b L(done_return_value) ++ ++L(float_return_value): ++ /* We only have a float to store. */ ++ stfs f1,0(r30) ++ b L(done_return_value) ++ ++LFE1: ++/* END(_ffi_call_DARWIN) */ ++ ++/* Provide a null definition of _ffi_call_AIX. */ ++.text ++ .align 2 ++.globl _ffi_call_AIX ++.text ++ .align 2 ++_ffi_call_AIX: ++ blr ++/* END(_ffi_call_AIX) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_call_DARWIN.eh ++_ffi_call_DARWIN.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x08 ; uleb128 0x08 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$5,LCFI1-LCFI0 ++ .long L$set$5 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .byte 0x9f ; DW_CFA_offset, column 0x1f ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x9e ; DW_CFA_offset, column 0x1e ++ .byte 0x2 ; uleb128 0x2 ++ .byte 0x9d ; DW_CFA_offset, column 0x1d ++ .byte 0x3 ; uleb128 0x3 ++ .byte 0x9c ; DW_CFA_offset, column 0x1c ++ .byte 0x4 ; uleb128 0x4 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$6,LCFI2-LCFI1 ++ .long L$set$6 ++ .byte 0xd ; DW_CFA_def_cfa_register ++ .byte 0x1c ; uleb128 0x1c ++ .align LOG2_GPR_BYTES ++LEFDE1: ++ ++#if defined(__ppc64__) ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_ram_form$stub: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_ram_form ++ ++LO$ffi64_struct_to_ram_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_ram_form$lazy_ptr - LO$ffi64_struct_to_ram_form)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_ram_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_ram_form ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ ++#endif // __ppc__ || __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +new file mode 100644 +index 0000000..cf4bd50 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin.h +@@ -0,0 +1,85 @@ ++/* ----------------------------------------------------------------------- ++ ppc-darwin.h - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define L(x) x ++ ++#define SF_ARG9 MODE_CHOICE(56,112) ++#define SF_ARG10 MODE_CHOICE(60,120) ++#define SF_ARG11 MODE_CHOICE(64,128) ++#define SF_ARG12 MODE_CHOICE(68,136) ++#define SF_ARG13 MODE_CHOICE(72,144) ++#define SF_ARG14 MODE_CHOICE(76,152) ++#define SF_ARG15 MODE_CHOICE(80,160) ++#define SF_ARG16 MODE_CHOICE(84,168) ++#define SF_ARG17 MODE_CHOICE(88,176) ++#define SF_ARG18 MODE_CHOICE(92,184) ++#define SF_ARG19 MODE_CHOICE(96,192) ++#define SF_ARG20 MODE_CHOICE(100,200) ++#define SF_ARG21 MODE_CHOICE(104,208) ++#define SF_ARG22 MODE_CHOICE(108,216) ++#define SF_ARG23 MODE_CHOICE(112,224) ++#define SF_ARG24 MODE_CHOICE(116,232) ++#define SF_ARG25 MODE_CHOICE(120,240) ++#define SF_ARG26 MODE_CHOICE(124,248) ++#define SF_ARG27 MODE_CHOICE(128,256) ++#define SF_ARG28 MODE_CHOICE(132,264) ++#define SF_ARG29 MODE_CHOICE(136,272) ++ ++#define ASM_NEEDS_REGISTERS 4 ++#define NUM_GPR_ARG_REGISTERS 8 ++#define NUM_FPR_ARG_REGISTERS 13 ++ ++#define FFI_TYPE_1_BYTE(x) ((x) == FFI_TYPE_UINT8 || (x) == FFI_TYPE_SINT8) ++#define FFI_TYPE_2_BYTE(x) ((x) == FFI_TYPE_UINT16 || (x) == FFI_TYPE_SINT16) ++#define FFI_TYPE_4_BYTE(x) \ ++ ((x) == FFI_TYPE_UINT32 || (x) == FFI_TYPE_SINT32 ||\ ++ (x) == FFI_TYPE_INT || (x) == FFI_TYPE_FLOAT) ++ ++#if !defined(LIBFFI_ASM) ++ ++enum { ++ FLAG_RETURNS_NOTHING = 1 << (31 - 30), // cr7 ++ FLAG_RETURNS_FP = 1 << (31 - 29), ++ FLAG_RETURNS_64BITS = 1 << (31 - 28), ++ FLAG_RETURNS_128BITS = 1 << (31 - 31), ++ ++ FLAG_RETURNS_STRUCT = 1 << (31 - 27), // cr6 ++ FLAG_STRUCT_CONTAINS_FP = 1 << (31 - 26), ++ ++ FLAG_ARG_NEEDS_COPY = 1 << (31 - 7), ++ FLAG_FP_ARGUMENTS = 1 << (31 - 6), // cr1.eq; specified by ABI ++ FLAG_4_GPR_ARGUMENTS = 1 << (31 - 5), ++ FLAG_RETVAL_REFERENCE = 1 << (31 - 4) ++}; ++ ++#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*); ++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*); ++#endif ++ ++#endif // !defined(LIBFFI_ASM) +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +new file mode 100644 +index 0000000..c3d30c2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-darwin_closure.S +@@ -0,0 +1,308 @@ ++#if defined(__ppc__) ++ ++/* ----------------------------------------------------------------------- ++ ppc-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 // Save return address ++ stg r0,SF_RETURN(r1) ++ ++LCFI0: ++ /* 24/48 bytes (Linkage Area) ++ 32/64 bytes (outgoing parameter area, always reserved) ++ 104 bytes (13*8 from FPR) ++ 16/32 bytes (result) ++ 176/232 total bytes */ ++ ++ /* skip over caller save area and keep stack aligned to 16/32. */ ++ stgu r1,-SF_ROUND(176)(r1) ++ ++LCFI1: ++ /* We want to build up an area for the parameters passed ++ in registers. (both floating point and integer) */ ++ ++ /* 176/256 bytes (callee stack frame aligned to 16/32) ++ 24/48 bytes (caller linkage area) ++ 200/304 (start of caller parameter area aligned to 4/8) ++ */ ++ ++ /* Save GPRs 3 - 10 (aligned to 4/8) ++ in the parents outgoing area. */ ++ 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,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. ++ 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. Use it to look up in a table ++ so we know how to deal with each type. */ ++ 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 ++ ++LFE1: ++/* Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ (4 instructions). For cache effectiveness we align to a 16 byte boundary ++ first. */ ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++/* case FFI_TYPE_VOID */ ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* case FFI_TYPE_INT */ ++Lret_type1: ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_FLOAT */ ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_DOUBLE */ ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_LONGDOUBLE */ ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT8 */ ++Lret_type5: ++ lbz r3,3(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT8 */ ++Lret_type6: ++ lbz r3,3(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_UINT16 */ ++Lret_type7: ++ lhz r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT16 */ ++Lret_type8: ++ lha r3,2(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT32 */ ++Lret_type9: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_SINT32 */ ++Lret_type10: // same as Lret_type1 ++ lwz r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++/* case FFI_TYPE_UINT64 */ ++Lret_type11: ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_SINT64 */ ++Lret_type12: // same as Lret_type11 ++ lwz r3,0(r5) ++ lwz r4,4(r5) ++ b Lfinish ++ nop ++ ++/* case FFI_TYPE_STRUCT */ ++Lret_type13: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++/* End 16-byte aligned cases */ ++/* case FFI_TYPE_POINTER */ ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ // fall through ++ ++/* case done */ ++Lfinish: ++ 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) */ ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++ ++#endif // __ppc__ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +new file mode 100644 +index 0000000..8953d5f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc-ffi_darwin.c +@@ -0,0 +1,1776 @@ ++#if defined(__ppc__) || defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1998 Geoffrey Keating ++ ++ PowerPC Foreign Function Interface ++ ++ Darwin ABI support (c) 2001 John Hornkvist ++ AIX ABI support (c) 2002 Free Software Foundation, Inc. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if 0 ++#if defined(POWERPC_DARWIN) ++#include // for sys_icache_invalidate() ++#endif ++ ++#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 ++// points to one of these. ++typedef struct aix_fd_struct { ++ void* code_pointer; ++ void* toc; ++} aix_fd; ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments. ++ ++ The stack layout we want looks like this: ++ ++ | Return address from ffi_call_DARWIN | higher addresses ++ |--------------------------------------------| ++ | Previous backchain pointer 4/8 | stack pointer here ++ |--------------------------------------------|-\ <<< on entry to ++ | Saved r28-r31 (4/8)*4 | | ffi_call_DARWIN ++ |--------------------------------------------| | ++ | Parameters (at least 8*(4/8)=32/64) | | (176) +112 - +288 ++ |--------------------------------------------| | ++ | Space for GPR2 4/8 | | ++ |--------------------------------------------| | stack | ++ | Reserved (4/8)*2 | | grows | ++ |--------------------------------------------| | down V ++ | Space for callee's LR 4/8 | | ++ |--------------------------------------------| | lower addresses ++ | Saved CR 4/8 | | ++ |--------------------------------------------| | stack pointer here ++ | Current backchain pointer 4/8 | | during ++ |--------------------------------------------|-/ <<< ffi_call_DARWIN ++ ++ Note: ppc64 CR is saved in the low word of a long on the stack. ++*/ ++ ++/*@-exportheader@*/ ++void ++ffi_prep_args( ++ extended_cif* inEcif, ++ unsigned *const stack) ++/*@=exportheader@*/ ++{ ++ /* Copy the ecif to a local var so we can trample the arg. ++ BC note: test this with GP later for possible problems... */ ++ volatile extended_cif* ecif = inEcif; ++ ++ const unsigned bytes = ecif->cif->bytes; ++ const unsigned flags = ecif->cif->flags; ++ ++ /* Cast the stack arg from int* to long*. sizeof(long) == 4 in 32-bit mode ++ and 8 in 64-bit mode. */ ++ unsigned long *const longStack = (unsigned long *const)stack; ++ ++ /* 'stacktop' points at the previous backchain pointer. */ ++#if defined(__ppc64__) ++ // In ppc-darwin.s, an extra 96 bytes is reserved for the linkage area, ++ // saved registers, and an extra FPR. ++ unsigned long *const stacktop = ++ (unsigned long *)(unsigned long)((char*)longStack + bytes + 96); ++#elif defined(__ppc__) ++ unsigned long *const stacktop = longStack + (bytes / sizeof(long)); ++#else ++#error undefined architecture ++#endif ++ ++ /* 'fpr_base' points at the space for fpr1, and grows upwards as ++ we use FPR registers. */ ++ double* fpr_base = (double*)(stacktop - ASM_NEEDS_REGISTERS) - ++ NUM_FPR_ARG_REGISTERS; ++ ++#if defined(__ppc64__) ++ // 64-bit saves an extra register, and uses an extra FPR. Knock fpr_base ++ // down a couple pegs. ++ fpr_base -= 2; ++#endif ++ ++ unsigned int fparg_count = 0; ++ ++ /* 'next_arg' grows up as we put parameters in it. */ ++ unsigned long* next_arg = longStack + 6; /* 6 reserved positions. */ ++ ++ int i; ++ double double_tmp; ++ void** p_argv = ecif->avalue; ++ unsigned long gprvalue; ++ ffi_type** ptr = ecif->cif->arg_types; ++ ++ /* Check that everything starts aligned properly. */ ++ FFI_ASSERT(stack == SF_ROUND(stack)); ++ FFI_ASSERT(stacktop == SF_ROUND(stacktop)); ++ FFI_ASSERT(bytes == SF_ROUND(bytes)); ++ ++ /* Deal with return values that are actually pass-by-reference. ++ Rule: ++ Return values are referenced by r3, so r4 is the first parameter. */ ++ ++ if (flags & FLAG_RETVAL_REFERENCE) ++ *next_arg++ = (unsigned long)(char*)ecif->rvalue; ++ ++ /* Now for the arguments. */ ++ for (i = ecif->cif->nargs; i > 0; i--, ptr++, p_argv++) ++ { ++ switch ((*ptr)->type) ++ { ++ /* If a floating-point parameter appears before all of the general- ++ purpose registers are filled, the corresponding GPRs that match ++ the size of the floating-point parameter are shadowed for the ++ benefit of vararg and pre-ANSI functions. */ ++ case FFI_TYPE_FLOAT: ++ double_tmp = *(float*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg++; ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ double_tmp = *(double*)*p_argv; ++ ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *fpr_base++ = double_tmp; ++ ++ *(double*)next_arg = double_tmp; ++ ++ next_arg += MODE_CHOICE(2,1); ++ fparg_count++; ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++#elif defined(__ppc__) ++ if (fparg_count < NUM_FPR_ARG_REGISTERS - 1) ++ *(long double*)fpr_base = *(long double*)*p_argv; ++ else if (fparg_count == NUM_FPR_ARG_REGISTERS - 1) ++ *(double*)fpr_base = *(double*)*p_argv; ++#else ++#error undefined architecture ++#endif ++ ++ *(long double*)next_arg = *(long double*)*p_argv; ++ fparg_count += 2; ++ fpr_base += 2; ++ next_arg += MODE_CHOICE(4,2); ++ FFI_ASSERT(flags & FLAG_FP_ARGUMENTS); ++ ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++#if defined(__ppc64__) ++ gprvalue = *(long long*)*p_argv; ++ goto putgpr; ++#elif defined(__ppc__) ++ *(long long*)next_arg = *(long long*)*p_argv; ++ next_arg += 2; ++ break; ++#else ++#error undefined architecture ++#endif ++ ++ case FFI_TYPE_POINTER: ++ gprvalue = *(unsigned long*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT8: ++ gprvalue = *(unsigned char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT8: ++ gprvalue = *(signed char*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_UINT16: ++ gprvalue = *(unsigned short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_SINT16: ++ gprvalue = *(signed short*)*p_argv; ++ goto putgpr; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ ++ ffi64_struct_to_reg_form(*ptr, (char*)*p_argv, NULL, &fparg_count, ++ (char*)next_arg, &gprSize, (char*)fpr_base, &fprSize); ++ next_arg += gprSize / sizeof(long); ++ fpr_base += fprSize / sizeof(double); ++ ++#elif defined(__ppc__) ++ char* dest_cpy = (char*)next_arg; ++ ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. ++ Structures with 3 byte in size are padded upwards. */ ++ unsigned size_al = (*ptr)->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++ if (ecif->cif->abi == FFI_DARWIN) ++ { ++ if (size_al < 3) ++ dest_cpy += 4 - size_al; ++ } ++ ++ memcpy((char*)dest_cpy, (char*)*p_argv, size_al); ++ next_arg += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ gprvalue = *(unsigned*)*p_argv; ++ ++putgpr: ++ *next_arg++ = gprvalue; ++ break; ++ ++ default: ++ break; ++ } ++ } ++ ++ /* Check that we didn't overrun the stack... */ ++ //FFI_ASSERT(gpr_base <= stacktop - ASM_NEEDS_REGISTERS); ++ //FFI_ASSERT((unsigned *)fpr_base ++ // <= stacktop - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); ++ //FFI_ASSERT(flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); ++} ++ ++#if defined(__ppc64__) ++ ++bool ++ffi64_struct_contains_fp( ++ const ffi_type* inType) ++{ ++ bool containsFP = false; ++ unsigned int i; ++ ++ for (i = 0; inType->elements[i] != NULL && !containsFP; i++) ++ { ++ if (inType->elements[i]->type == FFI_TYPE_FLOAT || ++ inType->elements[i]->type == FFI_TYPE_DOUBLE || ++ inType->elements[i]->type == FFI_TYPE_LONGDOUBLE) ++ containsFP = true; ++ else if (inType->elements[i]->type == FFI_TYPE_STRUCT) ++ containsFP = ffi64_struct_contains_fp(inType->elements[i]); ++ } ++ ++ return containsFP; ++} ++ ++#endif // defined(__ppc64__) ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ /* All this is for the DARWIN ABI. */ ++ int i; ++ ffi_type** ptr; ++ int intarg_count = 0; ++ int fparg_count = 0; ++ unsigned int flags = 0; ++ unsigned int size_al = 0; ++ ++ /* All the machine-independent calculation of cif->bytes will be wrong. ++ Redo the calculation for DARWIN. */ ++ ++ /* Space for the frame pointer, callee's LR, CR, etc, and for ++ the asm's temp regs. */ ++ unsigned int bytes = (6 + ASM_NEEDS_REGISTERS) * sizeof(long); ++ ++ /* Return value handling. The rules are as follows: ++ - 32-bit (or less) integer values are returned in gpr3; ++ - Structures of size <= 4 bytes also returned in gpr3; ++ - 64-bit integer values and structures between 5 and 8 bytes are ++ returned in gpr3 and gpr4; ++ - Single/double FP values are returned in fpr1; ++ - Long double FP (if not equivalent to double) values are returned in ++ fpr1 and fpr2; ++ - Larger structures values are allocated space and a pointer is passed ++ as the first argument. */ ++ switch (cif->rtype->type) ++ { ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ flags |= FLAG_RETURNS_128BITS; ++ flags |= FLAG_RETURNS_FP; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_DOUBLE: ++ flags |= FLAG_RETURNS_64BITS; ++ /* Fall through. */ ++ case FFI_TYPE_FLOAT: ++ flags |= FLAG_RETURNS_FP; ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ flags |= FLAG_RETURNS_64BITS; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ { ++#if defined(__ppc64__) ++ ++ if (ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++ { ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ } ++ else ++ { ++ flags |= FLAG_RETURNS_STRUCT; ++ ++ if (ffi64_struct_contains_fp(cif->rtype)) ++ flags |= FLAG_STRUCT_CONTAINS_FP; ++ } ++ ++#elif defined(__ppc__) ++ ++ flags |= FLAG_RETVAL_REFERENCE; ++ flags |= FLAG_RETURNS_NOTHING; ++ intarg_count++; ++ ++#else ++#error undefined architecture ++#endif ++ break; ++ } ++ ++ case FFI_TYPE_VOID: ++ flags |= FLAG_RETURNS_NOTHING; ++ break; ++ ++ default: ++ /* Returns 32-bit integer, or similar. Nothing to do here. */ ++ break; ++ } ++ ++ /* The first NUM_GPR_ARG_REGISTERS words of integer arguments, and the ++ first NUM_FPR_ARG_REGISTERS fp arguments, go in registers; the rest ++ goes on the stack. Structures are passed as a pointer to a copy of ++ the structure. Stuff on the stack needs to keep proper alignment. */ ++ for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) ++ { ++ switch ((*ptr)->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ fparg_count++; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ case FFI_TYPE_LONGDOUBLE: ++ fparg_count += 2; ++ /* If this FP arg is going on the stack, it must be ++ 8-byte-aligned. */ ++ ++ if ( ++#if defined(__ppc64__) ++ fparg_count > NUM_FPR_ARG_REGISTERS + 1 ++#elif defined(__ppc__) ++ fparg_count > NUM_FPR_ARG_REGISTERS ++#else ++#error undefined architecture ++#endif ++ && intarg_count % 2 != 0) ++ intarg_count++; ++ ++ intarg_count += 2; ++ break; ++#endif // FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ /* 'long long' arguments are passed as two words, but ++ either both words must fit in registers or both go ++ on the stack. If they go on the stack, they must ++ be 8-byte-aligned. */ ++ if (intarg_count == NUM_GPR_ARG_REGISTERS - 1 ++ || (intarg_count >= NUM_GPR_ARG_REGISTERS ++ && intarg_count % 2 != 0)) ++ intarg_count++; ++ ++ intarg_count += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ size_al = (*ptr)->size; ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN((*ptr)->size, 8); ++ ++#if defined(__ppc64__) ++ // Look for FP struct members. ++ unsigned int j; ++ ++ for (j = 0; (*ptr)->elements[j] != NULL; j++) ++ { ++ if ((*ptr)->elements[j]->type == FFI_TYPE_FLOAT || ++ (*ptr)->elements[j]->type == FFI_TYPE_DOUBLE) ++ { ++ fparg_count++; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS) ++ intarg_count++; ++ } ++ else if ((*ptr)->elements[j]->type == FFI_TYPE_LONGDOUBLE) ++ { ++ fparg_count += 2; ++ ++ if (fparg_count > NUM_FPR_ARG_REGISTERS + 1) ++ intarg_count += 2; ++ } ++ else ++ intarg_count++; ++ } ++#elif defined(__ppc__) ++ intarg_count += (size_al + 3) / 4; ++#else ++#error undefined architecture ++#endif ++ ++ break; ++ ++ default: ++ /* Everything else is passed as a 4/8-byte word in a GPR, either ++ the object itself or a pointer to it. */ ++ intarg_count++; ++ break; ++ } ++ } ++ ++ /* Space for the FPR registers, if needed. */ ++ if (fparg_count != 0) ++ { ++ flags |= FLAG_FP_ARGUMENTS; ++#if defined(__ppc64__) ++ bytes += (NUM_FPR_ARG_REGISTERS + 1) * sizeof(double); ++#elif defined(__ppc__) ++ bytes += NUM_FPR_ARG_REGISTERS * sizeof(double); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ /* Stack space. */ ++#if defined(__ppc64__) ++ if ((intarg_count + fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + fparg_count) * sizeof(long); ++#elif defined(__ppc__) ++ if ((intarg_count + 2 * fparg_count) > NUM_GPR_ARG_REGISTERS) ++ bytes += (intarg_count + 2 * fparg_count) * sizeof(long); ++#else ++#error undefined architecture ++#endif ++ else ++ bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); ++ ++ /* The stack space allocated needs to be a multiple of 16/32 bytes. */ ++ bytes = SF_ROUND(bytes); ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ ++ return FFI_OK; ++} ++ ++/*@-declundef@*/ ++/*@-exportheader@*/ ++extern void ++ffi_call_AIX( ++/*@out@*/ extended_cif*, ++ unsigned, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++ ++extern void ++ffi_call_DARWIN( ++/*@out@*/ extended_cif*, ++ unsigned long, ++ unsigned, ++/*@out@*/ unsigned*, ++ void (*fn)(void), ++ void (*fn2)(extended_cif*, unsigned *const)); ++/*@=declundef@*/ ++/*@=exportheader@*/ ++ ++void ++ffi_call( ++/*@dependent@*/ ffi_cif* cif, ++ void (*fn)(void), ++/*@out@*/ void* rvalue, ++/*@dependent@*/ 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) && ++ (cif->rtype->type == FFI_TYPE_STRUCT)) ++ { ++ /*@-sysunrecog@*/ ++ ecif.rvalue = alloca(cif->rtype->size); ++ /*@=sysunrecog@*/ ++ } ++ else ++ ecif.rvalue = rvalue; ++ ++ switch (cif->abi) ++ { ++ case FFI_AIX: ++ /*@-usedef@*/ ++ ffi_call_AIX(&ecif, -cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ case FFI_DARWIN: ++ /*@-usedef@*/ ++ ffi_call_DARWIN(&ecif, -(long)cif->bytes, ++ cif->flags, ecif.rvalue, fn, ffi_prep_args); ++ /*@=usedef@*/ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++/* here I'd like to add the stack frame layout we use in darwin_closure.S ++ and aix_clsoure.S ++ ++ SP previous -> +---------------------------------------+ <--- child frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 4 ++ | saved CR 4 | ++ +---------------------------------------+ 8 ++ | saved LR 4 | ++ +---------------------------------------+ 12 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 16 ++ | reserved for binders 4 | ++ +---------------------------------------+ 20 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 24 ++ | always reserved 8*4=32 (previous GPRs)| ++ | according to the linkage convention | ++ | from AIX | ++ +---------------------------------------+ 56 ++ | our FPR area 13*8=104 | ++ | f1 | ++ | . | ++ | f13 | ++ +---------------------------------------+ 160 ++ | result area 8 | ++ +---------------------------------------+ 168 ++ | alignement to the next multiple of 16 | ++SP current --> +---------------------------------------+ 176 <- parent frame ++ | back chain to caller 4 | ++ +---------------------------------------+ 180 ++ | saved CR 4 | ++ +---------------------------------------+ 184 ++ | saved LR 4 | ++ +---------------------------------------+ 188 ++ | reserved for compilers 4 | ++ +---------------------------------------+ 192 ++ | reserved for binders 4 | ++ +---------------------------------------+ 196 ++ | saved TOC pointer 4 | ++ +---------------------------------------+ 200 ++ | always reserved 8*4=32 we store our | ++ | GPRs here | ++ | r3 | ++ | . | ++ | r10 | ++ +---------------------------------------+ 232 ++ | overflow part | ++ +---------------------------------------+ xxx ++ | ???? | ++ +---------------------------------------+ xxx ++*/ ++ ++#if !defined(POWERPC_DARWIN) ++ ++#define MIN_LINE_SIZE 32 ++ ++static void ++flush_icache( ++ char* addr) ++{ ++#ifndef _AIX ++ __asm__ volatile ( ++ "dcbf 0,%0\n" ++ "sync\n" ++ "icbi 0,%0\n" ++ "sync\n" ++ "isync" ++ : : "r" (addr) : "memory"); ++#endif ++} ++ ++static void ++flush_range( ++ char* addr, ++ int size) ++{ ++ int i; ++ ++ for (i = 0; i < size; i += MIN_LINE_SIZE) ++ flush_icache(addr + i); ++ ++ flush_icache(addr + size - 1); ++} ++ ++#endif // !defined(POWERPC_DARWIN) ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ switch (cif->abi) ++ { ++ case FFI_DARWIN: ++ { ++ FFI_ASSERT (cif->abi == FFI_DARWIN); ++ ++ unsigned int* tramp = (unsigned int*)&closure->tramp[0]; ++ ++#if defined(__ppc64__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0xe98b0018; // ld r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0xe96b0020; // ld r11,32(r11) ++ tramp[7] = 0x4e800420; // bctr ++ *(unsigned long*)&tramp[8] = (unsigned long)ffi_closure_ASM; ++ *(unsigned long*)&tramp[10] = (unsigned long)closure; ++#elif defined(__ppc__) ++ tramp[0] = 0x7c0802a6; // mflr r0 ++ tramp[1] = 0x429f0005; // bcl 20,31,+0x8 ++ tramp[2] = 0x7d6802a6; // mflr r11 ++ tramp[3] = 0x7c0803a6; // mtlr r0 ++ tramp[4] = 0x818b0018; // lwz r12,24(r11) ++ tramp[5] = 0x7d8903a6; // mtctr r12 ++ tramp[6] = 0x816b001c; // lwz r11,28(r11) ++ tramp[7] = 0x4e800420; // bctr ++ tramp[8] = (unsigned long)ffi_closure_ASM; ++ tramp[9] = (unsigned long)closure; ++#else ++#error undefined architecture ++#endif ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ // Flush the icache. Only necessary on Darwin. ++#if defined(POWERPC_DARWIN) ++ sys_icache_invalidate(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#else ++ flush_range(closure->tramp, FFI_TRAMPOLINE_SIZE); ++#endif ++ ++ break; ++ } ++ ++ case FFI_AIX: ++ { ++ FFI_ASSERT (cif->abi == FFI_AIX); ++ ++ ffi_aix_trampoline_struct* tramp_aix = ++ (ffi_aix_trampoline_struct*)(closure->tramp); ++ aix_fd* fd = (aix_fd*)(void*)ffi_closure_ASM; ++ ++ tramp_aix->code_pointer = fd->code_pointer; ++ tramp_aix->toc = fd->toc; ++ tramp_aix->static_chain = closure; ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ break; ++ } ++ ++ default: ++ return FFI_BAD_ABI; ++ } ++ ++ return FFI_OK; ++} ++ ++#if defined(__ppc__) ++ typedef double ldbits[2]; ++ ++ typedef union ++ { ++ ldbits lb; ++ long double ld; ++ } 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 ++ for a return value, ffi_closure_ASM invokes the following helper function ++ to do most of the work. */ ++int ++ffi_closure_helper_DARWIN( ++ ffi_closure* closure, ++ void* rvalue, ++ unsigned long* pgr, ++ ffi_dblfl* pfr) ++{ ++ /* rvalue is the pointer to space for return value in closure assembly ++ pgr is the pointer to where r3-r10 are stored in ffi_closure_ASM ++ pfr is the pointer to where f1-f13 are stored in ffi_closure_ASM. */ ++ ++#if defined(__ppc__) ++ ldu temp_ld; ++#endif ++ ++ double temp; ++ unsigned int i; ++ unsigned int nf = 0; /* number of FPRs already used. */ ++ unsigned int ng = 0; /* number of GPRs already used. */ ++ ffi_cif* cif = closure->cif; ++ long avn = cif->nargs; ++ void** avalue = alloca(cif->nargs * sizeof(void*)); ++ ffi_type** arg_types = cif->arg_types; ++ ++ /* Copy the caller's structure return value address so that the closure ++ returns the data directly to the caller. */ ++#if defined(__ppc64__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT && ++ ffi64_stret_needs_ptr(cif->rtype, NULL, NULL)) ++#elif defined(__ppc__) ++ if (cif->rtype->type == FFI_TYPE_STRUCT) ++#else ++#error undefined architecture ++#endif ++ { ++ rvalue = (void*)*pgr; ++ pgr++; ++ ng++; ++ } ++ ++ /* Grab the addresses of the arguments from the stack frame. */ ++ for (i = 0; i < avn; i++) ++ { ++ switch (arg_types[i]->type) ++ { ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT8: ++ avalue[i] = (char*)pgr + MODE_CHOICE(3,7); ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT16: ++ avalue[i] = (char*)pgr + MODE_CHOICE(2,6); ++ ng++; ++ pgr++; ++ break; ++ ++#if defined(__ppc__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT32: ++ avalue[i] = (char*)pgr + MODE_CHOICE(0,4); ++ ng++; ++ pgr++; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ if (cif->abi == FFI_DARWIN) ++ { ++#if defined(__ppc64__) ++ unsigned int gprSize = 0; ++ unsigned int fprSize = 0; ++ unsigned int savedFPRSize = fprSize; ++ ++ avalue[i] = alloca(arg_types[i]->size); ++ ffi64_struct_to_ram_form(arg_types[i], (const char*)pgr, ++ &gprSize, (const char*)pfr, &fprSize, &nf, avalue[i], NULL); ++ ++ ng += gprSize / sizeof(long); ++ pgr += gprSize / sizeof(long); ++ pfr += (fprSize - savedFPRSize) / sizeof(double); ++ ++#elif defined(__ppc__) ++ /* Structures that match the basic modes (QI 1 byte, HI 2 bytes, ++ SI 4 bytes) are aligned as if they were those modes. */ ++ unsigned int size_al = size_al = arg_types[i]->size; ++ ++ /* If the first member of the struct is a double, then align ++ the struct to double-word. */ ++ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) ++ size_al = ALIGN(arg_types[i]->size, 8); ++ ++ if (size_al < 3) ++ avalue[i] = (void*)pgr + MODE_CHOICE(4,8) - size_al; ++ else ++ avalue[i] = (void*)pgr; ++ ++ ng += (size_al + 3) / sizeof(long); ++ pgr += (size_al + 3) / sizeof(long); ++#else ++#error undefined architecture ++#endif ++ } ++ ++ break; ++ ++#if defined(__ppc64__) ++ case FFI_TYPE_POINTER: ++#endif ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_UINT64: ++ /* Long long ints are passed in 1 or 2 GPRs. */ ++ avalue[i] = pgr; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++ case FFI_TYPE_FLOAT: ++ /* A float value consumes a GPR. ++ There are 13 64-bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ temp = pfr->d; ++ pfr->f = (float)temp; ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng++; ++ pgr++; ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ /* A double value consumes one or two GPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr++; ++ } ++ else ++ avalue[i] = pgr; ++ ++ nf++; ++ ng += MODE_CHOICE(2,1); ++ pgr += MODE_CHOICE(2,1); ++ ++ break; ++ ++#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE ++ ++ case FFI_TYPE_LONGDOUBLE: ++#if defined(__ppc64__) ++ if (nf < NUM_FPR_ARG_REGISTERS) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++#elif defined(__ppc__) ++ /* A long double value consumes 2/4 GPRs and 2 FPRs. ++ There are 13 64bit floating point registers. */ ++ if (nf < NUM_FPR_ARG_REGISTERS - 1) ++ { ++ avalue[i] = pfr; ++ pfr += 2; ++ } ++ /* Here we have the situation where one part of the long double ++ is stored in fpr13 and the other part is already on the stack. ++ 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(temp_ld.lb[0])); ++ memcpy (&temp_ld.lb[1], pgr + 2, sizeof(temp_ld.lb[1])); ++ avalue[i] = &temp_ld.ld; ++ } ++#else ++#error undefined architecture ++#endif ++ else ++ avalue[i] = pgr; ++ ++ nf += 2; ++ ng += MODE_CHOICE(4,2); ++ pgr += MODE_CHOICE(4,2); ++ ++ break; ++ ++#endif /* FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE */ ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ (closure->fun)(cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell ffi_closure_ASM to perform return type promotions. */ ++ return cif->rtype->type; ++} ++ ++#if defined(__ppc64__) ++ ++/* ffi64_struct_to_ram_form ++ ++ Rebuild a struct's natural layout from buffers of concatenated registers. ++ Return the number of registers used. ++ inGPRs[0-7] == r3, inFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_ram_form( ++ const ffi_type* inType, ++ const char* inGPRs, ++ unsigned int* ioGPRMarker, ++ const char* inFPRs, ++ unsigned int* ioFPRMarker, ++ unsigned int* ioFPRsUsed, ++ char* outStruct, // caller-allocated ++ unsigned int* ioStructMarker) ++{ ++ unsigned int srcGMarker = 0; ++ unsigned int srcFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ unsigned int destMarker = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioGPRMarker) ++ srcGMarker = *ioGPRMarker; ++ ++ if (ioFPRMarker) ++ { ++ srcFMarker = *ioFPRMarker; ++ savedFMarker = srcFMarker; ++ } ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioStructMarker) ++ destMarker = *ioStructMarker; ++ ++ size_t i; ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ srcGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ srcFMarker = ALIGN(srcFMarker, 4); ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(float*)&outStruct[destMarker] = ++ (float)*(double*)&inGPRs[srcGMarker]; ++ ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcFMarker = ALIGN(srcFMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inFPRs[srcFMarker]; ++ srcFMarker += 8; ++ fprsUsed++; ++ } ++ else ++ *(double*)&outStruct[destMarker] = ++ *(double*)&inGPRs[srcGMarker]; ++ ++ destMarker += 8; ++ ++ // Skip next GPR ++ srcGMarker += 8; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ destMarker = ALIGN(destMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ srcFMarker = ALIGN(srcFMarker, 8); ++ srcGMarker = ALIGN(srcGMarker, 8); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inFPRs[srcFMarker]; ++ srcFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ srcFMarker = ALIGN(srcFMarker, 16); ++ srcGMarker = ALIGN(srcGMarker, 16); ++ *(long double*)&outStruct[destMarker] = ++ *(long double*)&inGPRs[srcGMarker]; ++ } ++ ++ destMarker += 16; ++ ++ // Skip next 2 GPRs ++ srcGMarker += 16; ++ srcGMarker = ALIGN(srcGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ if (inType->alignment == 1) // chars only ++ { ++ if (inType->size == 1) ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ else if (inType->size == 2) ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ i++; ++ } ++ else ++ { ++ memcpy(&outStruct[destMarker], ++ &inGPRs[srcGMarker], inType->size); ++ srcGMarker += inType->size; ++ destMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // chars and other stuff ++ { ++ outStruct[destMarker++] = inGPRs[srcGMarker++]; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(srcGMarker, 8) - srcGMarker) < 4)) ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcGMarker = ALIGN(srcGMarker, 2); ++ destMarker = ALIGN(destMarker, 2); ++ ++ *(short*)&outStruct[destMarker] = ++ *(short*)&inGPRs[srcGMarker]; ++ srcGMarker += 2; ++ destMarker += 2; ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcGMarker = ALIGN(srcGMarker, 4); ++ destMarker = ALIGN(destMarker, 4); ++ ++ *(int*)&outStruct[destMarker] = ++ *(int*)&inGPRs[srcGMarker]; ++ srcGMarker += 4; ++ destMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcGMarker = ALIGN(srcGMarker, 8); ++ destMarker = ALIGN(destMarker, 8); ++ ++ *(long long*)&outStruct[destMarker] = ++ *(long long*)&inGPRs[srcGMarker]; ++ srcGMarker += 8; ++ destMarker += 8; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_ram_form(inType->elements[i], inGPRs, ++ &srcGMarker, inFPRs, &srcFMarker, &fprsUsed, ++ outStruct, &destMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); // unknown element type ++ break; ++ } ++ } ++ ++ srcGMarker = ALIGN(srcGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && srcGMarker == 16) ++ { ++ *(long double*)&outStruct[0] = *(long double*)&inGPRs[0]; ++ srcFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioGPRMarker) ++ *ioGPRMarker = ALIGN(srcGMarker, 8); ++ ++ if (ioFPRMarker) ++ *ioFPRMarker = srcFMarker; ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(destMarker, 8); ++} ++ ++/* ffi64_struct_to_reg_form ++ ++ Copy a struct's elements into buffers that can be sliced into registers. ++ Return the sizes of the output buffers in bytes. Pass NULL buffer pointers ++ to calculate size only. ++ outGPRs[0-7] == r3, outFPRs[0-7] == f1 ... ++*/ ++void ++ffi64_struct_to_reg_form( ++ const ffi_type* inType, ++ const char* inStruct, ++ unsigned int* ioStructMarker, ++ unsigned int* ioFPRsUsed, ++ char* outGPRs, // caller-allocated ++ unsigned int* ioGPRSize, ++ char* outFPRs, // caller-allocated ++ unsigned int* ioFPRSize) ++{ ++ size_t i; ++ unsigned int srcMarker = 0; ++ unsigned int destGMarker = 0; ++ unsigned int destFMarker = 0; ++ unsigned int savedFMarker = 0; ++ unsigned int fprsUsed = 0; ++ unsigned int savedFPRsUsed = 0; ++ ++ static unsigned int recurseCount = 0; ++ ++ if (ioStructMarker) ++ srcMarker = *ioStructMarker; ++ ++ if (ioFPRsUsed) ++ { ++ fprsUsed = *ioFPRsUsed; ++ savedFPRsUsed = fprsUsed; ++ } ++ ++ if (ioGPRSize) ++ destGMarker = *ioGPRSize; ++ ++ if (ioFPRSize) ++ { ++ destFMarker = *ioFPRSize; ++ savedFMarker = destFMarker; ++ } ++ ++ switch (inType->size) ++ { ++ case 1: case 2: case 4: ++ destGMarker += 8 - inType->size; ++ break; ++ ++ default: ++ break; ++ } ++ ++ for (i = 0; inType->elements[i] != NULL; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ // Shadow floating-point types in GPRs for vararg and pre-ANSI ++ // functions. ++ case FFI_TYPE_FLOAT: ++ // Nudge markers to next 4/8-byte boundary ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ (double)*(float*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (srcMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, 8); ++ } ++ ++ break; ++ ++ case FFI_TYPE_DOUBLE: ++ srcMarker = ALIGN(srcMarker, 8); ++ destFMarker = ALIGN(destFMarker, 8); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ if (outFPRs != NULL && inStruct != NULL) ++ *(double*)&outFPRs[destFMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ destFMarker += 8; ++ fprsUsed++; ++ } ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(double*)&outGPRs[destGMarker] = ++ *(double*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ ++ // Skip next GPR ++ destGMarker += 8; ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ srcMarker = ALIGN(srcMarker, 16); ++ ++ if (fprsUsed < NUM_FPR_ARG_REGISTERS) ++ { ++ destFMarker = ALIGN(destFMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outFPRs != NULL && inStruct != NULL) ++ *(long double*)&outFPRs[destFMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ ++ destFMarker += 16; ++ fprsUsed += 2; ++ } ++ else ++ { ++ destGMarker = ALIGN(destGMarker, 16); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[destGMarker] = ++ *(long double*)&inStruct[srcMarker]; ++ } ++ ++ srcMarker += 16; ++ destGMarker += 16; // Skip next 2 GPRs ++ destGMarker = ALIGN(destGMarker, 8); // was 16 ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ if (inType->alignment == 1) // bytes only ++ { ++ if (inType->size == 1) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ } ++ else if (inType->size == 2) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ outGPRs[destGMarker + 1] = inStruct[srcMarker + 1]; ++ } ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ i++; ++ } ++ else ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ { ++ // Avoid memcpy for small chunks. ++ if (inType->size <= sizeof(long)) ++ *(long*)&outGPRs[destGMarker] = ++ *(long*)&inStruct[srcMarker]; ++ else ++ memcpy(&outGPRs[destGMarker], ++ &inStruct[srcMarker], inType->size); ++ } ++ ++ srcMarker += inType->size; ++ destGMarker += inType->size; ++ i += inType->size - 1; ++ } ++ } ++ else // bytes and other stuff ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ outGPRs[destGMarker] = inStruct[srcMarker]; ++ ++ srcMarker++; ++ destGMarker++; ++ ++ // Skip to next GPR if next element won't fit and we're ++ // not already at a register boundary. ++ if (inType->elements[i + 1] != NULL && (destGMarker % 8)) ++ { ++ if (!FFI_TYPE_1_BYTE(inType->elements[i + 1]->type) && ++ (!FFI_TYPE_2_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 2) && ++ (!FFI_TYPE_4_BYTE(inType->elements[i + 1]->type) || ++ (ALIGN(destGMarker, 8) - destGMarker) < 4)) ++ destGMarker = ALIGN(destGMarker, inType->alignment); // was 8 ++ } ++ } ++ ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ srcMarker = ALIGN(srcMarker, 2); ++ destGMarker = ALIGN(destGMarker, 2); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(short*)&outGPRs[destGMarker] = ++ *(short*)&inStruct[srcMarker]; ++ ++ srcMarker += 2; ++ destGMarker += 2; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ srcMarker = ALIGN(srcMarker, 4); ++ destGMarker = ALIGN(destGMarker, 4); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(int*)&outGPRs[destGMarker] = ++ *(int*)&inStruct[srcMarker]; ++ ++ srcMarker += 4; ++ destGMarker += 4; ++ ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ srcMarker = ALIGN(srcMarker, 8); ++ destGMarker = ALIGN(destGMarker, 8); ++ ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long long*)&outGPRs[destGMarker] = ++ *(long long*)&inStruct[srcMarker]; ++ ++ srcMarker += 8; ++ destGMarker += 8; ++ ++ if (inType->elements[i + 1] == NULL) ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ recurseCount++; ++ ffi64_struct_to_reg_form(inType->elements[i], ++ inStruct, &srcMarker, &fprsUsed, outGPRs, ++ &destGMarker, outFPRs, &destFMarker); ++ recurseCount--; ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ destGMarker = ALIGN(destGMarker, inType->alignment); ++ ++ // Take care of the special case for 16-byte structs, but not for ++ // nested structs. ++ if (recurseCount == 0 && destGMarker == 16) ++ { ++ if (outGPRs != NULL && inStruct != NULL) ++ *(long double*)&outGPRs[0] = *(long double*)&inStruct[0]; ++ ++ destFMarker = savedFMarker; ++ fprsUsed = savedFPRsUsed; ++ } ++ ++ if (ioStructMarker) ++ *ioStructMarker = ALIGN(srcMarker, 8); ++ ++ if (ioFPRsUsed) ++ *ioFPRsUsed = fprsUsed; ++ ++ if (ioGPRSize) ++ *ioGPRSize = ALIGN(destGMarker, 8); ++ ++ if (ioFPRSize) ++ *ioFPRSize = ALIGN(destFMarker, 8); ++} ++ ++/* ffi64_stret_needs_ptr ++ ++ Determine whether a returned struct needs a pointer in r3 or can fit ++ in registers. ++*/ ++ ++bool ++ffi64_stret_needs_ptr( ++ const ffi_type* inType, ++ unsigned short* ioGPRCount, ++ unsigned short* ioFPRCount) ++{ ++ // Obvious case first- struct is larger than combined FPR size. ++ if (inType->size > 14 * 8) ++ return true; ++ ++ // Now the struct can physically fit in registers, determine if it ++ // also fits logically. ++ bool needsPtr = false; ++ unsigned short gprsUsed = 0; ++ unsigned short fprsUsed = 0; ++ size_t i; ++ ++ if (ioGPRCount) ++ gprsUsed = *ioGPRCount; ++ ++ if (ioFPRCount) ++ fprsUsed = *ioFPRCount; ++ ++ for (i = 0; inType->elements[i] != NULL && !needsPtr; i++) ++ { ++ switch (inType->elements[i]->type) ++ { ++ case FFI_TYPE_FLOAT: ++ case FFI_TYPE_DOUBLE: ++ gprsUsed++; ++ fprsUsed++; ++ ++ if (fprsUsed > 13) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ gprsUsed += 2; ++ fprsUsed += 2; ++ ++ if (fprsUsed > 14) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ { ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ { ++ needsPtr = true; ++ break; ++ } ++ ++ if (inType->elements[i + 1] == NULL) // last byte in the struct ++ break; ++ ++ // Count possible contiguous bytes ahead, up to 8. ++ unsigned short j; ++ ++ for (j = 1; j < 8; j++) ++ { ++ if (inType->elements[i + j] == NULL || ++ !FFI_TYPE_1_BYTE(inType->elements[i + j]->type)) ++ break; ++ } ++ ++ i += j - 1; // allow for i++ before the test condition ++ ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ gprsUsed++; ++ ++ if (gprsUsed > 8) ++ needsPtr = true; ++ ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ needsPtr = ffi64_stret_needs_ptr( ++ inType->elements[i], &gprsUsed, &fprsUsed); ++ ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ } ++ ++ if (ioGPRCount) ++ *ioGPRCount = gprsUsed; ++ ++ if (ioFPRCount) ++ *ioFPRCount = fprsUsed; ++ ++ return needsPtr; ++} ++ ++/* ffi64_data_size ++ ++ Calculate the size in bytes of an ffi type. ++*/ ++ ++unsigned int ++ffi64_data_size( ++ const ffi_type* inType) ++{ ++ unsigned int size = 0; ++ ++ switch (inType->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ size = 1; ++ break; ++ ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ size = 2; ++ break; ++ ++ case FFI_TYPE_INT: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_FLOAT: ++ size = 4; ++ break; ++ ++ case FFI_TYPE_POINTER: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_DOUBLE: ++ size = 8; ++ break; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ size = 16; ++ break; ++ ++ case FFI_TYPE_STRUCT: ++ ffi64_struct_to_reg_form( ++ inType, NULL, NULL, NULL, NULL, &size, NULL, NULL); ++ break; ++ ++ case FFI_TYPE_VOID: ++ break; ++ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++ ++ return size; ++} ++ ++#endif /* defined(__ppc64__) */ ++#endif /* __ppc__ || __ppc64__ */ +diff --git ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +new file mode 100644 +index 0000000..7162fa1 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/powerpc/ppc64-darwin_closure.S +@@ -0,0 +1,418 @@ ++#if defined(__ppc64__) ++ ++/* ----------------------------------------------------------------------- ++ ppc64-darwin_closure.S - Copyright (c) 2002, 2003, 2004, Free Software Foundation, ++ Inc. based on ppc_closure.S ++ ++ PowerPC Assembly glue. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#define LIBFFI_ASM ++ ++#include ++#include // for FFI_TRAMPOLINE_SIZE ++#include ++#include ++ ++ .file "ppc64-darwin_closure.S" ++.text ++ .align LOG2_GPR_BYTES ++ .globl _ffi_closure_ASM ++ ++.text ++ .align LOG2_GPR_BYTES ++ ++_ffi_closure_ASM: ++LFB1: ++ mflr r0 ++ stg r0,SF_RETURN(r1) // save return address ++ ++ // Save GPRs 3 - 10 (aligned to 8) in the parents outgoing area. ++ stg r3,SF_ARG1(r1) ++ stg r4,SF_ARG2(r1) ++ stg r5,SF_ARG3(r1) ++ stg r6,SF_ARG4(r1) ++ stg r7,SF_ARG5(r1) ++ stg r8,SF_ARG6(r1) ++ stg r9,SF_ARG7(r1) ++ stg r10,SF_ARG8(r1) ++ ++LCFI0: ++/* 48 bytes (Linkage Area) ++ 64 bytes (outgoing parameter area, always reserved) ++ 112 bytes (14*8 for incoming FPR) ++ ? bytes (result) ++ 112 bytes (14*8 for outgoing FPR) ++ 16 bytes (2 saved registers) ++ 352 + ? total bytes ++*/ ++ ++ std r31,-8(r1) // Save registers we use. ++ std r30,-16(r1) ++ mr r30,r1 // Save the old SP. ++ mr r31,r11 // Save the ffi_closure around ffi64_data_size. ++ ++ // Calculate the space we need. ++ stdu r1,-SF_MINSIZE(r1) ++ ld r3,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r3) // ffi_cif->rtype* ++ bl Lffi64_data_size$stub ++ ld r1,0(r1) ++ ++ addi r3,r3,352 // Add our overhead. ++ neg r3,r3 ++ li r0,-32 // Align to 32 bytes. ++ and r3,r3,r0 ++ stdux r1,r1,r3 // Grow the stack. ++ ++ mr r11,r31 // Copy the ffi_closure back. ++ ++LCFI1: ++ // We want to build up an area for the parameters passed ++ // in registers. (both floating point and integer) ++ ++/* 320 bytes (callee stack frame aligned to 32) ++ 48 bytes (caller linkage area) ++ 368 (start of caller parameter area aligned to 8) ++*/ ++ ++ // Save FPRs 1 - 14. (aligned to 8) ++ stfd f1,112(r1) ++ stfd f2,120(r1) ++ stfd f3,128(r1) ++ stfd f4,136(r1) ++ stfd f5,144(r1) ++ stfd f6,152(r1) ++ stfd f7,160(r1) ++ stfd f8,168(r1) ++ stfd f9,176(r1) ++ stfd f10,184(r1) ++ stfd f11,192(r1) ++ stfd f12,200(r1) ++ stfd f13,208(r1) ++ stfd f14,216(r1) ++ ++ // Set up registers for the routine that actually does the work. ++ mr r3,r11 // context pointer from the trampoline ++ addi r4,r1,224 // result storage ++ addi r5,r30,SF_ARG1 // saved GPRs ++ addi r6,r1,112 // saved FPRs ++ bl Lffi_closure_helper_DARWIN$stub ++ ++ // Look the proper starting point in table ++ // by using return type as an offset. ++ addi r5,r1,224 // 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. ++ mtctr r3 ++ bctr ++ ++LFE1: ++ // Each of the ret_typeX code fragments has to be exactly 16 bytes long ++ // (4 instructions). For cache effectiveness we align to a 16 byte ++ // boundary first. ++ .align 4 ++ nop ++ nop ++ nop ++ ++Lget_ret_type0_addr: ++ blrl ++ ++// case FFI_TYPE_VOID ++Lret_type0: ++ b Lfinish ++ nop ++ nop ++ nop ++ ++// case FFI_TYPE_INT ++Lret_type1: ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_FLOAT ++Lret_type2: ++ lfs f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_DOUBLE ++Lret_type3: ++ lfd f1,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_LONGDOUBLE ++Lret_type4: ++ lfd f1,0(r5) ++ lfd f2,8(r5) ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT8 ++Lret_type5: ++ lbz r3,7(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT8 ++Lret_type6: ++ lbz r3,7(r5) ++ extsb r3,r3 ++ b Lfinish ++ nop ++ ++// case FFI_TYPE_UINT16 ++Lret_type7: ++ lhz r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT16 ++Lret_type8: ++ lha r3,6(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT32 ++Lret_type9: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT32 ++Lret_type10: // same as Lret_type1 ++ lwz r3,4(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_UINT64 ++Lret_type11: ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_SINT64 ++Lret_type12: // same as Lret_type11 ++ ld r3,0(r5) ++ b Lfinish ++ nop ++ nop ++ ++// case FFI_TYPE_STRUCT ++Lret_type13: ++ b Lret_struct ++ nop ++ nop ++ nop ++ ++// ** End 16-byte aligned cases ** ++// case FFI_TYPE_POINTER ++// This case assumes that FFI_TYPE_POINTER == FFI_TYPE_LAST. If more types ++// are added in future, the following code will need to be updated and ++// padded to 16 bytes. ++Lret_type14: ++ lg r3,0(r5) ++ b Lfinish ++ ++// copy struct into registers ++Lret_struct: ++ ld r31,FFI_TRAMPOLINE_SIZE(r31) // ffi_closure->cif* ++ ld r3,16(r31) // ffi_cif->rtype* ++ ld r31,24(r31) // ffi_cif->flags ++ mr r4,r5 // copy struct* to 2nd arg ++ addi r7,r1,SF_ARG9 // GPR return area ++ addi r9,r30,-16-(14*8) // FPR return area ++ li r5,0 // struct offset ptr (NULL) ++ li r6,0 // FPR used count ptr (NULL) ++ li r8,0 // GPR return area size ptr (NULL) ++ li r10,0 // FPR return area size ptr (NULL) ++ bl Lffi64_struct_to_reg_form$stub ++ ++ // Load GPRs ++ ld r3,SF_ARG9(r1) ++ ld r4,SF_ARG10(r1) ++ ld r5,SF_ARG11(r1) ++ ld r6,SF_ARG12(r1) ++ nop ++ ld r7,SF_ARG13(r1) ++ ld r8,SF_ARG14(r1) ++ ld r9,SF_ARG15(r1) ++ ld r10,SF_ARG16(r1) ++ nop ++ ++ // Load FPRs ++ mtcrf 0x2,r31 ++ bf 26,Lfinish ++ lfd f1,-16-(14*8)(r30) ++ lfd f2,-16-(13*8)(r30) ++ lfd f3,-16-(12*8)(r30) ++ lfd f4,-16-(11*8)(r30) ++ nop ++ lfd f5,-16-(10*8)(r30) ++ lfd f6,-16-(9*8)(r30) ++ lfd f7,-16-(8*8)(r30) ++ lfd f8,-16-(7*8)(r30) ++ nop ++ lfd f9,-16-(6*8)(r30) ++ lfd f10,-16-(5*8)(r30) ++ lfd f11,-16-(4*8)(r30) ++ lfd f12,-16-(3*8)(r30) ++ nop ++ lfd f13,-16-(2*8)(r30) ++ lfd f14,-16-(1*8)(r30) ++ // Fall through ++ ++// case done ++Lfinish: ++ 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. ++ blr ++ ++// END(ffi_closure_ASM) ++ ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 ++ .long L$set$0 ; Length of Common Information Entry ++LSCIE1: ++ .long 0x0 ; CIE Identifier Tag ++ .byte 0x1 ; CIE Version ++ .ascii "zR\0" ; CIE Augmentation ++ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor ++ .byte 0x7c ; sleb128 -4; CIE Data Alignment Factor ++ .byte 0x41 ; CIE RA Column ++ .byte 0x1 ; uleb128 0x1; Augmentation size ++ .byte 0x10 ; FDE Encoding (pcrel) ++ .byte 0xc ; DW_CFA_def_cfa ++ .byte 0x1 ; uleb128 0x1 ++ .byte 0x0 ; uleb128 0x0 ++ .align LOG2_GPR_BYTES ++LECIE1: ++.globl _ffi_closure_ASM.eh ++_ffi_closure_ASM.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 ++ .long L$set$1 ; FDE Length ++ ++LASFDE1: ++ .long LASFDE1-EH_frame1 ; FDE CIE offset ++ .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 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$3,LCFI1-LCFI0 ++ .long L$set$3 ++ .byte 0xe ; DW_CFA_def_cfa_offset ++ .byte 176,1 ; uleb128 176 ++ .byte 0x4 ; DW_CFA_advance_loc4 ++ .set L$set$4,LCFI0-LFB1 ++ .long L$set$4 ++ .byte 0x11 ; DW_CFA_offset_extended_sf ++ .byte 0x41 ; uleb128 0x41 ++ .byte 0x7e ; sleb128 -2 ++ .align LOG2_GPR_BYTES ++ ++LEFDE1: ++.data ++ .align LOG2_GPR_BYTES ++LDFCM0: ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi_closure_helper_DARWIN$stub: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ mflr r0 ++ bcl 20,31,LO$ffi_closure_helper_DARWIN ++ ++LO$ffi_closure_helper_DARWIN: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN) ++ mtlr r0 ++ lgu r12,lo16(L_ffi_closure_helper_DARWIN$lazy_ptr - LO$ffi_closure_helper_DARWIN)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi_closure_helper_DARWIN$lazy_ptr: ++ .indirect_symbol _ffi_closure_helper_DARWIN ++ .g_long dyld_stub_binding_helper ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_struct_to_reg_form$stub: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ mflr r0 ++ bcl 20,31,LO$ffi64_struct_to_reg_form ++ ++LO$ffi64_struct_to_reg_form: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_struct_to_reg_form$lazy_ptr - LO$ffi64_struct_to_reg_form)(r11) ++ mtctr r12 ++ bctr ++ ++.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 ++ .align LOG2_GPR_BYTES ++ ++Lffi64_data_size$stub: ++ .indirect_symbol _ffi64_data_size ++ mflr r0 ++ bcl 20,31,LO$ffi64_data_size ++ ++LO$ffi64_data_size: ++ mflr r11 ++ addis r11,r11,ha16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size) ++ mtlr r0 ++ lgu r12,lo16(L_ffi64_data_size$lazy_ptr - LO$ffi64_data_size)(r11) ++ mtctr r12 ++ bctr ++ ++.lazy_symbol_pointer ++L_ffi64_struct_to_reg_form$lazy_ptr: ++ .indirect_symbol _ffi64_struct_to_reg_form ++ .g_long dyld_stub_binding_helper ++ ++L_ffi64_data_size$lazy_ptr: ++ .indirect_symbol _ffi64_data_size ++ .g_long dyld_stub_binding_helper ++ ++#endif // __ppc64__ +diff --git ./Modules/_ctypes/libffi_osx/types.c ./Modules/_ctypes/libffi_osx/types.c +new file mode 100644 +index 0000000..44806ae +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/types.c +@@ -0,0 +1,115 @@ ++/* ----------------------------------------------------------------------- ++ types.c - Copyright (c) 1996, 1998 Red Hat, Inc. ++ ++ Predefined ffi_types needed by libffi. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++/* Type definitions */ ++#define FFI_INTEGRAL_TYPEDEF(n, s, a, t) \ ++ ffi_type ffi_type_##n = { s, a, t, NULL } ++#define FFI_AGGREGATE_TYPEDEF(n, e) \ ++ ffi_type ffi_type_##n = { 0, 0, FFI_TYPE_STRUCT, e } ++ ++FFI_INTEGRAL_TYPEDEF(uint8, 1, 1, FFI_TYPE_UINT8); ++FFI_INTEGRAL_TYPEDEF(sint8, 1, 1, FFI_TYPE_SINT8); ++FFI_INTEGRAL_TYPEDEF(uint16, 2, 2, FFI_TYPE_UINT16); ++FFI_INTEGRAL_TYPEDEF(sint16, 2, 2, FFI_TYPE_SINT16); ++FFI_INTEGRAL_TYPEDEF(uint32, 4, 4, FFI_TYPE_UINT32); ++FFI_INTEGRAL_TYPEDEF(sint32, 4, 4, FFI_TYPE_SINT32); ++FFI_INTEGRAL_TYPEDEF(float, 4, 4, FFI_TYPE_FLOAT); ++ ++/* Size and alignment are fake here. They must not be 0. */ ++FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); ++ ++#if defined ALPHA || defined SPARC64 || defined X86_64 || \ ++ defined S390X || defined IA64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); ++#else ++FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); ++#endif ++ ++#if defined X86 || defined ARM || defined M68K || defined(X86_DARWIN) ++ ++# ifdef X86_64 ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++# else ++ FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++ FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++# endif ++ ++#elif defined(POWERPC_DARWIN) ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#elif defined SH ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, FFI_TYPE_SINT64); ++#else ++FFI_INTEGRAL_TYPEDEF(uint64, 8, 8, FFI_TYPE_UINT64); ++FFI_INTEGRAL_TYPEDEF(sint64, 8, 8, FFI_TYPE_SINT64); ++#endif ++ ++#if defined X86 || defined X86_WIN32 || defined M68K || defined(X86_DARWIN) ++ ++# if defined X86_WIN32 || defined X86_64 ++ FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++# endif ++ ++# ifdef X86_DARWIN ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined ARM || defined SH || defined POWERPC_AIX ++FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); ++#elif defined POWERPC_DARWIN ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# if __GNUC__ >= 4 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined SPARC ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++ ++# ifdef SPARC64 ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++# else ++ FFI_INTEGRAL_TYPEDEF(longdouble, 16, 8, FFI_TYPE_LONGDOUBLE); ++# endif ++ ++#elif defined X86_64 || defined POWERPC64 ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 16, 16, FFI_TYPE_LONGDOUBLE); ++#else ++FFI_INTEGRAL_TYPEDEF(double, 8, 8, FFI_TYPE_DOUBLE); ++FFI_INTEGRAL_TYPEDEF(longdouble, 8, 8, FFI_TYPE_LONGDOUBLE); ++#endif +\ No newline at end of file +diff --git ./Modules/_ctypes/libffi_osx/x86/darwin64.S ./Modules/_ctypes/libffi_osx/x86/darwin64.S +new file mode 100644 +index 0000000..165d469 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/darwin64.S +@@ -0,0 +1,417 @@ ++/* ----------------------------------------------------------------------- ++ darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. ++ derived from unix64.S ++ ++ x86-64 Foreign Function Interface for Darwin. ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#ifdef __x86_64__ ++#define LIBFFI_ASM ++#include ++#include ++ ++ .file "darwin64.S" ++.text ++ ++/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, ++ void *raddr, void (*fnaddr)()); ++ ++ Bit o trickiness here -- ARGS+BYTES is the base of the stack frame ++ for this function. This has been allocated by ffi_call. We also ++ deallocate some of the stack that has been alloca'd. */ ++ ++ .align 3 ++ .globl _ffi_call_unix64 ++ ++_ffi_call_unix64: ++LUW0: ++ movq (%rsp), %r10 /* Load return address. */ ++ movq %rdi, %r12 /* Save a copy of the register area. */ ++ leaq (%rdi, %rsi), %rax /* Find local stack base. */ ++ movq %rdx, (%rax) /* Save flags. */ ++ movq %rcx, 8(%rax) /* Save raddr. */ ++ movq %rbp, 16(%rax) /* Save old frame pointer. */ ++ movq %r10, 24(%rax) /* Relocate return address. */ ++ movq %rax, %rbp /* Finalize local stack frame. */ ++LUW1: ++ /* movq %rdi, %r10 // Save a copy of the register area. */ ++ movq %r12, %r10 ++ movq %r8, %r11 /* Save a copy of the target fn. */ ++ movl %r9d, %eax /* Set number of SSE registers. */ ++ ++ /* Load up all argument registers. */ ++ movq (%r10), %rdi ++ movq 8(%r10), %rsi ++ movq 16(%r10), %rdx ++ movq 24(%r10), %rcx ++ movq 32(%r10), %r8 ++ movq 40(%r10), %r9 ++ testl %eax, %eax ++ jnz Lload_sse ++Lret_from_load_sse: ++ ++ /* Deallocate the reg arg area. */ ++ leaq 176(%r10), %rsp ++ ++ /* Call the user function. */ ++ call *%r11 ++ ++ /* Deallocate stack arg area; local stack frame in redzone. */ ++ leaq 24(%rbp), %rsp ++ ++ movq 0(%rbp), %rcx /* Reload flags. */ ++ movq 8(%rbp), %rdi /* Reload raddr. */ ++ movq 16(%rbp), %rbp /* Reload old frame pointer. */ ++LUW2: ++ ++ /* The first byte of the flags contains the FFI_TYPE. */ ++ movzbl %cl, %r10d ++ leaq Lstore_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lstore_table: ++ .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ ++ .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ ++ .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ ++ .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ ++ .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ ++ .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ ++ .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ ++ .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ ++ .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ ++ .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ ++ .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lst_void: ++ ret ++ .align 3 ++Lst_uint8: ++ movzbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_sint8: ++ movsbq %al, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint16: ++ movzwq %ax, %rax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint16: ++ movswq %ax, %rax ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_uint32: ++ movl %eax, %eax ++ movq %rax, (%rdi) ++ .align 3 ++Lst_sint32: ++ cltq ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_int64: ++ movq %rax, (%rdi) ++ ret ++ .align 3 ++Lst_float: ++ movss %xmm0, (%rdi) ++ ret ++ .align 3 ++Lst_double: ++ movsd %xmm0, (%rdi) ++ ret ++Lst_ldouble: ++ fstpt (%rdi) ++ ret ++ .align 3 ++Lst_struct: ++ leaq -20(%rsp), %rsi /* Scratch area in redzone. */ ++ ++ /* We have to locate the values now, and since we don't want to ++ write too much data into the user's return value, we spill the ++ value to a 16 byte scratch area first. Bits 8, 9, and 10 ++ control where the values are located. Only one of the three ++ bits will be set; see ffi_prep_cif_machdep for the pattern. */ ++ movd %xmm0, %r10 ++ movd %xmm1, %r11 ++ testl $0x100, %ecx ++ cmovnz %rax, %rdx ++ cmovnz %r10, %rax ++ testl $0x200, %ecx ++ cmovnz %r10, %rdx ++ testl $0x400, %ecx ++ cmovnz %r10, %rax ++ cmovnz %r11, %rdx ++ movq %rax, (%rsi) ++ movq %rdx, 8(%rsi) ++ ++ /* Bits 12-31 contain the true size of the structure. Copy from ++ the scratch area to the true destination. */ ++ shrl $12, %ecx ++ rep movsb ++ ret ++ ++ /* Many times we can avoid loading any SSE registers at all. ++ It's not worth an indirect jump to load the exact set of ++ SSE registers needed; zero or all is a good compromise. */ ++ .align 3 ++LUW3: ++Lload_sse: ++ movdqa 48(%r10), %xmm0 ++ movdqa 64(%r10), %xmm1 ++ movdqa 80(%r10), %xmm2 ++ movdqa 96(%r10), %xmm3 ++ movdqa 112(%r10), %xmm4 ++ movdqa 128(%r10), %xmm5 ++ movdqa 144(%r10), %xmm6 ++ movdqa 160(%r10), %xmm7 ++ jmp Lret_from_load_sse ++ ++LUW4: ++ .align 3 ++ .globl _ffi_closure_unix64 ++ ++_ffi_closure_unix64: ++LUW5: ++ /* The carry flag is set by the trampoline iff SSE registers ++ are used. Don't clobber it before the branch instruction. */ ++ leaq -200(%rsp), %rsp ++LUW6: ++ movq %rdi, (%rsp) ++ movq %rsi, 8(%rsp) ++ movq %rdx, 16(%rsp) ++ movq %rcx, 24(%rsp) ++ movq %r8, 32(%rsp) ++ movq %r9, 40(%rsp) ++ jc Lsave_sse ++Lret_from_save_sse: ++ ++ movq %r10, %rdi ++ leaq 176(%rsp), %rsi ++ movq %rsp, %rdx ++ leaq 208(%rsp), %rcx ++ call _ffi_closure_unix64_inner ++ ++ /* Deallocate stack frame early; return value is now in redzone. */ ++ addq $200, %rsp ++LUW7: ++ ++ /* The first byte of the return value contains the FFI_TYPE. */ ++ movzbl %al, %r10d ++ leaq Lload_table(%rip), %r11 ++ movslq (%r11, %r10, 4), %r10 ++ addq %r11, %r10 ++ jmp *%r10 ++ ++Lload_table: ++ .long Lld_void-Lload_table /* FFI_TYPE_VOID */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_INT */ ++ .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ ++ .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ ++ .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ ++ .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ ++ .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ ++ .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ ++ .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ ++ .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ ++ ++ .text ++ .align 3 ++Lld_void: ++ ret ++ .align 3 ++Lld_int8: ++ movzbl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int16: ++ movzwl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int32: ++ movl -24(%rsp), %eax ++ ret ++ .align 3 ++Lld_int64: ++ movq -24(%rsp), %rax ++ ret ++ .align 3 ++Lld_float: ++ movss -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_double: ++ movsd -24(%rsp), %xmm0 ++ ret ++ .align 3 ++Lld_ldouble: ++ fldt -24(%rsp) ++ ret ++ .align 3 ++Lld_struct: ++ /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, ++ %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading ++ both rdx and xmm1 with the second word. For the remaining, ++ bit 8 set means xmm0 gets the second word, and bit 9 means ++ that rax gets the second word. */ ++ movq -24(%rsp), %rcx ++ movq -16(%rsp), %rdx ++ movq -16(%rsp), %xmm1 ++ testl $0x100, %eax ++ cmovnz %rdx, %rcx ++ movd %rcx, %xmm0 ++ testl $0x200, %eax ++ movq -24(%rsp), %rax ++ cmovnz %rdx, %rax ++ ret ++ ++ /* See the comment above Lload_sse; the same logic applies here. */ ++ .align 3 ++LUW8: ++Lsave_sse: ++ movdqa %xmm0, 48(%rsp) ++ movdqa %xmm1, 64(%rsp) ++ movdqa %xmm2, 80(%rsp) ++ movdqa %xmm3, 96(%rsp) ++ movdqa %xmm4, 112(%rsp) ++ movdqa %xmm5, 128(%rsp) ++ movdqa %xmm6, 144(%rsp) ++ movdqa %xmm7, 160(%rsp) ++ jmp Lret_from_save_sse ++ ++LUW9: ++.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support ++EH_frame1: ++ .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ ++ .long L$set$0 ++LSCIE1: ++ .long 0x0 /* CIE Identifier Tag */ ++ .byte 0x1 /* CIE Version */ ++ .ascii "zR\0" /* CIE Augmentation */ ++ .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ ++ .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ ++ .byte 0x10 /* CIE RA Column */ ++ .byte 0x1 /* uleb128 0x1; Augmentation size */ ++ .byte 0x10 /* FDE Encoding (pcrel sdata4) */ ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 /* uleb128 0x7 */ ++ .byte 0x8 /* uleb128 0x8 */ ++ .byte 0x90 /* DW_CFA_offset, column 0x10 */ ++ .byte 0x1 ++ .align 3 ++LECIE1: ++ .globl _ffi_call_unix64.eh ++_ffi_call_unix64.eh: ++LSFDE1: ++ .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ ++ .long L$set$1 ++LASFDE1: ++ .long LASFDE1-EH_frame1 /* FDE CIE offset */ ++ .quad LUW0-. /* FDE initial location */ ++ .set L$set$2,LUW4-LUW0 /* FDE address range */ ++ .quad L$set$2 ++ .byte 0x0 /* Augmentation size */ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$3,LUW1-LUW0 ++ .long L$set$3 ++ ++ /* New stack frame based off rbp. This is a itty bit of unwind ++ trickery in that the CFA *has* changed. There is no easy way ++ to describe it correctly on entry to the function. Fortunately, ++ it doesn't matter too much since at all points we can correctly ++ unwind back to ffi_call. Note that the location to which we ++ moved the return address is (the new) CFA-8, so from the ++ perspective of the unwind info, it hasn't moved. */ ++ .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ ++ .byte 0x6 ++ .byte 0x20 ++ .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ ++ .byte 0x2 ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$4,LUW2-LUW1 ++ .long L$set$4 ++ .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ ++ .byte 0x7 ++ .byte 0x8 ++ .byte 0xc0+6 /* DW_CFA_restore, %rbp */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$5,LUW3-LUW2 ++ .long L$set$5 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE1: ++ .globl _ffi_closure_unix64.eh ++_ffi_closure_unix64.eh: ++LSFDE3: ++ .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ ++ .long L$set$6 ++LASFDE3: ++ .long LASFDE3-EH_frame1 /* FDE CIE offset */ ++ .quad LUW5-. /* FDE initial location */ ++ .set L$set$7,LUW9-LUW5 /* FDE address range */ ++ .quad L$set$7 ++ .byte 0x0 /* Augmentation size */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$8,LUW6-LUW5 ++ .long L$set$8 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 208,1 /* uleb128 208 */ ++ .byte 0xa /* DW_CFA_remember_state */ ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$9,LUW7-LUW6 ++ .long L$set$9 ++ .byte 0xe /* DW_CFA_def_cfa_offset */ ++ .byte 0x8 ++ ++ .byte 0x4 /* DW_CFA_advance_loc4 */ ++ .set L$set$10,LUW8-LUW7 ++ .long L$set$10 ++ .byte 0xb /* DW_CFA_restore_state */ ++ ++ .align 3 ++LEFDE3: ++ .subsections_via_symbols ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +new file mode 100644 +index 0000000..925a841 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-darwin.S +@@ -0,0 +1,422 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003 Red Hat, Inc. ++ ++ X86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++/* ++ * This file is based on sysv.S and then hacked up by Ronald who hasn't done ++ * assembly programming in 8 years. ++ */ ++ ++#ifndef __x86_64__ ++ ++#define LIBFFI_ASM ++#include ++#include ++ ++#ifdef PyObjC_STRICT_DEBUGGING ++ /* XXX: Debugging of stack alignment, to be removed */ ++#define ASSERT_STACK_ALIGNED movdqa -16(%esp), %xmm0 ++#else ++#define ASSERT_STACK_ALIGNED ++#endif ++ ++.text ++ ++.globl _ffi_prep_args ++ ++ .align 4 ++.globl _ffi_call_SYSV ++ ++_ffi_call_SYSV: ++LFB1: ++ pushl %ebp ++LCFI0: ++ movl %esp,%ebp ++LCFI1: ++ subl $8,%esp ++ /* Make room for all of the new args. */ ++ movl 16(%ebp),%ecx ++ subl %ecx,%esp ++ ++ movl %esp,%eax ++ ++ /* Place all of the ffi_prep_args in position */ ++ subl $8,%esp ++ pushl 12(%ebp) ++ pushl %eax ++ call *8(%ebp) ++ ++ /* Return stack to previous state and call the function */ ++ addl $16,%esp ++ ++ call *28(%ebp) ++ ++ /* 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 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 Lnoretval ++ fstp %st(0) ++ ++ jmp Lepilogue ++ ++Lretint: ++ cmpl $FFI_TYPE_INT,%ecx ++ jne Lretfloat ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ movl %eax,0(%ecx) ++ jmp Lepilogue ++ ++Lretfloat: ++ cmpl $FFI_TYPE_FLOAT,%ecx ++ jne Lretdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstps (%ecx) ++ jmp Lepilogue ++ ++Lretdouble: ++ cmpl $FFI_TYPE_DOUBLE,%ecx ++ jne Lretlongdouble ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpl (%ecx) ++ jmp Lepilogue ++ ++Lretlongdouble: ++ cmpl $FFI_TYPE_LONGDOUBLE,%ecx ++ jne Lretint64 ++ /* Load %ecx with the pointer to storage for the return value */ ++ movl 24(%ebp),%ecx ++ fstpt (%ecx) ++ jmp Lepilogue ++ ++Lretint64: ++ cmpl $FFI_TYPE_SINT64,%ecx ++ 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 Lepilogue ++ ++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 ++ ++Lnoretval: ++Lepilogue: ++ addl $8,%esp ++ movl %ebp,%esp ++ popl %ebp ++ ret ++LFE1: ++.ffi_call_SYSV_end: ++ ++ .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_UINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_SINT8, %eax ++ je Lcls_retstruct1 ++ cmpl $FFI_TYPE_UINT16, %eax ++ je Lcls_retstruct2 ++ 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 ++ ++.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__ */ ++ ++#endif /* defined __i386__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +new file mode 100644 +index 0000000..06feaf2 +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi64.c +@@ -0,0 +1,734 @@ ++#ifdef __x86_64__ ++ ++/* ----------------------------------------------------------------------- ++ x86-ffi64.c - Copyright (c) 2002 Bo Thorsen ++ ++ x86-64 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++#include ++ ++#define MAX_GPR_REGS 6 ++#define MAX_SSE_REGS 8 ++ ++typedef struct RegisterArgs { ++ /* Registers for argument passing. */ ++ UINT64 gpr[MAX_GPR_REGS]; ++ __int128_t sse[MAX_SSE_REGS]; ++} RegisterArgs; ++ ++extern void ++ffi_call_unix64( ++ void* args, ++ unsigned long bytes, ++ unsigned flags, ++ void* raddr, ++ void (*fnaddr)(), ++ unsigned ssecount); ++ ++/* All reference to register classes here is identical to the code in ++ gcc/config/i386/i386.c. Do *not* change one without the other. */ ++ ++/* 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 reformating penalties. ++ ++ Similary we play games with INTEGERSI_CLASS to use cheaper SImode moves ++ whenever possible (upper half does contain padding). */ ++enum x86_64_reg_class ++{ ++ X86_64_NO_CLASS, ++ X86_64_INTEGER_CLASS, ++ X86_64_INTEGERSI_CLASS, ++ X86_64_SSE_CLASS, ++ X86_64_SSESF_CLASS, ++ X86_64_SSEDF_CLASS, ++ X86_64_SSEUP_CLASS, ++ X86_64_X87_CLASS, ++ X86_64_X87UP_CLASS, ++ X86_64_COMPLEX_X87_CLASS, ++ X86_64_MEMORY_CLASS ++}; ++ ++#define MAX_CLASSES 4 ++#define SSE_CLASS_P(X) ((X) >= X86_64_SSE_CLASS && X <= X86_64_SSEUP_CLASS) ++ ++/* x86-64 register passing implementation. See x86-64 ABI for details. Goal ++ of this code is to classify each 8bytes of incoming argument by the register ++ class and assign registers accordingly. */ ++ ++/* Return the union class of CLASS1 and CLASS2. ++ See the x86-64 PS ABI for details. */ ++static enum x86_64_reg_class ++merge_classes( ++ enum x86_64_reg_class class1, ++ enum x86_64_reg_class class2) ++{ ++ /* Rule #1: If both classes are equal, this is the resulting class. */ ++ if (class1 == class2) ++ return class1; ++ ++ /* Rule #2: If one of the classes is NO_CLASS, the resulting class is ++ the other class. */ ++ if (class1 == X86_64_NO_CLASS) ++ return class2; ++ ++ if (class2 == X86_64_NO_CLASS) ++ return class1; ++ ++ /* Rule #3: If one of the classes is MEMORY, the result is MEMORY. */ ++ if (class1 == X86_64_MEMORY_CLASS || class2 == X86_64_MEMORY_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #4: If one of the classes is INTEGER, the result is INTEGER. */ ++ if ((class1 == X86_64_INTEGERSI_CLASS && class2 == X86_64_SSESF_CLASS) ++ || (class2 == X86_64_INTEGERSI_CLASS && class1 == X86_64_SSESF_CLASS)) ++ return X86_64_INTEGERSI_CLASS; ++ ++ if (class1 == X86_64_INTEGER_CLASS || class1 == X86_64_INTEGERSI_CLASS ++ || class2 == X86_64_INTEGER_CLASS || class2 == X86_64_INTEGERSI_CLASS) ++ return X86_64_INTEGER_CLASS; ++ ++ /* Rule #5: If one of the classes is X87, X87UP, or COMPLEX_X87 class, ++ MEMORY is used. */ ++ if (class1 == X86_64_X87_CLASS ++ || class1 == X86_64_X87UP_CLASS ++ || class1 == X86_64_COMPLEX_X87_CLASS ++ || class2 == X86_64_X87_CLASS ++ || class2 == X86_64_X87UP_CLASS ++ || class2 == X86_64_COMPLEX_X87_CLASS) ++ return X86_64_MEMORY_CLASS; ++ ++ /* Rule #6: Otherwise class SSE is used. */ ++ return X86_64_SSE_CLASS; ++} ++ ++/* Classify the argument of type TYPE and mode MODE. ++ CLASSES will be filled by the register class used to pass each word ++ of the operand. The number of words is returned. In case the parameter ++ should be passed in memory, 0 is returned. As a special case for zero ++ sized containers, classes[0] will be NO_CLASS and 1 is returned. ++ ++ See the x86-64 PS ABI for details. */ ++ ++static int ++classify_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[], ++ size_t byte_offset) ++{ ++ switch (type->type) ++ { ++ case FFI_TYPE_UINT8: ++ case FFI_TYPE_SINT8: ++ case FFI_TYPE_UINT16: ++ case FFI_TYPE_SINT16: ++ case FFI_TYPE_UINT32: ++ case FFI_TYPE_SINT32: ++ case FFI_TYPE_UINT64: ++ case FFI_TYPE_SINT64: ++ case FFI_TYPE_POINTER: ++#if 0 ++ if (byte_offset + type->size <= 4) ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ else ++ classes[0] = X86_64_INTEGER_CLASS; ++ ++ return 1; ++#else ++ { ++ int size = byte_offset + type->size; ++ ++ if (size <= 4) ++ { ++ classes[0] = X86_64_INTEGERSI_CLASS; ++ return 1; ++ } ++ else if (size <= 8) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ return 1; ++ } ++ else if (size <= 12) ++ { ++ classes[0] = X86_64_INTEGER_CLASS; ++ classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else if (size <= 16) ++ { ++ classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; ++ return 2; ++ } ++ else ++ FFI_ASSERT (0); ++ } ++#endif ++ ++ case FFI_TYPE_FLOAT: ++ if (byte_offset == 0) ++ classes[0] = X86_64_SSESF_CLASS; ++ else ++ classes[0] = X86_64_SSE_CLASS; ++ ++ return 1; ++ ++ case FFI_TYPE_DOUBLE: ++ classes[0] = X86_64_SSEDF_CLASS; ++ return 1; ++ ++ case FFI_TYPE_LONGDOUBLE: ++ classes[0] = X86_64_X87_CLASS; ++ classes[1] = X86_64_X87UP_CLASS; ++ return 2; ++ ++ case FFI_TYPE_STRUCT: ++ { ++ ffi_type** ptr; ++ int i; ++ enum x86_64_reg_class subclasses[MAX_CLASSES]; ++ const int UNITS_PER_WORD = 8; ++ int words = ++ (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ++ ++ /* If the struct is larger than 16 bytes, pass it on the stack. */ ++ if (type->size > 16) ++ return 0; ++ ++ for (i = 0; i < words; i++) ++ classes[i] = X86_64_NO_CLASS; ++ ++ /* Merge the fields of structure. */ ++ for (ptr = type->elements; *ptr != NULL; ptr++) ++ { ++ byte_offset = ALIGN(byte_offset, (*ptr)->alignment); ++ ++ int num = classify_argument(*ptr, subclasses, byte_offset % 8); ++ ++ if (num == 0) ++ return 0; ++ ++ int pos = byte_offset / 8; ++ ++ for (i = 0; i < num; i++) ++ { ++ classes[i + pos] = ++ merge_classes(subclasses[i], classes[i + pos]); ++ } ++ ++ byte_offset += (*ptr)->size; ++ } ++ ++ if (words > 2) ++ { ++ /* When size > 16 bytes, if the first one isn't ++ X86_64_SSE_CLASS or any other ones aren't ++ X86_64_SSEUP_CLASS, everything should be passed in ++ memory. */ ++ if (classes[0] != X86_64_SSE_CLASS) ++ return 0; ++ ++ for (i = 1; i < words; i++) ++ if (classes[i] != X86_64_SSEUP_CLASS) ++ return 0; ++ } ++ ++ ++ /* Final merger cleanup. */ ++ for (i = 0; i < words; i++) ++ { ++ /* If one class is MEMORY, everything should be passed in ++ memory. */ ++ if (classes[i] == X86_64_MEMORY_CLASS) ++ return 0; ++ ++ /* The X86_64_SSEUP_CLASS should be always preceded by ++ X86_64_SSE_CLASS. */ ++ if (classes[i] == X86_64_SSEUP_CLASS ++ && classes[i - 1] != X86_64_SSE_CLASS ++ && classes[i - 1] != X86_64_SSEUP_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ ++ /* X86_64_X87UP_CLASS should be preceded by X86_64_X87_CLASS. */ ++ if (classes[i] == X86_64_X87UP_CLASS ++ && classes[i - 1] != X86_64_X87_CLASS) ++ { ++ FFI_ASSERT(i != 0); ++ classes[i] = X86_64_SSE_CLASS; ++ } ++ } ++ ++ return words; ++ } ++ ++ default: ++ FFI_ASSERT(0); ++ } ++ ++ return 0; /* Never reached. */ ++} ++ ++/* Examine the argument and return set number of register required in each ++ class. Return zero if parameter should be passed in memory, otherwise ++ the number of registers. */ ++static int ++examine_argument( ++ ffi_type* type, ++ enum x86_64_reg_class classes[MAX_CLASSES], ++ _Bool in_return, ++ int* pngpr, ++ int* pnsse) ++{ ++ int n = classify_argument(type, classes, 0); ++ int ngpr = 0; ++ int nsse = 0; ++ int i; ++ ++ if (n == 0) ++ return 0; ++ ++ for (i = 0; i < n; ++i) ++ { ++ switch (classes[i]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ ngpr++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSESF_CLASS: ++ case X86_64_SSEDF_CLASS: ++ nsse++; ++ break; ++ ++ case X86_64_NO_CLASS: ++ case X86_64_SSEUP_CLASS: ++ break; ++ ++ case X86_64_X87_CLASS: ++ case X86_64_X87UP_CLASS: ++ case X86_64_COMPLEX_X87_CLASS: ++ return in_return != 0; ++ ++ default: ++ abort(); ++ } ++ } ++ ++ *pngpr = ngpr; ++ *pnsse = nsse; ++ ++ return n; ++} ++ ++/* Perform machine dependent cif processing. */ ++ffi_status ++ffi_prep_cif_machdep( ++ ffi_cif* cif) ++{ ++ int gprcount = 0; ++ int ssecount = 0; ++ int flags = cif->rtype->type; ++ int i, avn, n, ngpr, nsse; ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ size_t bytes; ++ ++ if (flags != FFI_TYPE_VOID) ++ { ++ n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value is passed in memory. A pointer to that ++ memory is the first argument. Allocate a register for it. */ ++ gprcount++; ++ ++ /* We don't have to do anything in asm for the return. */ ++ flags = FFI_TYPE_VOID; ++ } ++ else if (flags == FFI_TYPE_STRUCT) ++ { ++ /* Mark which registers the result appears in. */ ++ _Bool sse0 = SSE_CLASS_P(classes[0]); ++ _Bool sse1 = n == 2 && SSE_CLASS_P(classes[1]); ++ ++ if (sse0 && !sse1) ++ flags |= 1 << 8; ++ else if (!sse0 && sse1) ++ flags |= 1 << 9; ++ else if (sse0 && sse1) ++ flags |= 1 << 10; ++ ++ /* Mark the true size of the structure. */ ++ flags |= cif->rtype->size << 12; ++ } ++ } ++ ++ /* Go over all arguments and determine the way they should be passed. ++ If it's in a register and there is space for it, let that be so. If ++ not, add it's size to the stack byte count. */ ++ for (bytes = 0, i = 0, avn = cif->nargs; i < avn; i++) ++ { ++ if (examine_argument(cif->arg_types[i], classes, 0, &ngpr, &nsse) == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = cif->arg_types[i]->alignment; ++ ++ if (align < 8) ++ align = 8; ++ ++ bytes = ALIGN(bytes, align); ++ bytes += cif->arg_types[i]->size; ++ } ++ else ++ { ++ gprcount += ngpr; ++ ssecount += nsse; ++ } ++ } ++ ++ if (ssecount) ++ flags |= 1 << 11; ++ ++ cif->flags = flags; ++ cif->bytes = bytes; ++ cif->bytes = ALIGN(bytes,8); ++ ++ return FFI_OK; ++} ++ ++void ++ffi_call( ++ ffi_cif* cif, ++ void (*fn)(), ++ void* rvalue, ++ void** avalue) ++{ ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ char* stack; ++ char* argp; ++ ffi_type** arg_types; ++ int gprcount, ssecount, ngpr, nsse, i, avn; ++ _Bool ret_in_memory; ++ RegisterArgs* reg_args; ++ ++ /* Can't call 32-bit mode from 64-bit mode. */ ++ FFI_ASSERT(cif->abi == FFI_UNIX64); ++ ++ /* If the return value is a struct and we don't have a return value ++ address then we need to make one. Note the setting of flags to ++ VOID above in ffi_prep_cif_machdep. */ ++ ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT ++ && (cif->flags & 0xff) == FFI_TYPE_VOID); ++ ++ if (rvalue == NULL && ret_in_memory) ++ rvalue = alloca (cif->rtype->size); ++ ++ /* Allocate the space for the arguments, plus 4 words of temp space. */ ++ stack = alloca(sizeof(RegisterArgs) + cif->bytes + 4 * 8); ++ reg_args = (RegisterArgs*)stack; ++ argp = stack + sizeof(RegisterArgs); ++ ++ gprcount = ssecount = 0; ++ ++ /* If the return value is passed in memory, add the pointer as the ++ first integer argument. */ ++ if (ret_in_memory) ++ reg_args->gpr[gprcount++] = (long) rvalue; ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ size_t size = arg_types[i]->size; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ memcpy (argp, avalue[i], size); ++ argp += size; ++ } ++ else ++ { /* The argument is passed entirely in registers. */ ++ char *a = (char *) avalue[i]; ++ int j; ++ ++ for (j = 0; j < n; j++, a += 8, size -= 8) ++ { ++ switch (classes[j]) ++ { ++ case X86_64_INTEGER_CLASS: ++ case X86_64_INTEGERSI_CLASS: ++ reg_args->gpr[gprcount] = 0; ++ switch (arg_types[i]->type) { ++ case FFI_TYPE_SINT8: ++ { ++ int8_t shortval = *(int8_t*)a; ++ int64_t actval = (int64_t)shortval; ++ reg_args->gpr[gprcount] = actval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ break; ++ } ++ ++ case FFI_TYPE_SINT16: ++ { ++ int16_t shortval = *(int16_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_SINT32: ++ { ++ int32_t shortval = *(int32_t*)a; ++ int64_t actval = (int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT8: ++ { ++ u_int8_t shortval = *(u_int8_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ /*memcpy (®_args->gpr[gprcount], &actval, 8);*/ ++ reg_args->gpr[gprcount] = actval; ++ break; ++ } ++ ++ case FFI_TYPE_UINT16: ++ { ++ u_int16_t shortval = *(u_int16_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ case FFI_TYPE_UINT32: ++ { ++ u_int32_t shortval = *(u_int32_t*)a; ++ u_int64_t actval = (u_int64_t)shortval; ++ memcpy (®_args->gpr[gprcount], &actval, 8); ++ break; ++ } ++ ++ default: ++ //memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); ++ reg_args->gpr[gprcount] = *(int64_t*)a; ++ } ++ gprcount++; ++ break; ++ ++ case X86_64_SSE_CLASS: ++ case X86_64_SSEDF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT64 *) a; ++ break; ++ ++ case X86_64_SSESF_CLASS: ++ reg_args->sse[ssecount++] = *(UINT32 *) a; ++ break; ++ ++ default: ++ abort(); ++ } ++ } ++ } ++ } ++ ++ ffi_call_unix64 (stack, cif->bytes + sizeof(RegisterArgs), ++ cif->flags, rvalue, fn, ssecount); ++} ++ ++extern void ffi_closure_unix64(void); ++ ++ffi_status ++ffi_prep_closure( ++ ffi_closure* closure, ++ ffi_cif* cif, ++ void (*fun)(ffi_cif*, void*, void**, void*), ++ void* user_data) ++{ ++ if (cif->abi != FFI_UNIX64) ++ return FFI_BAD_ABI; ++ ++ volatile unsigned short* tramp = ++ (volatile unsigned short*)&closure->tramp[0]; ++ ++ tramp[0] = 0xbb49; /* mov , %r11 */ ++ *(void* volatile*)&tramp[1] = ffi_closure_unix64; ++ tramp[5] = 0xba49; /* mov , %r10 */ ++ *(void* volatile*)&tramp[6] = closure; ++ ++ /* Set the carry bit if the function uses any sse registers. ++ This is clc or stc, together with the first byte of the jmp. */ ++ tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; ++ tramp[11] = 0xe3ff; /* jmp *%r11 */ ++ ++ closure->cif = cif; ++ closure->fun = fun; ++ closure->user_data = user_data; ++ ++ return FFI_OK; ++} ++ ++#pragma clang diagnostic push ++#pragma clang diagnostic ignored "-Wmissing-prototypes" ++int ++ffi_closure_unix64_inner( ++ ffi_closure* closure, ++ void* rvalue, ++ RegisterArgs* reg_args, ++ char* argp) ++#pragma clang diagnostic pop ++{ ++ ffi_cif* cif = closure->cif; ++ void** avalue = alloca(cif->nargs * sizeof(void *)); ++ ffi_type** arg_types; ++ long i, avn; ++ int gprcount = 0; ++ int ssecount = 0; ++ int ngpr, nsse; ++ int ret; ++ ++ ret = cif->rtype->type; ++ ++ if (ret != FFI_TYPE_VOID) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); ++ ++ if (n == 0) ++ { ++ /* The return value goes in memory. Arrange for the closure ++ return value to go directly back to the original caller. */ ++ rvalue = (void *) reg_args->gpr[gprcount++]; ++ ++ /* We don't have to do anything in asm for the return. */ ++ ret = FFI_TYPE_VOID; ++ } ++ else if (ret == FFI_TYPE_STRUCT && n == 2) ++ { ++ /* Mark which register the second word of the structure goes in. */ ++ _Bool sse0 = SSE_CLASS_P (classes[0]); ++ _Bool sse1 = SSE_CLASS_P (classes[1]); ++ ++ if (!sse0 && sse1) ++ ret |= 1 << 8; ++ else if (sse0 && !sse1) ++ ret |= 1 << 9; ++ } ++ } ++ ++ avn = cif->nargs; ++ arg_types = cif->arg_types; ++ ++ for (i = 0; i < avn; ++i) ++ { ++ enum x86_64_reg_class classes[MAX_CLASSES]; ++ int n; ++ ++ n = examine_argument (arg_types[i], classes, 0, &ngpr, &nsse); ++ ++ if (n == 0 ++ || gprcount + ngpr > MAX_GPR_REGS ++ || ssecount + nsse > MAX_SSE_REGS) ++ { ++ long align = arg_types[i]->alignment; ++ ++ /* Stack arguments are *always* at least 8 byte aligned. */ ++ if (align < 8) ++ align = 8; ++ ++ /* Pass this argument in memory. */ ++ argp = (void *) ALIGN (argp, align); ++ avalue[i] = argp; ++ argp += arg_types[i]->size; ++ } ++ ++#if !defined(X86_DARWIN) ++ /* If the argument is in a single register, or two consecutive ++ registers, then we can use that address directly. */ ++ else if (n == 1 || (n == 2 && ++ SSE_CLASS_P (classes[0]) == SSE_CLASS_P (classes[1]))) ++ { ++ // The argument is in a single register. ++ if (SSE_CLASS_P (classes[0])) ++ { ++ avalue[i] = ®_args->sse[ssecount]; ++ ssecount += n; ++ } ++ else ++ { ++ avalue[i] = ®_args->gpr[gprcount]; ++ gprcount += n; ++ } ++ } ++#endif ++ ++ /* Otherwise, allocate space to make them consecutive. */ ++ else ++ { ++ char *a = alloca (16); ++ int j; ++ ++ avalue[i] = a; ++ ++ for (j = 0; j < n; j++, a += 8) ++ { ++ if (SSE_CLASS_P (classes[j])) ++ memcpy (a, ®_args->sse[ssecount++], 8); ++ else ++ memcpy (a, ®_args->gpr[gprcount++], 8); ++ } ++ } ++ } ++ ++ /* Invoke the closure. */ ++ closure->fun (cif, rvalue, avalue, closure->user_data); ++ ++ /* Tell assembly how to perform return type promotions. */ ++ return ret; ++} ++ ++#endif /* __x86_64__ */ +diff --git ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +new file mode 100644 +index 0000000..706ea0f +--- /dev/null ++++ ./Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c +@@ -0,0 +1,438 @@ ++#ifdef __i386__ ++/* ----------------------------------------------------------------------- ++ ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ++ Copyright (c) 2002 Ranjit Mathew ++ Copyright (c) 2002 Bo Thorsen ++ Copyright (c) 2002 Roger Sayle ++ ++ x86 Foreign Function Interface ++ ++ Permission is hereby granted, free of charge, to any person obtaining ++ a copy of this software and associated documentation files (the ++ ``Software''), to deal in the Software without restriction, including ++ without limitation the rights to use, copy, modify, merge, publish, ++ distribute, sublicense, and/or sell copies of the Software, and to ++ permit persons to whom the Software is furnished to do so, subject to ++ the following conditions: ++ ++ The above copyright notice and this permission notice shall be included ++ in all copies or substantial portions of the Software. ++ ++ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS ++ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF ++ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. ++ IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR ++ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ++ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ++ OTHER DEALINGS IN THE SOFTWARE. ++ ----------------------------------------------------------------------- */ ++ ++#include ++#include ++ ++#include ++ ++/* ffi_prep_args is called by the assembly routine once stack space ++ has been allocated for the function's arguments */ ++ ++void ffi_prep_args(char *stack, extended_cif *ecif); ++ ++void ffi_prep_args(char *stack, extended_cif *ecif) ++{ ++ 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) ++ { ++ *(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) ++{ ++ /* 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_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; ++ } ++ ++#ifdef X86_DARWIN ++ cif->bytes = (cif->bytes + 15) & ~0xF; ++#endif ++ ++ return FFI_OK; ++} ++ ++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 *), extended_cif *, ++ unsigned, unsigned, unsigned *, void (*fn)()); ++ ++#endif /* X86_WIN32 */ ++ ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++ ++/** private members **/ ++ ++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 */ ++ ++unsigned int FFI_HIDDEN ++ffi_closure_SYSV_inner (closure, respp, args) ++ffi_closure *closure; ++void **respp; ++void *args; ++{ ++ // 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 - (__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) ++{ ++ if (cif->abi != FFI_SYSV) ++ return FFI_BAD_ABI; ++ ++ 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 ++ ++ffi_status ++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) ++{ ++ 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) ++{ ++ 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 *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++ ++#ifdef X86_WIN32 ++extern void ++ffi_call_STDCALL(void (*)(char *, extended_cif *), extended_cif *, unsigned, ++ unsigned, unsigned *, void (*fn)()); ++#endif /* X86_WIN32 */ ++ ++void ++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) && ++ (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: ++ ffi_call_STDCALL(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, ++ ecif.rvalue, fn); ++ break; ++#endif /* X86_WIN32 */ ++ default: ++ FFI_ASSERT(0); ++ break; ++ } ++} ++ ++#endif ++#endif // __i386__ +diff --git ./setup.py ./setup.py +index 46b92fe..2bf6b4b 100644 +--- ./setup.py ++++ ./setup.py +@@ -98,8 +98,14 @@ class PyBuildExt(build_ext): + self.detect_modules() + + # Remove modules that are present on the disabled list +- self.extensions = [ext for ext in self.extensions +- if ext.name not in disabled_module_list] ++ extensions = [ext for ext in self.extensions ++ if ext.name not in disabled_module_list] ++ # move ctypes to the end, it depends on other modules ++ ext_map = dict((ext.name, i) for i, ext in enumerate(extensions)) ++ if "_ctypes" in ext_map: ++ ctypes = extensions.pop(ext_map["_ctypes"]) ++ extensions.append(ctypes) ++ self.extensions = extensions + + # Fix up the autodetected modules, prefixing all the source files + # with Modules/ and adding Python's include directory to the path. +@@ -1330,9 +1336,39 @@ class PyBuildExt(build_ext): + # *** Uncomment these for TOGL extension only: + # -lGL -lGLU -lXext -lXmu \ + ++ def configure_ctypes_darwin(self, ext): ++ # Darwin (OS X) uses preconfigured files, in ++ # the Modules/_ctypes/libffi_osx directory. ++ srcdir = sysconfig.get_config_var('srcdir') ++ ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', ++ '_ctypes', 'libffi_osx')) ++ sources = [os.path.join(ffi_srcdir, p) ++ for p in ['ffi.c', ++ 'x86/darwin64.S', ++ 'x86/x86-darwin.S', ++ 'x86/x86-ffi_darwin.c', ++ 'x86/x86-ffi64.c', ++ 'powerpc/ppc-darwin.S', ++ 'powerpc/ppc-darwin_closure.S', ++ 'powerpc/ppc-ffi_darwin.c', ++ 'powerpc/ppc64-darwin_closure.S', ++ ]] ++ ++ # Add .S (preprocessed assembly) to C compiler source extensions. ++ self.compiler.src_extensions.append('.S') ++ ++ include_dirs = [os.path.join(ffi_srcdir, 'include'), ++ os.path.join(ffi_srcdir, 'powerpc')] ++ ext.include_dirs.extend(include_dirs) ++ ext.sources.extend(sources) ++ return True ++ + def configure_ctypes(self, ext): + if not self.use_system_libffi: +- (srcdir,) = sysconfig.get_config_vars('srcdir') ++ if sys.platform == 'darwin': ++ return self.configure_ctypes_darwin(ext) ++ ++ srcdir = sysconfig.get_config_var('srcdir') + ffi_builddir = os.path.join(self.build_temp, 'libffi') + ffi_srcdir = os.path.abspath(os.path.join(srcdir, 'Modules', + '_ctypes', 'libffi')) +@@ -1347,7 +1383,10 @@ class PyBuildExt(build_ext): + ffi_configfile): + from distutils.dir_util import mkpath + mkpath(ffi_builddir) +- config_args = [] ++ config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() ++ if (('--host=' in arg) or ('--build=' in arg))] ++ if not self.verbose: ++ config_args.append("-q") + + # Pass empty CFLAGS because we'll just append the resulting + # CFLAGS to Python's; -g or -O2 is to be avoided. +@@ -1367,10 +1406,12 @@ class PyBuildExt(build_ext): + self.compiler.src_extensions.append('.S') + + include_dirs = [os.path.join(ffi_builddir, 'include'), +- ffi_builddir, ffi_srcdir] ++ ffi_builddir, ++ os.path.join(ffi_srcdir, 'src')] + extra_compile_args = fficonfig['ffi_cflags'].split() + +- ext.sources.extend(fficonfig['ffi_sources']) ++ ext.sources.extend(os.path.join(ffi_srcdir, f) for f in ++ fficonfig['ffi_sources']) + ext.include_dirs.extend(include_dirs) + ext.extra_compile_args.extend(extra_compile_args) + return True +@@ -1390,6 +1431,7 @@ class PyBuildExt(build_ext): + + if sys.platform == 'darwin': + sources.append('_ctypes/darwin/dlfcn_simple.c') ++ extra_compile_args.append('-DMACOSX') + include_dirs.append('_ctypes/darwin') + # XXX Is this still needed? + ## extra_link_args.extend(['-read_only_relocs', 'warning']) +@@ -1419,7 +1461,14 @@ class PyBuildExt(build_ext): + if not '--with-system-ffi' in sysconfig.get_config_var("CONFIG_ARGS"): + return + +- ffi_inc = find_file('ffi.h', [], inc_dirs) ++ if sys.platform == 'darwin': ++ # OS X 10.5 comes with libffi.dylib; the include files are ++ # in /usr/include/ffi ++ inc_dirs.append('/usr/include/ffi') ++ ++ ffi_inc = [sysconfig.get_config_var("LIBFFI_INCLUDEDIR")] ++ if not ffi_inc or ffi_inc[0] == '': ++ ffi_inc = find_file('ffi.h', [], inc_dirs) + if ffi_inc is not None: + ffi_h = ffi_inc[0] + '/ffi.h' + fp = open(ffi_h)