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
