[libc-commits] [libc] 300f8da - [libc] Add Uint128 type as a fallback when __uint128_t is not available.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Fri Jun 24 09:03:56 PDT 2022


Author: Siva Chandra Reddy
Date: 2022-06-24T16:03:35Z
New Revision: 300f8da8e8682cbd881f1874801f59ed804e3560

URL: https://github.com/llvm/llvm-project/commit/300f8da8e8682cbd881f1874801f59ed804e3560
DIFF: https://github.com/llvm/llvm-project/commit/300f8da8e8682cbd881f1874801f59ed804e3560.diff

LOG: [libc] Add Uint128 type as a fallback when __uint128_t is not available.

Also, the unused specializations of __int128_t have been removed.

Differential Revision: https://reviews.llvm.org/D128304

Added: 
    libc/src/__support/CPP/UInt128.h

Modified: 
    libc/src/__support/CMakeLists.txt
    libc/src/__support/CPP/CMakeLists.txt
    libc/src/__support/CPP/Limits.h
    libc/src/__support/CPP/TypeTraits.h
    libc/src/__support/CPP/UInt.h
    libc/src/__support/FPUtil/CMakeLists.txt
    libc/src/__support/FPUtil/FloatProperties.h
    libc/src/__support/FPUtil/Hypot.h
    libc/src/__support/FPUtil/generic/CMakeLists.txt
    libc/src/__support/FPUtil/generic/FMA.h
    libc/src/__support/FPUtil/generic/sqrt.h
    libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
    libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
    libc/src/__support/str_to_float.h
    libc/test/src/__support/CMakeLists.txt
    libc/test/src/__support/CPP/CMakeLists.txt
    libc/test/src/__support/CPP/limits_test.cpp
    libc/test/src/__support/high_precision_decimal_test.cpp
    libc/test/src/__support/str_to_float_test.cpp
    libc/test/src/__support/uint128_test.cpp
    libc/test/src/stdlib/CMakeLists.txt
    libc/test/src/stdlib/strtold_test.cpp
    libc/utils/UnitTest/CMakeLists.txt
    libc/utils/UnitTest/LibcTest.cpp
    libc/utils/UnitTest/PrintfMatcher.cpp
    utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt
index 24c6372187234..4812f27a9819e 100644
--- a/libc/src/__support/CMakeLists.txt
+++ b/libc/src/__support/CMakeLists.txt
@@ -45,6 +45,7 @@ add_header_library(
     libc.include.errno
     libc.src.errno.errno
     libc.src.__support.CPP.limits
+    libc.src.__support.CPP.uint128
     libc.src.__support.FPUtil.fputil
 )
 

diff  --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 294a46b1e9a74..6920a0c2df926 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -4,6 +4,22 @@ add_header_library(
     Array.h
 )
 
