mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	bpo-35947: Update Windows to the current version of libffi (GH-11797)
We now use a pre-built libffi binary from our binaries repository, and no longer vendor the full implementation.
This commit is contained in:
		
							parent
							
								
									3396d1e0ca
								
							
						
					
					
						commit
						32119e10b7
					
				
					 24 changed files with 250 additions and 2365 deletions
				
			
		|  | @ -6,35 +6,6 @@ | |||
| 
 | ||||
| import _ctypes_test | ||||
| 
 | ||||
| # Only windows 32-bit has different calling conventions. | ||||
| @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') | ||||
| @unittest.skipUnless(sizeof(c_void_p) == sizeof(c_int), | ||||
|                      "sizeof c_void_p and c_int differ") | ||||
| class WindowsTestCase(unittest.TestCase): | ||||
|     def test_callconv_1(self): | ||||
|         # Testing stdcall function | ||||
| 
 | ||||
|         IsWindow = windll.user32.IsWindow | ||||
|         # ValueError: Procedure probably called with not enough arguments | ||||
|         # (4 bytes missing) | ||||
|         self.assertRaises(ValueError, IsWindow) | ||||
| 
 | ||||
|         # This one should succeed... | ||||
|         self.assertEqual(0, IsWindow(0)) | ||||
| 
 | ||||
|         # ValueError: Procedure probably called with too many arguments | ||||
|         # (8 bytes in excess) | ||||
|         self.assertRaises(ValueError, IsWindow, 0, 0, 0) | ||||
| 
 | ||||
|     def test_callconv_2(self): | ||||
|         # Calling stdcall function as cdecl | ||||
| 
 | ||||
|         IsWindow = cdll.user32.IsWindow | ||||
| 
 | ||||
|         # ValueError: Procedure called with not enough arguments | ||||
|         # (4 bytes missing) or wrong calling convention | ||||
|         self.assertRaises(ValueError, IsWindow, None) | ||||
| 
 | ||||
