-
-
Notifications
You must be signed in to change notification settings - Fork 30k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
bpo-41100: ctypes fixes for arm64 Mac OS #21249
Changes from all commits
ff883bc
36b35bc
bacf128
971ef00
da30587
80f852b
aeac14b
62fe20a
e160a59
bca75fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
setup.py: probe libffi for ffi_closure_alloc and ffi_prep_cif_var |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
#include "Python.h" | ||
#include "frameobject.h" | ||
|
||
#include <stdbool.h> | ||
|
||
#include <ffi.h> | ||
#ifdef MS_WIN32 | ||
#include <windows.h> | ||
|
@@ -18,7 +20,7 @@ CThunkObject_dealloc(PyObject *myself) | |
Py_XDECREF(self->callable); | ||
Py_XDECREF(self->restype); | ||
if (self->pcl_write) | ||
ffi_closure_free(self->pcl_write); | ||
Py_ffi_closure_free(self->pcl_write); | ||
PyObject_GC_Del(self); | ||
} | ||
|
||
|
@@ -361,8 +363,7 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable, | |
|
||
assert(CThunk_CheckExact((PyObject *)p)); | ||
|
||
p->pcl_write = ffi_closure_alloc(sizeof(ffi_closure), | ||
&p->pcl_exec); | ||
p->pcl_write = Py_ffi_closure_alloc(sizeof(ffi_closure), &p->pcl_exec); | ||
if (p->pcl_write == NULL) { | ||
PyErr_NoMemory(); | ||
goto error; | ||
|
@@ -408,13 +409,33 @@ CThunkObject *_ctypes_alloc_callback(PyObject *callable, | |
"ffi_prep_cif failed with %d", result); | ||
goto error; | ||
} | ||
#if defined(X86_DARWIN) || defined(POWERPC_DARWIN) | ||
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p); | ||
#if HAVE_FFI_PREP_CLOSURE_LOC | ||
# if USING_APPLE_OS_LIBFFI | ||
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) | ||
# else | ||
# define HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME true | ||
# endif | ||
if (HAVE_FFI_PREP_CLOSURE_LOC_RUNTIME) { | ||
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn, | ||
p, | ||
p->pcl_exec); | ||
} else | ||
#endif | ||
{ | ||
#if USING_APPLE_OS_LIBFFI && defined(__arm64__) | ||
PyErr_Format(PyExc_NotImplementedError, "ffi_prep_closure_loc() is missing"); | ||
goto error; | ||
#else | ||
result = ffi_prep_closure_loc(p->pcl_write, &p->cif, closure_fcn, | ||
p, | ||
p->pcl_exec); | ||
#if __clang__ | ||
#pragma clang diagnostic push | ||
#pragma clang diagnostic ignored "-Wdeprecated-declarations" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
#endif | ||
result = ffi_prep_closure(p->pcl_write, &p->cif, closure_fcn, p); | ||
#if __clang__ | ||
#pragma clang diagnostic pop | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto |
||
#endif | ||
#endif | ||
} | ||
if (result != FFI_OK) { | ||
PyErr_Format(PyExc_RuntimeError, | ||
"ffi_prep_closure failed with %d", result); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,8 @@ | |
#include "Python.h" | ||
#include "structmember.h" // PyMemberDef | ||
|
||
#include <stdbool.h> | ||
|
||
#ifdef MS_WIN32 | ||
#include <windows.h> | ||
#include <tchar.h> | ||
|
@@ -812,7 +814,8 @@ static int _call_function_pointer(int flags, | |
ffi_type **atypes, | ||
ffi_type *restype, | ||
void *resmem, | ||
int argcount) | ||
int argcount, | ||
int argtypecount) | ||
{ | ||
PyThreadState *_save = NULL; /* For Py_BLOCK_THREADS and Py_UNBLOCK_THREADS */ | ||
PyObject *error_object = NULL; | ||
|
@@ -835,14 +838,63 @@ static int _call_function_pointer(int flags, | |
if ((flags & FUNCFLAG_CDECL) == 0) | ||
cc = FFI_STDCALL; | ||
#endif | ||
if (FFI_OK != ffi_prep_cif(&cif, | ||
cc, | ||
argcount, | ||
restype, | ||
atypes)) { | ||
PyErr_SetString(PyExc_RuntimeError, | ||
"ffi_prep_cif failed"); | ||
return -1; | ||
|
||
# if USING_APPLE_OS_LIBFFI | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Proposed change: #if USING_APPLE_OS_LIBFFI && HAVE_FFI_PREP_CIF_VAR This way the __builtin_available is not used when building on older macOS versions. |
||
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME __builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *) | ||
# elif HAVE_FFI_PREP_CIF_VAR | ||
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME true | ||
# else | ||
# define HAVE_FFI_PREP_CIF_VAR_RUNTIME false | ||
# endif | ||
|
||
/* Even on Apple-arm64 the calling convention for variadic functions conincides | ||
* with the standard calling convention in the case that the function called | ||
* only with its fixed arguments. Thus, we do not need a special flag to be | ||
* set on variadic functions. We treat a function as variadic if it is called | ||
* with a nonzero number of variadic arguments */ | ||
bool is_variadic = (argtypecount != 0 && argcount > argtypecount); | ||
(void) is_variadic; | ||
|
||
#if defined(__APPLE__) && defined(__arm64__) | ||
if (is_variadic) { | ||
if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) { | ||
} else { | ||
PyErr_SetString(PyExc_NotImplementedError, "ffi_prep_cif_var() is missing"); | ||
return -1; | ||
} | ||
} | ||
#endif | ||
|
||
bool called_ffi_prep_cif_var = false; | ||
|
||
#if HAVE_FFI_PREP_CIF_VAR | ||
if (is_variadic) { | ||
if (HAVE_FFI_PREP_CIF_VAR_RUNTIME) { | ||
if (FFI_OK != ffi_prep_cif_var(&cif, | ||
cc, | ||
argtypecount, | ||
argcount, | ||
restype, | ||
atypes)) { | ||
PyErr_SetString(PyExc_RuntimeError, | ||
"ffi_prep_cif_var failed"); | ||
return -1; | ||
} | ||
called_ffi_prep_cif_var = true; | ||
} | ||
} | ||
#endif | ||
|
||
if (!called_ffi_prep_cif_var) { | ||
if (FFI_OK != ffi_prep_cif(&cif, | ||
cc, | ||
argcount, | ||
restype, | ||
atypes)) { | ||
PyErr_SetString(PyExc_RuntimeError, | ||
"ffi_prep_cif failed"); | ||
return -1; | ||
} | ||
} | ||
|
||
if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { | ||
|
@@ -1212,9 +1264,8 @@ PyObject *_ctypes_callproc(PPROC pProc, | |
|
||
if (-1 == _call_function_pointer(flags, pProc, avalues, atypes, | ||
rtype, resbuf, | ||
Py_SAFE_DOWNCAST(argcount, | ||
Py_ssize_t, | ||
int))) | ||
Py_SAFE_DOWNCAST(argcount, Py_ssize_t, int), | ||
Py_SAFE_DOWNCAST(argtype_count, Py_ssize_t, int))) | ||
goto cleanup; | ||
|
||
#ifdef WORDS_BIGENDIAN | ||
|
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should avoid
-Wunknown-pragmas
warnings when building on other platforms.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed