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;