Skip to content

Commit c103d57

Browse files
authored
[libc] Fix forward missing BigInt specialization of mask_leading_ones / mask_trailing_ones (llvm#84325)
llvm#84299 broke the arm32 build, this patch fixes it forward.
1 parent 7fc583c commit c103d57

File tree

8 files changed

+123
-34
lines changed

8 files changed

+123
-34
lines changed

libc/src/__support/UInt.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,4 +1056,60 @@ rotr(T value, int rotate) {
10561056

10571057
} // namespace LIBC_NAMESPACE::cpp
10581058

1059+
namespace LIBC_NAMESPACE {
1060+
1061+
// Specialization of mask_trailing_ones ('math_extras.h') for BigInt.
1062+
template <typename T, size_t count>
1063+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, T>
1064+
mask_trailing_ones() {
1065+
static_assert(!T::SIGNED);
1066+
if (count == 0)
1067+
return T();
1068+
constexpr unsigned T_BITS = CHAR_BIT * sizeof(T);
1069+
static_assert(count <= T_BITS && "Invalid bit index");
1070+
using word_type = typename T::word_type;
1071+
T out;
1072+
constexpr int CHUNK_INDEX_CONTAINING_BIT =
1073+
static_cast<int>(count / T::WORD_SIZE);
1074+
int index = 0;
1075+
for (auto &word : out.val) {
1076+
if (index < CHUNK_INDEX_CONTAINING_BIT)
1077+
word = -1;
1078+
else if (index > CHUNK_INDEX_CONTAINING_BIT)
1079+
word = 0;
1080+
else
1081+
word = mask_trailing_ones<word_type, count % T::WORD_SIZE>();
1082+
++index;
1083+
}
1084+
return out;
1085+
}
1086+
1087+
// Specialization of mask_leading_ones ('math_extras.h') for BigInt.
1088+
template <typename T, size_t count>
1089+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_big_int_v<T>, T>
1090+
mask_leading_ones() {
1091+
static_assert(!T::SIGNED);
1092+
if (count == 0)
1093+
return T();
1094+
constexpr unsigned T_BITS = CHAR_BIT * sizeof(T);
1095+
static_assert(count <= T_BITS && "Invalid bit index");
1096+
using word_type = typename T::word_type;
1097+
T out;
1098+
constexpr int CHUNK_INDEX_CONTAINING_BIT =
1099+
static_cast<int>((T::BITS - count - 1ULL) / T::WORD_SIZE);
1100+
int index = 0;
1101+
for (auto &word : out.val) {
1102+
if (index < CHUNK_INDEX_CONTAINING_BIT)
1103+
word = 0;
1104+
else if (index > CHUNK_INDEX_CONTAINING_BIT)
1105+
word = -1;
1106+
else
1107+
word = mask_leading_ones<word_type, count % T::WORD_SIZE>();
1108+
++index;
1109+
}
1110+
return out;
1111+
}
1112+
1113+
} // namespace LIBC_NAMESPACE
1114+
10591115
#endif // LLVM_LIBC_SRC___SUPPORT_UINT_H

libc/src/__support/math_extras.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,18 @@ namespace LIBC_NAMESPACE {
2020
// Create a bitmask with the count right-most bits set to 1, and all other bits
2121
// set to 0. Only unsigned types are allowed.
2222
template <typename T, size_t count>
23-
LIBC_INLINE constexpr T mask_trailing_ones() {
24-
static_assert(cpp::is_unsigned_v<T>);
23+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
24+
mask_trailing_ones() {
2525
constexpr unsigned T_BITS = CHAR_BIT * sizeof(T);
2626
static_assert(count <= T_BITS && "Invalid bit index");
27-
// It's important not to initialize T with -1, since T may be BigInt which
28-
// will take -1 as a uint64_t and only initialize the low 64 bits.
29-
constexpr T ALL_ZEROES(0);
30-
constexpr T ALL_ONES(~ALL_ZEROES); // bitwise NOT performs integer promotion.
31-
return count == 0 ? 0 : (ALL_ONES >> (T_BITS - count));
27+
return count == 0 ? 0 : (T(-1) >> (T_BITS - count));
3228
}
3329

3430
// Create a bitmask with the count left-most bits set to 1, and all other bits
3531
// set to 0. Only unsigned types are allowed.
3632
template <typename T, size_t count>
37-
LIBC_INLINE constexpr T mask_leading_ones() {
33+
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_unsigned_v<T>, T>
34+
mask_leading_ones() {
3835
constexpr T MASK(mask_trailing_ones<T, CHAR_BIT * sizeof(T) - count>());
3936
return T(~MASK); // bitwise NOT performs integer promotion.
4037
}

libc/src/stdio/printf_core/float_dec_converter.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "src/__support/CPP/string_view.h"
1313
#include "src/__support/FPUtil/FPBits.h"
1414
#include "src/__support/FPUtil/rounding_mode.h"
15+
#include "src/__support/UInt.h" // cpp::is_big_int_v
1516
#include "src/__support/float_to_string.h"
1617
#include "src/__support/integer_to_string.h"
1718
#include "src/__support/libc_assert.h"
@@ -33,7 +34,8 @@ using ExponentString =
3334

3435
// Returns true if value is divisible by 2^p.
3536
template <typename T>
36-
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_integral_v<T>, bool>
37+
LIBC_INLINE constexpr cpp::enable_if_t<
38+
cpp::is_integral_v<T> || cpp::is_big_int_v<T>, bool>
3739
multiple_of_power_of_2(T value, uint32_t p) {
3840
return (value & ((T(1) << p) - 1)) == 0;
3941
}
@@ -76,7 +78,8 @@ LIBC_INLINE RoundDirection get_round_direction(int last_digit, bool truncated,
7678
}
7779

7880
template <typename T>
79-
LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_integral_v<T>, bool>
81+
LIBC_INLINE constexpr cpp::enable_if_t<
82+
cpp::is_integral_v<T> || cpp::is_big_int_v<T>, bool>
8083
zero_after_digits(int32_t base_2_exp, int32_t digits_after_point, T mantissa,
8184
const int32_t mant_width) {
8285
const int32_t required_twos = -base_2_exp - digits_after_point - 1;

libc/test/UnitTest/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ add_header_library(
104104
DEPENDS
105105
libc.src.__support.CPP.string
106106
libc.src.__support.CPP.type_traits
107+
libc.src.__support.uint
107108
)
108109

109110
add_unittest_framework_library(

libc/test/UnitTest/StringUtils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111

1212
#include "src/__support/CPP/string.h"
1313
#include "src/__support/CPP/type_traits.h"
14+
#include "src/__support/UInt.h"
1415

1516
namespace LIBC_NAMESPACE {
1617

1718
// Return the first N hex digits of an integer as a string in upper case.
1819
template <typename T>
19-
cpp::enable_if_t<cpp::is_integral_v<T>, cpp::string>
20+
cpp::enable_if_t<cpp::is_integral_v<T> || cpp::is_big_int_v<T>, cpp::string>
2021
int_to_hex(T value, size_t length = sizeof(T) * 2) {
2122
cpp::string s(length, '0');
2223

libc/test/src/__support/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ add_libc_test(
2727
SRCS
2828
math_extras_test.cpp
2929
DEPENDS
30+
libc.src.__support.integer_literals
3031
libc.src.__support.math_extras
32+
libc.src.__support.uint128
3133
)
3234

3335
add_libc_test(

libc/test/src/__support/math_extras_test.cpp

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,59 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "src/__support/UInt128.h" // UInt128
10+
#include "src/__support/integer_literals.h"
911
#include "src/__support/math_extras.h"
1012
#include "test/UnitTest/Test.h"
1113

1214
namespace LIBC_NAMESPACE {
1315

1416
TEST(LlvmLibcBlockMathExtrasTest, mask_trailing_ones) {
15-
EXPECT_EQ(uint8_t(0), (mask_leading_ones<uint8_t, 0>()));
16-
EXPECT_EQ(uint8_t(0), (mask_trailing_ones<uint8_t, 0>()));
17-
EXPECT_EQ(uint16_t(0), (mask_leading_ones<uint16_t, 0>()));
18-
EXPECT_EQ(uint16_t(0), (mask_trailing_ones<uint16_t, 0>()));
19-
EXPECT_EQ(uint32_t(0), (mask_leading_ones<uint32_t, 0>()));
20-
EXPECT_EQ(uint32_t(0), (mask_trailing_ones<uint32_t, 0>()));
21-
EXPECT_EQ(uint64_t(0), (mask_leading_ones<uint64_t, 0>()));
22-
EXPECT_EQ(uint64_t(0), (mask_trailing_ones<uint64_t, 0>()));
23-
24-
EXPECT_EQ(uint32_t(0x00000003), (mask_trailing_ones<uint32_t, 2>()));
25-
EXPECT_EQ(uint32_t(0xC0000000), (mask_leading_ones<uint32_t, 2>()));
26-
27-
EXPECT_EQ(uint32_t(0x000007FF), (mask_trailing_ones<uint32_t, 11>()));
28-
EXPECT_EQ(uint32_t(0xFFE00000), (mask_leading_ones<uint32_t, 11>()));
29-
30-
EXPECT_EQ(uint32_t(0xFFFFFFFF), (mask_trailing_ones<uint32_t, 32>()));
31-
EXPECT_EQ(uint32_t(0xFFFFFFFF), (mask_leading_ones<uint32_t, 32>()));
32-
EXPECT_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), (mask_trailing_ones<uint64_t, 64>()));
33-
EXPECT_EQ(uint64_t(0xFFFFFFFFFFFFFFFF), (mask_leading_ones<uint64_t, 64>()));
34-
35-
EXPECT_EQ(uint64_t(0x0000FFFFFFFFFFFF), (mask_trailing_ones<uint64_t, 48>()));
36-
EXPECT_EQ(uint64_t(0xFFFFFFFFFFFF0000), (mask_leading_ones<uint64_t, 48>()));
17+
EXPECT_EQ(0_u8, (mask_leading_ones<uint8_t, 0>()));
18+
EXPECT_EQ(0_u8, (mask_trailing_ones<uint8_t, 0>()));
19+
EXPECT_EQ(0_u16, (mask_leading_ones<uint16_t, 0>()));
20+
EXPECT_EQ(0_u16, (mask_trailing_ones<uint16_t, 0>()));
21+
EXPECT_EQ(0_u32, (mask_leading_ones<uint32_t, 0>()));
22+
EXPECT_EQ(0_u32, (mask_trailing_ones<uint32_t, 0>()));
23+
EXPECT_EQ(0_u64, (mask_leading_ones<uint64_t, 0>()));
24+
EXPECT_EQ(0_u64, (mask_trailing_ones<uint64_t, 0>()));
25+
26+
EXPECT_EQ(0x00000003_u32, (mask_trailing_ones<uint32_t, 2>()));
27+
EXPECT_EQ(0xC0000000_u32, (mask_leading_ones<uint32_t, 2>()));
28+
29+
EXPECT_EQ(0x000007FF_u32, (mask_trailing_ones<uint32_t, 11>()));
30+
EXPECT_EQ(0xFFE00000_u32, (mask_leading_ones<uint32_t, 11>()));
31+
32+
EXPECT_EQ(0xFFFFFFFF_u32, (mask_trailing_ones<uint32_t, 32>()));
33+
EXPECT_EQ(0xFFFFFFFF_u32, (mask_leading_ones<uint32_t, 32>()));
34+
EXPECT_EQ(0xFFFFFFFFFFFFFFFF_u64, (mask_trailing_ones<uint64_t, 64>()));
35+
EXPECT_EQ(0xFFFFFFFFFFFFFFFF_u64, (mask_leading_ones<uint64_t, 64>()));
36+
37+
EXPECT_EQ(0x0000FFFFFFFFFFFF_u64, (mask_trailing_ones<uint64_t, 48>()));
38+
EXPECT_EQ(0xFFFFFFFFFFFF0000_u64, (mask_leading_ones<uint64_t, 48>()));
39+
40+
EXPECT_EQ(0_u128, (mask_trailing_ones<UInt128, 0>()));
41+
EXPECT_EQ(0_u128, (mask_leading_ones<UInt128, 0>()));
42+
43+
EXPECT_EQ(0x00000000000000007FFFFFFFFFFFFFFF_u128,
44+
(mask_trailing_ones<UInt128, 63>()));
45+
EXPECT_EQ(0xFFFFFFFFFFFFFFFE0000000000000000_u128,
46+
(mask_leading_ones<UInt128, 63>()));
47+
48+
EXPECT_EQ(0x0000000000000000FFFFFFFFFFFFFFFF_u128,
49+
(mask_trailing_ones<UInt128, 64>()));
50+
EXPECT_EQ(0xFFFFFFFFFFFFFFFF0000000000000000_u128,
51+
(mask_leading_ones<UInt128, 64>()));
52+
53+
EXPECT_EQ(0x0000000000000001FFFFFFFFFFFFFFFF_u128,
54+
(mask_trailing_ones<UInt128, 65>()));
55+
EXPECT_EQ(0xFFFFFFFFFFFFFFFF8000000000000000_u128,
56+
(mask_leading_ones<UInt128, 65>()));
57+
58+
EXPECT_EQ(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_u128,
59+
(mask_trailing_ones<UInt128, 128>()));
60+
EXPECT_EQ(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF_u128,
61+
(mask_leading_ones<UInt128, 128>()));
3762
}
3863

3964
} // namespace LIBC_NAMESPACE

utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ licenses(["notice"])
1313
libc_test(
1414
name = "math_extras_test",
1515
srcs = ["math_extras_test.cpp"],
16-
deps = ["//libc:__support_math_extras"],
16+
deps = [
17+
"//libc:__support_integer_literals",
18+
"//libc:__support_math_extras",
19+
"//libc:__support_uint128",
20+
],
1721
)
1822

1923
# This test is currently disabled because of an issue in

0 commit comments

Comments
 (0)