[Python-checkins] r51604 - in python/trunk: Lib/ctypes/__init__.py Lib/ctypes/test/test_win32.py Modules/_ctypes/_ctypes.c Modules/_ctypes/_ctypes_test.c Modules/_ctypes/callbacks.c Modules/_ctypes/callproc.c Modules/_ctypes/cfield.c Modules/_ctypes/libffi_msvc/ffi.c Modules/_ctypes/libffi_msvc/ffi.h Modules/_ctypes/libffi_msvc/ffitarget.h

thomas.heller python-checkins at python.org
Fri Aug 25 09:27:34 CEST 2006


Author: thomas.heller
Date: Fri Aug 25 09:27:33 2006
New Revision: 51604

Modified:
   python/trunk/Lib/ctypes/__init__.py
   python/trunk/Lib/ctypes/test/test_win32.py
   python/trunk/Modules/_ctypes/_ctypes.c
   python/trunk/Modules/_ctypes/_ctypes_test.c
   python/trunk/Modules/_ctypes/callbacks.c
   python/trunk/Modules/_ctypes/callproc.c
   python/trunk/Modules/_ctypes/cfield.c
   python/trunk/Modules/_ctypes/libffi_msvc/ffi.c
   python/trunk/Modules/_ctypes/libffi_msvc/ffi.h
   python/trunk/Modules/_ctypes/libffi_msvc/ffitarget.h
Log:
Port _ctypes.pyd to win64 on AMD64.



Modified: python/trunk/Lib/ctypes/__init__.py
==============================================================================
--- python/trunk/Lib/ctypes/__init__.py	(original)
+++ python/trunk/Lib/ctypes/__init__.py	Fri Aug 25 09:27:33 2006
@@ -427,6 +427,8 @@
     c_size_t = c_uint
 elif sizeof(c_ulong) == sizeof(c_void_p):
     c_size_t = c_ulong
+elif sizeof(c_ulonglong) == sizeof(c_void_p):
+    c_size_t = c_ulonglong
 
 # functions
 

Modified: python/trunk/Lib/ctypes/test/test_win32.py
==============================================================================
--- python/trunk/Lib/ctypes/test/test_win32.py	(original)
+++ python/trunk/Lib/ctypes/test/test_win32.py	Fri Aug 25 09:27:33 2006
@@ -6,7 +6,8 @@
 
 import _ctypes_test
 
-if sys.platform == "win32":
+if sys.platform == "win32" and sizeof(c_void_p) == sizeof(c_int):
+    # Only windows 32-bit has different calling conventions.
 
     class WindowsTestCase(unittest.TestCase):
         def test_callconv_1(self):

Modified: python/trunk/Modules/_ctypes/_ctypes.c
==============================================================================
--- python/trunk/Modules/_ctypes/_ctypes.c	(original)
+++ python/trunk/Modules/_ctypes/_ctypes.c	Fri Aug 25 09:27:33 2006
@@ -2589,16 +2589,22 @@
 	PPROC address;
 	char *mangled_name;
 	int i;
-	StgDictObject *dict = PyType_stgdict((PyObject *)type);
+	StgDictObject *dict;
 
 	address = (PPROC)GetProcAddress(handle, name);
+#ifdef _WIN64
+	/* win64 has no stdcall calling conv, so it should
+	   also not have the name mangling of it.
+	*/
+	return address;
+#else
 	if (address)
 		return address;
-
 	if (((size_t)name & ~0xFFFF) == 0) {
 		return NULL;
 	}
 
+	dict = PyType_stgdict((PyObject *)type);
 	/* It should not happen that dict is NULL, but better be safe */
 	if (dict==NULL || dict->flags & FUNCFLAG_CDECL)
 		return address;
@@ -2617,6 +2623,7 @@
 			return address;
 	}
 	return NULL;
+#endif
 }
 #endif
 

Modified: python/trunk/Modules/_ctypes/_ctypes_test.c
==============================================================================
--- python/trunk/Modules/_ctypes/_ctypes_test.c	(original)
+++ python/trunk/Modules/_ctypes/_ctypes_test.c	Fri Aug 25 09:27:33 2006
@@ -25,6 +25,16 @@
 
 /* some functions handy for testing */
 
