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 constexpr uint64_t pureNaN = 0x7FF8ULL << 48U; // Be sure return the NaN that is safe.
26 template <class S, class R>
27 union Data {
28 S src;
29 R dst;
30 };
31
32 template <typename T>
ReadBuffer(void ** buffer,size_t offset)33 inline 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
40 template <typename T>
ReadBuffer(void ** buffer)41 inline 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
ReadBuffer(void ** buffer)48 inline 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
55 template <typename T>
ReadBufferInSize(void ** buffer)56 inline 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
63 template <typename T>
CountLeadingZeros(T value)64 inline 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 : 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
CountLeadingZeros32(uint32_t value)81 inline constexpr uint32_t CountLeadingZeros32(uint32_t value)
82 {
83 return CountLeadingZeros(value);
84 }
85
CountLeadingZeros64(uint64_t value)86 inline constexpr uint32_t CountLeadingZeros64(uint64_t value)
87 {
88 return CountLeadingZeros(value);
89 }
90
CountLeadingOnes32(uint32_t value)91 inline constexpr uint32_t CountLeadingOnes32(uint32_t value)
92 {
93 return CountLeadingZeros(~value);
94 }
95
CountLeadingOnes64(uint64_t value)96 inline constexpr uint32_t CountLeadingOnes64(uint64_t value)
97 {
98 return CountLeadingZeros(~value);
99 }
100
101 template <typename T>
CountTrailingZeros(T value)102 inline 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 : 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
CountTrailingZeros32(uint32_t value)118 inline constexpr unsigned CountTrailingZeros32(uint32_t value)
119 {
120 return CountTrailingZeros(value);
121 }
122
CountTrailingZeros64(uint64_t value)123 inline constexpr unsigned CountTrailingZeros64(uint64_t value)
124 {
125 return CountTrailingZeros(value);
126 }
127
CountTrailingOnes32(uint32_t value)128 inline constexpr unsigned CountTrailingOnes32(uint32_t value)
129 {
130 return CountTrailingZeros(~value);
131 }
132
CountTrailingOnes64(uint64_t value)133 inline 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).
IsMask_64(uint64_t Value)141 constexpr 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.)
IsShiftedMask_64(uint64_t Value)148 constexpr inline bool IsShiftedMask_64(uint64_t Value)
149 {
150 return Value && IsMask_64((Value - 1) | Value);
151 }
152
153 template <typename T>
RoundUp(T x,size_t n)154 constexpr 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
160 template <class To, class From>
bit_cast(const From & src)161 inline 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
170 template <typename T>
BitNumbers()171 inline 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