+add_header_library(
+  uint
+  HDRS
+    UInt.h
+  DEPENDS
+    .array
+)
+
+add_header_library(
+  uint128
+  HDRS
+    UInt128.h
+  DEPENDS
+    .uint
+)
+
 add_header_library(
   array_ref
   HDRS
@@ -32,6 +48,8 @@ add_header_library(
   limits
   HDRS
     Limits.h
+  DEPENDS
+    .uint
 )
 
 add_header_library(
@@ -44,6 +62,8 @@ add_header_library(
   type_traits
   HDRS
     TypeTraits.h
+  DEPENDS
+    .uint
 )
 
 add_header_library(
@@ -77,11 +97,3 @@ add_header_library(
   HDRS
     error.h
 )
-
-add_header_library(
-  uint
-  HDRS
-    UInt.h
-  DEPENDS
-    libc.src.__support.CPP.array
-)

diff  --git a/libc/src/__support/CPP/Limits.h b/libc/src/__support/CPP/Limits.h
index 06104e99bbce9..8f27d075eae2a 100644
--- a/libc/src/__support/CPP/Limits.h
+++ b/libc/src/__support/CPP/Limits.h
@@ -9,6 +9,8 @@
 #ifndef LLVM_LIBC_SRC_SUPPORT_CPP_LIMITS_H
 #define LLVM_LIBC_SRC_SUPPORT_CPP_LIMITS_H
 
+#include "UInt.h"
+
 #include <limits.h>
 
 namespace __llvm_libc {
@@ -72,18 +74,26 @@ template <> class NumericLimits<unsigned char> {
   static constexpr unsigned char max() { return UCHAR_MAX; }
   static constexpr unsigned char min() { return 0; }
 };
+// This specialization enables two things:
+// 1. On platforms where UInt128 resolves to UInt<128>, this specialization
+//    provides limits of UInt128.
+// 2. On platforms where UInt128 resolves to __uint128_t, this specialization
+//    allows us to unittest UInt<128>.
+template <> class NumericLimits<UInt<128>> {
+public:
+  static constexpr UInt<128> max() { return ~UInt<128>(0); }
+  static constexpr UInt<128> min() { return 0; }
+};
 #ifdef __SIZEOF_INT128__
+// On platform where UInt128 resolves to __uint128_t, this specialization
+// provides the limits of UInt128.
 template <> class NumericLimits<__uint128_t> {
 public:
   static constexpr __uint128_t max() { return ~__uint128_t(0); }
   static constexpr __uint128_t min() { return 0; }
 };
-template <> class NumericLimits<__int128_t> {
-public:
-  static constexpr __int128_t max() { return ~__uint128_t(0) >> 1; }
-  static constexpr __int128_t min() { return __int128_t(1) << 127; }
-};
 #endif
+
 } // namespace cpp
 } // namespace __llvm_libc
 

diff  --git a/libc/src/__support/CPP/TypeTraits.h b/libc/src/__support/CPP/TypeTraits.h
index 61f55ff373e35..fba5f04fc73c7 100644
--- a/libc/src/__support/CPP/TypeTraits.h
+++ b/libc/src/__support/CPP/TypeTraits.h
@@ -56,9 +56,13 @@ template <typename Type> struct IsIntegral {
       IsSameV<unsigned int, TypeNoCV> || IsSameV<long, TypeNoCV> ||
       IsSameV<unsigned long, TypeNoCV> || IsSameV<long long, TypeNoCV> ||
       IsSameV<unsigned long long, TypeNoCV> || IsSameV<bool, TypeNoCV> ||
-      IsSameV<UInt<128>, TypeNoCV>
+      // We need to include UInt<128> and __uint128_t when available because
+      // we want to unittest UInt<128>. If we include only UInt128, then on
+      // platform where it resolves to __uint128_t, we cannot unittest
+      // UInt<128>.
+      IsSameV<__llvm_libc::cpp::UInt<128>, TypeNoCV>
 #ifdef __SIZEOF_INT128__
-      || IsSameV<__uint128_t, TypeNoCV> || IsSameV<__int128_t, TypeNoCV>
+      || IsSameV<__uint128_t, TypeNoCV>
 #endif
       ;
 };

diff  --git a/libc/src/__support/CPP/UInt.h b/libc/src/__support/CPP/UInt.h
index 8e002bdae0de0..66aa1aeccc679 100644
--- a/libc/src/__support/CPP/UInt.h
+++ b/libc/src/__support/CPP/UInt.h
@@ -183,6 +183,11 @@ template <size_t Bits> class UInt {
     return result;
   }
 
+  constexpr UInt<Bits> &operator<<=(size_t s) {
+    shift_left(s);
+    return *this;
+  }
+
   constexpr void shift_right(size_t s) {
     const size_t drop = s / 64;  // Number of words to drop
     const size_t shift = s % 64; // Bit shift in the remaining words.
@@ -208,6 +213,11 @@ template <size_t Bits> class UInt {
     return result;
   }
 
+  constexpr UInt<Bits> &operator>>=(size_t s) {
+    shift_right(s);
+    return *this;
+  }
+
   constexpr UInt<Bits> operator&(const UInt<Bits> &other) const {
     UInt<Bits> result;
     for (size_t i = 0; i < WordCount; ++i)
@@ -229,6 +239,13 @@ template <size_t Bits> class UInt {
     return result;
   }
 
+  constexpr UInt<Bits> operator~() const {
+    UInt<Bits> result;
+    for (size_t i = 0; i < WordCount; ++i)
+      result.val[i] = ~val[i];
+    return result;
+  }
+
   constexpr bool operator==(const UInt<Bits> &other) const {
     for (size_t i = 0; i < WordCount; ++i) {
       if (val[i] != other.val[i])
@@ -345,10 +362,4 @@ constexpr UInt<128> UInt<128>::operator*(const UInt<128> &other) const {
 } // namespace cpp
 } // namespace __llvm_libc
 
-/* TODO: determine the best way to support uint128 using this class.
-#if !defined(__SIZEOF_INT128__)
-using __uint128_t = __llvm_libc::internal::UInt<128>;
-#endif // uint128 is not defined, define it with this class.
-*/
-
 #endif // LLVM_LIBC_UTILS_CPP_UINT_H

diff  --git a/libc/src/__support/CPP/UInt128.h b/libc/src/__support/CPP/UInt128.h
new file mode 100644
index 0000000000000..e09271a415b6f
--- /dev/null
+++ b/libc/src/__support/CPP/UInt128.h
@@ -0,0 +1,20 @@
+//===-- A 128 bit unsigned int type -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_UINT128_H
+#define LLVM_LIBC_SRC_SUPPORT_CPP_UINT128_H
+
+#include "UInt.h"
+
+#if !defined(__SIZEOF_INT128__)
+using UInt128 = __llvm_libc::internal::UInt<128>;
+#else
+using UInt128 = __uint128_t;
+#endif
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CPP_UINT128_H

diff  --git a/libc/src/__support/FPUtil/CMakeLists.txt b/libc/src/__support/FPUtil/CMakeLists.txt
index fbde58ba78ae5..12f39d3087049 100644
--- a/libc/src/__support/FPUtil/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/CMakeLists.txt
@@ -12,15 +12,15 @@ add_header_library(
     NearestIntegerOperations.h
     NormalFloat.h
     PlatformDefs.h
-    UInt.h
     builtin_wrappers.h
   DEPENDS
     libc.include.math
     libc.include.errno
     libc.include.fenv
     libc.src.__support.common
-    libc.src.__support.CPP.type_traits
     libc.src.__support.CPP.bit
+    libc.src.__support.CPP.type_traits
+    libc.src.__support.CPP.uint128
     libc.src.errno.errno
 )
 

diff  --git a/libc/src/__support/FPUtil/FloatProperties.h b/libc/src/__support/FPUtil/FloatProperties.h
index cbef3908220cd..6fb96a5bd3dc8 100644
--- a/libc/src/__support/FPUtil/FloatProperties.h
+++ b/libc/src/__support/FPUtil/FloatProperties.h
@@ -10,6 +10,9 @@
 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_FLOAT_PROPERTIES_H
 
 #include "PlatformDefs.h"
+
+#include "src/__support/CPP/UInt128.h"
+
 #include <stdint.h>
 
 namespace __llvm_libc {
@@ -104,7 +107,7 @@ template <> struct FloatProperties<long double> {
 // Properties for numbers represented in 80 bits long double on non-Windows x86
 // platforms.
 template <> struct FloatProperties<long double> {
-  typedef __uint128_t BitsType;
+  typedef UInt128 BitsType;
   static_assert(sizeof(BitsType) == sizeof(long double),
                 "Unexpected size of 'long double' type.");
 
@@ -140,7 +143,7 @@ template <> struct FloatProperties<long double> {
 // Properties for numbers represented in 128 bits long double on non x86
 // platform.
 template <> struct FloatProperties<long double> {
-  typedef __uint128_t BitsType;
+  typedef UInt128 BitsType;
   static_assert(sizeof(BitsType) == sizeof(long double),
                 "Unexpected size of 'long double' type.");
 

diff  --git a/libc/src/__support/FPUtil/Hypot.h b/libc/src/__support/FPUtil/Hypot.h
index dc1056b22289c..0e3cefeeca576 100644
--- a/libc/src/__support/FPUtil/Hypot.h
+++ b/libc/src/__support/FPUtil/Hypot.h
@@ -15,6 +15,7 @@
 #include "builtin_wrappers.h"
 #include "src/__support/CPP/Bit.h"
 #include "src/__support/CPP/TypeTraits.h"
+#include "src/__support/CPP/UInt128.h"
 
 namespace __llvm_libc {
 namespace fputil {
@@ -38,7 +39,9 @@ template <> struct DoubleLength<uint16_t> { using Type = uint32_t; };
 
 template <> struct DoubleLength<uint32_t> { using Type = uint64_t; };
 
-template <> struct DoubleLength<uint64_t> { using Type = __uint128_t; };
+template <> struct DoubleLength<uint64_t> {
+  using Type = UInt128;
+};
 
 // Correctly rounded IEEE 754 HYPOT(x, y) with round to nearest, ties to even.
 //

diff  --git a/libc/src/__support/FPUtil/generic/CMakeLists.txt b/libc/src/__support/FPUtil/generic/CMakeLists.txt
index a755e7670ce68..227bd601ddb39 100644
--- a/libc/src/__support/FPUtil/generic/CMakeLists.txt
+++ b/libc/src/__support/FPUtil/generic/CMakeLists.txt
@@ -3,10 +3,14 @@ add_header_library(
   HDRS
     sqrt.h
     sqrt_80_bit_long_double.h
+  DEPENDS
+    libc.src.__support.CPP.uint128
 )
 
 add_header_library(
   fma
   HDRS
     FMA.h
+  DEPENDS
+    libc.src.__support.CPP.uint128
 )

diff  --git a/libc/src/__support/FPUtil/generic/FMA.h b/libc/src/__support/FPUtil/generic/FMA.h
index 3dad2adf10df9..c487cca0ce115 100644
--- a/libc/src/__support/FPUtil/generic/FMA.h
+++ b/libc/src/__support/FPUtil/generic/FMA.h
@@ -11,6 +11,7 @@
 
 #include "src/__support/CPP/Bit.h"
 #include "src/__support/CPP/TypeTraits.h"
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/FloatProperties.h"
@@ -78,12 +79,12 @@ namespace internal {
 
 // Extract the sticky bits and shift the `mantissa` to the right by
 // `shift_length`.
-static inline bool shift_mantissa(int shift_length, __uint128_t &mant) {
+static inline bool shift_mantissa(int shift_length, UInt128 &mant) {
   if (shift_length >= 128) {
     mant = 0;
     return true; // prod_mant is non-zero.
   }
-  __uint128_t mask = (__uint128_t(1) << shift_length) - 1;
+  UInt128 mask = (UInt128(1) << shift_length) - 1;
   bool sticky_bits = (mant & mask) != 0;
   mant >>= shift_length;
   return sticky_bits;
@@ -131,9 +132,9 @@ template <> inline double fma<double>(double x, double y, double z) {
     return x * y + z;
 
   // Extract mantissa and append hidden leading bits.
-  __uint128_t x_mant = x_bits.get_mantissa() | FPBits::MIN_NORMAL;
-  __uint128_t y_mant = y_bits.get_mantissa() | FPBits::MIN_NORMAL;
-  __uint128_t z_mant = z_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 x_mant = x_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 y_mant = y_bits.get_mantissa() | FPBits::MIN_NORMAL;
+  UInt128 z_mant = z_bits.get_mantissa() | FPBits::MIN_NORMAL;
 
   // If the exponent of the product x*y > the exponent of z, then no extra
   // precision beside the entire product x*y is needed.  On the other hand, when
@@ -154,7 +155,7 @@ template <> inline double fma<double>(double x, double y, double z) {
   // the original mantissa as high part when constructing 128-bit z_mant. So the
   // mantissa of prod will be left-shifted by 64 - 54 = 10 initially.
 
-  __uint128_t prod_mant = x_mant * y_mant << 10;
+  UInt128 prod_mant = x_mant * y_mant << 10;
   int prod_lsb_exp =
       x_exp + y_exp -
       (FPBits::EXPONENT_BIAS + 2 * MantissaWidth<double>::VALUE + 10);

diff  --git a/libc/src/__support/FPUtil/generic/sqrt.h b/libc/src/__support/FPUtil/generic/sqrt.h
index cd3a5ec48c82c..6bf1bfc600f13 100644
--- a/libc/src/__support/FPUtil/generic/sqrt.h
+++ b/libc/src/__support/FPUtil/generic/sqrt.h
@@ -12,6 +12,7 @@
 #include "sqrt_80_bit_long_double.h"
 #include "src/__support/CPP/Bit.h"
 #include "src/__support/CPP/TypeTraits.h"
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PlatformDefs.h"
@@ -48,7 +49,7 @@ inline void normalize<long double>(int &exponent, uint64_t &mantissa) {
 }
 #elif !defined(SPECIAL_X86_LONG_DOUBLE)
 template <>
-inline void normalize<long double>(int &exponent, __uint128_t &mantissa) {
+inline void normalize<long double>(int &exponent, UInt128 &mantissa) {
   const uint64_t hi_bits = static_cast<uint64_t>(mantissa >> 64);
   const int shift = hi_bits ? (clz(hi_bits) - 15)
                             : (clz(static_cast<uint64_t>(mantissa)) + 49);

diff  --git a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
index 0fa720b1ae8ae..2700ba3e12774 100644
--- a/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
+++ b/libc/src/__support/FPUtil/generic/sqrt_80_bit_long_double.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_LIBC_SRC_SUPPORT_FPUTIL_GENERIC_SQRT_80_BIT_LONG_DOUBLE_H
 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_GENERIC_SQRT_80_BIT_LONG_DOUBLE_H
 
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/FPUtil/FEnvImpl.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/PlatformDefs.h"
@@ -18,7 +19,7 @@ namespace __llvm_libc {
 namespace fputil {
 namespace x86 {
 
-inline void normalize(int &exponent, __uint128_t &mantissa) {
+inline void normalize(int &exponent, UInt128 &mantissa) {
   const int shift =
       clz(static_cast<uint64_t>(mantissa)) -
       (8 * sizeof(uint64_t) - 1 - MantissaWidth<long double>::VALUE);

diff  --git a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
index 0a2dc452fc73d..468176b27ee4f 100644
--- a/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
+++ b/libc/src/__support/FPUtil/x86_64/LongDoubleBits.h
@@ -10,6 +10,7 @@
 #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_X86_64_LONG_DOUBLE_BITS_H
 
 #include "src/__support/CPP/Bit.h"
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/architectures.h"
 
 #if !defined(LLVM_LIBC_ARCH_X86)
@@ -32,7 +33,7 @@ template <> struct Padding<4> { static constexpr unsigned VALUE = 16; };
 template <> struct Padding<8> { static constexpr unsigned VALUE = 48; };
 
 template <> struct FPBits<long double> {
-  using UIntType = __uint128_t;
+  using UIntType = UInt128;
 
   static constexpr int EXPONENT_BIAS = 0x3FFF;
   static constexpr int MAX_EXPONENT = 0x7FFF;

diff  --git a/libc/src/__support/str_to_float.h b/libc/src/__support/str_to_float.h
index 30a1f0eb4a9bc..a4c6b485a282d 100644
--- a/libc/src/__support/str_to_float.h
+++ b/libc/src/__support/str_to_float.h
@@ -10,6 +10,7 @@
 #define LIBC_SRC_SUPPORT_STR_TO_FLOAT_H
 
 #include "src/__support/CPP/Limits.h"
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/builtin_wrappers.h"
 #include "src/__support/ctype_utils.h"
@@ -58,11 +59,11 @@ template <> uint32_t inline leading_zeroes<uint64_t>(uint64_t inputNumber) {
   return inputNumber == 0 ? 64 : fputil::clz(inputNumber);
 }
 
-static inline uint64_t low64(__uint128_t num) {
+static inline uint64_t low64(const UInt128 &num) {
   return static_cast<uint64_t>(num & 0xffffffffffffffff);
 }
 
-static inline uint64_t high64(__uint128_t num) {
+static inline uint64_t high64(const UInt128 &num) {
   return static_cast<uint64_t>(num >> 64);
 }
 
@@ -116,11 +117,11 @@ eisel_lemire(typename fputil::FPBits<T>::UIntType mantissa, int32_t exp10,
   const uint64_t *power_of_ten =
       DETAILED_POWERS_OF_TEN[exp10 - DETAILED_POWERS_OF_TEN_MIN_EXP_10];
 
-  __uint128_t first_approx = static_cast<__uint128_t>(mantissa) *
-                             static_cast<__uint128_t>(power_of_ten[1]);
+  UInt128 first_approx =
+      static_cast<UInt128>(mantissa) * static_cast<UInt128>(power_of_ten[1]);
 
   // Wider Approximation
-  __uint128_t final_approx;
+  UInt128 final_approx;
   // The halfway constant is used to check if the bits that will be shifted away
   // intially are all 1. For doubles this is 64 (bitstype size) - 52 (final
   // mantissa size) - 3 (we shift away the last two bits separately for
@@ -132,10 +133,10 @@ eisel_lemire(typename fputil::FPBits<T>::UIntType mantissa, int32_t exp10,
       1;
   if ((high64(first_approx) & halfway_constant) == halfway_constant &&
       low64(first_approx) + mantissa < mantissa) {
-    __uint128_t low_bits = static_cast<__uint128_t>(mantissa) *
-                           static_cast<__uint128_t>(power_of_ten[0]);
-    __uint128_t second_approx =
-        first_approx + static_cast<__uint128_t>(high64(low_bits));
+    UInt128 low_bits =
+        static_cast<UInt128>(mantissa) * static_cast<UInt128>(power_of_ten[0]);
+    UInt128 second_approx =
+        first_approx + static_cast<UInt128>(high64(low_bits));
 
     if ((high64(second_approx) & halfway_constant) == halfway_constant &&
         low64(second_approx) + 1 == 0 &&
@@ -220,31 +221,31 @@ inline bool eisel_lemire<long double>(
   // full 128 bits of the power of ten to get an approximation with the same
   // number of significant bits. This means that we only get the one
   // approximation, and that approximation is 256 bits long.
-  __uint128_t approx_upper = static_cast<__uint128_t>(high64(mantissa)) *
-                             static_cast<__uint128_t>(power_of_ten[1]);
+  UInt128 approx_upper = static_cast<UInt128>(high64(mantissa)) *
+                         static_cast<UInt128>(power_of_ten[1]);
 
-  __uint128_t approx_middle = static_cast<__uint128_t>(high64(mantissa)) *
-                                  static_cast<__uint128_t>(power_of_ten[0]) +
-                              static_cast<__uint128_t>(low64(mantissa)) *
-                                  static_cast<__uint128_t>(power_of_ten[1]);
+  UInt128 approx_middle = static_cast<UInt128>(high64(mantissa)) *
+                              static_cast<UInt128>(power_of_ten[0]) +
+                          static_cast<UInt128>(low64(mantissa)) *
+                              static_cast<UInt128>(power_of_ten[1]);
 
-  __uint128_t approx_lower = static_cast<__uint128_t>(low64(mantissa)) *
-                             static_cast<__uint128_t>(power_of_ten[0]);
+  UInt128 approx_lower = static_cast<UInt128>(low64(mantissa)) *
+                         static_cast<UInt128>(power_of_ten[0]);
 
-  __uint128_t final_approx_lower =
-      approx_lower + (static_cast<__uint128_t>(low64(approx_middle)) << 64);
-  __uint128_t final_approx_upper = approx_upper + high64(approx_middle) +
-                                   (final_approx_lower < approx_lower ? 1 : 0);
+  UInt128 final_approx_lower =
+      approx_lower + (static_cast<UInt128>(low64(approx_middle)) << 64);
+  UInt128 final_approx_upper = approx_upper + high64(approx_middle) +
+                               (final_approx_lower < approx_lower ? 1 : 0);
 
   // The halfway constant is used to check if the bits that will be shifted away
   // intially are all 1. For 80 bit floats this is 128 (bitstype size) - 64
   // (final mantissa size) - 3 (we shift away the last two bits separately for
   // accuracy, and the most significant bit is ignored.) = 61 bits. Similarly,
   // it's 12 bits for 128 bit floats in this case.
-  constexpr __uint128_t HALFWAY_CONSTANT =
-      (__uint128_t(1) << (BITS_IN_MANTISSA -
-                          fputil::FloatProperties<long double>::MANTISSA_WIDTH -
-                          3)) -
+  constexpr UInt128 HALFWAY_CONSTANT =
+      (UInt128(1) << (BITS_IN_MANTISSA -
+                      fputil::FloatProperties<long double>::MANTISSA_WIDTH -
+                      3)) -
       1;
 
   if ((final_approx_upper & HALFWAY_CONSTANT) == HALFWAY_CONSTANT &&

diff  --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt
index 6f0750cd5d404..97ae33dd13b83 100644
--- a/libc/test/src/__support/CMakeLists.txt
+++ b/libc/test/src/__support/CMakeLists.txt
@@ -18,6 +18,7 @@ add_libc_unittest(
   high_precision_decimal_test.cpp
   DEPENDS
     libc.src.__support.high_precision_decimal
+    libc.src.__support.CPP.uint128
 )
 
 add_libc_unittest(
@@ -28,6 +29,7 @@ add_libc_unittest(
     str_to_float_test.cpp
   DEPENDS
     libc.src.__support.str_to_float
+    libc.src.__support.CPP.uint128
 )
 
 add_libc_unittest(

diff  --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt
index 9e8e5ae0d964c..9844425e3cc18 100644
--- a/libc/test/src/__support/CPP/CMakeLists.txt
+++ b/libc/test/src/__support/CPP/CMakeLists.txt
@@ -28,6 +28,7 @@ add_libc_unittest(
     limits_test.cpp
   DEPENDS
     libc.src.__support.CPP.limits
+    libc.src.__support.CPP.uint
 )
 
 add_libc_unittest(

diff  --git a/libc/test/src/__support/CPP/limits_test.cpp b/libc/test/src/__support/CPP/limits_test.cpp
index 0272b5a6521ae..b55823f5527db 100644
--- a/libc/test/src/__support/CPP/limits_test.cpp
+++ b/libc/test/src/__support/CPP/limits_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/CPP/Limits.h"
+#include "src/__support/CPP/UInt.h"
 #include "utils/UnitTest/Test.h"
 
 // This just checks against the C spec, almost all implementations will surpass
@@ -29,23 +30,15 @@ TEST(LlvmLibcLimitsTest, LimitsFollowSpec) {
             ULLONG_MAX);
 }
 
+TEST(LlvmLibcLimitsTest, UInt128Limits) {
+  auto umax128 =
+      __llvm_libc::cpp::NumericLimits<__llvm_libc::cpp::UInt<128>>::max();
+  auto umax64 = __llvm_libc::cpp::UInt<128>(
+      __llvm_libc::cpp::NumericLimits<uint64_t>::max());
+  EXPECT_GT(umax128, umax64);
+  ASSERT_EQ(~__llvm_libc::cpp::UInt<128>(0), umax128);
 #ifdef __SIZEOF_INT128__
-// This checks that the current environment supports 128 bit integers.
-TEST(LlvmLibcLimitsTest, Int128Works) {
-  __int128_t max128 = ~__uint128_t(0) >> 1;
-  __int128_t min128 = (__int128_t(1) << 127);
-  EXPECT_GT(__llvm_libc::cpp::NumericLimits<__int128_t>::max(),
-            __int128_t(__llvm_libc::cpp::NumericLimits<long long>::max()));
-  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<__int128_t>::max(), max128);
-
-  EXPECT_LT(__llvm_libc::cpp::NumericLimits<__int128_t>::min(),
-            __int128_t(__llvm_libc::cpp::NumericLimits<long long>::min()));
-  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<__int128_t>::min(), min128);
-
-  __uint128_t umax128 = ~__uint128_t(0);
-  EXPECT_GT(
-      __llvm_libc::cpp::NumericLimits<__uint128_t>::max(),
-      __uint128_t(__llvm_libc::cpp::NumericLimits<unsigned long long>::max()));
-  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<__uint128_t>::max(), umax128);
-}
+  ASSERT_EQ(~__uint128_t(0),
+            __llvm_libc::cpp::NumericLimits<__uint128_t>::max());
 #endif
+}

diff  --git a/libc/test/src/__support/high_precision_decimal_test.cpp b/libc/test/src/__support/high_precision_decimal_test.cpp
index 46cc572c7624d..a0d1043896aa2 100644
--- a/libc/test/src/__support/high_precision_decimal_test.cpp
+++ b/libc/test/src/__support/high_precision_decimal_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/high_precision_decimal.h"
 
 #include "utils/UnitTest/Test.h"
@@ -344,34 +345,26 @@ TEST(LlvmLibcHighPrecisionDecimalTest, RoundingTest) {
 
   EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(1));
   EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(1));
-#ifdef __SIZEOF_INT128__
-  EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(1));
-#endif
+  EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(1));
 
   hpd.shift(1); // shift left 1 to get 2.469 (rounds to 2)
 
   EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(2));
   EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(2));
-#ifdef __SIZEOF_INT128__
-  EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(2));
-#endif
+  EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(2));
 
   hpd.shift(1); // shift left 1 to get 4.938 (rounds to 5)
 
   EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(5));
   EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(5));
-#ifdef __SIZEOF_INT128__
-  EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(5));
-#endif
+  EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(5));
 
   // 2.5 is right between two integers, so we round to even (2)
   hpd = __llvm_libc::internal::HighPrecisionDecimal("2.5");
 
   EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(2));
   EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(2));
-#ifdef __SIZEOF_INT128__
-  EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(2));
-#endif
+  EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(2));
 
   // unless it's marked as having truncated, which means it's actually slightly
   // higher, forcing a round up (3)
@@ -379,9 +372,7 @@ TEST(LlvmLibcHighPrecisionDecimalTest, RoundingTest) {
 
   EXPECT_EQ(hpd.round_to_integer_type<uint32_t>(), uint32_t(3));
   EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(3));
-#ifdef __SIZEOF_INT128__
-  EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), __uint128_t(3));
-#endif
+  EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(3));
 
   // Check that the larger int types are being handled properly (overflow is not
   // handled, so int types that are too small are ignored for this test.)
@@ -390,16 +381,13 @@ TEST(LlvmLibcHighPrecisionDecimalTest, RoundingTest) {
   hpd = __llvm_libc::internal::HighPrecisionDecimal("1099511627776");
 
   EXPECT_EQ(hpd.round_to_integer_type<uint64_t>(), uint64_t(1099511627776));
-#ifdef __SIZEOF_INT128__
-  EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(),
-            __uint128_t(1099511627776));
+  EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), UInt128(1099511627776));
 
   // 1267650600228229401496703205376 = 2^100
   hpd = __llvm_libc::internal::HighPrecisionDecimal(
       "1267650600228229401496703205376");
 
-  __uint128_t result = __uint128_t(1) << 100;
+  UInt128 result = UInt128(1) << 100;
 
-  EXPECT_EQ(hpd.round_to_integer_type<__uint128_t>(), result);
-#endif
+  EXPECT_EQ(hpd.round_to_integer_type<UInt128>(), result);
 }

diff  --git a/libc/test/src/__support/str_to_float_test.cpp b/libc/test/src/__support/str_to_float_test.cpp
index 211e3dc04eebd..82e87bc8251c9 100644
--- a/libc/test/src/__support/str_to_float_test.cpp
+++ b/libc/test/src/__support/str_to_float_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/str_to_float.h"
 
@@ -273,14 +274,14 @@ TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Simple) {
 }
 
 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80LongerMantissa) {
-  eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) +
-                                     __uint128_t(0x1234567812345678),
+  eisel_lemire_test<long double>((UInt128(0x1234567812345678) << 64) +
+                                     UInt128(0x1234567812345678),
                                  0, 0x91a2b3c091a2b3c1, 16507);
-  eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) +
-                                     __uint128_t(0x1234567812345678),
+  eisel_lemire_test<long double>((UInt128(0x1234567812345678) << 64) +
+                                     UInt128(0x1234567812345678),
                                  300, 0xd97757de56adb65c, 17503);
-  eisel_lemire_test<long double>((__uint128_t(0x1234567812345678) << 64) +
-                                     __uint128_t(0x1234567812345678),
+  eisel_lemire_test<long double>((UInt128(0x1234567812345678) << 64) +
+                                     UInt128(0x1234567812345678),
                                  -300, 0xc30feb9a7618457d, 15510);
 }
 
@@ -299,7 +300,7 @@ TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80TableLimits) {
 
 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Fallback) {
   uint32_t outputExp2 = 0;
-  __uint128_t quadOutputMantissa = 0;
+  UInt128 quadOutputMantissa = 0;
 
   // This number is halfway between two possible results, and the algorithm
   // can't determine which is correct.
@@ -313,39 +314,33 @@ TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat80Fallback) {
   ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>(
       1, -1000, &quadOutputMantissa, &outputExp2));
 }
-#elif defined(__SIZEOF_INT128__)
+#else // Quad precision long double
 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128Simple) {
-  eisel_lemire_test<long double>(123, 0, (__uint128_t(0x1ec0000000000) << 64),
+  eisel_lemire_test<long double>(123, 0, (UInt128(0x1ec0000000000) << 64),
                                  16389);
-  eisel_lemire_test<long double>(12345678901234568192u, 0,
-                                 (__uint128_t(0x156a95319d63e) << 64) +
-                                     __uint128_t(0x1800000000000000),
-                                 16446);
+  eisel_lemire_test<long double>(
+      12345678901234568192u, 0,
+      (UInt128(0x156a95319d63e) << 64) + UInt128(0x1800000000000000), 16446);
 }
 
 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128LongerMantissa) {
   eisel_lemire_test<long double>(
-      (__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678),
-      0, (__uint128_t(0x1234567812345) << 64) + __uint128_t(0x6781234567812345),
-      16507);
+      (UInt128(0x1234567812345678) << 64) + UInt128(0x1234567812345678), 0,
+      (UInt128(0x1234567812345) << 64) + UInt128(0x6781234567812345), 16507);
   eisel_lemire_test<long double>(
-      (__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678),
-      300,
-      (__uint128_t(0x1b2eeafbcad5b) << 64) + __uint128_t(0x6cb8b4451dfcde19),
-      17503);
+      (UInt128(0x1234567812345678) << 64) + UInt128(0x1234567812345678), 300,
+      (UInt128(0x1b2eeafbcad5b) << 64) + UInt128(0x6cb8b4451dfcde19), 17503);
   eisel_lemire_test<long double>(
-      (__uint128_t(0x1234567812345678) << 64) + __uint128_t(0x1234567812345678),
-      -300,
-      (__uint128_t(0x1861fd734ec30) << 64) + __uint128_t(0x8afa7189f0f7595f),
-      15510);
+      (UInt128(0x1234567812345678) << 64) + UInt128(0x1234567812345678), -300,
+      (UInt128(0x1861fd734ec30) << 64) + UInt128(0x8afa7189f0f7595f), 15510);
 }
 
 TEST_F(LlvmLibcStrToFloatTest, EiselLemireFloat128Fallback) {
   uint32_t outputExp2 = 0;
-  __uint128_t quadOutputMantissa = 0;
+  UInt128 quadOutputMantissa = 0;
 
   ASSERT_FALSE(__llvm_libc::internal::eisel_lemire<long double>(
-      (__uint128_t(0x5ce0e9a56015fec5) << 64) + __uint128_t(0xaadfa328ae39b333),
-      1, &quadOutputMantissa, &outputExp2));
+      (UInt128(0x5ce0e9a56015fec5) << 64) + UInt128(0xaadfa328ae39b333), 1,
+      &quadOutputMantissa, &outputExp2));
 }
 #endif