+EXPORT(int)myprintf(char *fmt, ...)
+{
+	int result;
+	va_list argptr;
+	va_start(argptr, fmt);
+	result = vprintf(fmt, argptr);
+	va_end(argptr);
+	return result;
+}
+
 EXPORT(char *)my_strtok(char *token, const char *delim)
 {
 	return strtok(token, delim);

Modified: python/trunk/Modules/_ctypes/callbacks.c
==============================================================================
--- python/trunk/Modules/_ctypes/callbacks.c	(original)
+++ python/trunk/Modules/_ctypes/callbacks.c	Fri Aug 25 09:27:33 2006
@@ -300,7 +300,7 @@
 	}
 
 	cc = FFI_DEFAULT_ABI;
-#if defined(MS_WIN32) && !defined(_WIN32_WCE)
+#if defined(MS_WIN32) && !defined(_WIN32_WCE) && !defined(MS_WIN64)
 	if (is_cdecl == 0)
 		cc = FFI_STDCALL;
 #endif

Modified: python/trunk/Modules/_ctypes/callproc.c
==============================================================================
--- python/trunk/Modules/_ctypes/callproc.c	(original)
+++ python/trunk/Modules/_ctypes/callproc.c	Fri Aug 25 09:27:33 2006
@@ -638,7 +638,7 @@
 	}
 	
 	cc = FFI_DEFAULT_ABI;
-#if defined(MS_WIN32) && !defined(_WIN32_WCE)
+#if defined(MS_WIN32) && !defined(MS_WIN64) && !defined(_WIN32_WCE)
 	if ((flags & FUNCFLAG_CDECL) == 0)
 		cc = FFI_STDCALL;
 #endif
@@ -683,6 +683,14 @@
 		return -1;
 	}
 #endif
+#ifdef MS_WIN64
+	if (delta != 0) {
+		PyErr_Format(PyExc_RuntimeError,
+			     "ffi_call failed with code %d",
+			     delta);
+		return -1;
+	}
+#else
 	if (delta < 0) {
 		if (flags & FUNCFLAG_CDECL)
 			PyErr_Format(PyExc_ValueError,
@@ -704,6 +712,7 @@
 		return -1;
 	}
 #endif
+#endif
 	if ((flags & FUNCFLAG_PYTHONAPI) && PyErr_Occurred())
 		return -1;
 	return 0;
@@ -979,7 +988,11 @@
 	}
 	for (i = 0; i < argcount; ++i) {
 		atypes[i] = args[i].ffi_type;
-		if (atypes[i]->type == FFI_TYPE_STRUCT)
+		if (atypes[i]->type == FFI_TYPE_STRUCT 
+#ifdef _WIN64
+		    && atypes[i]->size <= sizeof(void *)
+#endif
+		    )
 			avalues[i] = (void *)args[i].value.p;
 		else
 			avalues[i] = (void *)&args[i].value;
@@ -1099,7 +1112,11 @@
 	hMod = LoadLibrary(name);
 	if (!hMod)
 		return PyErr_SetFromWindowsErr(GetLastError());
+#ifdef _WIN64
+	return PyLong_FromVoidPtr(hMod);
+#else
 	return Py_BuildValue("i", hMod);
+#endif
 }
 
 static char free_library_doc[] =

