[clang] [clang][bytecode] Support bitcasting into float fields (PR #114825)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 4 08:26:50 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/114825.diff
4 Files Affected:
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+1-1)
- (modified) clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp (+19-3)
- (modified) clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp (+10-3)
- (modified) clang/test/AST/ByteCode/builtin-bit-cast.cpp (+19)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 35116952901684..396213c7b2ae0e 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2735,7 +2735,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
- return this->visitInitializer(SubExpr);
+ return this->visitInitializer(SubExpr) && this->emitFinishInit(E);
}
}
return false;
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index dd02eb25c3fa1f..e1de151af3e021 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -397,19 +397,35 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
/*ReturnOnUninit=*/false);
// Now read the values out of the buffer again and into ToPtr.
+ const ASTContext &ASTCtx = S.getASTContext();
size_t BitOffset = 0;
bool Success = enumeratePointerFields(
ToPtr, S.getContext(),
[&](const Pointer &P, PrimType T, size_t _) -> bool {
- BITCAST_TYPE_SWITCH_FIXED_SIZE(T, {
- T &Val = P.deref<T>();
+ if (T == PT_Float) {
+ CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
+ const auto &Semantics = ASTCtx.getFloatTypeSemantics(P.getType());
+ unsigned NumBits = llvm::APFloatBase::getSizeInBits(Semantics);
+ assert(NumBits % 8 == 0);
+ assert(NumBits <= ASTCtx.toBits(ObjectReprChars));
+ std::byte *M = Buffer.getBytes(BitOffset);
+
+ if (llvm::sys::IsBigEndianHost)
+ swapBytes(M, NumBits / 8);
+ P.deref<Floating>() = Floating::bitcastFromMemory(M, Semantics);
+ P.initialize();
+ BitOffset += ASTCtx.toBits(ObjectReprChars);
+ return true;
+ }
+
+ BITCAST_TYPE_SWITCH_FIXED_SIZE(T, {
std::byte *M = Buffer.getBytes(BitOffset);
if (llvm::sys::IsBigEndianHost)
swapBytes(M, T::bitWidth() / 8);
- Val = T::bitcastFromMemory(M, T::bitWidth());
+ P.deref<T>() = T::bitcastFromMemory(M, T::bitWidth());
P.initialize();
BitOffset += T::bitWidth();
});
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
index 230680ff3ced7d..0929f7cb70b744 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
@@ -45,7 +45,7 @@ struct bytes {
unsigned char d[16];
};
-// static_assert(round_trip<bytes>(ld), "");
+static_assert(round_trip<bytes>(ld), "");
static_assert(round_trip<long double>(10.0L));
@@ -77,10 +77,17 @@ constexpr bytes ld539 = {
0x8, 0x40, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
};
-
constexpr long double fivehundredandthirtynine = 539.0;
-
static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, "");
+
+struct LD {
+ long double v;
+};
+
+constexpr LD ld2 = __builtin_bit_cast(LD, ld539.d);
+constexpr long double five39 = __builtin_bit_cast(long double, ld539.d);
+static_assert(ld2.v == five39);
+
#else
static_assert(round_trip<__int128_t>(34.0L));
#endif
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index 50382399eefc9c..0c55155ec64a24 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -467,3 +467,22 @@ struct ref_mem {
// both-error at +2 {{constexpr variable 'run_ref_mem' must be initialized by a constant expression}}
// both-note at +1 {{bit_cast from a type with a reference member is not allowed in a constant expression}}
constexpr intptr_t run_ref_mem = __builtin_bit_cast(intptr_t, ref_mem{global_int});
+
+
+
+
+namespace test_complex {
+ constexpr _Complex unsigned test_int_complex = { 0x0C05FEFE, 0xCAFEBABE };
+ static_assert(round_trip<_Complex unsigned>(0xCAFEBABE0C05FEFEULL), "");
+ static_assert(bit_cast<unsigned long long>(test_int_complex) == (LITTLE_END
+ ? 0xCAFEBABE0C05FEFE
+ : 0x0C05FEFECAFEBABE), "");
+ static_assert(sizeof(double) == 2 * sizeof(float));
+ struct TwoFloats { float A; float B; };
+ constexpr _Complex float test_float_complex = {1.0f, 2.0f};
+ constexpr TwoFloats TF = __builtin_bit_cast(TwoFloats, test_float_complex);
+ static_assert(TF.A == 1.0f && TF.B == 2.0f);
+
+ constexpr double D = __builtin_bit_cast(double, test_float_complex);
+ constexpr int M = __builtin_bit_cast(int, test_int_complex); // both-error {{__builtin_bit_cast source size does not equal destination size}}
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/114825
More information about the cfe-commits
mailing list