Skip to content

Commit 7fc9c53

Browse files
committed
[clang][bytecode] Implement bitcasts to floating-point values
1 parent 1e19f0f commit 7fc9c53

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-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));

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

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ namespace simple {
108108
static_assert(check_round_trip<unsigned>((int)0x12345678));
109109
static_assert(check_round_trip<unsigned>((int)0x87654321));
110110
static_assert(check_round_trip<unsigned>((int)0x0C05FEFE));
111-
// static_assert(round_trip<float>((int)0x0C05FEFE));
111+
static_assert(round_trip<float>((int)0x0C05FEFE));
112112

113113

114114
/// This works in GCC and in the bytecode interpreter, but the current interpreter
@@ -454,3 +454,57 @@ struct ref_mem {
454454
// both-error@+2 {{constexpr variable 'run_ref_mem' must be initialized by a constant expression}}
455455
// both-note@+1 {{bit_cast from a type with a reference member is not allowed in a constant expression}}
456456
constexpr intptr_t run_ref_mem = __builtin_bit_cast(intptr_t, ref_mem{global_int});
457+
458+
namespace test_long_double {
459+
#ifdef __x86_64
460+
#if 0
461+
constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\
462+
// expected-note{{in call}}
463+
#endif
464+
constexpr long double ld = 3.1425926539;
465+
466+
struct bytes {
467+
unsigned char d[16];
468+
};
469+
470+
// static_assert(round_trip<bytes>(ld), "");
471+
472+
static_assert(round_trip<long double>(10.0L));
473+
474+
#if 0
475+
constexpr bool f(bool read_uninit) {
476+
bytes b = bit_cast<bytes>(ld);
477+
unsigned char ld_bytes[10] = {
478+
0x0, 0x48, 0x9f, 0x49, 0xf0,
479+
0x3c, 0x20, 0xc9, 0x0, 0x40,
480+
};
481+
482+
for (int i = 0; i != 10; ++i)
483+
if (ld_bytes[i] != b.d[i])
484+
return false;
485+
486+
if (read_uninit && b.d[10]) // expected-note{{read of uninitialized object is not allowed in a constant expression}}
487+
return false;
488+
489+
return true;
490+
}
491+
492+
static_assert(f(/*read_uninit=*/false), "");
493+
static_assert(f(/*read_uninit=*/true), ""); // expected-error{{static assertion expression is not an integral constant expression}} \
494+
// expected-note{{in call to 'f(true)'}}
495+
#endif
496+
constexpr bytes ld539 = {
497+
0x0, 0x0, 0x0, 0x0,
498+
0x0, 0x0, 0xc0, 0x86,
499+
0x8, 0x40, 0x0, 0x0,
500+
0x0, 0x0, 0x0, 0x0,
501+
};
502+
503+
constexpr long double fivehundredandthirtynine = 539.0;
504+
505+
static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, "");
506+
507+
#else
508+
static_assert(round_trip<__int128_t>(34.0L));
509+
#endif
510+
}

0 commit comments

Comments
 (0)