[libc-commits] [libc] b62d72f - [libc] Add support for 128 bit ints in limits.h

Michael Jones via libc-commits libc-commits at lists.llvm.org
Tue Sep 28 16:50:20 PDT 2021


Author: Michael Jones
Date: 2021-09-28T23:50:16Z
New Revision: b62d72f3c542729349633c5f77697fe24921251d

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

LOG: [libc] Add support for 128 bit ints in limits.h

Also, this adds unit tests to check that limits.h complies with the C
standard.

Reviewed By: sivachandra

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

Added: 
    libc/test/utils/CPP/limits_test.cpp

Modified: 
    libc/test/utils/CPP/CMakeLists.txt
    libc/utils/CPP/Limits.h
    libc/utils/CPP/TypeTraits.h
    libc/utils/UnitTest/LibcTest.cpp

Removed: 
    


################################################################################
diff  --git a/libc/test/utils/CPP/CMakeLists.txt b/libc/test/utils/CPP/CMakeLists.txt
index 580fed5923e89..09c43d64ce938 100644
--- a/libc/test/utils/CPP/CMakeLists.txt
+++ b/libc/test/utils/CPP/CMakeLists.txt
@@ -20,6 +20,16 @@ add_libc_unittest(
     libc.utils.CPP.standalone_cpp
 )
 
+add_libc_unittest(
+  limits_test
+  SUITE
+    libc_cpp_utils_unittests
+  SRCS
+    limits_test.cpp
+  DEPENDS
+    libc.utils.CPP.standalone_cpp
+)
+
 add_libc_unittest(
   arrayref_test
   SUITE

diff  --git a/libc/test/utils/CPP/limits_test.cpp b/libc/test/utils/CPP/limits_test.cpp
new file mode 100644
index 0000000000000..6904a728c4cb1
--- /dev/null
+++ b/libc/test/utils/CPP/limits_test.cpp
@@ -0,0 +1,49 @@
+//===-- Unittests for Limits ----------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "utils/CPP/Limits.h"
+#include "utils/UnitTest/Test.h"
+
+// This just checks against the C spec, almost all implementations will surpass
+// this.
+TEST(LlvmLibcLimitsTest, LimitsFollowSpec) {
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<int>::max(), INT_MAX);
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<int>::min(), INT_MIN);
+
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<unsigned int>::max(), UINT_MAX);
+
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<long>::max(), LONG_MAX);
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<long>::min(), LONG_MIN);
+
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<unsigned long>::max(), ULONG_MAX);
+
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<long long>::max(), LLONG_MAX);
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<long long>::min(), LLONG_MIN);
+
+  ASSERT_EQ(__llvm_libc::cpp::NumericLimits<unsigned long long>::max(),
+            ULLONG_MAX);
+}
+
+// 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);
+}

diff  --git a/libc/utils/CPP/Limits.h b/libc/utils/CPP/Limits.h
index ac327b30ee71c..393c3b6a031a1 100644
--- a/libc/utils/CPP/Limits.h
+++ b/libc/utils/CPP/Limits.h
@@ -52,6 +52,16 @@ template <> class NumericLimits<unsigned long long> {
   static constexpr unsigned long long max() { return ULLONG_MAX; }
   static constexpr unsigned long long min() { return 0; }
 };
+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; }
+};
 
 } // namespace cpp
 } // namespace __llvm_libc

diff  --git a/libc/utils/CPP/TypeTraits.h b/libc/utils/CPP/TypeTraits.h
index 1f2c85af3a1cb..060d36e4e00e8 100644
--- a/libc/utils/CPP/TypeTraits.h
+++ b/libc/utils/CPP/TypeTraits.h
@@ -50,7 +50,7 @@ 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<__uint128_t, TypeNoCV>;
+      IsSameV<__uint128_t, TypeNoCV> || IsSameV<__int128_t, TypeNoCV>;
 };
 
 template <typename T> struct IsPointerTypeNoCV : public FalseValue {};

diff  --git a/libc/utils/UnitTest/LibcTest.cpp b/libc/utils/UnitTest/LibcTest.cpp
index dc5c0dd651ea4..710ee15bba3f9 100644
--- a/libc/utils/UnitTest/LibcTest.cpp
+++ b/libc/utils/UnitTest/LibcTest.cpp
@@ -44,7 +44,7 @@ std::string describeValue(std::string Value) { return std::string(Value); }
 
 // When the value is __uint128_t, also show its hexadecimal digits.
 // Using template to force exact match, prevent ambiguous promotion.
-template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
+std::string describeValue128(__uint128_t Value) {
   std::string S(sizeof(__uint128_t) * 2, '0');
 
   for (auto I = S.rbegin(), End = S.rend(); I != End; ++I, Value >>= 4) {
@@ -55,6 +55,13 @@ template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
   return "0x" + S;
 }
 
+template <> std::string describeValue<__int128_t>(__int128_t Value) {
+  return describeValue128(Value);
+}
+template <> std::string describeValue<__uint128_t>(__uint128_t Value) {
+  return describeValue128(Value);
+}
+
 template <typename ValType>
 void explainDifference(ValType LHS, ValType RHS, const char *LHSStr,
                        const char *RHSStr, const char *File, unsigned long Line,
@@ -209,6 +216,11 @@ template bool Test::test<long long, 0>(TestCondition Cond, long long LHS,
                                        const char *RHSStr, const char *File,
                                        unsigned long Line);
 
+template bool Test::test<__int128_t, 0>(TestCondition Cond, __int128_t LHS,
+                                        __int128_t RHS, const char *LHSStr,
+                                        const char *RHSStr, const char *File,
+                                        unsigned long Line);
+
 template bool Test::test<unsigned char, 0>(TestCondition Cond,
                                            unsigned char LHS, unsigned char RHS,
                                            const char *LHSStr,


        


More information about the libc-commits mailing list