diff  --git a/libc/test/src/__support/uint128_test.cpp b/libc/test/src/__support/uint128_test.cpp
index c13b2be2d24f4..bbfec2066afac 100644
--- a/libc/test/src/__support/uint128_test.cpp
+++ b/libc/test/src/__support/uint128_test.cpp
@@ -10,56 +10,59 @@
 
 #include "utils/UnitTest/Test.h"
 
-using UInt128 = __llvm_libc::cpp::UInt<128>;
+// We want to test __llvm_libc::cpp::UInt<128> explicitly. So, for convenience,
+// we use a sugar which does not conflict with the UInt128 type which can
+// resolve to __uint128_t if the platform has it.
+using LL_UInt128 = __llvm_libc::cpp::UInt<128>;
 
 TEST(LlvmLibcUInt128ClassTest, BasicInit) {
-  UInt128 empty;
-  UInt128 half_val(12345);
-  UInt128 full_val({12345, 67890});
+  LL_UInt128 empty;
+  LL_UInt128 half_val(12345);
+  LL_UInt128 full_val({12345, 67890});
   ASSERT_TRUE(half_val != full_val);
 }
 
 TEST(LlvmLibcUInt128ClassTest, AdditionTests) {
-  UInt128 val1(12345);
-  UInt128 val2(54321);
-  UInt128 result1(66666);
+  LL_UInt128 val1(12345);
+  LL_UInt128 val2(54321);
+  LL_UInt128 result1(66666);
   EXPECT_EQ(val1 + val2, result1);
   EXPECT_EQ((val1 + val2), (val2 + val1)); // addition is reciprocal
 
   // Test overflow
-  UInt128 val3({0xf000000000000001, 0});
-  UInt128 val4({0x100000000000000f, 0});
-  UInt128 result2({0x10, 0x1});
+  LL_UInt128 val3({0xf000000000000001, 0});
+  LL_UInt128 val4({0x100000000000000f, 0});
+  LL_UInt128 result2({0x10, 0x1});
   EXPECT_EQ(val3 + val4, result2);
   EXPECT_EQ(val3 + val4, val4 + val3);
 }
 
 TEST(LlvmLibcUInt128ClassTest, MultiplicationTests) {
-  UInt128 val1({5, 0});
-  UInt128 val2({10, 0});
-  UInt128 result1({50, 0});
+  LL_UInt128 val1({5, 0});
+  LL_UInt128 val2({10, 0});
+  LL_UInt128 result1({50, 0});
   EXPECT_EQ((val1 * val2), result1);
   EXPECT_EQ((val1 * val2), (val2 * val1)); // multiplication is reciprocal
 
   // Check that the multiplication works accross the whole number
-  UInt128 val3({0xf, 0});
-  UInt128 val4({0x1111111111111111, 0x1111111111111111});
-  UInt128 result2({0xffffffffffffffff, 0xffffffffffffffff});
+  LL_UInt128 val3({0xf, 0});
+  LL_UInt128 val4({0x1111111111111111, 0x1111111111111111});
+  LL_UInt128 result2({0xffffffffffffffff, 0xffffffffffffffff});
   EXPECT_EQ((val3 * val4), result2);
   EXPECT_EQ((val3 * val4), (val4 * val3));
 
   // Check that multiplication doesn't reorder the bits.
-  UInt128 val5({2, 0});
-  UInt128 val6({0x1357024675316420, 0x0123456776543210});
-  UInt128 result3({0x26ae048cea62c840, 0x02468aceeca86420});
+  LL_UInt128 val5({2, 0});
+  LL_UInt128 val6({0x1357024675316420, 0x0123456776543210});
+  LL_UInt128 result3({0x26ae048cea62c840, 0x02468aceeca86420});
 
   EXPECT_EQ((val5 * val6), result3);
   EXPECT_EQ((val5 * val6), (val6 * val5));
 
   // Make sure that multiplication handles overflow correctly.
-  UInt128 val7(2);
-  UInt128 val8({0x8000800080008000, 0x8000800080008000});
-  UInt128 result4({0x0001000100010000, 0x0001000100010001});
+  LL_UInt128 val7(2);
+  LL_UInt128 val8({0x8000800080008000, 0x8000800080008000});
+  LL_UInt128 result4({0x0001000100010000, 0x0001000100010001});
   EXPECT_EQ((val7 * val8), result4);
   EXPECT_EQ((val7 * val8), (val8 * val7));
 
@@ -67,92 +70,98 @@ TEST(LlvmLibcUInt128ClassTest, MultiplicationTests) {
   // 1e-60. They almost cancel on the high bits, but the result we're looking
   // for is just the low bits. The full result would be
   // 0x7fffffffffffffffffffffffffffffff3a4f32d17f40d08f917cf11d1e039c50
-  UInt128 val9({0x01D762422C946590, 0x9F4F2726179A2245});
-  UInt128 val10({0x3792F412CB06794D, 0xCDB02555653131B6});
-  UInt128 result5({0x917cf11d1e039c50, 0x3a4f32d17f40d08f});
+  LL_UInt128 val9({0x01D762422C946590, 0x9F4F2726179A2245});
+  LL_UInt128 val10({0x3792F412CB06794D, 0xCDB02555653131B6});
+  LL_UInt128 result5({0x917cf11d1e039c50, 0x3a4f32d17f40d08f});
   EXPECT_EQ((val9 * val10), result5);
   EXPECT_EQ((val9 * val10), (val10 * val9));
 }
 
 TEST(LlvmLibcUInt128ClassTest, ShiftLeftTests) {
-  UInt128 val1(0x0123456789abcdef);
-  UInt128 result1(0x123456789abcdef0);
+  LL_UInt128 val1(0x0123456789abcdef);
+  LL_UInt128 result1(0x123456789abcdef0);
   EXPECT_EQ((val1 << 4), result1);
 
-  UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
-  UInt128 result2({0x02468ace00000000, 0x9abcdef013579bdf});
+  LL_UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
+  LL_UInt128 result2({0x02468ace00000000, 0x9abcdef013579bdf});
   EXPECT_EQ((val2 << 32), result2);
+  LL_UInt128 val22 = val2;
+  val22 <<= 32;
+  EXPECT_EQ(val22, result2);
 
-  UInt128 result3({0, 0x13579bdf02468ace});
+  LL_UInt128 result3({0, 0x13579bdf02468ace});
   EXPECT_EQ((val2 << 64), result3);
 
-  UInt128 result4({0, 0x02468ace00000000});
+  LL_UInt128 result4({0, 0x02468ace00000000});
   EXPECT_EQ((val2 << 96), result4);
 
-  UInt128 result5({0, 0x2468ace000000000});
+  LL_UInt128 result5({0, 0x2468ace000000000});
   EXPECT_EQ((val2 << 100), result5);
 
-  UInt128 result6({0, 0});
+  LL_UInt128 result6({0, 0});
   EXPECT_EQ((val2 << 128), result6);
   EXPECT_EQ((val2 << 256), result6);
 }
 
 TEST(LlvmLibcUInt128ClassTest, ShiftRightTests) {
-  UInt128 val1(0x0123456789abcdef);
-  UInt128 result1(0x00123456789abcde);
+  LL_UInt128 val1(0x0123456789abcdef);
+  LL_UInt128 result1(0x00123456789abcde);
   EXPECT_EQ((val1 >> 4), result1);
 
-  UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
-  UInt128 result2({0x9abcdef013579bdf, 0x0000000012345678});
+  LL_UInt128 val2({0x13579bdf02468ace, 0x123456789abcdef0});
+  LL_UInt128 result2({0x9abcdef013579bdf, 0x0000000012345678});
   EXPECT_EQ((val2 >> 32), result2);
+  LL_UInt128 val22 = val2;
+  val22 >>= 32;
+  EXPECT_EQ(val22, result2);
 
-  UInt128 result3({0x123456789abcdef0, 0});
+  LL_UInt128 result3({0x123456789abcdef0, 0});
   EXPECT_EQ((val2 >> 64), result3);
 
-  UInt128 result4({0x0000000012345678, 0});
+  LL_UInt128 result4({0x0000000012345678, 0});
   EXPECT_EQ((val2 >> 96), result4);
 
-  UInt128 result5({0x0000000001234567, 0});
+  LL_UInt128 result5({0x0000000001234567, 0});
   EXPECT_EQ((val2 >> 100), result5);
 
-  UInt128 result6({0, 0});
+  LL_UInt128 result6({0, 0});
   EXPECT_EQ((val2 >> 128), result6);
   EXPECT_EQ((val2 >> 256), result6);
 }
 
 TEST(LlvmLibcUInt128ClassTest, AndTests) {
-  UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
-  UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
+  LL_UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
+  LL_UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
   uint64_t val64 = 0xf0f0f0f00f0f0f0f;
   int val32 = 0x0f0f0f0f;
-  UInt128 result128({0xf0f0000000000f0f, 0xff00ff0000000000});
-  UInt128 result64(0xf0f0000000000f0f);
-  UInt128 result32(0x00000f0f);
+  LL_UInt128 result128({0xf0f0000000000f0f, 0xff00ff0000000000});
+  LL_UInt128 result64(0xf0f0000000000f0f);
+  LL_UInt128 result32(0x00000f0f);
   EXPECT_EQ((base & val128), result128);
   EXPECT_EQ((base & val64), result64);
   EXPECT_EQ((base & val32), result32);
 }
 
 TEST(LlvmLibcUInt128ClassTest, OrTests) {
-  UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
-  UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
+  LL_UInt128 base({0xffff00000000ffff, 0xffffffff00000000});
+  LL_UInt128 val128({0xf0f0f0f00f0f0f0f, 0xff00ff0000ff00ff});
   uint64_t val64 = 0xf0f0f0f00f0f0f0f;
   int val32 = 0x0f0f0f0f;
-  UInt128 result128({0xfffff0f00f0fffff, 0xffffffff00ff00ff});
-  UInt128 result64({0xfffff0f00f0fffff, 0xffffffff00000000});
-  UInt128 result32({0xffff00000f0fffff, 0xffffffff00000000});
+  LL_UInt128 result128({0xfffff0f00f0fffff, 0xffffffff00ff00ff});
+  LL_UInt128 result64({0xfffff0f00f0fffff, 0xffffffff00000000});
+  LL_UInt128 result32({0xffff00000f0fffff, 0xffffffff00000000});
   EXPECT_EQ((base | val128), result128);
   EXPECT_EQ((base | val64), result64);
   EXPECT_EQ((base | val32), result32);
 }
 
 TEST(LlvmLibcUInt128ClassTest, EqualsTests) {
-  UInt128 a1({0xffffffff00000000, 0xffff00000000ffff});
-  UInt128 a2({0xffffffff00000000, 0xffff00000000ffff});
-  UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
-  UInt128 a_reversed({0xffff00000000ffff, 0xffffffff00000000});
-  UInt128 a_upper(0xffff00000000ffff);
-  UInt128 a_lower(0xffffffff00000000);
+  LL_UInt128 a1({0xffffffff00000000, 0xffff00000000ffff});
+  LL_UInt128 a2({0xffffffff00000000, 0xffff00000000ffff});
+  LL_UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
+  LL_UInt128 a_reversed({0xffff00000000ffff, 0xffffffff00000000});
+  LL_UInt128 a_upper(0xffff00000000ffff);
+  LL_UInt128 a_lower(0xffffffff00000000);
   ASSERT_TRUE(a1 == a1);
   ASSERT_TRUE(a1 == a2);
   ASSERT_FALSE(a1 == b);
@@ -163,15 +172,15 @@ TEST(LlvmLibcUInt128ClassTest, EqualsTests) {
 }
 
 TEST(LlvmLibcUInt128ClassTest, ComparisonTests) {
-  UInt128 a({0xffffffff00000000, 0xffff00000000ffff});
-  UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
+  LL_UInt128 a({0xffffffff00000000, 0xffff00000000ffff});
+  LL_UInt128 b({0xff00ff0000ff00ff, 0xf0f0f0f00f0f0f0f});
   EXPECT_GT(a, b);
   EXPECT_GE(a, b);
   EXPECT_LT(b, a);
   EXPECT_LE(b, a);
 
-  UInt128 x(0xffffffff00000000);
-  UInt128 y(0x00000000ffffffff);
+  LL_UInt128 x(0xffffffff00000000);
+  LL_UInt128 y(0x00000000ffffffff);
   EXPECT_GT(x, y);
   EXPECT_GE(x, y);
   EXPECT_LT(y, x);

diff  --git a/libc/test/src/stdlib/CMakeLists.txt b/libc/test/src/stdlib/CMakeLists.txt
index 0cdb69bcc59d6..065408908a10d 100644
--- a/libc/test/src/stdlib/CMakeLists.txt
+++ b/libc/test/src/stdlib/CMakeLists.txt
@@ -77,6 +77,7 @@ add_libc_unittest(
   SRCS
     strtold_test.cpp
   DEPENDS
+    libc.src.__support.CPP.uint128
     libc.src.stdlib.strtold
 )
 

diff  --git a/libc/test/src/stdlib/strtold_test.cpp b/libc/test/src/stdlib/strtold_test.cpp
index eb5cda72b90e4..3ddcdc1b1064c 100644
--- a/libc/test/src/stdlib/strtold_test.cpp
+++ b/libc/test/src/stdlib/strtold_test.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "src/__support/CPP/UInt128.h"
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/stdlib/strtold.h"
 
@@ -30,7 +31,7 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
                 const uint64_t expectedRawData, const int expectedErrno = 0)
 #else
   void run_test(const char *inputString, const ptr
diff _t expectedStrLen,
-                const __uint128_t expectedRawData, const int expectedErrno = 0)
+                const UInt128 expectedRawData, const int expectedErrno = 0)
 #endif
   {
     // expectedRawData64 is the expected long double result as a uint64_t,
@@ -46,7 +47,7 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
     //       |
     //       +-- 11 Exponent Bits
 
-    // expectedRawData80 is the expected long double result as a __uint128_t,
+    // expectedRawData80 is the expected long double result as a UInt128,
     // organized according to the x86 extended precision format:
     //
     // +-- 1 Sign Bit
@@ -59,7 +60,7 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
     //         |                                    |
     //         +-- 15 Exponent Bits                 +-- 63 Mantissa bits
 
-    // expectedRawData128 is the expected long double result as a __uint128_t,
+    // expectedRawData128 is the expected long double result as a UInt128,
     // organized according to IEEE754 quadruple precision format:
     //
     // +-- 1 Sign Bit                               +-- 112 Mantissa bits
@@ -97,73 +98,67 @@ class LlvmLibcStrToLDTest : public __llvm_libc::testing::Test {
 TEST_F(LlvmLibcStrToLDTest, SimpleTest) {
   run_test("123", 3,
            SELECT_CONST(uint64_t(0x405ec00000000000),
-                        __uint128_t(0x4005f60000) << 40,
-                        __uint128_t(0x4005ec0000000000) << 64));
+                        UInt128(0x4005f60000) << 40,
+                        UInt128(0x4005ec0000000000) << 64));
 
   // This should fail on Eisel-Lemire, forcing a fallback to simple decimal
   // conversion.
   run_test("12345678901234549760", 20,
            SELECT_CONST(uint64_t(0x43e56a95319d63d8),
-                        (__uint128_t(0x403eab54a9) << 40) +
-                            __uint128_t(0x8ceb1ec400),
-                        (__uint128_t(0x403e56a95319d63d) << 64) +
-                            __uint128_t(0x8800000000000000)));
+                        (UInt128(0x403eab54a9) << 40) + UInt128(0x8ceb1ec400),
+                        (UInt128(0x403e56a95319d63d) << 64) +
+                            UInt128(0x8800000000000000)));
 
   // Found while looking for 
