From a92bb2248b145f295c96bebb79557d8278fb1022 Mon Sep 17 00:00:00 2001 From: Ruihang Lai Date: Thu, 21 Aug 2025 17:08:14 -0400 Subject: [PATCH] [FFI] Fix JSON parser/writer for the fast-math flag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR fixes the JSON parser and writer for the support of the fast-math flag. Prior to this PR, there would be the following error when compiling TVM with fast-math. This PR fixes this issue. ``` /home/ruihangl/Workspace/tvm/ffi/src/ffi/extra/json_writer.cc: In static member function ‘static bool tvm::ffi::json::JSONWriter::FastMathSafeIsNaN(double)’: /home/ruihangl/Workspace/tvm/ffi/src/ffi/extra/json_writer.cc:69:22: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] 69 | uint64_t bits = *reinterpret_cast(&x); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/ruihangl/Workspace/tvm/ffi/src/ffi/extra/json_writer.cc: In static member function ‘static bool tvm::ffi::json::JSONWriter::FastMathSafeIsInf(double)’: /home/ruihangl/Workspace/tvm/ffi/src/ffi/extra/json_writer.cc:84:22: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] 84 | uint64_t bits = *reinterpret_cast(&x); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` --- ffi/src/ffi/extra/json_parser.cc | 24 ++++++++++++++++++------ ffi/src/ffi/extra/json_writer.cc | 14 ++++++++++++-- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/ffi/src/ffi/extra/json_parser.cc b/ffi/src/ffi/extra/json_parser.cc index 3107e4ddf1ad..8bd372699dad 100644 --- a/ffi/src/ffi/extra/json_parser.cc +++ b/ffi/src/ffi/extra/json_parser.cc @@ -298,8 +298,12 @@ class JSONParserContext { private: static double FastMathSafePosInf() { #ifdef __FAST_MATH__ - const uint64_t inf_bits = 0x7FF0000000000000ULL; - return *reinterpret_cast(&inf_bits); + union { + uint64_t from; + double to; + } u; + u.from = 0x7FF0000000000000ULL; // write "from", read "to" + return u.to; #else return std::numeric_limits::infinity(); #endif @@ -307,8 +311,12 @@ class JSONParserContext { static double FastMathSafeNegInf() { #ifdef __FAST_MATH__ - const uint64_t inf_bits = 0xFFF0000000000000ULL; - return *reinterpret_cast(&inf_bits); + union { + uint64_t from; + double to; + } u; + u.from = 0xFFF0000000000000ULL; // write "from", read "to" + return u.to; #else return -std::numeric_limits::infinity(); #endif @@ -316,8 +324,12 @@ class JSONParserContext { static double FastMathSafeNaN() { #ifdef __FAST_MATH__ - const uint64_t nan_bits = 0x7FF8000000000000ULL; - return *reinterpret_cast(&nan_bits); + union { + uint64_t from; + double to; + } u; + u.from = 0x7FF8000000000000ULL; // write "from", read "to" + return u.to; #else return std::numeric_limits::quiet_NaN(); #endif diff --git a/ffi/src/ffi/extra/json_writer.cc b/ffi/src/ffi/extra/json_writer.cc index 81d321d9a754..c2cd3f2f36d3 100644 --- a/ffi/src/ffi/extra/json_writer.cc +++ b/ffi/src/ffi/extra/json_writer.cc @@ -66,7 +66,12 @@ class JSONWriter { // IEEE 754 standard: https://en.wikipedia.org/wiki/IEEE_754 // NaN is encoded as all 1s in the exponent and non-zero in the mantissa static_assert(sizeof(double) == sizeof(uint64_t), "Unexpected double size"); - uint64_t bits = *reinterpret_cast(&x); + union { + double from; + uint64_t to; + } u; + u.from = x; // write "from", read "to" + uint64_t bits = u.to; uint64_t exponent = (bits >> 52) & 0x7FF; uint64_t mantissa = bits & 0xFFFFFFFFFFFFFull; return (exponent == 0x7FF) && (mantissa != 0); @@ -81,7 +86,12 @@ class JSONWriter { // IEEE 754 standard: https://en.wikipedia.org/wiki/IEEE_754 // Inf is encoded as all 1s in the exponent and zero in the mantissa static_assert(sizeof(double) == sizeof(uint64_t), "Unexpected double size"); - uint64_t bits = *reinterpret_cast(&x); + union { + double from; + uint64_t to; + } u; + u.from = x; // write "from", read "to" + uint64_t bits = u.to; uint64_t exponent = (bits >> 52) & 0x7FF; uint64_t mantissa = bits & 0xFFFFFFFFFFFFFull; // inf is encoded as all 1s in the exponent and zero in the mantissa