mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
AK: Ensure unions with bitfield structs actually have correct sizes
The fun pattern of `union { struct { u32 a : 1; u64 b : 7; }; u8 x; }` produces complete garbage on windows, this commit fixes the two instances of those that exist in AK. This commit also makes sure that the generated unions have the correct size (whereas FloatExtractor<f32> previously did not!) by adding some nice static_asserts.
This commit is contained in:
parent
4676b288a2
commit
7976e1852c
Notes:
sideshowbarker
2024-07-16 20:05:14 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/7976e1852c Pull-request: https://github.com/SerenityOS/serenity/pull/21722 Reviewed-by: https://github.com/DanShaders Reviewed-by: https://github.com/skyrising
2 changed files with 24 additions and 14 deletions
|
@ -13,7 +13,7 @@ VALIDATE_IS_X86();
|
|||
|
||||
namespace AK {
|
||||
|
||||
enum class RoundingMode : u8 {
|
||||
enum class RoundingMode : u16 {
|
||||
NEAREST = 0b00,
|
||||
DOWN = 0b01,
|
||||
UP = 0b10,
|
||||
|
|
|
@ -22,16 +22,16 @@ union FloatExtractor<f128> {
|
|||
static constexpr int exponent_bias = 16383;
|
||||
static constexpr int exponent_bits = 15;
|
||||
static constexpr unsigned exponent_max = 32767;
|
||||
struct {
|
||||
struct [[gnu::packed]] {
|
||||
unsigned __int128 mantissa : 112;
|
||||
unsigned exponent : 15;
|
||||
unsigned sign : 1;
|
||||
unsigned __int128 exponent : 15;
|
||||
unsigned __int128 sign : 1;
|
||||
};
|
||||
f128 d;
|
||||
};
|
||||
// Validate that f128 and the FloatExtractor union are 128 bits.
|
||||
static_assert(sizeof(f128) == 16);
|
||||
static_assert(sizeof(FloatExtractor<f128>) == 16);
|
||||
static_assert(AssertSize<f128, 16>());
|
||||
static_assert(AssertSize<FloatExtractor<f128>, sizeof(f128)>());
|
||||
#endif
|
||||
|
||||
#ifdef AK_HAS_FLOAT_80
|
||||
|
@ -42,13 +42,14 @@ union FloatExtractor<f80> {
|
|||
static constexpr int exponent_bias = 16383;
|
||||
static constexpr int exponent_bits = 15;
|
||||
static constexpr unsigned exponent_max = 32767;
|
||||
struct {
|
||||
struct [[gnu::packed]] {
|
||||
unsigned long long mantissa;
|
||||
unsigned exponent : 15;
|
||||
unsigned sign : 1;
|
||||
unsigned long long exponent : 15;
|
||||
unsigned long long sign : 1;
|
||||
};
|
||||
f80 d;
|
||||
};
|
||||
static_assert(AssertSize<FloatExtractor<f80>, sizeof(f80)>());
|
||||
#endif
|
||||
|
||||
template<>
|
||||
|
@ -58,13 +59,21 @@ union FloatExtractor<f64> {
|
|||
static constexpr int exponent_bias = 1023;
|
||||
static constexpr int exponent_bits = 11;
|
||||
static constexpr unsigned exponent_max = 2047;
|
||||
struct {
|
||||
struct [[gnu::packed]] {
|
||||
// FIXME: These types have to all be the same, otherwise this struct
|
||||
// goes from being a bitfield describing the layout of an f64
|
||||
// into being a multibyte mess on windows.
|
||||
// Technically, '-mno-ms-bitfields' is supposed to disable this
|
||||
// very intuitive and portable behaviour on windows, but it doesn't
|
||||
// work with the msvc ABI.
|
||||
// See <https://github.com/llvm/llvm-project/issues/24757>
|
||||
unsigned long long mantissa : 52;
|
||||
unsigned exponent : 11;
|
||||
unsigned sign : 1;
|
||||
unsigned long long exponent : 11;
|
||||
unsigned long long sign : 1;
|
||||
};
|
||||
f64 d;
|
||||
};
|
||||
static_assert(AssertSize<FloatExtractor<f64>, sizeof(f64)>());
|
||||
|
||||
template<>
|
||||
union FloatExtractor<f32> {
|
||||
|
@ -73,13 +82,14 @@ union FloatExtractor<f32> {
|
|||
static constexpr int exponent_bias = 127;
|
||||
static constexpr int exponent_bits = 8;
|
||||
static constexpr unsigned exponent_max = 255;
|
||||
struct {
|
||||
unsigned long long mantissa : 23;
|
||||
struct [[gnu::packed]] {
|
||||
unsigned mantissa : 23;
|
||||
unsigned exponent : 8;
|
||||
unsigned sign : 1;
|
||||
};
|
||||
f32 d;
|
||||
};
|
||||
static_assert(AssertSize<FloatExtractor<f32>, sizeof(f32)>());
|
||||
|
||||
template<size_t S, size_t E, size_t M>
|
||||
requires(S <= 1 && E >= 1 && M >= 1 && (S + E + M) <= 64) class FloatingPointBits final {
|
||||
|
|
Loading…
Reference in a new issue