1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#ifndef ECMASCRIPT_BASE_BIT_HELPER_H 17#define ECMASCRIPT_BASE_BIT_HELPER_H 18 19#include <cstdint> 20#include <cstring> 21#include <limits> 22#include <type_traits> 23 24namespace panda::ecmascript::base { 25constexpr uint64_t pureNaN = 0x7FF8ULL << 48U; // Be sure return the NaN that is safe. 26template <class S, class R> 27union Data { 28 S src; 29 R dst; 30}; 31 32template <typename T> 33inline T ReadBuffer(void **buffer, size_t offset) 34{ 35 T result = *(reinterpret_cast<T *>(*buffer)); 36 *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + offset); 37 return result; 38} 39 40template <typename T> 41inline T ReadBuffer(void **buffer) 42{ 43 T result = *(reinterpret_cast<T *>(*buffer)); 44 *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result.offset_); 45 return result; 46} 47 48inline char *ReadBuffer(void **buffer) 49{ 50 auto result = reinterpret_cast<char *>(*buffer); 51 *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + strlen(result) + 1); 52 return result; 53} 54 55template <typename T> 56inline T *ReadBufferInSize(void **buffer) 57{ 58 T *result = reinterpret_cast<T *>(*buffer); 59 *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result->Size()); 60 return result; 61} 62 63template <typename T> 64inline constexpr uint32_t CountLeadingZeros(T value) 65{ 66 constexpr size_t RADIX = 2; 67 static_assert(std::is_integral<T>::value, "T must be integral"); 68 static_assert(std::is_unsigned<T>::value, "T must be unsigned"); 69 static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!"); 70 static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)"); 71 if (value == 0) { 72 return sizeof(T) * 8; // 8: Each byte has 8 bits 73 } 74 if (sizeof(T) == sizeof(uint64_t)) { 75 return __builtin_clzll(static_cast<uint64_t>(value)); 76 } 77 // 32 : 32 mean the bits of type T is less than 32 78 return __builtin_clz(static_cast<uint32_t>(value)) - (32 - std::numeric_limits<T>::digits); 79} 80 81inline constexpr uint32_t CountLeadingZeros32(uint32_t value) 82{ 83 return CountLeadingZeros(value); 84} 85 86inline constexpr uint32_t CountLeadingZeros64(uint64_t value) 87{ 88 return CountLeadingZeros(value); 89} 90 91inline constexpr uint32_t CountLeadingOnes32(uint32_t value) 92{ 93 return CountLeadingZeros(~value); 94} 95 96inline constexpr uint32_t CountLeadingOnes64(uint64_t value) 97{ 98 return CountLeadingZeros(~value); 99} 100 101template <typename T> 102inline constexpr uint32_t CountTrailingZeros(T value) 103{ 104 constexpr size_t RADIX = 2; 105 static_assert(std::is_integral<T>::value, "T must be integral"); 106 static_assert(std::is_unsigned<T>::value, "T must be unsigned"); 107 static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!"); 108 static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)"); 109 if (value == 0) { 110 return sizeof(T) * 8; // 8: Each byte has 8 bits 111 } 112 if (sizeof(T) == sizeof(uint64_t)) { 113 return __builtin_ctzll(static_cast<uint64_t>(value)); 114 } 115 return __builtin_ctz(static_cast<uint32_t>(value)); 116} 117 118inline constexpr unsigned CountTrailingZeros32(uint32_t value) 119{ 120 return CountTrailingZeros(value); 121} 122 123inline constexpr unsigned CountTrailingZeros64(uint64_t value) 124{ 125 return CountTrailingZeros(value); 126} 127 128inline constexpr unsigned CountTrailingOnes32(uint32_t value) 129{ 130 return CountTrailingZeros(~value); 131} 132 133inline constexpr unsigned CountTrailingOnes64(uint64_t value) 134{ 135 return CountTrailingZeros(~value); 136} 137 138/// isMask_64 - This function returns true if the argument is a non-empty 139/// sequence of ones starting at the least significant bit with the remainder 140/// zero (64 bit version). 141constexpr inline bool IsMask_64(uint64_t Value) 142{ 143 return Value && ((Value + 1) & Value) == 0; 144} 145 146/// isShiftedMask_64 - This function returns true if the argument contains a 147/// non-empty sequence of ones with the remainder zero (64 bit version.) 148constexpr inline bool IsShiftedMask_64(uint64_t Value) 149{ 150 return Value && IsMask_64((Value - 1) | Value); 151} 152 153template <typename T> 154constexpr T RoundUp(T x, size_t n) 155{ 156 static_assert(std::is_integral<T>::value, "T must be integral"); 157 return (static_cast<size_t>(x) + n - 1U) & (-n); 158} 159 160template <class To, class From> 161inline To bit_cast(const From &src) noexcept // NOLINT(readability-identifier-naming) 162{ 163 static_assert(sizeof(To) == sizeof(From), "size of the types must be equal"); 164 // The use of security functions 'memcpy_s' here will have a greater impact on performance 165 Data<From, To> data; 166 data.src = src; 167 return data.dst; 168} 169 170template <typename T> 171inline constexpr uint32_t BitNumbers() 172{ 173 constexpr int BIT_NUMBER_OF_CHAR = 8; 174 return sizeof(T) * BIT_NUMBER_OF_CHAR; 175} 176} // panda::ecmascript::base 177#endif 178