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