diff icult test cases here:
   // https://github.com/nigeltao/parse-number-fxx-test-data/blob/main/more-test-cases/golang-org-issue-36657.txt
   run_test("1090544144181609348835077142190", 31,
            SELECT_CONST(uint64_t(0x462b8779f2474dfb),
-                        (__uint128_t(0x4062dc3bcf) << 40) +
-                            __uint128_t(0x923a6fd402),
-                        (__uint128_t(0x4062b8779f2474df) << 64) +
-                            __uint128_t(0xa804bfd8c6d5c000)));
+                        (UInt128(0x4062dc3bcf) << 40) + UInt128(0x923a6fd402),
+                        (UInt128(0x4062b8779f2474df) << 64) +
+                            UInt128(0xa804bfd8c6d5c000)));
 
   run_test("0x123", 5,
            SELECT_CONST(uint64_t(0x4072300000000000),
-                        (__uint128_t(0x4007918000) << 40),
-                        (__uint128_t(0x4007230000000000) << 64)));
+                        (UInt128(0x4007918000) << 40),
+                        (UInt128(0x4007230000000000) << 64)));
 }
 
 // These are tests that have caused problems for doubles in the past.
 TEST_F(LlvmLibcStrToLDTest, Float64SpecificFailures) {
   run_test("3E70000000000000", 16,
            SELECT_CONST(uint64_t(0x7FF0000000000000),
-                        (__uint128_t(0x7fff800000) << 40),
-                        (__uint128_t(0x7fff000000000000) << 64)),
+                        (UInt128(0x7fff800000) << 40),
+                        (UInt128(0x7fff000000000000) << 64)),
            ERANGE);
   run_test("358416272e-33", 13,
            SELECT_CONST(uint64_t(0x3adbbb2a68c9d0b9),
-                        (__uint128_t(0x3fadddd953) << 40) +
-                            __uint128_t(0x464e85c400),
-                        (__uint128_t(0x3fadbbb2a68c9d0b) << 64) +
-                            __uint128_t(0x8800e7969e1c5fc8)));
+                        (UInt128(0x3fadddd953) << 40) + UInt128(0x464e85c400),
+                        (UInt128(0x3fadbbb2a68c9d0b) << 64) +
+                            UInt128(0x8800e7969e1c5fc8)));
   run_test("2.16656806400000023841857910156251e9", 36,
            SELECT_CONST(uint64_t(0x41e0246690000001),
-                        (__uint128_t(0x401e812334) << 40) +
-                            __uint128_t(0x8000000400),
-                        (__uint128_t(0x401e024669000000) << 64) +
-                            __uint128_t(0x800000000000018)));
+                        (UInt128(0x401e812334) << 40) + UInt128(0x8000000400),
+                        (UInt128(0x401e024669000000) << 64) +
+                            UInt128(0x800000000000018)));
   run_test("27949676547093071875", 20,
            SELECT_CONST(uint64_t(0x43f83e132bc608c9),
-                        (__uint128_t(0x403fc1f099) << 40) +
-                            __uint128_t(0x5e30464402),
-                        (__uint128_t(0x403f83e132bc608c) << 64) +
-                            __uint128_t(0x8803000000000000)));
+                        (UInt128(0x403fc1f099) << 40) + UInt128(0x5e30464402),
+                        (UInt128(0x403f83e132bc608c) << 64) +
+                            UInt128(0x8803000000000000)));
 }
 
 TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) {
   run_test("1.1897314953572317650e4932", 26,
            SELECT_CONST(uint64_t(0x7FF0000000000000),
-                        (__uint128_t(0x7ffeffffff) << 40) +
-                            __uint128_t(0xffffffffff),
-                        (__uint128_t(0x7ffeffffffffffff) << 64) +
-                            __uint128_t(0xfffd57322e3f8675)),
+                        (UInt128(0x7ffeffffff) << 40) + UInt128(0xffffffffff),
+                        (UInt128(0x7ffeffffffffffff) << 64) +
+                            UInt128(0xfffd57322e3f8675)),
            SELECT_CONST(ERANGE, 0, 0));
   run_test("1.18973149535723176508e4932", 27,
            SELECT_CONST(uint64_t(0x7FF0000000000000),
-                        (__uint128_t(0x7fff800000) << 40),
-                        (__uint128_t(0x7ffeffffffffffff) << 64) +
-                            __uint128_t(0xffffd2478338036c)),
+                        (UInt128(0x7fff800000) << 40),
+                        (UInt128(0x7ffeffffffffffff) << 64) +
+                            UInt128(0xffffd2478338036c)),
            SELECT_CONST(ERANGE, ERANGE, 0));
 }
 
