Use sw::bit_cast<> for type punning Type punning through pointer or reference type cast breaks strict aliasing rules which can lead to undefined behavior. Note that sw::bit_cast<> makes use of a union to perform type punning, which is also in violation of strict C++ rules, but is supported by extension in at least the Visual Studio, Clang, and GCC compilers. It will also be trivial to replace with std::bit_cast<> once we can upgrade to C++20. Bug: b/227975743 Change-Id: I4b94764aa6445d7c8d6463ba3a4b23a09ac975ef Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/69169 Tested-by: Nicolas Capens <nicolascapens@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com> Commit-Queue: Alexis Hétu <sugoi@google.com> Kokoro-Result: kokoro <noreply+kokoro@google.com>
diff --git a/src/Pipeline/Constants.cpp b/src/Pipeline/Constants.cpp index 1937e8b..8db8562 100644 --- a/src/Pipeline/Constants.cpp +++ b/src/Pipeline/Constants.cpp
@@ -306,7 +306,7 @@ for(int i = 0; i <= 0xFFFF; i++) { - half2float[i] = (float)reinterpret_cast<half &>(i); + half2float[i] = static_cast<float>(bit_cast<half>(i)); } }
diff --git a/src/System/Half.cpp b/src/System/Half.cpp index abadc2d..c102d6e 100644 --- a/src/System/Half.cpp +++ b/src/System/Half.cpp
@@ -18,7 +18,7 @@ half::half(float fp32) { - unsigned int fp32i = *(unsigned int *)&fp32; + unsigned int fp32i = bit_cast<unsigned int>(fp32); unsigned int sign = (fp32i & 0x80000000) >> 16; unsigned int abs = fp32i & 0x7FFFFFFF; @@ -62,7 +62,7 @@ { fp32i = s << 31; - return (float &)fp32i; + return bit_cast<float>(fp32i); } else { @@ -82,7 +82,7 @@ fp32i = (s << 31) | (e << 23) | m; - return (float &)fp32i; + return bit_cast<float>(fp32i); } half &half::operator=(float f)
diff --git a/src/System/Half.hpp b/src/System/Half.hpp index eebad3f..45b7869 100644 --- a/src/System/Half.hpp +++ b/src/System/Half.hpp
@@ -194,7 +194,7 @@ const unsigned int float32MinNormfloat11 = 0x38800000; const unsigned int float32MinDenormfloat11 = 0x35000080; - const unsigned int float32Bits = *reinterpret_cast<unsigned int *>(&fp32); + const unsigned int float32Bits = bit_cast<unsigned int>(fp32); const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; unsigned int float32Val = float32Bits & float32ValueMask; @@ -273,7 +273,7 @@ const unsigned int float32MinNormfloat10 = 0x38800000; const unsigned int float32MinDenormfloat10 = 0x35800040; - const unsigned int float32Bits = *reinterpret_cast<unsigned int *>(&fp32); + const unsigned int float32Bits = bit_cast<unsigned int>(fp32); const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; unsigned int float32Val = float32Bits & float32ValueMask;