summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
authorNick Johnson <sylvyrfysh@gmail.com>2021-12-12 16:52:57 -0600
committerAndreas Kling <kling@serenityos.org>2021-12-18 23:36:08 +0100
commit548529ace403130b88072d548277f489eaaf4d9e (patch)
tree0c9cf4d35f38c95c2beba51139799c19ba6dc2a5 /AK
parent01eefc344a63e5b64a23d9c1c71ddc78bfcb80ef (diff)
downloadserenity-548529ace403130b88072d548277f489eaaf4d9e.zip
AK: Add BuiltinWrappers.h
The goal of this file is to enable C++ overloaded functions for standard builtin functions that we use. It contains fallback implementations for systems that do not have the builtins available.
Diffstat (limited to 'AK')
-rw-r--r--AK/BuiltinWrappers.h110
1 files changed, 110 insertions, 0 deletions
diff --git a/AK/BuiltinWrappers.h b/AK/BuiltinWrappers.h
new file mode 100644
index 0000000000..79f3a61a45
--- /dev/null
+++ b/AK/BuiltinWrappers.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2021, Nick Johnson <sylvyrfysh@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include "Concepts.h"
+#include "Platform.h"
+
+template<Unsigned IntType>
+inline constexpr int popcount(IntType value)
+{
+#if defined(__GNUC__) || defined(__clang__)
+ static_assert(sizeof(IntType) <= sizeof(unsigned long long));
+ if constexpr (sizeof(IntType) <= sizeof(unsigned int))
+ return __builtin_popcount(value);
+ if constexpr (sizeof(IntType) == sizeof(unsigned long))
+ return __builtin_popcountl(value);
+ if constexpr (sizeof(IntType) == sizeof(unsigned long long))
+ return __builtin_popcountll(value);
+ VERIFY_NOT_REACHED();
+#else
+ int ones = 0;
+ for (size_t i = 0; i < 8 * sizeof(IntType); ++i) {
+ if ((val >> i) & 1) {
+ ++ones;
+ }
+ }
+ return ones;
+#endif
+}
+
+// The function will return the number of trailing zeroes in the type. If
+// the given number if zero, this function may contain undefined
+// behavior, or it may return the number of bits in the number. If
+// this function can be called with zero, the use of
+// count_trailing_zeroes_safe is preferred.
+template<Unsigned IntType>
+inline constexpr int count_trailing_zeroes(IntType value)
+{
+#if defined(__GNUC__) || defined(__clang__)
+ static_assert(sizeof(IntType) <= sizeof(unsigned long long));
+ if constexpr (sizeof(IntType) <= sizeof(unsigned int))
+ return __builtin_ctz(value);
+ if constexpr (sizeof(IntType) == sizeof(unsigned long))
+ return __builtin_ctzl(value);
+ if constexpr (sizeof(IntType) == sizeof(unsigned long long))
+ return __builtin_ctzll(value);
+ VERIFY_NOT_REACHED();
+#else
+ for (size_t i = 0; i < 8 * sizeof(IntType); ++i) {
+ if ((val >> i) & 1) {
+ return i;
+ }
+ }
+ return 8 * sizeof(IntType);
+#endif
+}
+
+// The function will return the number of trailing zeroes in the type. If
+// the given number is zero, this function will return the number of bits
+// bits in the IntType.
+template<Unsigned IntType>
+inline constexpr int count_trailing_zeroes_safe(IntType value)
+{
+ if (value == 0)
+ return 8 * sizeof(IntType);
+ return count_trailing_zeroes(value);
+}
+
+// The function will return the number of leading zeroes in the type. If
+// the given number if zero, this function may contain undefined
+// behavior, or it may return the number of bits in the number. If
+// this function can be called with zero, the use of
+// count_leading_zeroes_safe is preferred.
+template<Unsigned IntType>
+inline constexpr int count_leading_zeroes(IntType value)
+{
+#if defined(__GNUC__) || defined(__clang__)
+ static_assert(sizeof(IntType) <= sizeof(unsigned long long));
+ if constexpr (sizeof(IntType) <= sizeof(unsigned int))
+ return __builtin_clz(value) - (32 - (8 * sizeof(IntType)));
+ if constexpr (sizeof(IntType) == sizeof(unsigned long))
+ return __builtin_clzl(value);
+ if constexpr (sizeof(IntType) == sizeof(unsigned long long))
+ return __builtin_clzll(value);
+ VERIFY_NOT_REACHED();
+#else
+ // Wrap around, catch going past zero by noticing that i is greater than the number of bits in the number
+ for (size_t i = (8 * sizeof(IntType)) - 1; i < 8 * sizeof(IntType); --i) {
+ if ((val >> i) & 1) {
+ return i;
+ }
+ }
+ return 8 * sizeof(IntType);
+#endif
+}
+
+// The function will return the number of leading zeroes in the type. If
+// the given number is zero, this function will return the number of bits
+// in the IntType.
+template<Unsigned IntType>
+inline constexpr int count_leading_zeroes_safe(IntType value)
+{
+ if (value == 0)
+ return 8 * sizeof(IntType);
+ return count_leading_zeroes(value);
+}