@@ -171,94 +166,86 @@ TEST_F(LlvmLibcStrToLDTest, MaxSizeNumbers) {
 // be too small for 64 bit floats.
 TEST_F(LlvmLibcStrToLDTest, SubnormalTests) {
   run_test("1e-4950", 7,
-           SELECT_CONST(uint64_t(0), (__uint128_t(0x00000000000000000003)),
-                        (__uint128_t(0x000000000000000000057c9647e1a018))),
+           SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000003)),
+                        (UInt128(0x000000000000000000057c9647e1a018))),
            ERANGE);
   run_test("1.89e-4951", 10,
-           SELECT_CONST(uint64_t(0), (__uint128_t(0x00000000000000000001)),
-                        (__uint128_t(0x0000000000000000000109778a006738))),
+           SELECT_CONST(uint64_t(0), (UInt128(0x00000000000000000001)),
+                        (UInt128(0x0000000000000000000109778a006738))),
            ERANGE);
   run_test("4e-4966", 7,
-           SELECT_CONST(uint64_t(0), (__uint128_t(0)),
-                        (__uint128_t(0x00000000000000000000000000000001))),
+           SELECT_CONST(uint64_t(0), (UInt128(0)),
+                        (UInt128(0x00000000000000000000000000000001))),
            ERANGE);
 }
 
 TEST_F(LlvmLibcStrToLDTest, SmallNormalTests) {
-  run_test(
-      "3.37e-4932", 10,
-      SELECT_CONST(uint64_t(0),
-                   (__uint128_t(0x1804cf7) << 40) + __uint128_t(0x908850712),
-                   (__uint128_t(0x10099ee12110a) << 64) +
-                       __uint128_t(0xe24b75c0f50dc0c)),
-      SELECT_CONST(ERANGE, 0, 0));
+  run_test("3.37e-4932", 10,
+           SELECT_CONST(
+               uint64_t(0), (UInt128(0x1804cf7) << 40) + UInt128(0x908850712),
+               (UInt128(0x10099ee12110a) << 64) + UInt128(0xe24b75c0f50dc0c)),
+           SELECT_CONST(ERANGE, 0, 0));
 }
 
 TEST_F(LlvmLibcStrToLDTest, ComplexHexadecimalTests) {
   run_test("0x1p16383", 9,
-           SELECT_CONST(0x7ff0000000000000, (__uint128_t(0x7ffe800000) << 40),
-                        (__uint128_t(0x7ffe000000000000) << 64)),
+           SELECT_CONST(0x7ff0000000000000, (UInt128(0x7ffe800000) << 40),
+                        (UInt128(0x7ffe000000000000) << 64)),
            SELECT_CONST(ERANGE, 0, 0));
   run_test("0x123456789abcdef", 17,
            SELECT_CONST(0x43723456789abcdf,
-                        (__uint128_t(0x403791a2b3) << 40) +
-                            __uint128_t(0xc4d5e6f780),
-                        (__uint128_t(0x403723456789abcd) << 64) +
-                            __uint128_t(0xef00000000000000)));
+                        (UInt128(0x403791a2b3) << 40) + UInt128(0xc4d5e6f780),
+                        (UInt128(0x403723456789abcd) << 64) +
+                            UInt128(0xef00000000000000)));
   run_test("0x123456789abcdef0123456789ABCDEF", 33,
            SELECT_CONST(0x47723456789abcdf,
-                        (__uint128_t(0x407791a2b3) << 40) +
-                            __uint128_t(0xc4d5e6f781),
-                        (__uint128_t(0x407723456789abcd) << 64) +
-                            __uint128_t(0xef0123456789abce)));
+                        (UInt128(0x407791a2b3) << 40) + UInt128(0xc4d5e6f781),
+                        (UInt128(0x407723456789abcd) << 64) +
+                            UInt128(0xef0123456789abce)));
 }
 
 TEST_F(LlvmLibcStrToLDTest, InfTests) {
   run_test("INF", 3,
-           SELECT_CONST(0x7ff0000000000000, (__uint128_t(0x7fff800000) << 40),
-                        (__uint128_t(0x7fff000000000000) << 64)));
+           SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
+                        (UInt128(0x7fff000000000000) << 64)));
   run_test("INFinity", 8,
-           SELECT_CONST(0x7ff0000000000000, (__uint128_t(0x7fff800000) << 40),
-                        (__uint128_t(0x7fff000000000000) << 64)));
+           SELECT_CONST(0x7ff0000000000000, (UInt128(0x7fff800000) << 40),
+                        (UInt128(0x7fff000000000000) << 64)));
   run_test("-inf", 4,
-           SELECT_CONST(0xfff0000000000000, (__uint128_t(0xffff800000) << 40),
-                        (__uint128_t(0xffff000000000000) << 64)));
+           SELECT_CONST(0xfff0000000000000, (UInt128(0xffff800000) << 40),
+                        (UInt128(0xffff000000000000) << 64)));
 }
 
 TEST_F(LlvmLibcStrToLDTest, NaNTests) {
   run_test("NaN", 3,
-           SELECT_CONST(0x7ff8000000000000, (__uint128_t(0x7fffc00000) << 40),
-                        (__uint128_t(0x7fff800000000000) << 64)));
+           SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+                        (UInt128(0x7fff800000000000) << 64)));
   run_test("-nAn", 4,
-           SELECT_CONST(0xfff8000000000000, (__uint128_t(0xffffc00000) << 40),
-                        (__uint128_t(0xffff800000000000) << 64)));
+           SELECT_CONST(0xfff8000000000000, (UInt128(0xffffc00000) << 40),
+                        (UInt128(0xffff800000000000) << 64)));
   run_test("NaN()", 5,
-           SELECT_CONST(0x7ff8000000000000, (__uint128_t(0x7fffc00000) << 40),
-                        (__uint128_t(0x7fff800000000000) << 64)));
+           SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+                        (UInt128(0x7fff800000000000) << 64)));
   run_test("NaN(1234)", 9,
            SELECT_CONST(0x7ff80000000004d2,
-                        (__uint128_t(0x7fffc00000) << 40) + __uint128_t(0x4d2),
-                        (__uint128_t(0x7fff800000000000) << 64) +
-                            __uint128_t(0x4d2)));
+                        (UInt128(0x7fffc00000) << 40) + UInt128(0x4d2),
+                        (UInt128(0x7fff800000000000) << 64) + UInt128(0x4d2)));
   run_test("NaN(0xffffffffffff)", 19,
            SELECT_CONST(0x7ff8ffffffffffff,
-                        (__uint128_t(0x7fffc000ff) << 40) +
-                            __uint128_t(0xffffffffff),
-                        (__uint128_t(0x7fff800000000000) << 64) +
-                            __uint128_t(0xffffffffffff)));
+                        (UInt128(0x7fffc000ff) << 40) + UInt128(0xffffffffff),
+                        (UInt128(0x7fff800000000000) << 64) +
+                            UInt128(0xffffffffffff)));
   run_test("NaN(0xfffffffffffff)", 20,
            SELECT_CONST(0x7fffffffffffffff,
-                        (__uint128_t(0x7fffc00fff) << 40) +
-                            __uint128_t(0xffffffffff),
-                        (__uint128_t(0x7fff800000000000) << 64) +
-                            __uint128_t(0xfffffffffffff)));
+                        (UInt128(0x7fffc00fff) << 40) + UInt128(0xffffffffff),
+                        (UInt128(0x7fff800000000000) << 64) +
+                            UInt128(0xfffffffffffff)));
   run_test("NaN(0xffffffffffffffff)", 23,
            SELECT_CONST(0x7fffffffffffffff,
-                        (__uint128_t(0x7fffffffff) << 40) +
-                            __uint128_t(0xffffffffff),
-                        (__uint128_t(0x7fff800000000000) << 64) +
-                            __uint128_t(0xffffffffffffffff)));
+                        (UInt128(0x7fffffffff) << 40) + UInt128(0xffffffffff),
+                        (UInt128(0x7fff800000000000) << 64) +
+                            UInt128(0xffffffffffffffff)));
   run_test("NaN( 1234)", 3,
-           SELECT_CONST(0x7ff8000000000000, (__uint128_t(0x7fffc00000) << 40),
-                        (__uint128_t(0x7fff800000000000) << 64)));
+           SELECT_CONST(0x7ff8000000000000, (UInt128(0x7fffc00000) << 40),
+                        (UInt128(0x7fff800000000000) << 64)));
 }

