Author: Timm Baeder Date: 2024-11-05T05:52:03+01:00 New Revision: 2f13fbfcd1b874019191ab68b661d9b9d82d8556
URL: https://github.com/llvm/llvm-project/commit/2f13fbfcd1b874019191ab68b661d9b9d82d8556 DIFF: https://github.com/llvm/llvm-project/commit/2f13fbfcd1b874019191ab68b661d9b9d82d8556.diff LOG: [clang][bytecode] Support bitcasting into float fields (#114825) Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp clang/test/AST/ByteCode/builtin-bit-cast.cpp Removed: ################################################################################ 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@+2 {{constexpr variable 'run_ref_mem' must be initialized by a constant expression}} // both-note@+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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits