From 08e4a1a4dcbf07853f3c1a63adb64298fc236e3f Mon Sep 17 00:00:00 2001 From: Nick Johnson Date: Sun, 19 Dec 2021 15:46:55 -0600 Subject: [PATCH] AK+Everywhere: Replace __builtin bit functions In order to reduce our reliance on __builtin_{ffs, clz, ctz, popcount}, this commit removes all calls to these functions and replaces them with the equivalent functions in AK/BuiltinWrappers.h. --- AK/BitmapView.h | 68 +++++++++---------- AK/BuiltinWrappers.h | 23 ++++++- AK/Math.h | 19 +----- AK/Platform.h | 23 ------- AK/UFixedBigInt.h | 15 ++-- Kernel/Arch/x86/common/Processor.cpp | 9 +-- Kernel/Memory/PhysicalRegion.cpp | 3 +- Kernel/Memory/PhysicalZone.cpp | 3 +- Kernel/Scheduler.cpp | 5 +- Kernel/Storage/ATA/AHCIController.cpp | 5 +- Kernel/ThreadBlockers.cpp | 3 +- .../DevTools/UserspaceEmulator/SoftCPU.cpp | 3 +- Userland/Libraries/LibC/malloc.cpp | 3 +- .../BigInt/Algorithms/BitwiseOperations.cpp | 3 +- Userland/Libraries/LibGfx/BMPLoader.cpp | 5 +- Userland/Libraries/LibGfx/BitmapFont.cpp | 5 +- .../Libraries/LibJS/Runtime/GlobalObject.cpp | 3 +- .../Libraries/LibJS/Runtime/MathObject.cpp | 3 +- Userland/Libraries/LibM/math.cpp | 3 +- .../LibWasm/AbstractMachine/Operators.h | 19 ++---- 20 files changed, 108 insertions(+), 115 deletions(-) diff --git a/AK/BitmapView.h b/AK/BitmapView.h index 49319b39846..813385ac6e9 100644 --- a/AK/BitmapView.h +++ b/AK/BitmapView.h @@ -54,30 +54,30 @@ public: byte &= bitmask_first_byte[start % 8]; if (first == last) { byte &= bitmask_last_byte[(start + len) % 8]; - count = __builtin_popcount(byte); + count = popcount(byte); } else { - count = __builtin_popcount(byte); + count = popcount(byte); // Don't access *last if it's out of bounds if (last < &m_data[size_in_bytes()]) { byte = *last; byte &= bitmask_last_byte[(start + len) % 8]; - count += __builtin_popcount(byte); + count += popcount(byte); } if (++first < last) { - const u32* ptr32 = (const u32*)(((FlatPtr)first + sizeof(u32) - 1) & ~(sizeof(u32) - 1)); - if ((const u8*)ptr32 > last) - ptr32 = (const u32*)last; - while (first < (const u8*)ptr32) { - count += __builtin_popcount(*first); + const size_t* ptr_large = (const size_t*)(((FlatPtr)first + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1)); + if ((const u8*)ptr_large > last) + ptr_large = (const size_t*)last; + while (first < (const u8*)ptr_large) { + count += popcount(*first); first++; } - const u32* last32 = (const u32*)((FlatPtr)last & ~(sizeof(u32) - 1)); - while (ptr32 < last32) { - count += __builtin_popcountl(*ptr32); - ptr32++; + const size_t* last_large = (const size_t*)((FlatPtr)last & ~(sizeof(size_t) - 1)); + while (ptr_large < last_large) { + count += popcount(*ptr_large); + ptr_large++; } - for (first = (const u8*)ptr32; first < last; first++) - count += __builtin_popcount(*first); + for (first = (const u8*)ptr_large; first < last; first++) + count += popcount(*first); } } @@ -100,34 +100,34 @@ public: // We will use hint as what it is: a hint. Because we try to // scan over entire 32 bit words, we may start searching before // the hint! - const u32* ptr32 = (const u32*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(u32) - 1)); - if ((const u8*)ptr32 < &m_data[0]) { - ptr32++; + const size_t* ptr_large = (const size_t*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(size_t) - 1)); + if ((const u8*)ptr_large < &m_data[0]) { + ptr_large++; // m_data isn't aligned, check first bytes - size_t start_ptr32 = (const u8*)ptr32 - &m_data[0]; + size_t start_ptr_large = (const u8*)ptr_large - &m_data[0]; size_t i = 0; u8 byte = VALUE ? 0x00 : 0xff; - while (i < start_ptr32 && m_data[i] == byte) + while (i < start_ptr_large && m_data[i] == byte) i++; - if (i < start_ptr32) { + if (i < start_ptr_large) { byte = m_data[i]; if constexpr (!VALUE) byte = ~byte; VERIFY(byte != 0); - return i * 8 + __builtin_ffs(byte) - 1; + return i * 8 + bit_scan_forward(byte) - 1; } } - u32 val32 = VALUE ? 0x0 : 0xffffffff; - const u32* end32 = (const u32*)((FlatPtr)end & ~(sizeof(u32) - 1)); - while (ptr32 < end32 && *ptr32 == val32) - ptr32++; + size_t val_large = VALUE ? 0x0 : NumericLimits::max(); + const size_t* end_large = (const size_t*)((FlatPtr)end & ~(sizeof(size_t) - 1)); + while (ptr_large < end_large && *ptr_large == val_large) + ptr_large++; - if (ptr32 == end32) { + if (ptr_large == end_large) { // We didn't find anything, check the remaining few bytes (if any) u8 byte = VALUE ? 0x00 : 0xff; - size_t i = (const u8*)ptr32 - &m_data[0]; + size_t i = (const u8*)ptr_large - &m_data[0]; size_t byte_count = m_size / 8; VERIFY(i <= byte_count); while (i < byte_count && m_data[i] == byte) @@ -137,7 +137,7 @@ public: return {}; // We already checked from the beginning // Try scanning before the hint - end = (const u8*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(u32) - 1)); + end = (const u8*)((FlatPtr)&m_data[hint / 8] & ~(sizeof(size_t) - 1)); hint = 0; continue; } @@ -145,16 +145,16 @@ public: if constexpr (!VALUE) byte = ~byte; VERIFY(byte != 0); - return i * 8 + __builtin_ffs(byte) - 1; + return i * 8 + bit_scan_forward(byte) - 1; } // NOTE: We don't really care about byte ordering. We found *one* // free bit, just calculate the position and return it - val32 = *ptr32; + val_large = *ptr_large; if constexpr (!VALUE) - val32 = ~val32; - VERIFY(val32 != 0); - return ((const u8*)ptr32 - &m_data[0]) * 8 + __builtin_ffsl(val32) - 1; + val_large = ~val_large; + VERIFY(val_large != 0); + return ((const u8*)ptr_large - &m_data[0]) * 8 + bit_scan_forward(val_large) - 1; } } @@ -184,7 +184,7 @@ public: if constexpr (!VALUE) byte = ~byte; VERIFY(byte != 0); - return i * 8 + __builtin_ffs(byte) - 1; + return i * 8 + bit_scan_forward(byte) - 1; } Optional find_first_set() const { return find_first(); } diff --git a/AK/BuiltinWrappers.h b/AK/BuiltinWrappers.h index 79f3a61a451..c095b7308da 100644 --- a/AK/BuiltinWrappers.h +++ b/AK/BuiltinWrappers.h @@ -7,7 +7,6 @@ #pragma once #include "Concepts.h" -#include "Platform.h" template inline constexpr int popcount(IntType value) @@ -108,3 +107,25 @@ inline constexpr int count_leading_zeroes_safe(IntType value) return 8 * sizeof(IntType); return count_leading_zeroes(value); } + +// 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 +inline constexpr int bit_scan_forward(IntType value) +{ +#if defined(__GNUC__) || defined(__clang__) + static_assert(sizeof(IntType) <= sizeof(unsigned long long)); + if constexpr (sizeof(IntType) <= sizeof(unsigned int)) + return __builtin_ffs(value); + if constexpr (sizeof(IntType) == sizeof(unsigned long)) + return __builtin_ffsl(value); + if constexpr (sizeof(IntType) == sizeof(unsigned long long)) + return __builtin_ffsll(value); + VERIFY_NOT_REACHED(); +#else + if (value == 0) + return 0; + return 1 + count_trailing_zeroes(static_cast>(value)); +#endif +} diff --git a/AK/Math.h b/AK/Math.h index d7aaf9ed111..ed6d91c3678 100644 --- a/AK/Math.h +++ b/AK/Math.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -45,21 +46,6 @@ constexpr size_t product_odd() { return value * product_odd(); } return __builtin_##function##f(args); \ } -#define INTEGER_BUILTIN(name) \ - template \ - constexpr T name(T x) \ - { \ - if constexpr (sizeof(T) == sizeof(long long)) \ - return __builtin_##name##ll(x); \ - if constexpr (sizeof(T) == sizeof(long)) \ - return __builtin_##name##l(x); \ - return __builtin_##name(x); \ - } - -INTEGER_BUILTIN(clz); -INTEGER_BUILTIN(ctz); -INTEGER_BUILTIN(popcnt); - namespace Division { template constexpr T fmod(T x, T y) @@ -312,7 +298,7 @@ constexpr T log2(T x) template constexpr T log2(T x) { - return x ? 8 * sizeof(T) - clz(x) : 0; + return x ? 8 * sizeof(T) - count_leading_zeroes(static_cast>(x)) : 0; } template @@ -468,6 +454,5 @@ constexpr T pow(T x, T y) } #undef CONSTEXPR_STATE -#undef INTEGER_BUILTIN } diff --git a/AK/Platform.h b/AK/Platform.h index f57afce7988..d69ceba3af1 100644 --- a/AK/Platform.h +++ b/AK/Platform.h @@ -106,29 +106,6 @@ extern "C" { # endif #endif -#ifdef __cplusplus -ALWAYS_INLINE int count_trailing_zeroes_32(unsigned int val) -{ -# if defined(__GNUC__) || defined(__clang__) - return __builtin_ctz(val); -# else - for (u8 i = 0; i < 32; ++i) { - if ((val >> i) & 1) { - return i; - } - } - return 0; -# endif -} - -ALWAYS_INLINE int count_trailing_zeroes_32_safe(unsigned int val) -{ - if (val == 0) - return 32; - return count_trailing_zeroes_32(val); -} -#endif - #ifdef AK_OS_BSD_GENERIC # define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC # define CLOCK_REALTIME_COARSE CLOCK_REALTIME diff --git a/AK/UFixedBigInt.h b/AK/UFixedBigInt.h index 762a4eb32df..52f02971d3d 100644 --- a/AK/UFixedBigInt.h +++ b/AK/UFixedBigInt.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -90,9 +91,9 @@ public: constexpr size_t clz() const requires(IsSame) { if (m_high) - return __builtin_clzll(m_high); + return count_leading_zeroes(m_high); else - return sizeof(T) * 8 + __builtin_clzll(m_low); + return sizeof(T) * 8 + count_leading_zeroes(m_low); } constexpr size_t clz() const requires(!IsSame) { @@ -104,9 +105,9 @@ public: constexpr size_t ctz() const requires(IsSame) { if (m_low) - return __builtin_ctzll(m_low); + return count_trailing_zeroes(m_low); else - return sizeof(T) * 8 + __builtin_ctzll(m_high); + return sizeof(T) * 8 + count_trailing_zeroes(m_high); } constexpr size_t ctz() const requires(!IsSame) { @@ -598,7 +599,7 @@ public: R x1 = *this; R x2 = *this * *this; u64 exp_copy = exp; - for (ssize_t i = sizeof(u64) * 8 - __builtin_clzll(exp) - 2; i >= 0; --i) { + for (ssize_t i = sizeof(u64) * 8 - count_leading_zeroes(exp) - 2; i >= 0; --i) { if (exp_copy & 1u) { x2 *= x1; x1 *= x1; @@ -642,7 +643,7 @@ public: U res = 1; u64 exp_copy = exp; - for (size_t i = sizeof(u64) - __builtin_clzll(exp) - 1u; i < exp; ++i) { + for (size_t i = sizeof(u64) - count_leading_zeroes(exp) - 1u; i < exp; ++i) { res *= res; res %= mod; if (exp_copy & 1u) { @@ -682,7 +683,7 @@ public: constexpr size_t logn(u64 base) { // FIXME: proper rounding - return log2() / (sizeof(u64) - __builtin_clzll(base)); + return log2() / (sizeof(u64) - count_leading_zeroes(base)); } template requires(sizeof(U) > sizeof(u64)) constexpr size_t logn(U base) diff --git a/Kernel/Arch/x86/common/Processor.cpp b/Kernel/Arch/x86/common/Processor.cpp index d1a3576b7c8..7987f49425a 100644 --- a/Kernel/Arch/x86/common/Processor.cpp +++ b/Kernel/Arch/x86/common/Processor.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -771,13 +772,13 @@ u32 Processor::smp_wake_n_idle_processors(u32 wake_count) while (did_wake_count < wake_count) { // Try to get a set of idle CPUs and flip them to busy u32 idle_mask = s_idle_cpu_mask.load(AK::MemoryOrder::memory_order_relaxed) & ~(1u << current_id); - u32 idle_count = __builtin_popcountl(idle_mask); + u32 idle_count = popcount(idle_mask); if (idle_count == 0) break; // No (more) idle processor available u32 found_mask = 0; for (u32 i = 0; i < idle_count; i++) { - u32 cpu = __builtin_ffsl(idle_mask) - 1; + u32 cpu = bit_scan_forward(idle_mask) - 1; idle_mask &= ~(1u << cpu); found_mask |= 1u << cpu; } @@ -785,9 +786,9 @@ u32 Processor::smp_wake_n_idle_processors(u32 wake_count) idle_mask = s_idle_cpu_mask.fetch_and(~found_mask, AK::MemoryOrder::memory_order_acq_rel) & found_mask; if (idle_mask == 0) continue; // All of them were flipped to busy, try again - idle_count = __builtin_popcountl(idle_mask); + idle_count = popcount(idle_mask); for (u32 i = 0; i < idle_count; i++) { - u32 cpu = __builtin_ffsl(idle_mask) - 1; + u32 cpu = bit_scan_forward(idle_mask) - 1; idle_mask &= ~(1u << cpu); // Send an IPI to that CPU to wake it up. There is a possibility diff --git a/Kernel/Memory/PhysicalRegion.cpp b/Kernel/Memory/PhysicalRegion.cpp index c21fd990795..fb6794b2b0d 100644 --- a/Kernel/Memory/PhysicalRegion.cpp +++ b/Kernel/Memory/PhysicalRegion.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -80,7 +81,7 @@ OwnPtr PhysicalRegion::try_take_pages_from_beginning(unsigned pa NonnullRefPtrVector PhysicalRegion::take_contiguous_free_pages(size_t count) { auto rounded_page_count = next_power_of_two(count); - auto order = __builtin_ctz(rounded_page_count); + auto order = count_trailing_zeroes(rounded_page_count); Optional page_base; for (auto& zone : m_usable_zones) { diff --git a/Kernel/Memory/PhysicalZone.cpp b/Kernel/Memory/PhysicalZone.cpp index f533a20d171..65fcd75b75c 100644 --- a/Kernel/Memory/PhysicalZone.cpp +++ b/Kernel/Memory/PhysicalZone.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -31,7 +32,7 @@ PhysicalZone::PhysicalZone(PhysicalAddress base_address, size_t page_count) bucket.bitmap.grow(bitmap_size_for_order, false); } - auto first_order = __builtin_ctz(page_count); + auto first_order = count_trailing_zeroes(page_count); size_t block_size = 2u << first_order; auto& bucket = m_buckets[first_order]; size_t remaining_chunk_count = chunk_count; diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 10e80dfe1fa..c1ff0b24665 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -77,7 +78,7 @@ Thread& Scheduler::pull_next_runnable_thread() return g_ready_queues->with([&](auto& ready_queues) -> Thread& { auto priority_mask = ready_queues.mask; while (priority_mask != 0) { - auto priority = __builtin_ffsl(priority_mask); + auto priority = bit_scan_forward(priority_mask); VERIFY(priority > 0); auto& ready_queue = ready_queues.queues[--priority]; for (auto& thread : ready_queue.thread_list) { @@ -116,7 +117,7 @@ Thread* Scheduler::peek_next_runnable_thread() return g_ready_queues->with([&](auto& ready_queues) -> Thread* { auto priority_mask = ready_queues.mask; while (priority_mask != 0) { - auto priority = __builtin_ffsl(priority_mask); + auto priority = bit_scan_forward(priority_mask); VERIFY(priority > 0); auto& ready_queue = ready_queues.queues[--priority]; for (auto& thread : ready_queue.thread_list) { diff --git a/Kernel/Storage/ATA/AHCIController.cpp b/Kernel/Storage/ATA/AHCIController.cpp index 1524fbfa1ca..6d5aa9d8c63 100644 --- a/Kernel/Storage/ATA/AHCIController.cpp +++ b/Kernel/Storage/ATA/AHCIController.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -185,12 +186,12 @@ RefPtr AHCIController::device(u32 index) const { NonnullRefPtrVector connected_devices; u32 pi = hba().control_regs.pi; - u32 bit = __builtin_ffsl(pi); + u32 bit = bit_scan_forward(pi); while (bit) { dbgln_if(AHCI_DEBUG, "Checking implemented port {}, pi {:b}", bit - 1, pi); pi &= ~(1u << (bit - 1)); auto checked_device = device_by_port(bit - 1); - bit = __builtin_ffsl(pi); + bit = bit_scan_forward(pi); if (checked_device.is_null()) continue; connected_devices.append(checked_device.release_nonnull()); diff --git a/Kernel/ThreadBlockers.cpp b/Kernel/ThreadBlockers.cpp index 2ad4109a82f..466c902b743 100644 --- a/Kernel/ThreadBlockers.cpp +++ b/Kernel/ThreadBlockers.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -473,7 +474,7 @@ bool Thread::SignalBlocker::check_pending_signals(bool from_add_blocker) if (m_did_unblock) return false; - auto matching_pending_signal = __builtin_ffsl(thread().pending_signals() & m_pending_set); + auto matching_pending_signal = bit_scan_forward(thread().pending_signals() & m_pending_set); if (matching_pending_signal == 0) return false; diff --git a/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp b/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp index 614bd13ff84..9d66b074114 100644 --- a/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp +++ b/Userland/DevTools/UserspaceEmulator/SoftCPU.cpp @@ -8,6 +8,7 @@ #include "SoftCPU.h" #include "Emulator.h" #include +#include #include #include #include @@ -978,7 +979,7 @@ void SoftCPU::BOUND(const X86::Instruction&) { TODO_INSN(); } template ALWAYS_INLINE static T op_bsf(SoftCPU&, T value) { - return { (typename T::ValueType)__builtin_ctz(value.value()), value.shadow() }; + return { (typename T::ValueType)bit_scan_forward(value.value()), value.shadow() }; } template diff --git a/Userland/Libraries/LibC/malloc.cpp b/Userland/Libraries/LibC/malloc.cpp index e4268fb76c1..bdaf8b1f534 100644 --- a/Userland/Libraries/LibC/malloc.cpp +++ b/Userland/Libraries/LibC/malloc.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -437,7 +438,7 @@ void* malloc(size_t size) // _aligned_free(), so it can be easily implemented on top of malloc(). void* _aligned_malloc(size_t size, size_t alignment) { - if (__builtin_popcount(alignment) != 1) { + if (popcount(alignment) != 1) { errno = EINVAL; return nullptr; } diff --git a/Userland/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp b/Userland/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp index 38e4059246d..f0333d1940a 100644 --- a/Userland/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp +++ b/Userland/Libraries/LibCrypto/BigInt/Algorithms/BitwiseOperations.cpp @@ -6,6 +6,7 @@ */ #include "UnsignedBigIntegerAlgorithms.h" +#include namespace Crypto { @@ -153,7 +154,7 @@ FLATTEN void UnsignedBigIntegerAlgorithms::bitwise_not_without_allocation( auto last_word_index = right.length() - 1; auto last_word = right.words()[last_word_index]; - output.m_words[last_word_index] = ((u32)0xffffffffffffffff >> __builtin_clz(last_word)) & ~last_word; + output.m_words[last_word_index] = ((u32)0xffffffffffffffff >> count_leading_zeroes(last_word)) & ~last_word; } /** diff --git a/Userland/Libraries/LibGfx/BMPLoader.cpp b/Userland/Libraries/LibGfx/BMPLoader.cpp index d642117177b..1e5a0f0d6ff 100644 --- a/Userland/Libraries/LibGfx/BMPLoader.cpp +++ b/Userland/Libraries/LibGfx/BMPLoader.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -326,9 +327,9 @@ static void populate_dib_mask_info_if_needed(BMPLoadingContext& context) mask_sizes.append(0); continue; } - int trailing_zeros = count_trailing_zeroes_32(mask); + int trailing_zeros = count_trailing_zeroes(mask); // If mask is exactly `0xFFFFFFFF`, then we might try to count the trailing zeros of 0x00000000 here, so we need the safe version: - int size = count_trailing_zeroes_32_safe(~(mask >> trailing_zeros)); + int size = count_trailing_zeroes_safe(~(mask >> trailing_zeros)); if (size > 8) { // Drop lowest bits if mask is longer than 8 bits. trailing_zeros += size - 8; diff --git a/Userland/Libraries/LibGfx/BitmapFont.cpp b/Userland/Libraries/LibGfx/BitmapFont.cpp index d7d55e0dd66..6d2f1b6ee66 100644 --- a/Userland/Libraries/LibGfx/BitmapFont.cpp +++ b/Userland/Libraries/LibGfx/BitmapFont.cpp @@ -6,6 +6,7 @@ #include "BitmapFont.h" #include "Emoji.h" +#include #include #include #include @@ -95,7 +96,7 @@ NonnullRefPtr BitmapFont::masked_character_set() const } size_t new_glyph_count { 0 }; for (size_t i = 0; i < new_range_mask_size; ++i) { - new_glyph_count += 256 * __builtin_popcount(new_range_mask[i]); + new_glyph_count += 256 * popcount(new_range_mask[i]); } size_t bytes_per_glyph = sizeof(u32) * m_glyph_height; auto* new_rows = static_cast(calloc(new_glyph_count, bytes_per_glyph)); @@ -191,7 +192,7 @@ RefPtr BitmapFont::load_from_memory(const u8* data) size_t glyph_count { 0 }; u8* range_mask = const_cast(data + sizeof(FontFileHeader)); for (size_t i = 0; i < header.range_mask_size; ++i) - glyph_count += 256 * __builtin_popcount(range_mask[i]); + glyph_count += 256 * popcount(range_mask[i]); u8* rows = range_mask + header.range_mask_size; u8* widths = (u8*)(rows) + glyph_count * bytes_per_glyph; return adopt_ref(*new BitmapFont(String(header.name), String(header.family), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing, header.range_mask_size, range_mask, header.baseline, header.mean_line, header.presentation_size, header.weight, header.slope)); diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp index 6d2df8eb8ef..2d74a8b1b0d 100644 --- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -500,7 +501,7 @@ static ThrowCompletionOr decode(JS::GlobalObject& global_object, const S continue; } - auto leading_ones = count_trailing_zeroes_32_safe(~decoded_code_unit) - 24; + auto leading_ones = count_trailing_zeroes_safe(static_cast(~decoded_code_unit)) - 24; if (leading_ones == 1 || leading_ones > 4) return global_object.vm().throw_completion(global_object, ErrorType::URIMalformed); diff --git a/Userland/Libraries/LibJS/Runtime/MathObject.cpp b/Userland/Libraries/LibJS/Runtime/MathObject.cpp index 562cee40df2..7ba81c9c6ab 100644 --- a/Userland/Libraries/LibJS/Runtime/MathObject.cpp +++ b/Userland/Libraries/LibJS/Runtime/MathObject.cpp @@ -6,6 +6,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -303,7 +304,7 @@ JS_DEFINE_NATIVE_FUNCTION(MathObject::clz32) auto number = TRY(vm.argument(0).to_u32(global_object)); if (number == 0) return Value(32); - return Value(__builtin_clz(number)); + return Value(count_leading_zeroes(number)); } // 21.3.2.2 Math.acos ( x ), https://tc39.es/ecma262/#sec-math.acos diff --git a/Userland/Libraries/LibM/math.cpp b/Userland/Libraries/LibM/math.cpp index 40eecdcf944..b0a34590647 100644 --- a/Userland/Libraries/LibM/math.cpp +++ b/Userland/Libraries/LibM/math.cpp @@ -5,6 +5,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -278,7 +279,7 @@ static FloatT internal_scalbn(FloatT x, int exponent) NOEXCEPT return extractor.d; } - unsigned leading_mantissa_zeroes = extractor.mantissa == 0 ? 32 : __builtin_clz(extractor.mantissa); + unsigned leading_mantissa_zeroes = extractor.mantissa == 0 ? 32 : count_leading_zeroes(extractor.mantissa); int shift = min((int)leading_mantissa_zeroes, exponent); exponent = max(exponent - shift, 0); diff --git a/Userland/Libraries/LibWasm/AbstractMachine/Operators.h b/Userland/Libraries/LibWasm/AbstractMachine/Operators.h index de06a3cb796..4d8560abc93 100644 --- a/Userland/Libraries/LibWasm/AbstractMachine/Operators.h +++ b/Userland/Libraries/LibWasm/AbstractMachine/Operators.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include @@ -176,10 +177,8 @@ struct CountLeadingZeros { if (lhs == 0) return sizeof(Lhs) * CHAR_BIT; - if constexpr (sizeof(Lhs) == 4) - return __builtin_clz(lhs); - else if constexpr (sizeof(Lhs) == 8) - return __builtin_clzll(lhs); + if constexpr (sizeof(Lhs) == 4 || sizeof(Lhs) == 8) + return count_leading_zeroes(MakeUnsigned(lhs)); else VERIFY_NOT_REACHED(); } @@ -193,10 +192,8 @@ struct CountTrailingZeros { if (lhs == 0) return sizeof(Lhs) * CHAR_BIT; - if constexpr (sizeof(Lhs) == 4) - return __builtin_ctz(lhs); - else if constexpr (sizeof(Lhs) == 8) - return __builtin_ctzll(lhs); + if constexpr (sizeof(Lhs) == 4 || sizeof(Lhs) == 8) + return count_trailing_zeroes(MakeUnsigned(lhs)); else VERIFY_NOT_REACHED(); } @@ -207,10 +204,8 @@ struct PopCount { template auto operator()(Lhs lhs) const { - if constexpr (sizeof(Lhs) == 4) - return __builtin_popcount(lhs); - else if constexpr (sizeof(Lhs) == 8) - return __builtin_popcountll(lhs); + if constexpr (sizeof(Lhs) == 4 || sizeof(Lhs) == 8) + return popcount(MakeUnsigned(lhs)); else VERIFY_NOT_REACHED(); }