[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