Repository navigation
[libclang/python] Fix visitor callback return data type - #221024
Conversation
|
@llvm/pr-subscribers-clang Author: Milad Fa (miladfarca) ChangesDeclare the visitor callbacks return as c_long, i.e. a full register word rather than c_int. This is currently causing an issue on s390x, a 64-bit big-endian target. cindex.py calls into libclang through ctypes, which builds the callback closures using Using c_long makes the value fill the register at its native width on all platforms. 1 Files Affected:
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index bc00dd770ce3b..4423096085535 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -71,6 +71,7 @@
byref,
c_char_p,
c_int,
+ c_long,
c_longlong,
c_uint,
c_ulong,
@@ -4117,8 +4118,8 @@ def set_property(self, property, value):
translation_unit_includes_callback = CFUNCTYPE(
None, c_object_p, POINTER(SourceLocation), c_uint, py_object
)
-cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
-fields_visit_callback = CFUNCTYPE(c_int, Cursor, py_object)
+cursor_visit_callback = CFUNCTYPE(c_long, Cursor, Cursor, py_object)
+fields_visit_callback = CFUNCTYPE(c_long, Cursor, py_object)
# Functions strictly alphabetical order.
FUNCTION_LIST: list[LibFunc] = [
|
|
Perhaps I'm misunderstanding something, but the visitor should return instances of Also adding @Endilll because C++ isn't my strong suite |
Endilll
left a comment
There was a problem hiding this comment.
LGTM, but I want @AaronBallman to also take a look before this lands
The issue is that when this enum is put into a register that serves as the return slot, @miladfarca can you raise or find an existing issue about this on ctypes side, and put it as a comment in the code? My hope is that this would be a somewhat temporary fix, until Python releases with this bug reach EOL. Also, can we limit this workaround to s390x? I guess For the reference, I dug up the following in s390x psABI version 1.7 (1.2.5 "Return Values"):
|
|
@DeinAlptraum It's correct that the type is an enum however similar to @Endilll's explanation, ctypes has no concept of an enum. They get passed a data size (8/4/2 etc.) and in this case all they see is a I have also created an issue on cpython upstream and have made this patch s390x specific: |
AaronBallman
left a comment
There was a problem hiding this comment.
Generally LGTM! But this should come with a release note so users know about the fix. It should also come with a test which demonstrates the fix, if possible.
|
I have added a release note as well as a test, the crash itself came from V8's metagen on s390x. |
|
LGMT, but could you confirm again this is what you imaged @AaronBallman ? |
AaronBallman
left a comment
There was a problem hiding this comment.
LGTM!
Can you update your email address to be public (https://llvm.org/docs/DeveloperPolicy.html#email-addresses), please? It comes up as this for me:
Then we can land the changes on your behalf.
|
@AaronBallman not a problem, I've made it public. |
Declare the visitor callbacks return as c_long, i.e. a full register word rather than c_int. This is currently causing an issue on s390x, a 64-bit big-endian target. The V8 JavaScript engine has recently started using libclang as a dependency to parse header files. It is currently crashing on s390x with a SIGFPE due to this issue. Both the s390x ELF ABI and libffi require the value to be sign/zero extended to register size, and leaving it as `c_int` leaves garbage on the high side. cindex.py calls into libclang through ctypes, which builds the callback closures using libffi. With a `c_int` return, ctypes writes only the low 32 bits and skips the extension that both the ABI and libffi's closure contract require, so libffi hands libclang a register whose high bits are garbage. Using c_long makes the value fill the register at its native width on all platforms.
Declare the visitor callbacks return as c_long, i.e. a full register word rather than c_int.
This is currently causing an issue on s390x, a 64-bit big-endian target.
The V8 JavaScript engine has recently started using libclang as a dependency
to parse header files. It is currently crashing on s390x with a SIGFPE due to this issue.
Both the s390x ELF ABI and libffi require the value to be sign/zero extended to register
size, and leaving it as
c_intleaves garbage on the high side.cindex.py calls into libclang through ctypes, which builds the callback closures using
libffi. With a
c_intreturn, ctypes writes only the low 32 bits and skips the extensionthat both the ABI and libffi's closure contract require, so libffi hands libclang a register
whose high bits are garbage.
Using c_long makes the value fill the register at its native width on all platforms.