diff  --git a/libc/utils/UnitTest/CMakeLists.txt b/libc/utils/UnitTest/CMakeLists.txt
index 622dbb426c5ca..bc9e7b3e607da 100644
--- a/libc/utils/UnitTest/CMakeLists.txt
+++ b/libc/utils/UnitTest/CMakeLists.txt
@@ -5,7 +5,7 @@ add_library(
   LibcTest.h
 )
 target_include_directories(LibcUnitTest PUBLIC ${LIBC_SOURCE_DIR})
-add_dependencies(LibcUnitTest libc.src.__support.CPP.type_traits)
+add_dependencies(LibcUnitTest libc.src.__support.CPP.type_traits libc.src.__support.CPP.uint128)
 target_link_libraries(LibcUnitTest PUBLIC libc_test_utils)
 
 add_library(
@@ -71,6 +71,7 @@ target_link_libraries(LibcPrintfHelpers LibcUnitTest)
 add_dependencies(
   LibcPrintfHelpers
   LibcUnitTest
-  libc.utils.UnitTest.string_utils
+  libc.src.__support.CPP.uint128
   libc.src.stdio.printf_core.core_structs
+  libc.utils.UnitTest.string_utils
 )

diff  --git a/libc/utils/UnitTest/LibcTest.cpp b/libc/utils/UnitTest/LibcTest.cpp
index f37440dc4bde4..42b99a2b951c0 100644
--- a/libc/utils/UnitTest/LibcTest.cpp
+++ b/libc/utils/UnitTest/LibcTest.cpp
@@ -8,7 +8,7 @@
 
 #include "LibcTest.h"
 
-#include "src/__support/CPP/UInt.h"
+#include "src/__support/CPP/UInt128.h"
 #include "utils/testutils/ExecuteFunction.h"
 #include <cassert>
 #include <iostream>
@@ -42,11 +42,15 @@ describeValue(ValType Value) {
 }
 
 std::string describeValue(std::string Value) { return std::string(Value); }
-#ifdef __SIZEOF_INT128__
-// When the value is __uint128_t, also show its hexadecimal digits.
-// Using template to force exact match, prevent ambiguous promotion.
-std::string describeValue128(__uint128_t Value) {
-  std::string S(sizeof(__uint128_t) * 2, '0');
+
+// When the value is UInt128 or __uint128_t, show its hexadecimal digits.
+// We cannot just use a UInt128 specialization as that resolves to only
+// one type, UInt<128> or __uint128_t. We want both overloads as we want to
+// be able to unittest UInt<128> on platforms where UInt128 resolves to
+// UInt128.
+template <typename UInt128Type>
+std::string describeValue128(UInt128Type Value) {
+  std::string S(sizeof(UInt128) * 2, '0');
 
   for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value >>= 4) {
     unsigned char Mod = static_cast<unsigned char>(Value) & 15;
@@ -56,26 +60,16 @@ std::string describeValue128(__uint128_t Value) {
   return "0x" + S;
 }
 
-template <> std::string describeValue<__int128_t>(__int128_t Value) {
-  return describeValue128(Value);
-}
+#ifdef __SIZEOF_INT128__
 template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
   return describeValue128(Value);
 }
 #endif
 
-// When the value is UInt<128>, also show its hexadecimal digits.
 template <>
 std::string
 describeValue<__llvm_libc::cpp::UInt<128>>(__llvm_libc::cpp::UInt<128> Value) {
-  std::string S(sizeof(__llvm_libc::cpp::UInt<128>) * 2, '0');
-
-  for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value = Value >> 4) {
-    unsigned char Mod = static_cast<unsigned char>(Value) & 15;
-    *I = Mod < 10 ? '0' + Mod : 'a' + Mod - 10;
-  }
-
-  return "0x" + S;
+  return describeValue128(Value);
 }
 
 template <typename ValType>
@@ -234,17 +228,6 @@ template bool test<long long>(RunContext *Ctx, TestCondition Cond,
                               const char *RHSStr, const char *File,
                               unsigned long Line);
 
-#ifdef __SIZEOF_INT128__
-template bool test<__int128_t>(RunContext *Ctx, TestCondition Cond,
-                               __int128_t LHS, __int128_t RHS,
-                               const char *LHSStr, const char *RHSStr,
-                               const char *File, unsigned long Line);
-#endif
-template bool test<__llvm_libc::cpp::UInt<128>>(
-    RunContext *Ctx, TestCondition Cond, __llvm_libc::cpp::UInt<128> LHS,
-    __llvm_libc::cpp::UInt<128> RHS, const char *LHSStr, const char *RHSStr,
-    const char *File, unsigned long Line);
-
 template bool test<unsigned char>(RunContext *Ctx, TestCondition Cond,
                                   unsigned char LHS, unsigned char RHS,
                                   const char *LHSStr, const char *RHSStr,
@@ -275,13 +258,24 @@ template bool test<unsigned long long>(RunContext *Ctx, TestCondition Cond,
                                        const char *LHSStr, const char *RHSStr,
                                        const char *File, unsigned long Line);
 
+// We cannot just use a single UInt128 specialization as that resolves to only
+// one type, UInt<128> or __uint128_t. We want both overloads as we want to
+// be able to unittest UInt<128> on platforms where UInt128 resolves to
+// UInt128.
 #ifdef __SIZEOF_INT128__
+// When builtin __uint128_t type is available, include its specialization
+// also.
 template bool test<__uint128_t>(RunContext *Ctx, TestCondition Cond,
                                 __uint128_t LHS, __uint128_t RHS,
                                 const char *LHSStr, const char *RHSStr,
                                 const char *File, unsigned long Line);
 #endif
 
+template bool test<__llvm_libc::cpp::UInt<128>>(
+    RunContext *Ctx, TestCondition Cond, __llvm_libc::cpp::UInt<128> LHS,
+    __llvm_libc::cpp::UInt<128> RHS, const char *LHSStr, const char *RHSStr,
+    const char *File, unsigned long Line);
+
 } // namespace internal
 
 bool Test::testStrEq(const char *LHS, const char *RHS, const char *LHSStr,

diff  --git a/libc/utils/UnitTest/PrintfMatcher.cpp b/libc/utils/UnitTest/PrintfMatcher.cpp
index f30b1ce31b0d0..cd17060faa8b1 100644
--- a/libc/utils/UnitTest/PrintfMatcher.cpp
+++ b/libc/utils/UnitTest/PrintfMatcher.cpp
@@ -7,6 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "PrintfMatcher.h"
+
+#include "src/__support/CPP/UInt128.h"
 #include "src/stdio/printf_core/core_structs.h"
 
 #include "utils/UnitTest/StringUtils.h"
@@ -70,8 +72,7 @@ void display(testutils::StreamWrapper &stream, FormatSection form) {
                     reinterpret_cast<uintptr_t>(form.conv_val_ptr))
              << "\n";
     else if (form.conv_name != '%')
-      stream << "\tvalue: " << int_to_hex<__uint128_t>(form.conv_val_raw)
-             << "\n";
+      stream << "\tvalue: " << int_to_hex<UInt128>(form.conv_val_raw) << "\n";
   }
 }
 } // anonymous namespace