Modified: python/trunk/Modules/_ctypes/cfield.c
==============================================================================
--- python/trunk/Modules/_ctypes/cfield.c	(original)
+++ python/trunk/Modules/_ctypes/cfield.c	Fri Aug 25 09:27:33 2006
@@ -1315,7 +1315,11 @@
 		*(char **)ptr = PyString_AS_STRING(str);
 		return str;
 	} else if (PyInt_Check(value) || PyLong_Check(value)) {
+#if SIZEOF_VOID_P == SIZEOF_LONG_LONG
+		*(char **)ptr = (char *)PyInt_AsUnsignedLongLongMask(value);
+#else
 		*(char **)ptr = (char *)PyInt_AsUnsignedLongMask(value);
+#endif
 		_RET(value);
 	}
 	PyErr_Format(PyExc_TypeError,
@@ -1360,7 +1364,11 @@
 		if (!value)
 			return NULL;
 	} else if (PyInt_Check(value) || PyLong_Check(value)) {
+#if SIZEOF_VOID_P == SIZEOF_LONG_LONG
+		*(wchar_t **)ptr = (wchar_t *)PyInt_AsUnsignedLongLongMask(value);
+#else
 		*(wchar_t **)ptr = (wchar_t *)PyInt_AsUnsignedLongMask(value);
+#endif
 		Py_INCREF(Py_None);
 		return Py_None;
 	} else if (!PyUnicode_Check(value)) {

Modified: python/trunk/Modules/_ctypes/libffi_msvc/ffi.c
==============================================================================
--- python/trunk/Modules/_ctypes/libffi_msvc/ffi.c	(original)
+++ python/trunk/Modules/_ctypes/libffi_msvc/ffi.c	Fri Aug 25 09:27:33 2006
@@ -34,6 +34,8 @@
 /* ffi_prep_args is called by the assembly routine once stack space
    has been allocated for the function's arguments */
 
+extern void Py_FatalError(char *msg);
+
 /*@-exportheader@*/
 void ffi_prep_args(char *stack, extended_cif *ecif)
 /*@=exportheader@*/
@@ -44,11 +46,10 @@
   register ffi_type **p_arg;
 
   argp = stack;
-
   if (ecif->cif->rtype->type == FFI_TYPE_STRUCT)
     {
       *(void **) argp = ecif->rvalue;
-      argp += 4;
+      argp += sizeof(void *);
     }
 
   p_argv = ecif->avalue;
@@ -60,8 +61,8 @@
       size_t z;
 
       /* Align if necessary */
-      if ((sizeof(int) - 1) & (unsigned) argp)
-	argp = (char *) ALIGN(argp, sizeof(int));
+      if ((sizeof(void *) - 1) & (size_t) argp)
+	argp = (char *) ALIGN(argp, sizeof(void *));
 
       z = (*p_arg)->size;
       if (z < sizeof(int))
@@ -108,7 +109,11 @@
       p_argv++;
       argp += z;
     }
-  
+
+  if (argp - stack > ecif->cif->bytes) 
+    {
+      Py_FatalError("FFI BUG: not enough stack space for arguments");
+    }
   return;
 }
 
@@ -128,6 +133,9 @@
       break;
 
     case FFI_TYPE_UINT64:
+#ifdef _WIN64
+    case FFI_TYPE_POINTER:
+#endif
       cif->flags = FFI_TYPE_SINT64;
       break;
 
@@ -139,6 +147,7 @@
   return FFI_OK;
 }
 
+#ifdef _WIN32
 /*@-declundef@*/
 /*@-exportheader@*/
 extern int
@@ -160,6 +169,16 @@
 		 void (*fn)());
 /*@=declundef@*/
 /*@=exportheader@*/
+#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, 
@@ -188,6 +207,7 @@
   
   switch (cif->abi) 
     {
+#if !defined(_WIN64)
     case FFI_SYSV:
       /*@-usedef@*/
       return ffi_call_SYSV(ffi_prep_args, &ecif, cif->bytes, 
@@ -201,6 +221,14 @@
 			      cif->flags, ecif.rvalue, fn);
       /*@=usedef@*/
       break;
+#else
+    case FFI_SYSV:
+      /*@-usedef@*/
+      return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes, 
+			   cif->flags, ecif.rvalue, fn);
+      /*@=usedef@*/
+      break;
+#endif
 
     default:
       FFI_ASSERT(0);
@@ -213,10 +241,14 @@
 /** private members **/
 
 static void ffi_prep_incoming_args_SYSV (char *stack, void **ret,
-					 void** args, ffi_cif* cif);
+					  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, int *argp)
 {
   // this is our return value storage
@@ -244,6 +276,7 @@
 
   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)
@@ -303,6 +336,15 @@
 	   : "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@*/
