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
24 namespace panda::ecmascript::base {
25 template <class S, class R>
26 union Data {
27 S src;
28 R dst;
29 };
30
31 template <typename T>
ReadBuffer(void ** buffer)32 inline T ReadBuffer(void **buffer)
33 {
34 T result = *(reinterpret_cast<T *>(*buffer));
35 *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result.offset_);
36 return result;
37 }
38
ReadBuffer(void ** buffer)39 inline char *ReadBuffer(void **buffer)
40 {
41 auto result = reinterpret_cast<char *>(*buffer);
42 *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + strlen(result) + 1);
43 return result;
44 }
45
46 template <typename T>
ReadBufferInSize(void ** buffer)47 inline T *ReadBufferInSize(void **buffer)
48 {
49 T *result = reinterpret_cast<T *>(*buffer);
50 *buffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(*buffer) + result->Size());
51 return result;
52 }
53
54 template <typename T>
CountLeadingZeros(T value)55 inline constexpr uint32_t CountLeadingZeros(T value)
56 {
57 constexpr size_t RADIX = 2;
58 static_assert(std::is_integral<T>::value, "T must be integral");
59 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
60 static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!");
61 static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)");
62 if (value == 0) {
63 return sizeof(T) * 8;
64 }
65 if (sizeof(T) == sizeof(uint64_t)) {
66 return __builtin_clzll(static_cast<uint64_t>(value));
67 }
68 // 32 : 32 mean the bits of type T is less than 32
69 return __builtin_clz(static_cast<uint32_t>(value)) - (32 - std::numeric_limits<T>::digits);
70 }
71
CountLeadingZeros32(uint32_t value)72 inline constexpr uint32_t CountLeadingZeros32(uint32_t value)
73 {
74 return CountLeadingZeros(value);
75 }
76
CountLeadingZeros64(uint64_t value)77 inline constexpr uint32_t CountLeadingZeros64(uint64_t value)
78 {
79 return CountLeadingZeros(value);
80 }
81
CountLeadingOnes32(uint32_t value)82 inline constexpr uint32_t CountLeadingOnes32(uint32_t value)
83 {
84 return CountLeadingZeros(~value);
85 }
86
CountLeadingOnes64(uint64_t value)87 inline constexpr uint32_t CountLeadingOnes64(uint64_t value)
88 {
89 return CountLeadingZeros(~value);
90 }
91
92 template <typename T>
CountTrailingZeros(T value)93 inline constexpr uint32_t CountTrailingZeros(T value)
94 {
95 constexpr size_t RADIX = 2;
96 static_assert(std::is_integral<T>::value, "T must be integral");
97 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
98 static_assert(std::numeric_limits<T>::radix == RADIX, "Unexpected radix!");
99 static_assert(sizeof(T) == sizeof(uint64_t) || sizeof(T) <= sizeof(uint32_t), "Unsupported sizeof(T)");
100 if (value == 0) {
101 return sizeof(T) * 8;
102 }
103 if (sizeof(T) == sizeof(uint64_t)) {
104 return __builtin_ctzll(static_cast<uint64_t>(value));
105 }
106 return __builtin_ctz(static_cast<uint32_t>(value));
107 }
108
CountTrailingZeros32(uint32_t value)109 inline constexpr unsigned CountTrailingZeros32(uint32_t value)
110 {
111 return CountTrailingZeros(value);
112 }
113
CountTrailingZeros64(uint64_t value)114 inline constexpr unsigned CountTrailingZeros64(uint64_t value)
115 {
116 return CountTrailingZeros(value);
117 }
118
CountTrailingOnes32(uint32_t value)119 inline constexpr unsigned CountTrailingOnes32(uint32_t value)
120 {
121 return CountTrailingZeros(~value);
122 }
123
CountTrailingOnes64(uint64_t value)124 inline constexpr unsigned CountTrailingOnes64(uint64_t value)
125 {
126 return CountTrailingZeros(~value);
127 }
128
129 /// isMask_64 - This function returns true if the argument is a non-empty
130 /// sequence of ones starting at the least significant bit with the remainder
131 /// zero (64 bit version).
IsMask_64(uint64_t Value)132 constexpr inline bool IsMask_64(uint64_t Value)
133 {
134 return Value && ((Value + 1) & Value) == 0;
135 }
136
137 /// isShiftedMask_64 - This function returns true if the argument contains a
138 /// non-empty sequence of ones with the remainder zero (64 bit version.)
IsShiftedMask_64(uint64_t Value)139 constexpr inline bool IsShiftedMask_64(uint64_t Value)
140 {
141 return Value && IsMask_64((Value - 1) | Value);
142 }
143
144 template <typename T>
RoundUp(T x,size_t n)145 constexpr T RoundUp(T x, size_t n)
146 {
147 static_assert(std::is_integral<T>::value, "T must be integral");
148 return (static_cast<size_t>(x) + n - 1U) & (-n);
149 }
150
151 template <class To, class From>
bit_cast(const From & src)152 inline To bit_cast(const From &src) noexcept // NOLINT(readability-identifier-naming)
153 {
154 static_assert(sizeof(To) == sizeof(From), "size of the types must be equal");
155 // The use of security functions 'memcpy_s' here will have a greater impact on performance
156 Data<From, To> data_;
157 data_.src = src;
158 return data_.dst;
159 }
160
161 template <typename T>
BitNumbers()162 inline constexpr uint32_t BitNumbers()
163 {
164 constexpr int BIT_NUMBER_OF_CHAR = 8;
165 return sizeof(T) * BIT_NUMBER_OF_CHAR;
166 }
167 } // panda::ecmascript::base
168 #endif
169