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;