| @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') | ||||
| class FunctionCallTestCase(unittest.TestCase): | ||||
|     @unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC") | ||||
|  |  | |||
|  | @ -0,0 +1,2 @@ | |||
| Added current version of libffi to cpython-source-deps.  | ||||
| Change _ctypes to use current version of libffi on Windows. | ||||
|  | @ -403,24 +403,35 @@ static PyCArgObject * | |||
| StructUnionType_paramfunc(CDataObject *self) | ||||
| { | ||||
|     PyCArgObject *parg; | ||||
|     CDataObject *copied_self; | ||||
|     StgDictObject *stgdict; | ||||
| 
 | ||||
|     parg = PyCArgObject_new(); | ||||
|     if (parg == NULL) | ||||
|     if (self->b_size > sizeof(void*)) { | ||||
|         void *new_ptr = PyMem_Malloc(self->b_size); | ||||
|         if (new_ptr == NULL) | ||||
|             return NULL; | ||||
|         memcpy(new_ptr, self->b_ptr, self->b_size); | ||||
|         copied_self = (CDataObject *)PyCData_AtAddress( | ||||
|             (PyObject *)Py_TYPE(self), new_ptr); | ||||
|         copied_self->b_needsfree = 1; | ||||
|     } else { | ||||
|         copied_self = self; | ||||
|         Py_INCREF(copied_self); | ||||
|     } | ||||
| 
 | ||||
|     parg = PyCArgObject_new(); | ||||
|     if (parg == NULL) { | ||||
|         Py_DECREF(copied_self); | ||||
|         return NULL; | ||||
|     } | ||||
| 
 | ||||
|     parg->tag = 'V'; | ||||
|     stgdict = PyObject_stgdict((PyObject *)self); | ||||
|     stgdict = PyObject_stgdict((PyObject *)copied_self); | ||||
|     assert(stgdict); /* Cannot be NULL for structure/union instances */ | ||||
|     parg->pffi_type = &stgdict->ffi_type_pointer; | ||||
|     /* For structure parameters (by value), parg->value doesn't contain the structure
 | ||||
|        data itself, instead parg->value.p *points* to the structure's data | ||||
|        See also _ctypes.c, function _call_function_pointer(). | ||||
|     */ | ||||
|     parg->value.p = self->b_ptr; | ||||
|     parg->size = self->b_size; | ||||
|     Py_INCREF(self); | ||||
|     parg->obj = (PyObject *)self; | ||||
|     parg->value.p = copied_self->b_ptr; | ||||
|     parg->size = copied_self->b_size; | ||||
|     parg->obj = (PyObject *)copied_self; | ||||
|     return parg; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -729,6 +729,23 @@ static int ConvParam(PyObject *obj, Py_ssize_t index, struct argument *pa) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| #if defined(MS_WIN32) && !defined(_WIN32_WCE) | ||||
| /*
 | ||||
| Per: https://msdn.microsoft.com/en-us/library/7572ztz4.aspx
 | ||||
| To be returned by value in RAX, user-defined types must have a length  | ||||
| of 1, 2, 4, 8, 16, 32, or 64 bits | ||||
| */ | ||||
| int can_return_struct_as_int(size_t s) | ||||
| { | ||||
|   return s == 1 || s == 2 || s == 4; | ||||
| } | ||||
| 
 | ||||
| int can_return_struct_as_sint64(size_t s) | ||||
| { | ||||
|   return s == 8; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| ffi_type *_ctypes_get_ffi_type(PyObject *obj) | ||||
| { | ||||
|  | @ -778,12 +795,9 @@ static int _call_function_pointer(int flags, | |||
|     int *space; | ||||
|     ffi_cif cif; | ||||
|     int cc; | ||||
| #ifdef MS_WIN32 | ||||
|     int delta; | ||||
| #ifndef DONT_USE_SEH | ||||
| #if defined(MS_WIN32) && !defined(DONT_USE_SEH) | ||||
|     DWORD dwExceptionCode = 0; | ||||
|     EXCEPTION_RECORD record; | ||||
| #endif | ||||
| #endif | ||||
|     /* XXX check before here */ | ||||
|     if (restype == NULL) { | ||||
|  | @ -828,7 +842,6 @@ static int _call_function_pointer(int flags, | |||
| #ifndef DONT_USE_SEH | ||||
|     __try { | ||||
| #endif | ||||
|         delta = | ||||
| #endif | ||||
|                 ffi_call(&cif, (void *)pProc, resmem, avalues); | ||||
| #ifdef MS_WIN32 | ||||
|  | @ -860,35 +873,6 @@ static int _call_function_pointer(int flags, | |||
|         return -1; | ||||
|     } | ||||
| #endif | ||||
| #ifdef MS_WIN64 | ||||
|     if (delta != 0) { | ||||
|         PyErr_Format(PyExc_RuntimeError, | ||||
|                  "ffi_call failed with code %d", | ||||
|                  delta); | ||||
|         return -1; | ||||
|     } | ||||
| #else | ||||
|     if (delta < 0) { | ||||
|         if (flags & FUNCFLAG_CDECL) | ||||
|             PyErr_Format(PyExc_ValueError, | ||||
|                      "Procedure called with not enough " | ||||
|                      "arguments (%d bytes missing) " | ||||
|                      "or wrong calling convention", | ||||
|                      -delta); | ||||
|         else | ||||
|             PyErr_Format(PyExc_ValueError, | ||||
|                      "Procedure probably called with not enough " | ||||
|                      "arguments (%d bytes missing)", | ||||
|                      -delta); | ||||
|         return -1; | ||||
|     } else if (delta > 0) { | ||||
|         PyErr_Format(PyExc_ValueError, | ||||
|                  "Procedure probably called with too many " | ||||
|                  "arguments (%d bytes in excess)", | ||||
|                  delta); | ||||
|         return -1; | ||||
|     } | ||||
| #endif | ||||
| #endif | ||||
|     if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred()) | ||||
|         return -1; | ||||
|  |  | |||
|  | @ -1,20 +0,0 @@ | |||
| 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. | ||||
|  | @ -1,500 +0,0 @@ | |||
| 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: <URL:http://sources.redhat.com/libffi/>. | ||||
| 
 | ||||
| 
 | ||||
| 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 <stdio.h> | ||||
|     #include <ffi.h> | ||||
|      | ||||
|     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 Cryptic 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 | ||||
| <http://larch-www.lcs.mit.edu:8001/larch/lclint/index.html>. | ||||
| 
 | ||||
| 
 | ||||
| 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 | ||||
| 	<mcmanr@eq.gs.com>. | ||||
| 
 | ||||
| 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 <green@cygnus.com>. | ||||
| 
 | ||||
| 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 <http://www.vdi.com>. Further enhancements were | ||||
| made by Gordon Irlam at Cygnus Solutions <http://www.cygnus.com>. | ||||
| 
 | ||||
| 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. | ||||
|  | @ -1,7 +0,0 @@ | |||
| The purpose is to hack the libffi sources so that they can be compiled | ||||
| with MSVC, and to extend them so that they have the features I need | ||||
| for ctypes. | ||||
| 
 | ||||
| I retrieved the libffi sources from the gcc cvs repository on | ||||
| 2004-01-27.  Then I did 'configure' in a 'build' subdirectory on a x86 | ||||
| linux system, and copied the files I found useful. | ||||
|  | @ -1,530 +0,0 @@ | |||
| /* -----------------------------------------------------------------------
 | ||||
|    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 <ffi.h> | ||||
| #include <ffi_common.h> | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| /* ffi_prep_args is called by the assembly routine once stack space
 | ||||
|    has been allocated for the function's arguments */ | ||||
| 
 | ||||
| extern void Py_FatalError(const char *msg); | ||||
| 
 | ||||
| /*@-exportheader@*/ | ||||
| void ffi_prep_args(char *stack, extended_cif *ecif) | ||||
| /*@=exportheader@*/ | ||||
| { | ||||
|   register unsigned int i; | ||||
|   register void **p_argv; | ||||
|   register char *argp; | ||||
|   register ffi_type **p_arg; | ||||
| 
 | ||||
|   argp = stack; | ||||
|   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) | ||||
|     { | ||||
|       *(void **) argp = ecif->rvalue; | ||||
|       argp += sizeof(void *); | ||||
|     } | ||||
| 
 | ||||
|   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(void *) - 1) & (size_t) argp) | ||||
| 	argp = (char *) ALIGN(argp, sizeof(void *)); | ||||
| 
 | ||||
|       z = (*p_arg)->size; | ||||
|       if (z < sizeof(intptr_t)) | ||||
| 	{ | ||||
| 	  z = sizeof(intptr_t); | ||||
| 	  switch ((*p_arg)->type) | ||||
| 	    { | ||||
| 	    case FFI_TYPE_SINT8: | ||||
| 	      *(intptr_t *) argp = (intptr_t)*(SINT8 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_UINT8: | ||||
| 	      *(uintptr_t *) argp = (uintptr_t)*(UINT8 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_SINT16: | ||||
| 	      *(intptr_t *) argp = (intptr_t)*(SINT16 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_UINT16: | ||||
| 	      *(uintptr_t *) argp = (uintptr_t)*(UINT16 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_SINT32: | ||||
| 	      *(intptr_t *) argp = (intptr_t)*(SINT32 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_UINT32: | ||||
| 	      *(uintptr_t *) argp = (uintptr_t)*(UINT32 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_FLOAT: | ||||
| 	      *(uintptr_t *) argp = 0; | ||||
| 	      *(float *) argp = *(float *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    // 64-bit value cases should never be used for x86 and AMD64 builds
 | ||||
| 	    case FFI_TYPE_SINT64: | ||||
| 	      *(intptr_t *) argp = (intptr_t)*(SINT64 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_UINT64: | ||||
| 	      *(uintptr_t *) argp = (uintptr_t)*(UINT64 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_STRUCT: | ||||
| 	      *(uintptr_t *) argp = (uintptr_t)*(UINT32 *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    case FFI_TYPE_DOUBLE: | ||||
| 	      *(uintptr_t *) argp = 0; | ||||
| 	      *(double *) argp = *(double *)(* p_argv); | ||||
| 	      break; | ||||
| 
 | ||||
| 	    default: | ||||
| 	      FFI_ASSERT(0); | ||||
| 	    } | ||||
| 	} | ||||
| #ifdef _WIN64 | ||||
|       else if (z > 8) | ||||
|         { | ||||
|           /* On Win64, if a single argument takes more than 8 bytes,
 | ||||
|              then it is always passed by reference. */ | ||||
|           *(void **)argp = *p_argv; | ||||
|           z = 8; | ||||
|         } | ||||
| #endif | ||||
|       else | ||||
| 	{ | ||||
| 	  memcpy(argp, *p_argv, z); | ||||
| 	} | ||||
|       p_argv++; | ||||
|       argp += z; | ||||
|     } | ||||
| 
 | ||||
|   if (argp >= stack && (unsigned)(argp - stack) > ecif->cif->bytes)  | ||||
|     { | ||||
|       Py_FatalError("FFI BUG: not enough stack space for arguments"); | ||||
|     } | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| Per: https://msdn.microsoft.com/en-us/library/7572ztz4.aspx
 | ||||
| To be returned by value in RAX, user-defined types must have a length  | ||||
| of 1, 2, 4, 8, 16, 32, or 64 bits | ||||
| */ | ||||
| int can_return_struct_as_int(size_t s) | ||||
| { | ||||
|   return s == 1 || s == 2 || s == 4; | ||||
| } | ||||
| 
 | ||||
| int can_return_struct_as_sint64(size_t s) | ||||
| { | ||||
|   return s == 8; | ||||
| } | ||||
| 
 | ||||
| /* 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: | ||||
|     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_STRUCT: | ||||
|       /* MSVC returns small structures in registers.  Put in cif->flags
 | ||||
|          the value FFI_TYPE_STRUCT only if the structure is big enough; | ||||
|          otherwise, put the 4- or 8-bytes integer type. */ | ||||
|       if (can_return_struct_as_int(cif->rtype->size)) | ||||
|         cif->flags = FFI_TYPE_INT; | ||||
|       else if (can_return_struct_as_sint64(cif->rtype->size)) | ||||
|         cif->flags = FFI_TYPE_SINT64; | ||||
|       else | ||||
|         cif->flags = FFI_TYPE_STRUCT; | ||||
|       break; | ||||
| 
 | ||||
|     case FFI_TYPE_UINT64: | ||||
| #ifdef _WIN64 | ||||
|     case FFI_TYPE_POINTER: | ||||
| #endif | ||||
|       cif->flags = FFI_TYPE_SINT64; | ||||
|       break; | ||||
| 
 | ||||
|     default: | ||||
|       cif->flags = FFI_TYPE_INT; | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|   return FFI_OK; | ||||
| } | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| extern int | ||||
| ffi_call_x86(void (*)(char *, extended_cif *),  | ||||
| 	     /*@out@*/ extended_cif *,  | ||||
| 	     unsigned, unsigned,  | ||||
| 	     /*@out@*/ unsigned *,  | ||||
| 	     void (*fn)()); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
| extern int | ||||
| ffi_call_AMD64(void (*)(char *, extended_cif *), | ||||
| 		 /*@out@*/ extended_cif *, | ||||
| 		 unsigned, unsigned, | ||||
| 		 /*@out@*/ unsigned *, | ||||
| 		 void (*fn)()); | ||||
| #endif | ||||
| 
 | ||||
| int | ||||
| ffi_call(/*@dependent@*/ ffi_cif *cif,  | ||||
| 	 void (*fn)(),  | ||||
| 	 /*@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)  | ||||
|     { | ||||
| #if !defined(_WIN64) | ||||
|     case FFI_SYSV: | ||||
|     case FFI_STDCALL: | ||||
|       return ffi_call_x86(ffi_prep_args, &ecif, cif->bytes,  | ||||
| 			  cif->flags, ecif.rvalue, fn); | ||||
|       break; | ||||
| #else | ||||
|     case FFI_SYSV: | ||||
|       /* If a single argument takes more than 8 bytes,
 | ||||
|          then a copy is passed by reference. */ | ||||
|       for (unsigned i = 0; i < cif->nargs; i++) { | ||||
|           size_t z = cif->arg_types[i]->size; | ||||
|           if (z > 8) { | ||||
|               void *temp = alloca(z); | ||||
|               memcpy(temp, avalue[i], z); | ||||
|               avalue[i] = temp; | ||||
|           } | ||||
|       } | ||||
|       /*@-usedef@*/ | ||||
|       return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes, | ||||
| 			   cif->flags, ecif.rvalue, fn); | ||||
|       /*@=usedef@*/ | ||||
|       break; | ||||
| #endif | ||||
| 
 | ||||
|     default: | ||||
|       FFI_ASSERT(0); | ||||
|       break; | ||||
|     } | ||||
|   return -1; /* theller: Hrm. */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** private members **/ | ||||
| 
 | ||||
| static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, | ||||
| 					  void** args, ffi_cif* cif); | ||||
| /* This function is jumped to by the trampoline */ | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
| void * | ||||
| #else | ||||
| static void __fastcall | ||||
| #endif | ||||
| ffi_closure_SYSV (ffi_closure *closure, char *argp) | ||||
| { | ||||
|   // this is our return value storage
 | ||||
|   long double    res; | ||||
| 
 | ||||
|   // our various things...
 | ||||
|   ffi_cif       *cif; | ||||
|   void         **arg_area; | ||||
|   unsigned short rtype; | ||||
|   void          *resp = (void*)&res; | ||||
|   void *args = argp + sizeof(void*); | ||||
| 
 | ||||
|   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, (void**)&resp, arg_area, cif); | ||||
|    | ||||
|   (closure->fun) (cif, resp, arg_area, closure->user_data); | ||||
| 
 | ||||
|   rtype = cif->flags; | ||||
| 
 | ||||
| #if defined(_WIN32) && !defined(_WIN64) | ||||
| #ifdef _MSC_VER | ||||
|   /* now, do a generic return based on the value of rtype */ | ||||
|   if (rtype == FFI_TYPE_INT) | ||||
|     { | ||||
| 	    _asm mov eax, resp ; | ||||
| 	    _asm mov eax, [eax] ; | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_FLOAT) | ||||
|     { | ||||
| 	    _asm mov eax, resp ; | ||||
| 	    _asm fld DWORD PTR [eax] ; | ||||
| //      asm ("flds (%0)" : : "r" (resp) : "st" );
 | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_DOUBLE) | ||||
|     { | ||||
| 	    _asm mov eax, resp ; | ||||
| 	    _asm fld QWORD PTR [eax] ; | ||||
| //      asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" );
 | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_LONGDOUBLE) | ||||
|     { | ||||
| //      asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" );
 | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_SINT64) | ||||
|     { | ||||
| 	    _asm mov edx, resp ; | ||||
| 	    _asm mov eax, [edx] ; | ||||
| 	    _asm mov edx, [edx + 4] ; | ||||
| //      asm ("movl 0(%0),%%eax;"
 | ||||
| //	   "movl 4(%0),%%edx" 
 | ||||
| //	   : : "r"(resp)
 | ||||
| //	   : "eax", "edx");
 | ||||
|     } | ||||
| #else | ||||
|   /* now, do a generic return based on the value of rtype */ | ||||
|   if (rtype == FFI_TYPE_INT) | ||||
|     { | ||||
|       asm ("movl (%0),%%eax" : : "r" (resp) : "eax"); | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_FLOAT) | ||||
|     { | ||||
|       asm ("flds (%0)" : : "r" (resp) : "st" ); | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_DOUBLE) | ||||
|     { | ||||
|       asm ("fldl (%0)" : : "r" (resp) : "st", "st(1)" ); | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_LONGDOUBLE) | ||||
|     { | ||||
|       asm ("fldt (%0)" : : "r" (resp) : "st", "st(1)" ); | ||||
|     } | ||||
|   else if (rtype == FFI_TYPE_SINT64) | ||||
|     { | ||||
|       asm ("movl 0(%0),%%eax;" | ||||
| 	   "movl 4(%0),%%edx"  | ||||
| 	   : : "r"(resp) | ||||
| 	   : "eax", "edx"); | ||||
|     } | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
|   /* The result is returned in rax.  This does the right thing for
 | ||||
|      result types except for floats; we have to 'mov xmm0, rax' in the | ||||
|      caller to correct this. | ||||
|   */ | ||||
|   return *(void **)resp; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /*@-exportheader@*/ | ||||
| static void  | ||||
| ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, | ||||
| 			    void **avalue, ffi_cif *cif) | ||||
| /*@=exportheader@*/ | ||||
| { | ||||
|   register unsigned int i; | ||||
|   register void **p_argv; | ||||
|   register char *argp; | ||||
|   register ffi_type **p_arg; | ||||
| 
 | ||||
|   argp = stack; | ||||
| 
 | ||||
|   if ( cif->rtype->type == FFI_TYPE_STRUCT ) { | ||||
|     *rvalue = *(void **) argp; | ||||
|     argp += sizeof(void *); | ||||
|   } | ||||
| 
 | ||||
|   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(char *) - 1) & (size_t) argp) { | ||||
|         argp = (char *) ALIGN(argp, sizeof(char*)); | ||||
|       } | ||||
| 
 | ||||
|       z = (*p_arg)->size; | ||||
| 
 | ||||
|       /* because we're little endian, this is what it turns into.   */ | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
|       if (z > 8) { | ||||
|         /* On Win64, if a single argument takes more than 8 bytes,
 | ||||
|          * then it is always passed by reference. | ||||
|          */ | ||||
|         *p_argv = *((void**) argp); | ||||
|         z = 8; | ||||
|       } | ||||
|       else | ||||
| #endif | ||||
|       *p_argv = (void*) argp; | ||||
| 
 | ||||
|       p_argv++; | ||||
|       argp += z; | ||||
|     } | ||||
|    | ||||
|   return; | ||||
| } | ||||
| 
 | ||||
| /* the cif must already be prep'ed */ | ||||
| extern void ffi_closure_OUTER(); | ||||
| 
 | ||||
| ffi_status | ||||
| ffi_prep_closure_loc (ffi_closure* closure, | ||||
| 					  ffi_cif* cif, | ||||
| 					  void (*fun)(ffi_cif*,void*,void**,void*), | ||||
| 					  void *user_data, | ||||
| 					  void *codeloc) | ||||
| { | ||||
|   short bytes; | ||||
|   char *tramp; | ||||
| #ifdef _WIN64 | ||||
|   int mask = 0; | ||||
| #endif | ||||
|   FFI_ASSERT (cif->abi == FFI_SYSV); | ||||
|    | ||||
|   if (cif->abi == FFI_SYSV) | ||||
|     bytes = 0; | ||||
| #if !defined(_WIN64) | ||||
|   else if (cif->abi == FFI_STDCALL) | ||||
|     bytes = cif->bytes; | ||||
| #endif | ||||
|   else | ||||
|     return FFI_BAD_ABI; | ||||
| 
 | ||||
|   tramp = &closure->tramp[0]; | ||||
| 
 | ||||
| #define BYTES(text) memcpy(tramp, text, sizeof(text)), tramp += sizeof(text)-1 | ||||
| #define POINTER(x) *(void**)tramp = (void*)(x), tramp += sizeof(void*) | ||||
| #define SHORT(x) *(short*)tramp = x, tramp += sizeof(short) | ||||
| #define INT(x) *(int*)tramp = x, tramp += sizeof(int) | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
|   if (cif->nargs >= 1 && | ||||
|       (cif->arg_types[0]->type == FFI_TYPE_FLOAT | ||||
|        || cif->arg_types[0]->type == FFI_TYPE_DOUBLE)) | ||||
|     mask |= 1; | ||||
|   if (cif->nargs >= 2 && | ||||
|       (cif->arg_types[1]->type == FFI_TYPE_FLOAT | ||||
|        || cif->arg_types[1]->type == FFI_TYPE_DOUBLE)) | ||||
|     mask |= 2; | ||||
|   if (cif->nargs >= 3 && | ||||
|       (cif->arg_types[2]->type == FFI_TYPE_FLOAT | ||||
|        || cif->arg_types[2]->type == FFI_TYPE_DOUBLE)) | ||||
|     mask |= 4; | ||||
|   if (cif->nargs >= 4 && | ||||
|       (cif->arg_types[3]->type == FFI_TYPE_FLOAT | ||||
|        || cif->arg_types[3]->type == FFI_TYPE_DOUBLE)) | ||||
|     mask |= 8; | ||||
| 
 | ||||
|   /* 41 BB ----         mov         r11d,mask */ | ||||
|   BYTES("\x41\xBB"); INT(mask); | ||||
| 
 | ||||
|   /* 48 B8 --------     mov         rax, closure			*/ | ||||
|   BYTES("\x48\xB8"); POINTER(closure); | ||||
| 
 | ||||
|   /* 49 BA --------     mov         r10, ffi_closure_OUTER */ | ||||
|   BYTES("\x49\xBA"); POINTER(ffi_closure_OUTER); | ||||
| 
 | ||||
|   /* 41 FF E2           jmp         r10 */ | ||||
|   BYTES("\x41\xFF\xE2"); | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
|   /* mov ecx, closure */ | ||||
|   BYTES("\xb9"); POINTER(closure); | ||||
| 
 | ||||
|   /* mov edx, esp */ | ||||
|   BYTES("\x8b\xd4"); | ||||
| 
 | ||||
|   /* call ffi_closure_SYSV */ | ||||
|   BYTES("\xe8"); POINTER((char*)&ffi_closure_SYSV - (tramp + 4)); | ||||
| 
 | ||||
|   /* ret bytes */ | ||||
|   BYTES("\xc2"); | ||||
|   SHORT(bytes); | ||||
|    | ||||
| #endif | ||||
| 
 | ||||
|   if (tramp - &closure->tramp[0] > FFI_TRAMPOLINE_SIZE) | ||||
|     Py_FatalError("FFI_TRAMPOLINE_SIZE too small in " __FILE__); | ||||
| 
 | ||||
|   closure->cif  = cif; | ||||
|   closure->user_data = user_data; | ||||
|   closure->fun  = fun; | ||||
|   return FFI_OK; | ||||
| } | ||||
|  | @ -1,322 +0,0 @@ | |||
| /* -----------------------------------------------------------------*-C-*-
 | ||||
|    libffi 2.00-beta - 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 cloure 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. */ | ||||
| //XXX #define X86
 | ||||
| 
 | ||||
| /* ---- System configuration information --------------------------------- */ | ||||
| 
 | ||||
| #include <ffitarget.h> | ||||
| 
 | ||||
| #ifndef LIBFFI_ASM | ||||
| 
 | ||||
| #include <stddef.h> | ||||
| #include <limits.h> | ||||
| 
 | ||||
| /* 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 | ||||
| #  ifdef _MSC_VER | ||||
| #   define FFI_LONG_LONG_MAX _I64_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; | ||||
| 
 | ||||
| int can_return_struct_as_int(size_t); | ||||
| int can_return_struct_as_sint64(size_t); | ||||
| 
 | ||||
| /* 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_OK = 0, | ||||
|   FFI_BAD_TYPEDEF, | ||||
|   FFI_BAD_ABI  | ||||
| } ffi_status; | ||||
| 
 | ||||
| typedef unsigned FFI_TYPE; | ||||
| 
 | ||||
| typedef struct { | ||||
|   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 -------------------------------------- */ | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
| #define FFI_SIZEOF_ARG 8 | ||||
| #else | ||||
| #define FFI_SIZEOF_ARG 4 | ||||
| #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)(),  | ||||
| 		   /*@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)(),  | ||||
| 		        /*@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 { | ||||
|   char tramp[FFI_TRAMPOLINE_SIZE]; | ||||
|   ffi_cif   *cif; | ||||
|   void     (*fun)(ffi_cif*,void*,void**,void*); | ||||
|   void      *user_data; | ||||
| } ffi_closure; | ||||
| 
 | ||||
| void ffi_closure_free(void *); | ||||
| void *ffi_closure_alloc (size_t size, void **code); | ||||
| 
 | ||||
| ffi_status | ||||
| ffi_prep_closure_loc (ffi_closure*, | ||||
| 		  ffi_cif *, | ||||
| 		  void (*fun)(ffi_cif*,void*,void**,void*), | ||||
| 		  void *user_data, | ||||
| 		  void *codeloc); | ||||
| 
 | ||||
| typedef struct { | ||||
|   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*, | ||||
| 		      ffi_cif *cif, | ||||
| 		      void (*fun)(ffi_cif*,void*,ffi_raw*,void*), | ||||
| 		      void *user_data); | ||||
| 
 | ||||
| ffi_status | ||||
| ffi_prep_java_raw_closure (ffi_raw_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); | ||||
| 
 | ||||
| int | ||||
| ffi_call(/*@dependent@*/ ffi_cif *cif,  | ||||
| 	 void (*fn)(),  | ||||
| 	 /*@out@*/ void *rvalue,  | ||||
| 	 /*@dependent@*/ void **avalue); | ||||
| 
 | ||||
| /* Useful for eliminating compiler warnings */ | ||||
| #define FFI_FN(f) ((void (*)())f) | ||||
| 
 | ||||
| /* ---- Definitions shared with assembly code ---------------------------- */ | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /* 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 | ||||
| #if 1 | ||||
| #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 | ||||
| 
 | ||||
|  | @ -1,77 +0,0 @@ | |||
| /* -----------------------------------------------------------------------
 | ||||
|    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> | ||||
| #include <malloc.h> | ||||
| 
 | ||||
| /* Check for the existence of memcpy. */ | ||||
| #if STDC_HEADERS | ||||
| # include <string.h> | ||||
| #else | ||||
| # ifndef HAVE_MEMCPY | ||||
| #  define memcpy(d, s, n) bcopy ((s), (d), (n)) | ||||
| # endif | ||||
| #endif | ||||
| 
 | ||||
| #if defined(FFI_DEBUG)  | ||||
| #include <stdio.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifdef FFI_DEBUG | ||||
| /*@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 | ||||
| 
 | ||||
| #define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+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 | ||||
| { | ||||
|   /*@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 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1,96 +0,0 @@ | |||
| /* fficonfig.h.  Originally created by configure, now hand_maintained for MSVC. */ | ||||
| 
 | ||||
| /* fficonfig.h.  Generated automatically by configure.  */ | ||||
| /* fficonfig.h.in.  Generated automatically from configure.in by autoheader.  */ | ||||
| 
 | ||||
| /* Define this for MSVC, but not for mingw32! */ | ||||
| #ifdef _MSC_VER | ||||
| #define __attribute__(x) /* */ | ||||
| #endif | ||||
| #define alloca _alloca | ||||
| 
 | ||||
| /*----------------------------------------------------------------*/ | ||||
| 
 | ||||
| /* Define if using alloca.c.  */ | ||||
| /* #undef C_ALLOCA */ | ||||
| 
 | ||||
| /* 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 if you have alloca, as a function or macro.  */ | ||||
| #define HAVE_ALLOCA 1 | ||||
| 
 | ||||
| /* Define if you have <alloca.h> and it should be used (not on Ultrix).  */ | ||||
| /* #define HAVE_ALLOCA_H 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 if you have the ANSI C header files.  */ | ||||
| #define STDC_HEADERS 1 | ||||
| 
 | ||||
| /* Define if you have the memcpy function.  */ | ||||
| #define HAVE_MEMCPY 1 | ||||
| 
 | ||||
| /* Define if read-only mmap of a plain file works. */ | ||||
| //#define HAVE_MMAP_FILE 1
 | ||||
| 
 | ||||
| /* Define if mmap of /dev/zero works. */ | ||||
| //#define HAVE_MMAP_DEV_ZERO 1
 | ||||
| 
 | ||||
| /* Define if mmap with MAP_ANON(YMOUS) works. */ | ||||
| //#define HAVE_MMAP_ANON 1
 | ||||
| 
 | ||||
| /* The number of bytes in type double */ | ||||
| #define SIZEOF_DOUBLE 8 | ||||
| 
 | ||||
| /* The number of bytes in type long double */ | ||||
| #define SIZEOF_LONG_DOUBLE 12 | ||||
| 
 | ||||
| /* Define if you have the long double type and it is bigger than a double */ | ||||
| #define HAVE_LONG_DOUBLE 1 | ||||
| 
 | ||||
| /* whether byteorder is bigendian */ | ||||
| /* #undef WORDS_BIGENDIAN */ | ||||
| 
 | ||||
| /* Define if the host machine stores words of multi-word integers in
 | ||||
|    big-endian order. */ | ||||
| /* #undef HOST_WORDS_BIG_ENDIAN */ | ||||
| 
 | ||||
| /* 1234 = LIL_ENDIAN, 4321 = BIGENDIAN */ | ||||
| #define BYTEORDER 1234 | ||||
| 
 | ||||
| /* Define if your assembler and linker support unaligned PC relative relocs. */ | ||||
| /* #undef HAVE_AS_SPARC_UA_PCREL */ | ||||
| 
 | ||||
| /* Define if your assembler supports .register. */ | ||||
| /* #undef HAVE_AS_REGISTER_PSEUDO_OP */ | ||||
| 
 | ||||
| /* Define if .eh_frame sections should be read-only. */ | ||||
| /* #undef HAVE_RO_EH_FRAME */ | ||||
| 
 | ||||
| /* Define to the flags needed for the .section .eh_frame directive. */ | ||||
| /* #define EH_FRAME_FLAGS "aw" */ | ||||
| 
 | ||||
| /* 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 aggregate types. */ | ||||
| /* #undef FFI_NO_STRUCTS */ | ||||
| 
 | ||||
| /* Define this is you do not want support for the raw API. */ | ||||
| /* #undef FFI_NO_RAW_API */ | ||||
| 
 | ||||
| /* Define this if you are using Purify and want to suppress spurious messages. */ | ||||
| /* #undef USING_PURIFY */ | ||||
| 
 | ||||
|  | @ -1,85 +0,0 @@ | |||
| /* -----------------------------------------------------------------*-C-*-
 | ||||
|    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 | ||||
| 
 | ||||
| /* ---- Generic type definitions ----------------------------------------- */ | ||||
| 
 | ||||
| #ifndef LIBFFI_ASM | ||||
| #ifndef _WIN64 | ||||
| typedef unsigned long          ffi_arg; | ||||
| #else | ||||
| typedef unsigned __int64       ffi_arg; | ||||
| #endif | ||||
| typedef signed long            ffi_sarg; | ||||
| 
 | ||||
| typedef enum ffi_abi { | ||||
|   FFI_FIRST_ABI = 0, | ||||
| 
 | ||||
|   /* ---- Intel x86 Win32 ---------- */ | ||||
|   FFI_SYSV, | ||||
| #ifndef _WIN64 | ||||
|   FFI_STDCALL, | ||||
| #endif | ||||
|   /* TODO: Add fastcall support for the sake of completeness */ | ||||
|   FFI_DEFAULT_ABI = FFI_SYSV, | ||||
| 
 | ||||
|   /* ---- 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 | ||||
| 
 | ||||
| /* ---- Definitions for closures ----------------------------------------- */ | ||||
| 
 | ||||
| #define FFI_CLOSURES 1 | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
| #define FFI_TRAMPOLINE_SIZE 29 | ||||
| #define FFI_NATIVE_RAW_API 0 | ||||
| #else | ||||
| #define FFI_TRAMPOLINE_SIZE 15 | ||||
| #define FFI_NATIVE_RAW_API 1	/* x86 has native raw api support */ | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  | @ -1,188 +0,0 @@ | |||
| /* -----------------------------------------------------------------------
 | ||||
|    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 <ffi.h> | ||||
| #include <ffi_common.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| 
 | ||||
| /* 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) | ||||
| { | ||||
|   ffi_type **ptr;  | ||||
| 
 | ||||
|   FFI_ASSERT(arg != NULL); | ||||
| 
 | ||||
|   /*@-usedef@*/ | ||||
| 
 | ||||
|   FFI_ASSERT(arg->elements != NULL); | ||||
|   FFI_ASSERT(arg->size == 0); | ||||
|   FFI_ASSERT(arg->alignment == 0); | ||||
| 
 | ||||
|   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); | ||||
| 
 | ||||
|       arg->size = ALIGN(arg->size, (*ptr)->alignment); | ||||
|       arg->size += (*ptr)->size; | ||||
| 
 | ||||
|       arg->alignment = (arg->alignment > (*ptr)->alignment) ?  | ||||
| 	arg->alignment : (*ptr)->alignment; | ||||
| 
 | ||||
|       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; | ||||
|   else | ||||
|     return FFI_OK; | ||||
| 
 | ||||
|   /*@=usedef@*/ | ||||
| } | ||||
| 
 | ||||
| /* Perform machine independent ffi_cif preparation, then call
 | ||||
|    machine dependent routine. */ | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|   unsigned bytes = 0; | ||||
|   unsigned int i; | ||||
|   ffi_type **ptr; | ||||
| 
 | ||||
|   FFI_ASSERT(cif != NULL); | ||||
|   FFI_ASSERT((abi > FFI_FIRST_ABI) && (abi <= FFI_DEFAULT_ABI)); | ||||
| 
 | ||||
|   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 | ||||
|   /* Make space for the return structure pointer */ | ||||
|   if (cif->rtype->type == FFI_TYPE_STRUCT | ||||
| #ifdef _WIN32 | ||||
|       && !can_return_struct_as_int(cif->rtype->size)  /* MSVC returns small structs in registers */ | ||||
|       && !can_return_struct_as_sint64(cif->rtype->size) | ||||
| #endif | ||||
| #ifdef SPARC | ||||
|       && (cif->abi != FFI_V9 || cif->rtype->size > 32) | ||||
| #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; | ||||
| 
 | ||||
|       /* Perform a sanity check on the argument type, do this 
 | ||||
| 	 check after the initialization.  */ | ||||
|       FFI_ASSERT_VALID_TYPE(*ptr); | ||||
| 
 | ||||
| #if !defined __x86_64__ && !defined S390 | ||||
| #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 | ||||
| #elif defined (_WIN64) | ||||
|       if ((*ptr)->type == FFI_TYPE_STRUCT &&  | ||||
|           !can_return_struct_as_int((*ptr)->size) && | ||||
|           !can_return_struct_as_sint64((*ptr)->size)) | ||||
| 	    bytes += sizeof(void*); | ||||
|       else | ||||
| #endif | ||||
| 	{ | ||||
| #if !defined(_MSC_VER) && !defined(__MINGW32__) | ||||
| 		/* Don't know if this is a libffi bug or not.  At least on
 | ||||
| 		   Windows with MSVC, function call parameters are *not* | ||||
| 		   aligned in the same way as structure fields are, they are | ||||
| 		   only aligned in integer boundaries. | ||||
| 
 | ||||
| 		   This doesn't do any harm for cdecl functions and closures, | ||||
| 		   since the caller cleans up the stack, but it is wrong for | ||||
| 		   stdcall functions where the callee cleans. | ||||
| 		*/ | ||||
| 
 | ||||
| 	  /* Add any padding if necessary */ | ||||
| 	  if (((*ptr)->alignment - 1) & bytes) | ||||
| 	    bytes = ALIGN(bytes, (*ptr)->alignment); | ||||
| 	   | ||||
| #endif | ||||
| 	  bytes += STACK_ARG_SIZE((*ptr)->size); | ||||
| 	} | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
| #ifdef _WIN64 | ||||
|   /* Function call needs at least 40 bytes stack size, on win64 AMD64 */ | ||||
|   if (bytes < 40) | ||||
|       bytes = 40; | ||||
| #endif | ||||
| 
 | ||||
|   cif->bytes = bytes; | ||||
| 
 | ||||
|   /* Perform machine dependent cif processing */ | ||||
|   return ffi_prep_cif_machdep(cif); | ||||
| } | ||||
|  | @ -1,104 +0,0 @@ | |||
| /* -----------------------------------------------------------------------
 | ||||
|    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 <ffi.h> | ||||
| #include <ffi_common.h> | ||||
| 
 | ||||
| /* 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 } | ||||
| 
 | ||||
| /* Size and alignment are fake here. They must not be 0. */ | ||||
| FFI_INTEGRAL_TYPEDEF(void, 1, 1, FFI_TYPE_VOID); | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
| #if defined ALPHA || defined SPARC64 || defined X86_64 || defined S390X \ | ||||
|     || defined IA64 || defined _WIN64 | ||||
| 
 | ||||
| FFI_INTEGRAL_TYPEDEF(pointer, 8, 8, FFI_TYPE_POINTER); | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| FFI_INTEGRAL_TYPEDEF(pointer, 4, 4, FFI_TYPE_POINTER); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if defined X86 || defined X86_WIN32 || defined ARM || defined M68K | ||||
| 
 | ||||
| FFI_INTEGRAL_TYPEDEF(uint64, 8, 4, FFI_TYPE_UINT64); | ||||
| FFI_INTEGRAL_TYPEDEF(sint64, 8, 4, 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 | ||||
| 
 | ||||
| FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); | ||||
| FFI_INTEGRAL_TYPEDEF(longdouble, 12, 4, FFI_TYPE_LONGDOUBLE); | ||||
| 
 | ||||
| #elif defined ARM || defined SH || defined POWERPC_AIX || defined POWERPC_DARWIN | ||||
| 
 | ||||
| FFI_INTEGRAL_TYPEDEF(double, 8, 4, FFI_TYPE_DOUBLE); | ||||
| FFI_INTEGRAL_TYPEDEF(longdouble, 8, 4, FFI_TYPE_LONGDOUBLE); | ||||
| 
 | ||||
| #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 | ||||
| 
 | ||||
| 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 | ||||
| 
 | ||||
|  | @ -1,162 +0,0 @@ | |||
| /* -----------------------------------------------------------------------
 | ||||
|    win32.S - Copyright (c) 1996, 1998, 2001, 2002  Red Hat, Inc. | ||||
| 	     Copyright (c) 2001  John Beniton | ||||
| 	     Copyright (c) 2002  Ranjit Mathew | ||||
| 			 | ||||
|   | ||||
|    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. | ||||
|    ----------------------------------------------------------------------- */ | ||||
| 
 | ||||
| /* theller: almost verbatim translation from gas syntax to MSVC inline
 | ||||
|    assembler code. */ | ||||
| 
 | ||||
| /* theller: ffi_call_x86 now returns an integer - the difference of the stack
 | ||||
|    pointer before and after the function call.  If everything is ok, zero is | ||||
|    returned.  If stdcall functions are passed the wrong number of arguments, | ||||
|    the difference will be nonzero. */ | ||||
| 
 | ||||
| #include <ffi.h> | ||||
| #include <ffi_common.h> | ||||
| 
 | ||||
| __declspec(naked) int | ||||
| ffi_call_x86(void (* prepfunc)(char *, extended_cif *), /* 8 */ | ||||
| 	     extended_cif *ecif, /* 12 */ | ||||
| 	     unsigned bytes, /* 16 */ | ||||
| 	     unsigned flags, /* 20 */ | ||||
| 	     unsigned *rvalue, /* 24 */ | ||||
| 	     void (*fn)()) /* 28 */ | ||||
| { | ||||
| 	_asm { | ||||
| 		push ebp | ||||
| 		mov ebp, esp | ||||
| 
 | ||||
| 		push esi // NEW: this register must be preserved across function calls
 | ||||
| // XXX SAVE ESP NOW!
 | ||||
| 		mov esi, esp		// save stack pointer before the call
 | ||||
| 
 | ||||
| // Make room for all of the new args.
 | ||||
| 		mov ecx, [ebp+16] | ||||
| 		sub esp, ecx		// sub esp, bytes
 | ||||
| 		 | ||||
| 		mov eax, esp | ||||
| 
 | ||||
| // Place all of the ffi_prep_args in position
 | ||||
| 		push [ebp + 12] // ecif
 | ||||
| 		push eax | ||||
| 		call [ebp + 8] // prepfunc
 | ||||
| 
 | ||||
| // Return stack to previous state and call the function
 | ||||
| 		add esp, 8 | ||||
| // FIXME: Align the stack to a 128-bit boundary to avoid
 | ||||
| // potential performance hits.
 | ||||
| 		call [ebp + 28] | ||||
| 
 | ||||
| // Load ecif->cif->abi
 | ||||
| 		mov ecx, [ebp + 12] | ||||
| 		mov ecx, [ecx]ecif.cif | ||||
| 		mov ecx, [ecx]ecif.cif.abi | ||||
| 		 | ||||
| 		cmp ecx, FFI_STDCALL | ||||
| 		je noclean | ||||
| // STDCALL: Remove the space we pushed for the args
 | ||||
| 		mov ecx, [ebp + 16] | ||||
| 		add esp, ecx | ||||
| // CDECL: Caller has already cleaned the stack
 | ||||
| noclean: | ||||
| // Check that esp has the same value as before!
 | ||||
| 		sub esi, esp | ||||
| 
 | ||||
| // Load %ecx with the return type code
 | ||||
| 		mov ecx, [ebp + 20] | ||||
| 
 | ||||
| // If the return value pointer is NULL, assume no return value.
 | ||||
| /*
 | ||||
|   Intel asm is weird. We have to explicitly specify 'DWORD PTR' in the next instruction, | ||||
|   otherwise only one BYTE will be compared (instead of a DWORD)! | ||||
|  */ | ||||
| 		cmp DWORD PTR [ebp + 24], 0 | ||||
| 		jne sc_retint | ||||
| 
 | ||||
| // Even if there is no space for the return value, we are
 | ||||
| // obliged to handle floating-point values.
 | ||||
| 		cmp ecx, FFI_TYPE_FLOAT | ||||
| 		jne sc_noretval | ||||
| //        fstp  %st(0)
 | ||||
| 		fstp st(0) | ||||
| 
 | ||||
| 		jmp sc_epilogue | ||||
| 
 | ||||
| sc_retint: | ||||
| 		cmp ecx, FFI_TYPE_INT | ||||
| 		jne sc_retfloat | ||||
| //        # Load %ecx with the pointer to storage for the return value
 | ||||
| 		mov ecx, [ebp + 24] | ||||
| 		mov [ecx + 0], eax | ||||
| 		jmp sc_epilogue | ||||
| 
 | ||||
| sc_retfloat: | ||||
| 		cmp ecx, FFI_TYPE_FLOAT | ||||
| 		jne sc_retdouble | ||||
| // Load %ecx with the pointer to storage for the return value
 | ||||
| 		mov ecx, [ebp+24] | ||||
| //        fstps (%ecx)
 | ||||
| 		fstp DWORD PTR [ecx] | ||||
| 		jmp sc_epilogue | ||||
| 
 | ||||
| sc_retdouble: | ||||
| 		cmp ecx, FFI_TYPE_DOUBLE | ||||
| 		jne sc_retlongdouble | ||||
| //        movl  24(%ebp),%ecx
 | ||||
| 		mov ecx, [ebp+24] | ||||
| 		fstp QWORD PTR [ecx] | ||||
| 		jmp sc_epilogue | ||||
| 
 | ||||
| 		jmp sc_retlongdouble // avoid warning about unused label
 | ||||
| sc_retlongdouble: | ||||
| 		cmp ecx, FFI_TYPE_LONGDOUBLE | ||||
| 		jne sc_retint64 | ||||
| // Load %ecx with the pointer to storage for the return value
 | ||||
| 		mov ecx, [ebp+24] | ||||
| //        fstpt (%ecx)
 | ||||
| 		fstp QWORD PTR [ecx] /* XXX ??? */ | ||||
| 		jmp sc_epilogue | ||||
| 
 | ||||
| sc_retint64: | ||||
| 		cmp ecx, FFI_TYPE_SINT64 | ||||
| 		jne sc_retstruct | ||||
| // Load %ecx with the pointer to storage for the return value
 | ||||
| 		mov ecx, [ebp+24] | ||||
| 		mov [ecx+0], eax | ||||
| 		mov [ecx+4], edx | ||||
| 
 | ||||
| sc_retstruct: | ||||
| // Nothing to do!
 | ||||
| 
 | ||||
| sc_noretval: | ||||
| sc_epilogue: | ||||
| 		mov eax, esi | ||||
| 		pop esi // NEW restore: must be preserved across function calls
 | ||||
| 		mov esp, ebp | ||||
| 		pop ebp | ||||
| 		ret | ||||
| 	} | ||||
| } | ||||
|  | @ -1,156 +0,0 @@ | |||
| PUBLIC	ffi_call_AMD64 | ||||
| 
 | ||||
| EXTRN	__chkstk:NEAR | ||||
| EXTRN	ffi_closure_SYSV:NEAR | ||||
| 
 | ||||
| _TEXT	SEGMENT | ||||
| 
 | ||||
| ;;; ffi_closure_OUTER will be called with these registers set: | ||||
| ;;;    rax points to 'closure' | ||||
| ;;;    r11 contains a bit mask that specifies which of the | ||||
| ;;;    first four parameters are float or double | ||||
| ;;; | ||||
| ;;; It must move the parameters passed in registers to their stack location, | ||||
| ;;; call ffi_closure_SYSV for the actual work, then return the result. | ||||
| ;;;  | ||||
| ffi_closure_OUTER PROC FRAME | ||||
| 	;; save actual arguments to their stack space. | ||||
| 	test	r11, 1 | ||||
| 	jne	first_is_float	 | ||||
| 	mov	QWORD PTR [rsp+8], rcx | ||||
| 	jmp	second | ||||
| first_is_float: | ||||
| 	movlpd	QWORD PTR [rsp+8], xmm0 | ||||
| 
 | ||||
| second: | ||||
| 	test	r11, 2 | ||||
| 	jne	second_is_float	 | ||||
| 	mov	QWORD PTR [rsp+16], rdx | ||||
| 	jmp	third | ||||
| second_is_float: | ||||
| 	movlpd	QWORD PTR [rsp+16], xmm1 | ||||
| 
 | ||||
| third: | ||||
| 	test	r11, 4 | ||||
| 	jne	third_is_float	 | ||||
| 	mov	QWORD PTR [rsp+24], r8 | ||||
| 	jmp	forth | ||||
| third_is_float: | ||||
| 	movlpd	QWORD PTR [rsp+24], xmm2 | ||||
| 
 | ||||
| forth: | ||||
| 	test	r11, 8 | ||||
| 	jne	forth_is_float	 | ||||
| 	mov	QWORD PTR [rsp+32], r9 | ||||
| 	jmp	done | ||||
| forth_is_float: | ||||
| 	movlpd	QWORD PTR [rsp+32], xmm3 | ||||
| 
 | ||||
| done: | ||||
| .ALLOCSTACK 40 | ||||
| 	sub	rsp, 40 | ||||
| .ENDPROLOG | ||||
| 	mov	rcx, rax	; context is first parameter | ||||
| 	mov	rdx, rsp	; stack is second parameter | ||||
| 	add	rdx, 40		; correct our own area | ||||
| 	mov	rax, ffi_closure_SYSV | ||||
| 	call	rax		; call the real closure function | ||||
| 	;; Here, code is missing that handles float return values | ||||
| 	add	rsp, 40 | ||||
| 	movd	xmm0, rax	; In case the closure returned a float. | ||||
| 	ret	0 | ||||
| ffi_closure_OUTER ENDP | ||||
| 
 | ||||
| 
 | ||||
| ;;; ffi_call_AMD64 | ||||
| 
 | ||||
| stack$ = 0 | ||||
| prepfunc$ = 32 | ||||
| ecif$ = 40 | ||||
| bytes$ = 48 | ||||
| flags$ = 56 | ||||
| rvalue$ = 64 | ||||
| fn$ = 72 | ||||
| 
 | ||||
| ffi_call_AMD64 PROC FRAME | ||||
| 
 | ||||
| 	mov	QWORD PTR [rsp+32], r9 | ||||
| 	mov	QWORD PTR [rsp+24], r8 | ||||
| 	mov	QWORD PTR [rsp+16], rdx | ||||
| 	mov	QWORD PTR [rsp+8], rcx | ||||
| .PUSHREG rbp | ||||
| 	push	rbp | ||||
| .ALLOCSTACK 48 | ||||
| 	sub	rsp, 48					; 00000030H | ||||
| .SETFRAME rbp, 32 | ||||
| 	lea	rbp, QWORD PTR [rsp+32] | ||||
| .ENDPROLOG | ||||
| 
 | ||||
| 	mov	eax, DWORD PTR bytes$[rbp] | ||||
| 	add	rax, 15 | ||||
| 	and	rax, -16 | ||||
| 	call	__chkstk | ||||
| 	sub	rsp, rax | ||||
| 	lea	rax, QWORD PTR [rsp+32] | ||||
| 	mov	QWORD PTR stack$[rbp], rax | ||||
| 
 | ||||
| 	mov	rdx, QWORD PTR ecif$[rbp] | ||||
| 	mov	rcx, QWORD PTR stack$[rbp] | ||||
| 	call	QWORD PTR prepfunc$[rbp] | ||||
| 
 | ||||
| 	mov	rsp, QWORD PTR stack$[rbp] | ||||
| 
 | ||||
| 	movlpd	xmm3, QWORD PTR [rsp+24] | ||||
| 	movd	r9, xmm3 | ||||
| 
 | ||||
| 	movlpd	xmm2, QWORD PTR [rsp+16] | ||||
| 	movd	r8, xmm2 | ||||
| 
 | ||||
| 	movlpd	xmm1, QWORD PTR [rsp+8] | ||||
| 	movd	rdx, xmm1 | ||||
| 
 | ||||
| 	movlpd	xmm0, QWORD PTR [rsp] | ||||
| 	movd	rcx, xmm0 | ||||
| 
 | ||||
| 	call	QWORD PTR fn$[rbp] | ||||
| ret_int$: | ||||
|  	cmp	DWORD PTR flags$[rbp], 1 ; FFI_TYPE_INT | ||||
|  	jne	ret_float$ | ||||
| 
 | ||||
| 	mov	rcx, QWORD PTR rvalue$[rbp] | ||||
| 	mov	DWORD PTR [rcx], eax | ||||
| 	jmp	SHORT ret_nothing$ | ||||
| 
 | ||||
| ret_float$: | ||||
|  	cmp	DWORD PTR flags$[rbp], 2 ; FFI_TYPE_FLOAT | ||||
|  	jne	SHORT ret_double$ | ||||
| 
 | ||||
|  	mov	rax, QWORD PTR rvalue$[rbp] | ||||
|  	movlpd	QWORD PTR [rax], xmm0 | ||||
|  	jmp	SHORT ret_nothing$ | ||||
| 
 | ||||
| ret_double$: | ||||
|  	cmp	DWORD PTR flags$[rbp], 3 ; FFI_TYPE_DOUBLE | ||||
|  	jne	SHORT ret_int64$ | ||||
| 
 | ||||
|  	mov	rax, QWORD PTR rvalue$[rbp] | ||||
|  	movlpd	QWORD PTR [rax], xmm0 | ||||
|  	jmp	SHORT ret_nothing$ | ||||
| 
 | ||||
| ret_int64$: | ||||
|   	cmp	DWORD PTR flags$[rbp], 12 ; FFI_TYPE_SINT64 | ||||
|   	jne	ret_nothing$ | ||||
| 
 | ||||
|  	mov	rcx, QWORD PTR rvalue$[rbp] | ||||
|  	mov	QWORD PTR [rcx], rax | ||||
|  	jmp	SHORT ret_nothing$ | ||||
| 	 | ||||
| ret_nothing$: | ||||
| 	xor	eax, eax | ||||
| 
 | ||||
| 	lea	rsp, QWORD PTR [rbp+16] | ||||
| 	pop	rbp | ||||
| 	ret	0 | ||||
| ffi_call_AMD64 ENDP | ||||
| _TEXT	ENDS | ||||
| END | ||||
|  | @ -52,7 +52,7 @@ | |||
| EXCLUDE_FROM_COMPILE = FileNameSet("badsyntax_*", "bad_*") | ||||
| EXCLUDE_FROM_CATALOG = FileSuffixSet(".exe", ".pyd", ".dll") | ||||
| 
 | ||||
| REQUIRED_DLLS = FileStemSet("libcrypto*", "libssl*") | ||||
| REQUIRED_DLLS = FileStemSet("libcrypto*", "libssl*", "libffi*") | ||||
| 
 | ||||
| LIB2TO3_GRAMMAR_FILES = FileNameSet("Grammar.txt", "PatternGrammar.txt") | ||||
| 
 | ||||
|  |  | |||
|  | @ -70,6 +70,7 @@ | |||
|   <ImportGroup Label="PropertySheets"> | ||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
|     <Import Project="pyproject.props" /> | ||||
|     <Import Project="libffi.props" /> | ||||
|   </ImportGroup> | ||||
|   <PropertyGroup Label="UserMacros" /> | ||||
|   <PropertyGroup> | ||||
|  | @ -77,7 +78,7 @@ | |||
|   </PropertyGroup> | ||||
|   <ItemDefinitionGroup> | ||||
|     <ClCompile> | ||||
|       <AdditionalIncludeDirectories>..\Modules\_ctypes\libffi_msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|       <PreprocessorDefinitions>FFI_BUILDING;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <AdditionalOptions>/EXPORT:DllGetClassObject,PRIVATE /EXPORT:DllCanUnloadNow,PRIVATE %(AdditionalOptions)</AdditionalOptions> | ||||
|  | @ -86,32 +87,14 @@ | |||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\Modules\_ctypes\ctypes.h" /> | ||||
|     <ClInclude Include="..\Modules\_ctypes\ctypes_dlfcn.h" /> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi.h" /> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi_common.h" /> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\fficonfig.h" /> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffitarget.h" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="..\Modules\_ctypes\_ctypes.c" /> | ||||
|     <ClCompile Include="..\Modules\_ctypes\callbacks.c" /> | ||||
|     <ClCompile Include="..\Modules\_ctypes\callproc.c" /> | ||||
|     <ClCompile Include="..\Modules\_ctypes\cfield.c" /> | ||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\ffi.c" /> | ||||
|     <ClCompile Include="..\Modules\_ctypes\malloc_closure.c" /> | ||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\prep_cif.c"> | ||||
|       <DisableSpecificWarnings Condition="'$(Platform)'=='x64'">4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\Modules\_ctypes\stgdict.c" /> | ||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\win32.c"> | ||||
|       <ExcludedFromBuild Condition="'$(Platform)'=='x64'">true</ExcludedFromBuild> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <CustomBuild Include="..\Modules\_ctypes\libffi_msvc\win64.asm"> | ||||
|       <ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild> | ||||
|       <Command>ml64 /nologo /c /Zi /Fo "$(IntDir)win64.obj" "%(FullPath)"</Command> | ||||
|       <Outputs>$(IntDir)win64.obj;%(Outputs)</Outputs> | ||||
|     </CustomBuild> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ResourceCompile Include="..\PC\python_nt.rc" /> | ||||
|  |  | |||
|  | @ -15,18 +15,6 @@ | |||
|     <ClInclude Include="..\Modules\_ctypes\ctypes_dlfcn.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffi_common.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\fficonfig.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="..\Modules\_ctypes\libffi_msvc\ffitarget.h"> | ||||
|       <Filter>Header Files</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="..\Modules\_ctypes\_ctypes.c"> | ||||
|  | @ -41,25 +29,14 @@ | |||
|     <ClCompile Include="..\Modules\_ctypes\cfield.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\ffi.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\Modules\_ctypes\malloc_closure.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\prep_cif.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\Modules\_ctypes\stgdict.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\win32.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <CustomBuild Include="..\Modules\_ctypes\libffi_msvc\win64.asm"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </CustomBuild> | ||||
|     <ResourceCompile Include="..\PC\python_nt.rc" /> | ||||
|   </ItemGroup> | ||||
| </Project> | ||||
|  | @ -7,14 +7,17 @@ if NOT DEFINED EXTERNALS_DIR (set EXTERNALS_DIR=%PCBUILD%\..\externals) | |||
| 
 | ||||
| set DO_FETCH=true | ||||
| set DO_CLEAN=false | ||||
| set IncludeLibffiSrc=false | ||||
| set IncludeTkinterSrc=false | ||||
| set IncludeSSLSrc=false | ||||
| 
 | ||||
| :CheckOpts | ||||
| if "%~1"=="--no-tkinter" (set IncludeTkinter=false) & shift & goto CheckOpts | ||||
| if "%~1"=="--no-openssl" (set IncludeSSL=false) & shift & goto CheckOpts | ||||
| if "%~1"=="--no-libffi" (set IncludeLibffi=false) & shift & goto CheckOpts | ||||
| if "%~1"=="--tkinter-src" (set IncludeTkinterSrc=true) & shift & goto CheckOpts | ||||
| if "%~1"=="--openssl-src" (set IncludeSSLSrc=true) & shift & goto CheckOpts | ||||
| if "%~1"=="--libffi-src" (set IncludeLibffiSrc=true) & shift & goto CheckOpts | ||||
| if "%~1"=="--python" (set PYTHON=%2) & shift & shift & goto CheckOpts | ||||
| if "%~1"=="--organization" (set ORG=%2) & shift & shift & goto CheckOpts | ||||
| if "%~1"=="-c" (set DO_CLEAN=true) & shift & goto CheckOpts | ||||
|  | @ -49,6 +52,7 @@ echo.Fetching external libraries... | |||
| 
 | ||||
| set libraries= | ||||
| set libraries=%libraries%                                       bzip2-1.0.6 | ||||
| if NOT "%IncludeLibffiSrc%"=="false" set libraries=%libraries%  libffi-3.3.0-rc0-r1 | ||||
| if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries%     openssl-1.1.0j | ||||
| set libraries=%libraries%                                       sqlite-3.21.0.0 | ||||
| if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.0 | ||||
|  | @ -72,6 +76,7 @@ for %%e in (%libraries%) do ( | |||
| echo.Fetching external binaries... | ||||
| 
 | ||||
| set binaries= | ||||
| if NOT "%IncludeLibffi%"=="false"  set binaries=%binaries% libffi | ||||
| if NOT "%IncludeSSL%"=="false"     set binaries=%binaries% openssl-bin-1.1.0j | ||||
| if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0 | ||||
| if NOT "%IncludeSSLSrc%"=="false"  set binaries=%binaries% nasm-2.11.06 | ||||
|  |  | |||
							
								
								
									
										21
									
								
								PCbuild/libffi.props
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								PCbuild/libffi.props
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||||
|   <ItemDefinitionGroup> | ||||
|     <ClCompile> | ||||
|       <AdditionalIncludeDirectories>$(libffiIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <AdditionalLibraryDirectories>$(libffiOutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> | ||||
|       <AdditionalDependencies>libffi-7.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemGroup> | ||||
|     <_LIBFFIDLL Include="$(libffiOutDir)\libffi-7.dll" /> | ||||
|   </ItemGroup> | ||||
|   <Target Name="_CopyLIBFFIDLL" Inputs="@(_LIBFFIDLL)" Outputs="@(_LIBFFIDLL->'$(OutDir)%(Filename)%(Extension)')" AfterTargets="Build"> | ||||
|     <Copy SourceFiles="@(_LIBFFIDLL)" DestinationFolder="$(OutDir)" /> | ||||
|   </Target> | ||||
|   <Target Name="_CleanLIBFFIDLL" BeforeTargets="Clean"> | ||||
|     <Delete Files="@(_LIBFFIDLL->'$(OutDir)%(Filename)%(Extension)')" TreatErrorsAsWarnings="true" /> | ||||
|   </Target> | ||||
| </Project> | ||||
							
								
								
									
										169
									
								
								PCbuild/prepare_libffi.bat
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								PCbuild/prepare_libffi.bat
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,169 @@ | |||
| @echo off | ||||
| goto :Run | ||||
| 
 | ||||
| :Usage | ||||
| echo. | ||||
| echo Before running prepare_libffi.bat  | ||||
| echo   LIBFFI_SOURCE environment variable must be set to the location of | ||||
| echo     of python-source-deps clone of libffi branch | ||||
| echo   VCVARSALL must be set to location of vcvarsall.bat | ||||
| echo   cygwin must be installed (see below) | ||||
| echo   SH environment variable must be set to the location of sh.exe | ||||
| echo. | ||||
| echo Tested with cygwin-x86 from https://www.cygwin.com/install.html | ||||
| echo Select http://mirrors.kernel.org as the download site | ||||
| echo Include the following cygwin packages in cygwin configuration: | ||||
| echo     make, autoconf, automake, libtool, dejagnu | ||||
| echo. | ||||
| echo NOTE: dejagnu is only required for running tests. | ||||
| echo       set LIBFFI_TEST=1 to run tests (optional) | ||||
| echo. | ||||
| echo Based on https://github.com/libffi/libffi/blob/master/.appveyor.yml | ||||
| echo. | ||||
| echo. | ||||
| echo.Available flags: | ||||
| echo.  -x64    build for x64 | ||||
| echo.  -x86    build for x86 | ||||
| echo.  -?      this help | ||||
| echo.  --install-cygwin  install cygwin to c:\cygwin | ||||
| exit /b 127 | ||||
| 
 | ||||
| :Run | ||||
| 
 | ||||
| set BUILD_X64= | ||||
| set BUILD_X86= | ||||
| set INSTALL_CYGWIN= | ||||
| 
 | ||||
| :CheckOpts | ||||
| if "%1"=="" goto :CheckOptsDone | ||||
| if /I "%1"=="-x64" (set BUILD_X64=1) & shift & goto :CheckOpts | ||||
| if /I "%1"=="-x86" (set BUILD_X86=1) & shift & goto :CheckOpts | ||||
| if /I "%1"=="-?" goto :Usage | ||||
| if /I "%1"=="--install-cygwin" (set INSTALL_CYGWIN=1) & shift & goto :CheckOpts | ||||
| goto :Usage | ||||
| 
 | ||||
| :CheckOptsDone | ||||
| 
 | ||||
| if NOT DEFINED BUILD_X64 if NOT DEFINED BUILD_X86 if NOT DEFINED BUILD_ARM32 ( | ||||
|     set BUILD_X64=1 | ||||
|     set BUILD_X86=1 | ||||
| ) | ||||
| 
 | ||||
| if "%INSTALL_CYGWIN%"=="1" call :InstallCygwin | ||||
| 
 | ||||
| setlocal | ||||
| if NOT DEFINED SH if exist c:\cygwin\bin\sh.exe set SH=c:\cygwin\bin\sh.exe | ||||
| 
 | ||||
| if NOT DEFINED VCVARSALL ( | ||||
|     if exist "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" ( | ||||
|         set VCVARSALL="C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" | ||||
|     ) | ||||
| ) | ||||
| if ^%VCVARSALL:~0,1% NEQ ^" SET VCVARSALL="%VCVARSALL%" | ||||
| 
 | ||||
| if NOT DEFINED LIBFFI_SOURCE echo.&&echo ERROR LIBFFI_SOURCE environment variable not set && goto :Usage | ||||
| if NOT DEFINED SH echo ERROR SH environment variable not set && goto :Usage | ||||
| 
 | ||||
| if not exist %SH% echo ERROR %SH% does not exist && goto :Usage | ||||
| if not exist %LIBFFI_SOURCE% echo ERROR %LIBFFI_SOURCE% does not exist && goto :Usage | ||||
| 
 | ||||
| set OLDPWD=%LIBFFI_SOURCE% | ||||
| pushd %LIBFFI_SOURCE% | ||||
| 
 | ||||
| %SH% --login -lc "cygcheck -dc cygwin" | ||||
| set GET_MSVCC=%SH% -lc "cd $OLDPWD; export MSVCC=`/usr/bin/find $PWD -name msvcc.sh`; echo ${MSVCC};" | ||||
| FOR /F "usebackq delims==" %%i IN (`%GET_MSVCC%`) do @set MSVCC=%%i | ||||
| 
 | ||||
| echo. | ||||
| echo VCVARSALL    : %VCVARSALL% | ||||
| echo SH           : %SH% | ||||
| echo LIBFFI_SOURCE: %LIBFFI_SOURCE%  | ||||
| echo MSVCC        : %MSVCC% | ||||
| echo. | ||||
| 
 | ||||
| if not exist Makefile.in (%SH% -lc "(cd $LIBFFI_SOURCE; ./autogen.sh;)") | ||||
| 
 | ||||
| call :BuildOne x86 i686-pc-cygwin i686-pc-cygwin | ||||
| call :BuildOne x64 x86_64-w64-cygwin x86_64-w64-cygwin | ||||
| 
 | ||||
| popd | ||||
| endlocal | ||||
| exit /b 0 | ||||
| REM all done | ||||
| 
 | ||||
| 
 | ||||
| REM this subroutine is called once for each architecture | ||||
| :BuildOne | ||||
| 
 | ||||
| setlocal | ||||
| 
 | ||||
| REM Initialize variables | ||||
| set VCVARS_PLATFORM=%1 | ||||
| set BUILD=%2 | ||||
| set HOST=%3 | ||||
| set ASSEMBLER= | ||||
| set SRC_ARCHITECTURE=x86 | ||||
| 
 | ||||
| if NOT DEFINED VCVARS_PLATFORM echo ERROR bad VCVARS_PLATFORM&&exit /b 123 | ||||
| 
 | ||||
| if /I "%VCVARS_PLATFORM%" EQU "x64" ( | ||||
|     set ARCH=amd64 | ||||
|     set ARTIFACTS=%LIBFFI_SOURCE%\x86_64-w64-cygwin | ||||
|     set ASSEMBLER=-m64 | ||||
|     set SRC_ARCHITECTURE=x86 | ||||
| ) | ||||
| if /I "%VCVARS_PLATFORM%" EQU "x86" ( | ||||
|     set ARCH=win32 | ||||
|     set ARTIFACTS=%LIBFFI_SOURCE%\i686-pc-cygwin | ||||
|     set ASSEMBLER= | ||||
|     set SRC_ARCHITECTURE=x86 | ||||
| ) | ||||
| 
 | ||||
| if NOT DEFINED LIBFFI_OUT set LIBFFI_OUT=%~dp0\..\externals\libffi | ||||
| set _LIBFFI_OUT=%LIBFFI_OUT%\%ARCH% | ||||
| 
 | ||||
| echo get VS build environment | ||||
| call %VCVARSALL% %VCVARS_PLATFORM% | ||||
| 
 | ||||
| echo clean %_LIBFFI_OUT% | ||||
| if exist %_LIBFFI_OUT% (rd %_LIBFFI_OUT% /s/q) | ||||
| 
 | ||||
| echo Configure the build to generate fficonfig.h and ffi.h | ||||
| %SH% -lc "(cd $OLDPWD; ./configure CC='%MSVCC% %ASSEMBLER%' CXX='%MSVCC% %ASSEMBLER%' LD='link' CPP='cl -nologo -EP' CXXCPP='cl -nologo -EP' CPPFLAGS='-DFFI_BUILDING_DLL' NM='dumpbin -symbols' STRIP=':' --build=$BUILD --host=$HOST;)" | ||||
| 
 | ||||
| echo Building libffi | ||||
| %SH% -lc "(cd $OLDPWD; export PATH=/usr/bin:$PATH; cp src/%SRC_ARCHITECTURE%/ffitarget.h include; make; find .;)" | ||||
| 
 | ||||
| REM Tests are not needed to produce artifacts | ||||
| if "%LIBFFI_TEST%" EQU "1" ( | ||||
|     echo "Running tests..." | ||||
|     %SH% -lc "(cd $OLDPWD; export PATH=/usr/bin:$PATH; cp `find $PWD -name 'libffi-?.dll'` $HOST/testsuite/; make check; cat `find ./ -name libffi.log`)" | ||||
| ) else ( | ||||
|     echo "Not running tests" | ||||
| ) | ||||
| 
 | ||||
| 
 | ||||
| echo copying files to %_LIBFFI_OUT% | ||||
| if not exist %_LIBFFI_OUT%\include (md %_LIBFFI_OUT%\include) | ||||
| copy %ARTIFACTS%\.libs\libffi-7.dll %_LIBFFI_OUT% | ||||
| copy %ARTIFACTS%\.libs\libffi-7.lib %_LIBFFI_OUT% | ||||
| copy %ARTIFACTS%\fficonfig.h %_LIBFFI_OUT%\include | ||||
| copy %ARTIFACTS%\include\*.h %_LIBFFI_OUT%\include | ||||
| 
 | ||||
| endlocal | ||||
| exit /b | ||||
| 
 | ||||
| :InstallCygwin | ||||
| setlocal | ||||
| 
 | ||||
| if NOT DEFINED CYG_ROOT (set CYG_ROOT=c:/cygwin) | ||||
| if NOT DEFINED CYG_CACHE (set CYG_CACHE=C:/cygwin/var/cache/setup) | ||||
| if NOT DEFINED CYG_MIRROR (set CYG_MIRROR=http://mirrors.kernel.org/sourceware/cygwin/) | ||||
| 
 | ||||
| powershell -c "md $env:CYG_ROOT -ErrorAction SilentlyContinue" | ||||
| powershell -c "$setup = $env:CYG_ROOT+'/setup.exe'; if (!(Test-Path $setup)){invoke-webrequest https://cygwin.com/setup-x86.exe -outfile $setup} | ||||
| %CYG_ROOT%/setup.exe -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P make -P autoconf -P automake -P libtool -P dejagnu | ||||
| 
 | ||||
| endlocal | ||||
| exit /b | ||||
| 
 | ||||
|  | @ -53,6 +53,9 @@ | |||
|     <sqlite3Dir>$(ExternalsDir)sqlite-3.21.0.0\</sqlite3Dir> | ||||
|     <bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir> | ||||
|     <lzmaDir>$(ExternalsDir)xz-5.2.2\</lzmaDir> | ||||
|     <libffiDir>$(ExternalsDir)libffi\</libffiDir> | ||||
|     <libffiOutDir>$(ExternalsDir)libffi\$(ArchName)\</libffiOutDir> | ||||
|     <libffiIncludeDir>$(libffiOutDir)include</libffiIncludeDir> | ||||
|     <opensslDir>$(ExternalsDir)openssl-1.1.0j\</opensslDir> | ||||
|     <opensslOutDir>$(ExternalsDir)openssl-bin-1.1.0j\$(ArchName)\</opensslOutDir> | ||||
|     <opensslIncludeDir>$(opensslOutDir)include</opensslIncludeDir> | ||||
|  |  | |||
|  | @ -22,6 +22,9 @@ | |||
|             <Component Id="libssl.dll" Directory="DLLs" Guid="*"> | ||||
|                 <File Name="libssl$(var.ssltag).dll" KeyPath="yes" /> | ||||
|             </Component> | ||||
|             <Component Id="libffi.dll" Directory="DLLs" Guid="*"> | ||||
|                 <File Name="libffi-7.dll" KeyPath="yes" /> | ||||
|             </Component> | ||||
|             <Component Id="venvlauncher.exe" Directory="Lib_venv_scripts_nt" Guid="*"> | ||||
|                 <File Name="python.exe" Source="venvlauncher.exe" KeyPath="yes" /> | ||||
|             </Component> | ||||
|  | @ -59,6 +62,9 @@ | |||
|             <Component Id="libssl.pdb" Directory="DLLs" Guid="*"> | ||||
|                 <File Name="libssl$(var.ssltag).pdb" KeyPath="yes" /> | ||||
|             </Component> | ||||
|             <Component Id="libffi.pdb" Directory="DLLs" Guid="*"> | ||||
|                 <File Name="libffi-7.pdb" KeyPath="yes" /> | ||||
|             </Component> | ||||
|             <Component Id="venvlauncher.pdb" Directory="Lib_venv_scripts_nt__pdbs" Guid="*"> | ||||
|                 <File Name="python.pdb" Source="venvlauncher.pdb" KeyPath="yes" /> | ||||
|             </Component> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Paul Monson
						Paul Monson