@@ -330,8 +372,8 @@
       size_t z;
 
       /* Align if necessary */
-      if ((sizeof(int) - 1) & (unsigned) argp) {
-	argp = (char *) ALIGN(argp, sizeof(int));
+      if ((sizeof(char *) - 1) & (size_t) argp) {
+	argp = (char *) ALIGN(argp, sizeof(char*));
       }
 
       z = (*p_arg)->size;
@@ -347,24 +389,8 @@
   return;
 }
 
-/* How to make a trampoline.  Derived from gcc/config/i386/i386.c. */
-
-#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,BYTES) \
-{ unsigned char *__tramp = (unsigned char*)(TRAMP); \
-   unsigned int  __fun = (unsigned int)(FUN); \
-   unsigned int  __ctx = (unsigned int)(CTX); \
-   unsigned int  __dis = __fun - ((unsigned int) __tramp + 8 + 4); \
-   *(unsigned char*)  &__tramp[0] = 0xb9; \
-   *(unsigned int*)   &__tramp[1] = __ctx; /* mov ecx, __ctx */ \
-   *(unsigned char*)  &__tramp[5] = 0x8b; \
-   *(unsigned char*)  &__tramp[6] = 0xd4; /* mov edx, esp */ \
-   *(unsigned char*)  &__tramp[7] = 0xe8; \
-   *(unsigned int*)   &__tramp[8] = __dis; /* call __fun  */ \
-   *(unsigned char*)  &__tramp[12] = 0xC2; /* ret BYTES */ \
-   *(unsigned short*) &__tramp[13] = BYTES; \
- }
-
 /* the cif must already be prep'ed */
+extern void ffi_closure_OUTER();
 
 ffi_status
 ffi_prep_closure (ffi_closure* closure,
@@ -373,19 +399,78 @@
 		  void *user_data)
 {
   short bytes;
+  char *tramp;
+#ifdef _WIN64
+  int mask;
+#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;
 
-  FFI_INIT_TRAMPOLINE (&closure->tramp[0],
-		       &ffi_closure_SYSV,
-		       (void*)closure,
-		       bytes);
+  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;

Modified: python/trunk/Modules/_ctypes/libffi_msvc/ffi.h
==============================================================================
--- python/trunk/Modules/_ctypes/libffi_msvc/ffi.h	(original)
+++ python/trunk/Modules/_ctypes/libffi_msvc/ffi.h	Fri Aug 25 09:27:33 2006
@@ -174,12 +174,10 @@
 
 /* ---- Definitions for the raw API -------------------------------------- */
 
-#ifndef FFI_SIZEOF_ARG
-# if LONG_MAX == 2147483647
-#  define FFI_SIZEOF_ARG        4
-# elif LONG_MAX == 9223372036854775807
-#  define FFI_SIZEOF_ARG        8
-# endif
+#ifdef _WIN64
+#define FFI_SIZEOF_ARG 8
+#else
+#define FFI_SIZEOF_ARG 4
 #endif
 
 typedef union {

Modified: python/trunk/Modules/_ctypes/libffi_msvc/ffitarget.h
==============================================================================
--- python/trunk/Modules/_ctypes/libffi_msvc/ffitarget.h	(original)
+++ python/trunk/Modules/_ctypes/libffi_msvc/ffitarget.h	Fri Aug 25 09:27:33 2006
@@ -44,7 +44,9 @@
 
   /* ---- Intel x86 Win32 ---------- */
   FFI_SYSV,
+#ifndef _WIN64
   FFI_STDCALL,
+#endif
   /* TODO: Add fastcall support for the sake of completeness */
   FFI_DEFAULT_ABI = FFI_SYSV,
 
@@ -67,8 +69,8 @@
 
 #define FFI_CLOSURES 1
 
-#ifdef X86_64
-#define FFI_TRAMPOLINE_SIZE 24
+#ifdef _WIN64
+#define FFI_TRAMPOLINE_SIZE 29
 #define FFI_NATIVE_RAW_API 0
 #else
 #define FFI_TRAMPOLINE_SIZE 15


More information about the Python-checkins mailing list