8#include "tpde/base.hpp"
13constexpr T align_down(T val, std::type_identity_t<T> align) {
15 assert((align & (align - 1)) == 0);
16 return val & ~(align - 1);
20constexpr T align_up(T val, std::type_identity_t<T> align) {
22 assert((align & (align - 1)) == 0);
23 return (val + (align - 1)) & ~(align - 1);
32constexpr inline u8 cnt_tz<u8>(
const u8 val) {
33 return __builtin_ctz(val);
37constexpr inline u16 cnt_tz<u16>(
const u16 val) {
38 return __builtin_ctz(val);
42constexpr inline u32 cnt_tz<u32>(
const u32 val) {
43 return __builtin_ctz(val);
47constexpr inline u64 cnt_tz<u64>(
const u64 val) {
48 return __builtin_ctzll(val);
57constexpr u8 cnt_lz<u8>(
const u8 val) {
58 return __builtin_clz((u32)val) - 24;
62constexpr u16 cnt_lz<u16>(
const u16 val) {
63 return __builtin_clz((u32)val) - 16;
67constexpr u32 cnt_lz<u32>(
const u32 val) {
68 return __builtin_clz(val);
72constexpr u64 cnt_lz<u64>(
const u64 val) {
73 return __builtin_clzll(val);
76inline u64 zext(
const u64 val,
const unsigned bits) {
77 assert(bits > 0 && bits < 64 &&
"invalid sext bit width");
78 return val & ((u64{1} << bits) - 1);
81inline i64 sext(
const u64 val,
const unsigned bits) {
82 assert(bits > 0 && bits < 64 &&
"invalid sext bit width");
83 return (i64)(val << (64 - bits)) >> (64 - bits);
86constexpr unsigned uleb_len(u64 value) {
87 return value ? (64 - cnt_lz(value) + 6) / 7 : 1;
90constexpr unsigned uleb_write(u8 *dst, u64 value)
noexcept {
93 u8 write = value & 0b0111'1111;
99 *dst++ = write | 0b1000'0000;
103constexpr unsigned sleb_write(u8 *dst, i64 value)
noexcept {
106 u8 write = value & 0b0111'1111;
108 if ((value == 0 && (value & 0x40) == 0) || (value == -1 && value & 0x40)) {
112 *dst++ = write | 0b1000'0000;
116template <
bool Reverse = false>
117struct BitSetIterator {
123 Iter &operator++() noexcept {
124 if constexpr (Reverse) {
125 set = set & ~(1ull << (63 - cnt_lz(set)));
127 set = set & (set - 1);
132 [[nodiscard]] u64 operator*() const noexcept {
134 if constexpr (Reverse) {
135 return 63 - cnt_lz(set);
141 [[nodiscard]]
bool operator!=(
const Iter &rhs)
const noexcept {
142 return rhs.set != set;
146 explicit BitSetIterator(
const u64 set) : set(set) {}
148 [[nodiscard]] Iter begin() const noexcept {
return Iter{.set = set}; }
150 [[nodiscard]] Iter end() const noexcept {
return Iter{.set = 0}; }