https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/114485
>From 724a6366d9562a480c9ecbe242d4236ebcdcce45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Fri, 1 Nov 2024 00:16:28 +0100 Subject: [PATCH] [clang][bytecode] Implement bitcasts to floating-point values --- clang/lib/AST/ByteCode/Interp.h | 3 +- .../ByteCode/builtin-bit-cast-long-double.cpp | 87 +++++++++++++++++++ clang/test/AST/ByteCode/builtin-bit-cast.cpp | 4 +- 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index ade6f7424b1fd6..52d3a19ca99593 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -3062,7 +3062,8 @@ inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte, return false; if constexpr (std::is_same_v<T, Floating>) { - assert(false && "Implement bitcasting to a floating type"); + assert(Sem); + S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem)); } else { assert(!Sem); S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth)); diff --git a/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp new file mode 100644 index 00000000000000..230680ff3ced7d --- /dev/null +++ b/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp @@ -0,0 +1,87 @@ +// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s +// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char +// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s + +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter + +// both-no-diagnostics + +typedef decltype(nullptr) nullptr_t; +typedef __INTPTR_TYPE__ intptr_t; + +static_assert(sizeof(int) == 4); +static_assert(sizeof(long long) == 8); + +template <class To, class From> +constexpr To bit_cast(const From &from) { + static_assert(sizeof(To) == sizeof(From)); + return __builtin_bit_cast(To, from); +} + +template <class Intermediate, class Init> +constexpr bool check_round_trip(const Init &init) { + return bit_cast<Init>(bit_cast<Intermediate>(init)) == init; +} + +template <class Intermediate, class Init> +constexpr Init round_trip(const Init &init) { + return bit_cast<Init>(bit_cast<Intermediate>(init)); +} + + + + +namespace test_long_double { +#if __x86_64 +#if 0 +constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\ + // expected-note{{in call}} +#endif +constexpr long double ld = 3.1425926539; + +struct bytes { + unsigned char d[16]; +}; + +// static_assert(round_trip<bytes>(ld), ""); + +static_assert(round_trip<long double>(10.0L)); + +#if 0 +constexpr bool f(bool read_uninit) { + bytes b = bit_cast<bytes>(ld); + unsigned char ld_bytes[10] = { + 0x0, 0x48, 0x9f, 0x49, 0xf0, + 0x3c, 0x20, 0xc9, 0x0, 0x40, + }; + + for (int i = 0; i != 10; ++i) + if (ld_bytes[i] != b.d[i]) + return false; + + if (read_uninit && b.d[10]) // expected-note{{read of uninitialized object is not allowed in a constant expression}} + return false; + + return true; +} + +static_assert(f(/*read_uninit=*/false), ""); +static_assert(f(/*read_uninit=*/true), ""); // expected-error{{static assertion expression is not an integral constant expression}} \ + // expected-note{{in call to 'f(true)'}} +#endif +constexpr bytes ld539 = { + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xc0, 0x86, + 0x8, 0x40, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; + +constexpr long double fivehundredandthirtynine = 539.0; + +static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, ""); +#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 0e86da9133b33d..a48d9549959e90 100644 --- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp +++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp @@ -76,6 +76,8 @@ static_assert(check_round_trip<__int128_t>((__int128_t)34)); static_assert(check_round_trip<__int128_t>((__int128_t)-34)); #endif +static_assert(check_round_trip<double>(17.0)); + namespace simple { constexpr int A = __builtin_bit_cast(int, 10); @@ -108,7 +110,7 @@ namespace simple { static_assert(check_round_trip<unsigned>((int)0x12345678)); static_assert(check_round_trip<unsigned>((int)0x87654321)); static_assert(check_round_trip<unsigned>((int)0x0C05FEFE)); - // static_assert(round_trip<float>((int)0x0C05FEFE)); + static_assert(round_trip<float>((int)0x0C05FEFE)); /// This works in GCC and in the bytecode interpreter, but the current interpreter _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits