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 | 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') | @unittest.skipUnless(sys.platform == "win32", 'Windows-specific test') | ||||||
| class FunctionCallTestCase(unittest.TestCase): | class FunctionCallTestCase(unittest.TestCase): | ||||||
|     @unittest.skipUnless('MSC' in sys.version, "SEH only supported by MSC") |     @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) | StructUnionType_paramfunc(CDataObject *self) | ||||||
| { | { | ||||||
|     PyCArgObject *parg; |     PyCArgObject *parg; | ||||||
|  |     CDataObject *copied_self; | ||||||
|     StgDictObject *stgdict; |     StgDictObject *stgdict; | ||||||
| 
 | 
 | ||||||
|     parg = PyCArgObject_new(); |     if (self->b_size > sizeof(void*)) { | ||||||
|     if (parg == NULL) |         void *new_ptr = PyMem_Malloc(self->b_size); | ||||||
|  |         if (new_ptr == NULL) | ||||||
|             return 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'; |     parg->tag = 'V'; | ||||||
|     stgdict = PyObject_stgdict((PyObject *)self); |     stgdict = PyObject_stgdict((PyObject *)copied_self); | ||||||
|     assert(stgdict); /* Cannot be NULL for structure/union instances */ |     assert(stgdict); /* Cannot be NULL for structure/union instances */ | ||||||
|     parg->pffi_type = &stgdict->ffi_type_pointer; |     parg->pffi_type = &stgdict->ffi_type_pointer; | ||||||
|     /* For structure parameters (by value), parg->value doesn't contain the structure
 |     parg->value.p = copied_self->b_ptr; | ||||||
|        data itself, instead parg->value.p *points* to the structure's data |     parg->size = copied_self->b_size; | ||||||
|        See also _ctypes.c, function _call_function_pointer(). |     parg->obj = (PyObject *)copied_self; | ||||||
|     */ |  | ||||||
|     parg->value.p = self->b_ptr; |  | ||||||
|     parg->size = self->b_size; |  | ||||||
|     Py_INCREF(self); |  | ||||||
|     parg->obj = (PyObject *)self; |  | ||||||
|     return parg; |     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) | ffi_type *_ctypes_get_ffi_type(PyObject *obj) | ||||||
| { | { | ||||||
|  | @ -778,12 +795,9 @@ static int _call_function_pointer(int flags, | ||||||
|     int *space; |     int *space; | ||||||
|     ffi_cif cif; |     ffi_cif cif; | ||||||
|     int cc; |     int cc; | ||||||
| #ifdef MS_WIN32 | #if defined(MS_WIN32) && !defined(DONT_USE_SEH) | ||||||
|     int delta; |  | ||||||
| #ifndef DONT_USE_SEH |  | ||||||
|     DWORD dwExceptionCode = 0; |     DWORD dwExceptionCode = 0; | ||||||
|     EXCEPTION_RECORD record; |     EXCEPTION_RECORD record; | ||||||
| #endif |  | ||||||
| #endif | #endif | ||||||
|     /* XXX check before here */ |     /* XXX check before here */ | ||||||
|     if (restype == NULL) { |     if (restype == NULL) { | ||||||
|  | @ -828,7 +842,6 @@ static int _call_function_pointer(int flags, | ||||||
| #ifndef DONT_USE_SEH | #ifndef DONT_USE_SEH | ||||||
|     __try { |     __try { | ||||||
| #endif | #endif | ||||||
|         delta = |  | ||||||
| #endif | #endif | ||||||
|                 ffi_call(&cif, (void *)pProc, resmem, avalues); |                 ffi_call(&cif, (void *)pProc, resmem, avalues); | ||||||
| #ifdef MS_WIN32 | #ifdef MS_WIN32 | ||||||
|  | @ -860,35 +873,6 @@ static int _call_function_pointer(int flags, | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| #endif | #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 | #endif | ||||||
|     if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred()) |     if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred()) | ||||||
|         return -1; |         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_COMPILE = FileNameSet("badsyntax_*", "bad_*") | ||||||
| EXCLUDE_FROM_CATALOG = FileSuffixSet(".exe", ".pyd", ".dll") | 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") | LIB2TO3_GRAMMAR_FILES = FileNameSet("Grammar.txt", "PatternGrammar.txt") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -70,6 +70,7 @@ | ||||||
|   <ImportGroup Label="PropertySheets"> |   <ImportGroup Label="PropertySheets"> | ||||||
|     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||||
|     <Import Project="pyproject.props" /> |     <Import Project="pyproject.props" /> | ||||||
|  |     <Import Project="libffi.props" /> | ||||||
|   </ImportGroup> |   </ImportGroup> | ||||||
|   <PropertyGroup Label="UserMacros" /> |   <PropertyGroup Label="UserMacros" /> | ||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|  | @ -77,7 +78,7 @@ | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|   <ItemDefinitionGroup> |   <ItemDefinitionGroup> | ||||||
|     <ClCompile> |     <ClCompile> | ||||||
|       <AdditionalIncludeDirectories>..\Modules\_ctypes\libffi_msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |       <PreprocessorDefinitions>FFI_BUILDING;%(PreprocessorDefinitions)</PreprocessorDefinitions> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <Link> |     <Link> | ||||||
|       <AdditionalOptions>/EXPORT:DllGetClassObject,PRIVATE /EXPORT:DllCanUnloadNow,PRIVATE %(AdditionalOptions)</AdditionalOptions> |       <AdditionalOptions>/EXPORT:DllGetClassObject,PRIVATE /EXPORT:DllCanUnloadNow,PRIVATE %(AdditionalOptions)</AdditionalOptions> | ||||||
|  | @ -86,32 +87,14 @@ | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="..\Modules\_ctypes\ctypes.h" /> |     <ClInclude Include="..\Modules\_ctypes\ctypes.h" /> | ||||||
|     <ClInclude Include="..\Modules\_ctypes\ctypes_dlfcn.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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\_ctypes.c" /> |     <ClCompile Include="..\Modules\_ctypes\_ctypes.c" /> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\callbacks.c" /> |     <ClCompile Include="..\Modules\_ctypes\callbacks.c" /> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\callproc.c" /> |     <ClCompile Include="..\Modules\_ctypes\callproc.c" /> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\cfield.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\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\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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ResourceCompile Include="..\PC\python_nt.rc" /> |     <ResourceCompile Include="..\PC\python_nt.rc" /> | ||||||
|  |  | ||||||
|  | @ -15,18 +15,6 @@ | ||||||
|     <ClInclude Include="..\Modules\_ctypes\ctypes_dlfcn.h"> |     <ClInclude Include="..\Modules\_ctypes\ctypes_dlfcn.h"> | ||||||
|       <Filter>Header Files</Filter> |       <Filter>Header Files</Filter> | ||||||
|     </ClInclude> |     </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> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\_ctypes.c"> |     <ClCompile Include="..\Modules\_ctypes\_ctypes.c"> | ||||||
|  | @ -41,25 +29,14 @@ | ||||||
|     <ClCompile Include="..\Modules\_ctypes\cfield.c"> |     <ClCompile Include="..\Modules\_ctypes\cfield.c"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\ffi.c"> |  | ||||||
|       <Filter>Source Files</Filter> |  | ||||||
|     </ClCompile> |  | ||||||
|     <ClCompile Include="..\Modules\_ctypes\malloc_closure.c"> |     <ClCompile Include="..\Modules\_ctypes\malloc_closure.c"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\prep_cif.c"> |  | ||||||
|       <Filter>Source Files</Filter> |  | ||||||
|     </ClCompile> |  | ||||||
|     <ClCompile Include="..\Modules\_ctypes\stgdict.c"> |     <ClCompile Include="..\Modules\_ctypes\stgdict.c"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|     <ClCompile Include="..\Modules\_ctypes\libffi_msvc\win32.c"> |  | ||||||
|       <Filter>Source Files</Filter> |  | ||||||
|     </ClCompile> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <CustomBuild Include="..\Modules\_ctypes\libffi_msvc\win64.asm"> |     <ResourceCompile Include="..\PC\python_nt.rc" /> | ||||||
|       <Filter>Source Files</Filter> |  | ||||||
|     </CustomBuild> |  | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
|  | @ -7,14 +7,17 @@ if NOT DEFINED EXTERNALS_DIR (set EXTERNALS_DIR=%PCBUILD%\..\externals) | ||||||
| 
 | 
 | ||||||
| set DO_FETCH=true | set DO_FETCH=true | ||||||
| set DO_CLEAN=false | set DO_CLEAN=false | ||||||
|  | set IncludeLibffiSrc=false | ||||||
| set IncludeTkinterSrc=false | set IncludeTkinterSrc=false | ||||||
| set IncludeSSLSrc=false | set IncludeSSLSrc=false | ||||||
| 
 | 
 | ||||||
| :CheckOpts | :CheckOpts | ||||||
| if "%~1"=="--no-tkinter" (set IncludeTkinter=false) & shift & goto CheckOpts | if "%~1"=="--no-tkinter" (set IncludeTkinter=false) & shift & goto CheckOpts | ||||||
| if "%~1"=="--no-openssl" (set IncludeSSL=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"=="--tkinter-src" (set IncludeTkinterSrc=true) & shift & goto CheckOpts | ||||||
| if "%~1"=="--openssl-src" (set IncludeSSLSrc=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"=="--python" (set PYTHON=%2) & shift & shift & goto CheckOpts | ||||||
| if "%~1"=="--organization" (set ORG=%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 | if "%~1"=="-c" (set DO_CLEAN=true) & shift & goto CheckOpts | ||||||
|  | @ -49,6 +52,7 @@ echo.Fetching external libraries... | ||||||
| 
 | 
 | ||||||
| set libraries= | set libraries= | ||||||
| set libraries=%libraries%                                       bzip2-1.0.6 | 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 | if NOT "%IncludeSSLSrc%"=="false" set libraries=%libraries%     openssl-1.1.0j | ||||||
| set libraries=%libraries%                                       sqlite-3.21.0.0 | set libraries=%libraries%                                       sqlite-3.21.0.0 | ||||||
| if NOT "%IncludeTkinterSrc%"=="false" set libraries=%libraries% tcl-core-8.6.9.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... | echo.Fetching external binaries... | ||||||
| 
 | 
 | ||||||
| set 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 "%IncludeSSL%"=="false"     set binaries=%binaries% openssl-bin-1.1.0j | ||||||
| if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0 | if NOT "%IncludeTkinter%"=="false" set binaries=%binaries% tcltk-8.6.9.0 | ||||||
| if NOT "%IncludeSSLSrc%"=="false"  set binaries=%binaries% nasm-2.11.06 | 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> |     <sqlite3Dir>$(ExternalsDir)sqlite-3.21.0.0\</sqlite3Dir> | ||||||
|     <bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir> |     <bz2Dir>$(ExternalsDir)bzip2-1.0.6\</bz2Dir> | ||||||
|     <lzmaDir>$(ExternalsDir)xz-5.2.2\</lzmaDir> |     <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> |     <opensslDir>$(ExternalsDir)openssl-1.1.0j\</opensslDir> | ||||||
|     <opensslOutDir>$(ExternalsDir)openssl-bin-1.1.0j\$(ArchName)\</opensslOutDir> |     <opensslOutDir>$(ExternalsDir)openssl-bin-1.1.0j\$(ArchName)\</opensslOutDir> | ||||||
|     <opensslIncludeDir>$(opensslOutDir)include</opensslIncludeDir> |     <opensslIncludeDir>$(opensslOutDir)include</opensslIncludeDir> | ||||||
|  |  | ||||||
|  | @ -22,6 +22,9 @@ | ||||||
|             <Component Id="libssl.dll" Directory="DLLs" Guid="*"> |             <Component Id="libssl.dll" Directory="DLLs" Guid="*"> | ||||||
|                 <File Name="libssl$(var.ssltag).dll" KeyPath="yes" /> |                 <File Name="libssl$(var.ssltag).dll" KeyPath="yes" /> | ||||||
|             </Component> |             </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="*"> |             <Component Id="venvlauncher.exe" Directory="Lib_venv_scripts_nt" Guid="*"> | ||||||
|                 <File Name="python.exe" Source="venvlauncher.exe" KeyPath="yes" /> |                 <File Name="python.exe" Source="venvlauncher.exe" KeyPath="yes" /> | ||||||
|             </Component> |             </Component> | ||||||
|  | @ -59,6 +62,9 @@ | ||||||
|             <Component Id="libssl.pdb" Directory="DLLs" Guid="*"> |             <Component Id="libssl.pdb" Directory="DLLs" Guid="*"> | ||||||
|                 <File Name="libssl$(var.ssltag).pdb" KeyPath="yes" /> |                 <File Name="libssl$(var.ssltag).pdb" KeyPath="yes" /> | ||||||
|             </Component> |             </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="*"> |             <Component Id="venvlauncher.pdb" Directory="Lib_venv_scripts_nt__pdbs" Guid="*"> | ||||||
|                 <File Name="python.pdb" Source="venvlauncher.pdb" KeyPath="yes" /> |                 <File Name="python.pdb" Source="venvlauncher.pdb" KeyPath="yes" /> | ||||||
|             </Component> |             </Component> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Paul Monson
						Paul Monson