This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch refactor-s1
in repository https://gitbox.apache.org/repos/asf/tvm.git

commit dd4bdad2123c9ad59d0d421ef6c4a4096b11cf5e
Author: tqchen <[email protected]>
AuthorDate: Mon Apr 14 09:58:35 2025 -0400

    [FFI] consistent header size and alignment across platforms
---
 ffi/include/tvm/ffi/c_api.h       | 13 ++++++++++---
 ffi/include/tvm/ffi/type_traits.h | 13 +++++--------
 ffi/tests/cpp/test_c_ffi_abi.cc   |  1 +
 3 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/ffi/include/tvm/ffi/c_api.h b/ffi/include/tvm/ffi/c_api.h
index 3b4a33509c..14265acd37 100644
--- a/ffi/include/tvm/ffi/c_api.h
+++ b/ffi/include/tvm/ffi/c_api.h
@@ -103,7 +103,7 @@ typedef enum {
 typedef void* TVMFFIObjectHandle;
 
 /*!
- * \brief C-based type of all FFI object types that allocates on heap.
+ * \brief C-based type of all FFI object header that allocates on heap.
  * \note TVMFFIObject and TVMFFIAny share the common type_index header
  */
 typedef struct TVMFFIObject {
@@ -114,8 +114,15 @@ typedef struct TVMFFIObject {
   int32_t type_index;
   /*! \brief Reference counter of the object. */
   int32_t ref_counter;
-  /*! \brief Deleter to be invoked when reference counter goes to zero. */
-  void (*deleter)(struct TVMFFIObject* self);
+  union {
+    /*! \brief Deleter to be invoked when reference counter goes to zero. */
+    void (*deleter)(struct TVMFFIObject* self);
+    /*!
+     * \brief auxilary field to TVMFFIObject is always 8 bytes aligned.
+     * \note This helps us to ensure cross platform compatibility.
+     */
+    int64_t __ensure_align;
+  };
 } TVMFFIObject;
 
 /*!
diff --git a/ffi/include/tvm/ffi/type_traits.h 
b/ffi/include/tvm/ffi/type_traits.h
index 5f0b94d078..91a1e070dd 100644
--- a/ffi/include/tvm/ffi/type_traits.h
+++ b/ffi/include/tvm/ffi/type_traits.h
@@ -396,14 +396,11 @@ struct TypeTraits<DLTensor*> : public TypeTraitsBase {
       return static_cast<DLTensor*>(src->v_ptr);
     } else if (src->type_index == TypeIndex::kTVMFFINDArray) {
       // Conversion from NDArray pointer to DLTensor
-      // use temp struct so we can calculate ABI offset on 32/64 bit platforms.
-      // TODO(tqchen): followup once we bring NDArray related containers to FFI
-      // and move DLTensor* to the right place.
-      struct Temp {
-        TVMFFIObject header;
-        DLTensor dl_tensor;
-      };
-      return &(reinterpret_cast<Temp*>(src->v_obj)->dl_tensor);
+      // based on the assumption that NDArray always follows the TVMFFIObject 
header
+      static_assert(sizeof(TVMFFIObject) == 16, "TVMFFIObject must be 8 
bytes");
+      static_assert(alignof(DLTensor) == 8, "DLTensor must be 8 bytes 
aligned");
+      return reinterpret_cast<DLTensor*>(reinterpret_cast<char*>(src->v_obj) +
+                                         sizeof(TVMFFIObject));
     }
     return std::nullopt;
   }
diff --git a/ffi/tests/cpp/test_c_ffi_abi.cc b/ffi/tests/cpp/test_c_ffi_abi.cc
index 9cbc7e67e1..1efceef297 100644
--- a/ffi/tests/cpp/test_c_ffi_abi.cc
+++ b/ffi/tests/cpp/test_c_ffi_abi.cc
@@ -25,6 +25,7 @@ TEST(ABIHeaderAlignment, Default) {
   TVMFFIObject value;
   value.type_index = 10;
   EXPECT_EQ(reinterpret_cast<TVMFFIAny*>(&value)->type_index, 10);
+  static_assert(sizeof(TVMFFIObject) == 16, "TVMFFIObject must be 16 bytes");
 }
 
 }  // namespace

Reply via email to