Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015 Andrew Kelley
3 : : *
4 : : * This file is part of zig, which is MIT licensed.
5 : : * See http://opensource.org/licenses/MIT
6 : : */
7 : :
8 : : #ifndef ZIG_UTIL_HPP
9 : : #define ZIG_UTIL_HPP
10 : :
11 : : #include <stdlib.h>
12 : : #include <stdint.h>
13 : : #include <string.h>
14 : : #include <assert.h>
15 : : #include <ctype.h>
16 : :
17 : : #if defined(_MSC_VER)
18 : :
19 : : #include <intrin.h>
20 : :
21 : : #define ATTRIBUTE_COLD __declspec(noinline)
22 : : #define ATTRIBUTE_PRINTF(a, b)
23 : : #define ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict)
24 : : #define ATTRIBUTE_NORETURN __declspec(noreturn)
25 : : #define ATTRIBUTE_MUST_USE
26 : :
27 : : #else
28 : :
29 : : #define ATTRIBUTE_COLD __attribute__((cold))
30 : : #define ATTRIBUTE_PRINTF(a, b) __attribute__((format(printf, a, b)))
31 : : #define ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__))
32 : : #define ATTRIBUTE_NORETURN __attribute__((noreturn))
33 : : #define ATTRIBUTE_MUST_USE __attribute__((warn_unused_result))
34 : :
35 : : #endif
36 : :
37 : : #include "softfloat.hpp"
38 : :
39 : : #define BREAKPOINT __asm("int $0x03")
40 : :
41 : : ATTRIBUTE_COLD
42 : : ATTRIBUTE_NORETURN
43 : : ATTRIBUTE_PRINTF(1, 2)
44 : : void zig_panic(const char *format, ...);
45 : :
46 : : #ifdef _WIN32
47 : : #define __func__ __FUNCTION__
48 : : #endif
49 : :
50 : : #define zig_unreachable() zig_panic("unreachable: %s:%s:%d", __FILE__, __func__, __LINE__)
51 : :
52 : : // Assertions in stage1 are always on, and they call zig @panic.
53 : : #undef assert
54 : : void assert(bool ok);
55 : :
56 : : #if defined(_MSC_VER)
57 : : static inline int clzll(unsigned long long mask) {
58 : : unsigned long lz;
59 : : #if defined(_WIN64)
60 : : if (_BitScanReverse64(&lz, mask))
61 : : return static_cast<int>(63 - lz);
62 : : zig_unreachable();
63 : : #else
64 : : if (_BitScanReverse(&lz, mask >> 32))
65 : : lz += 32;
66 : : else
67 : : _BitScanReverse(&lz, mask & 0xffffffff);
68 : : return 63 - lz;
69 : : #endif
70 : : }
71 : : static inline int ctzll(unsigned long long mask) {
72 : : unsigned long result;
73 : : #if defined(_WIN64)
74 : : if (_BitScanForward64(&result, mask))
75 : : return result;
76 : : zig_unreachable();
77 : : #else
78 : : if (_BitScanForward(&result, mask & 0xffffffff))
79 : : return result;
80 : : }
81 : : if (_BitScanForward(&result, mask >> 32))
82 : : return 32 + result;
83 : : zig_unreachable();
84 : : #endif
85 : : }
86 : : #else
87 : : #define clzll(x) __builtin_clzll(x)
88 : : #define ctzll(x) __builtin_ctzll(x)
89 : : #endif
90 : :
91 : :
92 : : template<typename T>
93 : 963415 : ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
94 : : #ifndef NDEBUG
95 : : // make behavior when size == 0 portable
96 [ - + ][ - + ]: 963415 : if (count == 0)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ - + ]
[ - + ]
97 : 0 : return nullptr;
98 : : #endif
99 : 963415 : T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T)));
100 [ - + ][ - + ]: 963415 : if (!ptr)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ - + ]
[ - + ]
101 : 0 : zig_panic("allocation failed");
102 : 963415 : return ptr;
103 : : }
104 : :
105 : : template<typename T>
106 : 59878304 : ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {
107 : : #ifndef NDEBUG
108 : : // make behavior when size == 0 portable
109 [ - + ][ - + ]: 59878304 : if (count == 0)
[ - + ][ - + ]
[ - + ][ - + ]
[ + + ][ - + ]
[ - + ][ + + ]
[ + + ][ + + ]
[ - + ][ - + ]
[ + + ][ + + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ + + ][ + + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ + + ][ + + ]
[ + + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ # # ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ + + ]
[ - + ][ - + ]
[ - + ][ # # ]
[ - + ][ - + ]
[ + + ][ - + ]
[ + + ][ - + ]
[ - + ][ - + ]
[ # # ][ - + ]
[ + + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
110 : 449543 : return nullptr;
111 : : #endif
112 : 59428761 : T *ptr = reinterpret_cast<T*>(calloc(count, sizeof(T)));
113 [ - + ][ - + ]: 59428761 : if (!ptr)
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ - + ][ # # ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ # # ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ # # ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
114 : 0 : zig_panic("allocation failed");
115 : 59428761 : return ptr;
116 : : }
117 : :
118 : : template<typename T>
119 : 4370 : static inline T *reallocate(T *old, size_t old_count, size_t new_count) {
120 : 4370 : T *ptr = reallocate_nonzero(old, old_count, new_count);
121 [ + + ]: 4370 : if (new_count > old_count) {
122 : 2392 : memset(&ptr[old_count], 0, (new_count - old_count) * sizeof(T));
123 : : }
124 : 4370 : return ptr;
125 : : }
126 : :
127 : : template<typename T>
128 : 5681008 : static inline T *reallocate_nonzero(T *old, size_t old_count, size_t new_count) {
129 : : #ifndef NDEBUG
130 : : // make behavior when size == 0 portable
131 [ - + ][ # # ]: 5681008 : if (new_count == 0 && old == nullptr)
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ - + ][ # # ]
[ # # ][ # # ]
[ - + ][ # # ]
132 : 0 : return nullptr;
133 : : #endif
134 : 5681008 : T *ptr = reinterpret_cast<T*>(realloc(old, new_count * sizeof(T)));
135 [ - + ][ - + ]: 5681008 : if (!ptr)
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ - + ][ - + ]
[ # # ][ - + ]
136 : 0 : zig_panic("allocation failed");
137 : 5681008 : return ptr;
138 : : }
139 : :
140 : : template <typename T, size_t n>
141 : 48903199 : constexpr size_t array_length(const T (&)[n]) {
142 : 48903199 : return n;
143 : : }
144 : :
145 : : template <typename T>
146 : 96415 : static inline T max(T a, T b) {
147 [ + + ][ + + ]: 96415 : return (a >= b) ? a : b;
148 : : }
149 : :
150 : : template <typename T>
151 : : static inline T min(T a, T b) {
152 : : return (a <= b) ? a : b;
153 : : }
154 : :
155 : : template<typename T>
156 : : static inline T clamp(T min_value, T value, T max_value) {
157 : : return max(min(value, max_value), min_value);
158 : : }
159 : :
160 : 59370818 : static inline bool mem_eql_mem(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
161 [ + + ]: 59370818 : if (a_len != b_len)
162 : 50755672 : return false;
163 : 8615146 : return memcmp(a_ptr, b_ptr, a_len) == 0;
164 : : }
165 : 62 : static inline bool mem_eql_mem_ignore_case(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
166 [ + + ]: 62 : if (a_len != b_len)
167 : 38 : return false;
168 [ + + ]: 50 : for (size_t i = 0; i < a_len; i += 1) {
169 [ + + ]: 46 : if (tolower(a_ptr[i]) != tolower(b_ptr[i]))
170 : 20 : return false;
171 : : }
172 : 4 : return true;
173 : : }
174 : :
175 : 48095497 : static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {
176 : 48095497 : return mem_eql_mem(mem, mem_len, str, strlen(str));
177 : : }
178 : :
179 : 2710 : static inline bool is_power_of_2(uint64_t x) {
180 [ + - ][ + + ]: 2710 : return x != 0 && ((x & (~x + 1)) == x);
181 : : }
182 : :
183 : 1504 : static inline uint64_t round_to_next_power_of_2(uint64_t x) {
184 : 1504 : --x;
185 : 1504 : x |= x >> 1;
186 : 1504 : x |= x >> 2;
187 : 1504 : x |= x >> 4;
188 : 1504 : x |= x >> 8;
189 : 1504 : x |= x >> 16;
190 : 1504 : x |= x >> 32;
191 : 1504 : return x + 1;
192 : : }
193 : :
194 : : uint32_t int_hash(int i);
195 : : bool int_eq(int a, int b);
196 : : uint32_t uint64_hash(uint64_t i);
197 : : bool uint64_eq(uint64_t a, uint64_t b);
198 : : uint32_t ptr_hash(const void *ptr);
199 : : bool ptr_eq(const void *a, const void *b);
200 : :
201 : 19546 : static inline uint8_t log2_u64(uint64_t x) {
202 : 19546 : return (63 - clzll(x));
203 : : }
204 : :
205 : 144 : static inline float16_t zig_double_to_f16(double x) {
206 : : float64_t y;
207 : : static_assert(sizeof(x) == sizeof(y), "");
208 : 144 : memcpy(&y, &x, sizeof(x));
209 : 144 : return f64_to_f16(y);
210 : : }
211 : :
212 : :
213 : : // Return value is safe to coerce to float even when |x| is NaN or Infinity.
214 : 312 : static inline double zig_f16_to_double(float16_t x) {
215 : 312 : float64_t y = f16_to_f64(x);
216 : : double z;
217 : : static_assert(sizeof(y) == sizeof(z), "");
218 : 312 : memcpy(&z, &y, sizeof(y));
219 : 312 : return z;
220 : : }
221 : :
222 : : template<typename T>
223 : : struct Optional {
224 : : T value;
225 : : bool is_some;
226 : :
227 : 335534 : static inline Optional<T> some(T x) {
228 : 335534 : return {x, true};
229 : : }
230 : :
231 : 790425 : static inline Optional<T> none() {
232 : 790425 : return {{}, false};
233 : : }
234 : :
235 : 796233 : inline bool unwrap(T *res) {
236 : 796233 : *res = value;
237 : 796233 : return is_some;
238 : : }
239 : : };
240 : :
241 : : template<typename T>
242 : : struct Slice {
243 : : T *ptr;
244 : : size_t len;
245 : :
246 : : inline T &at(size_t i) {
247 : : assert(i < len);
248 : : return &ptr[i];
249 : : }
250 : :
251 : 329726 : inline Slice<T> slice(size_t start, size_t end) {
252 : 329726 : assert(end <= len);
253 : 329726 : assert(end >= start);
254 : : return {
255 : 329726 : ptr + start,
256 : 329726 : end - start,
257 : 329726 : };
258 : : }
259 : :
260 : 2502 : inline Slice<T> sliceFrom(size_t start) {
261 : 2502 : assert(start <= len);
262 : : return {
263 : 2502 : ptr + start,
264 : 2502 : len - start,
265 : 2502 : };
266 : : }
267 : :
268 : : static inline Slice<T> alloc(size_t n) {
269 : : return {allocate_nonzero<T>(n), n};
270 : : }
271 : : };
272 : :
273 : : template<typename T, size_t n>
274 : : struct Array {
275 : : static const size_t len = n;
276 : : T items[n];
277 : :
278 : : inline Slice<T> slice() {
279 : : return {
280 : : &items[0],
281 : : len,
282 : : };
283 : : }
284 : : };
285 : :
286 : 289651 : static inline Slice<uint8_t> str(const char *literal) {
287 : 289651 : return {(uint8_t*)(literal), strlen(literal)};
288 : : }
289 : :
290 : : // Ported from std/mem.zig
291 : : template<typename T>
292 : 159014 : static inline bool memEql(Slice<T> a, Slice<T> b) {
293 [ + + ]: 159014 : if (a.len != b.len)
294 : 158215 : return false;
295 [ + + ]: 1185 : for (size_t i = 0; i < a.len; i += 1) {
296 [ + + ]: 991 : if (a.ptr[i] != b.ptr[i])
297 : 605 : return false;
298 : : }
299 : 194 : return true;
300 : : }
301 : :
302 : : // Ported from std/mem.zig
303 : : template<typename T>
304 : : static inline bool memStartsWith(Slice<T> haystack, Slice<T> needle) {
305 : : if (needle.len > haystack.len)
306 : : return false;
307 : : return memEql(haystack.slice(0, needle.len), needle);
308 : : }
309 : :
310 : : // Ported from std/mem.zig
311 : : template<typename T>
312 : : static inline void memCopy(Slice<T> dest, Slice<T> src) {
313 : : assert(dest.len >= src.len);
314 : : memcpy(dest.ptr, src.ptr, src.len * sizeof(T));
315 : : }
316 : :
317 : : // Ported from std/mem.zig.
318 : : // Coordinate struct fields with memSplit function
319 : : struct SplitIterator {
320 : : size_t index;
321 : : Slice<uint8_t> buffer;
322 : : Slice<uint8_t> split_bytes;
323 : : };
324 : :
325 : : bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte);
326 : : Optional< Slice<uint8_t> > SplitIterator_next(SplitIterator *self);
327 : : Optional< Slice<uint8_t> > SplitIterator_next_separate(SplitIterator *self);
328 : : Slice<uint8_t> SplitIterator_rest(SplitIterator *self);
329 : : SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes);
330 : :
331 : : #endif
|