Skip to content

Commit

Permalink
[libc] Fix a bug in fx_bits.h due to integer promotion of bitwise ops. (
Browse files Browse the repository at this point in the history
  • Loading branch information
lntue committed Mar 2, 2024
1 parent 06ac828 commit 73dfc7b
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 15 deletions.
2 changes: 1 addition & 1 deletion libc/src/__support/fixed_point/fx_bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ bit_not(T x) {
using BitType = typename FXRep<T>::StorageType;
BitType x_bit = cpp::bit_cast<BitType>(x);
// For some reason, bit_cast cannot deduce BitType from the input.
return cpp::bit_cast<T, BitType>(~x_bit);
return cpp::bit_cast<T, BitType>(static_cast<BitType>(~x_bit));
}

template <typename T> LIBC_INLINE constexpr T abs(T x) {
Expand Down
77 changes: 63 additions & 14 deletions libc/test/src/__support/fixed_point/fx_bits_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,22 @@ using LIBC_NAMESPACE::operator""_u16;
using LIBC_NAMESPACE::operator""_u32;
using LIBC_NAMESPACE::operator""_u64;

class LlvmLibcFxBitsTest : public LIBC_NAMESPACE::testing::Test {
public:
template <typename T> void testBitwiseOps() {
EXPECT_EQ(LIBC_NAMESPACE::fixed_point::bit_and(T(0.75), T(0.375)), T(0.25));
EXPECT_EQ(LIBC_NAMESPACE::fixed_point::bit_or(T(0.75), T(0.375)), T(0.875));
using StorageType = typename FXRep<T>::StorageType;
StorageType a = LIBC_NAMESPACE::cpp::bit_cast<StorageType>(T(0.75));
a = ~a;
EXPECT_EQ(LIBC_NAMESPACE::fixed_point::bit_not(T(0.75)),
FXBits<T>(a).get_val());
}
};

// -------------------------------- SHORT TESTS --------------------------------

TEST(LlvmLibcFxBitsTest, FXBits_UnsignedShortFract) {
TEST_F(LlvmLibcFxBitsTest, FXBits_UnsignedShortFract) {
auto bits_var = FXBits<unsigned short fract>(0b00000000_u8);

EXPECT_EQ(bits_var.get_sign(), false);
Expand Down Expand Up @@ -51,9 +64,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_UnsignedShortFract) {
EXPECT_EQ(bits_var.get_sign(), false);
EXPECT_EQ(bits_var.get_integral(), 0x00_u8);
EXPECT_EQ(bits_var.get_fraction(), 0xcd_u8);

// Bitwise ops
testBitwiseOps<unsigned short fract>();
}

TEST(LlvmLibcFxBitsTest, FXBits_UnsignedShortAccum) {
TEST_F(LlvmLibcFxBitsTest, FXBits_UnsignedShortAccum) {
auto bits_var = FXBits<unsigned short accum>(0b00000000'00000000_u16);

EXPECT_EQ(bits_var.get_sign(), false);
Expand All @@ -77,9 +93,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_UnsignedShortAccum) {
EXPECT_EQ(bits_var.get_sign(), false);
EXPECT_EQ(bits_var.get_integral(), 0x00cd_u16);
EXPECT_EQ(bits_var.get_fraction(), 0x00fe_u16);

// Bitwise ops
testBitwiseOps<unsigned short accum>();
}

TEST(LlvmLibcFxBitsTest, FXBits_ShortFract) {
TEST_F(LlvmLibcFxBitsTest, FXBits_ShortFract) {
auto bits_var = FXBits<short fract>(0b0'0000000_u8);

EXPECT_EQ(bits_var.get_sign(), false);
Expand All @@ -103,9 +122,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_ShortFract) {
EXPECT_EQ(bits_var.get_sign(), true);
EXPECT_EQ(bits_var.get_integral(), 0x00_u8);
EXPECT_EQ(bits_var.get_fraction(), 0x4d_u8);

// Bitwise ops
testBitwiseOps<short fract>();
}

TEST(LlvmLibcFxBitsTest, FXBits_ShortAccum) {
TEST_F(LlvmLibcFxBitsTest, FXBits_ShortAccum) {
auto bits_var = FXBits<short accum>(0b0'00000000'0000000_u16);

EXPECT_EQ(bits_var.get_sign(), false);
Expand All @@ -129,9 +151,14 @@ TEST(LlvmLibcFxBitsTest, FXBits_ShortAccum) {
EXPECT_EQ(bits_var.get_sign(), true);
EXPECT_EQ(bits_var.get_integral(), 0x00cd_u16);
EXPECT_EQ(bits_var.get_fraction(), 0x007e_u16);

// Bitwise ops
testBitwiseOps<short accum>();
}

TEST(LlvmLibcFxBitsTest, FXBits_UnsignedFract) {
// -------------------------------- NORMAL TESTS -------------------------------

TEST_F(LlvmLibcFxBitsTest, FXBits_UnsignedFract) {
auto bits_var = FXBits<unsigned fract>(0b0000000000000000_u16);

EXPECT_EQ(bits_var.get_sign(), false);
Expand All @@ -155,11 +182,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_UnsignedFract) {
EXPECT_EQ(bits_var.get_sign(), false);
EXPECT_EQ(bits_var.get_integral(), 0x0000_u16);
EXPECT_EQ(bits_var.get_fraction(), 0xef12_u16);
}

// -------------------------------- NORMAL TESTS -------------------------------
// Bitwise ops
testBitwiseOps<unsigned fract>();
}

TEST(LlvmLibcFxBitsTest, FXBits_UnsignedAccum) {
TEST_F(LlvmLibcFxBitsTest, FXBits_UnsignedAccum) {
auto bits_var =
FXBits<unsigned accum>(0b0000000000000000'0000000000000000_u32);

Expand All @@ -184,9 +212,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_UnsignedAccum) {
EXPECT_EQ(bits_var.get_sign(), false);
EXPECT_EQ(bits_var.get_integral(), 0x0000abcd_u32);
EXPECT_EQ(bits_var.get_fraction(), 0x0000ef12_u32);

// Bitwise ops
testBitwiseOps<unsigned accum>();
}

TEST(LlvmLibcFxBitsTest, FXBits_Fract) {
TEST_F(LlvmLibcFxBitsTest, FXBits_Fract) {
auto bits_var = FXBits<fract>(0b0'000000000000000_u16);

EXPECT_EQ(bits_var.get_sign(), false);
Expand All @@ -210,9 +241,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_Fract) {
EXPECT_EQ(bits_var.get_sign(), true);
EXPECT_EQ(bits_var.get_integral(), 0x0000_u16);
EXPECT_EQ(bits_var.get_fraction(), 0x6f12_u16);

// Bitwise ops
testBitwiseOps<fract>();
}

TEST(LlvmLibcFxBitsTest, FXBits_Accum) {
TEST_F(LlvmLibcFxBitsTest, FXBits_Accum) {
auto bits_var = FXBits<accum>(0b0'0000000000000000'000000000000000_u32);

EXPECT_EQ(bits_var.get_sign(), false);
Expand All @@ -236,11 +270,14 @@ TEST(LlvmLibcFxBitsTest, FXBits_Accum) {
EXPECT_EQ(bits_var.get_sign(), true);
EXPECT_EQ(bits_var.get_integral(), 0x0000abcd_u32);
EXPECT_EQ(bits_var.get_fraction(), 0x00006f12_u32);

// Bitwise ops
testBitwiseOps<accum>();
}

// --------------------------------- LONG TESTS --------------------------------

TEST(LlvmLibcFxBitsTest, FXBits_UnsignedLongFract) {
TEST_F(LlvmLibcFxBitsTest, FXBits_UnsignedLongFract) {
auto bits_var =
FXBits<unsigned long fract>(0b00000000000000000000000000000000_u32);

Expand All @@ -265,9 +302,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_UnsignedLongFract) {
EXPECT_EQ(bits_var.get_sign(), false);
EXPECT_EQ(bits_var.get_integral(), 0x00000000_u32);
EXPECT_EQ(bits_var.get_fraction(), 0xfedcba98_u32);

// Bitwise ops
testBitwiseOps<unsigned long fract>();
}

TEST(LlvmLibcFxBitsTest, FXBits_UnsignedLongAccum) {
TEST_F(LlvmLibcFxBitsTest, FXBits_UnsignedLongAccum) {
auto bits_var = FXBits<unsigned long accum>(
0b00000000000000000000000000000000'00000000000000000000000000000000_u64);

Expand All @@ -292,9 +332,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_UnsignedLongAccum) {
EXPECT_EQ(bits_var.get_sign(), false);
EXPECT_EQ(bits_var.get_integral(), 0x00000000abcdef12_u64);
EXPECT_EQ(bits_var.get_fraction(), 0x00000000fedcba98_u64);

// Bitwise ops
testBitwiseOps<unsigned long accum>();
}

TEST(LlvmLibcFxBitsTest, FXBits_LongFract) {
TEST_F(LlvmLibcFxBitsTest, FXBits_LongFract) {
auto bits_var = FXBits<long fract>(0b0'0000000000000000000000000000000_u32);

EXPECT_EQ(bits_var.get_sign(), false);
Expand All @@ -318,9 +361,12 @@ TEST(LlvmLibcFxBitsTest, FXBits_LongFract) {
EXPECT_EQ(bits_var.get_sign(), true);
EXPECT_EQ(bits_var.get_integral(), 0x00000000_u32);
EXPECT_EQ(bits_var.get_fraction(), 0x7edcba98_u32);

// Bitwise ops
testBitwiseOps<long fract>();
}

TEST(LlvmLibcFxBitsTest, FXBits_LongAccum) {
TEST_F(LlvmLibcFxBitsTest, FXBits_LongAccum) {
auto bits_var = FXBits<long accum>(
0b0'00000000000000000000000000000000'0000000000000000000000000000000_u64);

Expand All @@ -345,4 +391,7 @@ TEST(LlvmLibcFxBitsTest, FXBits_LongAccum) {
EXPECT_EQ(bits_var.get_sign(), true);
EXPECT_EQ(bits_var.get_integral(), 0x00000000abcdef12_u64);
EXPECT_EQ(bits_var.get_fraction(), 0x000000007edcba98_u64);

// Bitwise ops
testBitwiseOps<long accum>();
}

0 comments on commit 73dfc7b

Please sign in to comment.