Emscripten: Don't unbox single element structs if they are larger than 16 bytes ...
authorHood Chatham <roberthoodchatham@gmail.com>
Thu, 15 Feb 2024 12:51:12 +0000 (04:51 -0800)
committerGitHub <noreply@github.com>
Thu, 15 Feb 2024 12:51:12 +0000 (07:51 -0500)
This arguably is a compensation for a Python ctypes bug / strange behavior
described here:
https://github.com/python/cpython/blob/a16a9f978f42b8a09297c1efbf33877f6388c403/Modules/_ctypes/stgdict.c#L718-L779

If a struct is larger than 16 bytes, Python does not bother to accurately report
its contents figuring that we don't need to know.

src/wasm32/ffi.c

index 399a06e334047accea748fad4cce6b64767ed384..1a8c9aea7661189fad2b7ebd0e196b066f26b3a9 100644 (file)
@@ -172,6 +172,19 @@ void,
 unbox_small_structs, (ffi_type type_ptr), {
   var type_id = FFI_TYPE__TYPEID(type_ptr);
   while (type_id === FFI_TYPE_STRUCT) {
+    // Don't unbox single element structs if they are bigger than 16 bytes. This
+    // is a work around for the fact that Python will give incorrect values for
+    // the size of the field in these cases: it says that the struct has pointer
+    // size and alignment and are of type pointer, even though it is more
+    // accurately a struct and has a larger size. Keeping it as a struct here
+    // will let us get the ABI right (which is in fact that the true argument is
+    // a pointer to the stack... so maybe Python issn't so wrong??)
+    //
+    // See the Python comment here:
+    // https://github.com/python/cpython/blob/a16a9f978f42b8a09297c1efbf33877f6388c403/Modules/_ctypes/stgdict.c#L718-L779
+    if (FFI_TYPE__SIZE(type_ptr) > 16) {
+      break;
+    }
     var elements = FFI_TYPE__ELEMENTS(type_ptr);
     var first_element = DEREF_U32(elements, 0);
     if (first_element === 0) {