Skip to content

Commit c752efb

Browse files
authored
[clang][bytecode] Implement bitcasts to floating-point values (#114485)
1 parent edd6b1f commit c752efb

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3062,7 +3062,8 @@ inline bool BitCast(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
30623062
return false;
30633063

30643064
if constexpr (std::is_same_v<T, Floating>) {
3065-
assert(false && "Implement bitcasting to a floating type");
3065+
assert(Sem);
3066+
S.Stk.push<Floating>(T::bitcastFromMemory(Buff.data(), *Sem));
30663067
} else {
30673068
assert(!Sem);
30683069
S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s
2+
// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char
3+
// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s
4+
5+
// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fexperimental-new-constant-interpreter
6+
// 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
7+
// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter
8+
9+
// both-no-diagnostics
10+
11+
typedef decltype(nullptr) nullptr_t;
12+
typedef __INTPTR_TYPE__ intptr_t;
13+
14+
static_assert(sizeof(int) == 4);
15+
static_assert(sizeof(long long) == 8);
16+
17+
template <class To, class From>
18+
constexpr To bit_cast(const From &from) {
19+
static_assert(sizeof(To) == sizeof(From));
20+
return __builtin_bit_cast(To, from);
21+
}
22+
23+
template <class Intermediate, class Init>
24+
constexpr bool check_round_trip(const Init &init) {
25+
return bit_cast<Init>(bit_cast<Intermediate>(init)) == init;
26+
}
27+
28+
template <class Intermediate, class Init>
29+
constexpr Init round_trip(const Init &init) {
30+
return bit_cast<Init>(bit_cast<Intermediate>(init));
31+
}
32+
33+
34+
35+
36+
namespace test_long_double {
37+
#if __x86_64
38+
#if 0
39+
constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\
40+
// expected-note{{in call}}
41+
#endif
42+
constexpr long double ld = 3.1425926539;
43+
44+
struct bytes {
45+
unsigned char d[16];
46+
};
47+
48+
// static_assert(round_trip<bytes>(ld), "");
49+
50+
static_assert(round_trip<long double>(10.0L));
51+
52+
#if 0
53+
constexpr bool f(bool read_uninit) {
54+
bytes b = bit_cast<bytes>(ld);
55+
unsigned char ld_bytes[10] = {
56+
0x0, 0x48, 0x9f, 0x49, 0xf0,
57+
0x3c, 0x20, 0xc9, 0x0, 0x40,
58+
};
59+
60+
for (int i = 0; i != 10; ++i)
61+
if (ld_bytes[i] != b.d[i])
62+
return false;
63+
64+
if (read_uninit && b.d[10]) // expected-note{{read of uninitialized object is not allowed in a constant expression}}
65+
return false;
66+
67+
return true;
68+
}
69+
70+
static_assert(f(/*read_uninit=*/false), "");
71+
static_assert(f(/*read_uninit=*/true), ""); // expected-error{{static assertion expression is not an integral constant expression}} \
72+
// expected-note{{in call to 'f(true)'}}
73+
#endif
74+
constexpr bytes ld539 = {
75+
0x0, 0x0, 0x0, 0x0,
76+
0x0, 0x0, 0xc0, 0x86,
77+
0x8, 0x40, 0x0, 0x0,
78+
0x0, 0x0, 0x0, 0x0,
79+
};
80+
81+
constexpr long double fivehundredandthirtynine = 539.0;
82+
83+
static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, "");
84+
#else
85+
static_assert(round_trip<__int128_t>(34.0L));
86+
#endif
87+
}

clang/test/AST/ByteCode/builtin-bit-cast.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ static_assert(check_round_trip<__int128_t>((__int128_t)34));
7676
static_assert(check_round_trip<__int128_t>((__int128_t)-34));
7777
#endif
7878

79+
static_assert(check_round_trip<double>(17.0));
80+
7981

8082
namespace simple {
8183
constexpr int A = __builtin_bit_cast(int, 10);
@@ -108,7 +110,7 @@ namespace simple {
108110
static_assert(check_round_trip<unsigned>((int)0x12345678));
109111
static_assert(check_round_trip<unsigned>((int)0x87654321));
110112
static_assert(check_round_trip<unsigned>((int)0x0C05FEFE));
111-
// static_assert(round_trip<float>((int)0x0C05FEFE));
113+
static_assert(round_trip<float>((int)0x0C05FEFE));
112114

113115

114116
/// This works in GCC and in the bytecode interpreter, but the current interpreter

0 commit comments

Comments
 (0)