diff  --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 0509790069e7e..1ab1469be7fba 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -72,7 +72,7 @@ cc_library(
 cc_library(
     name = "__support_cpp_limits",
     hdrs = ["src/__support/CPP/Limits.h"],
-    deps = [":libc_root"],
+    deps = [":libc_root", "__support_cpp_uint"],
 )
 
 cc_library(
@@ -89,6 +89,14 @@ cc_library(
     deps = [":libc_root","__support_cpp_array"],
 )
 
+cc_library(
+    name = "__support_cpp_uint128",
+    hdrs = [
+        "src/__support/CPP/UInt128.h",
+    ],
+    deps = [":libc_root",":__support_cpp_uint"],
+)
+
 cc_library(
     name = "__support_cpp_type_traits",
     hdrs = [
@@ -174,6 +182,7 @@ cc_library(
         ":__support_common",
         ":__support_cpp_bit",
         ":__support_cpp_type_traits",
+        ":__support_cpp_uint128",
         ":libc_root",
     ],
 )
@@ -201,6 +210,7 @@ cc_library(
         ":__support_common",
         ":__support_cpp_bit",
         ":__support_cpp_type_traits",
+        ":__support_cpp_uint128",
         ":__support_fputil",
         ":libc_root",
     ],
@@ -226,6 +236,7 @@ cc_library(
         ":__support_common",
         ":__support_cpp_bit",
         ":__support_cpp_type_traits",
+        ":__support_cpp_uint128",
         ":__support_fputil",
         ":libc_root",
     ],


        


More information about the libc-commits mailing list