authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-23 12:55:20-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:29-04:00
log1bab8548688ec13d29abbf3820bb2f9723e09c66
tree9121e2e04275e4e552eb5a718af17bfa5bd82169
parent65a48df5324278c3d876e168b523894c8662e546

cbe: implement 128-bit and fix smaller integer builtins


14 files changed, 1640 insertions(+), 1865 deletions(-)

lib/include/zig.h+1115-1245
......@@ -1,103 +1,108 @@
11#undef linux
22
3#define __STDC_WANT_IEC_60559_TYPES_EXT__
4#include <float.h>
5#include <limits.h>
6#include <stdint.h>
7
8#if defined(__has_builtin)
9#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)
10#else
11#define zig_has_builtin(builtin) 0
12#endif
13
14#if defined(__has_attribute)
15#define zig_has_attribute(attribute) __has_attribute(attribute)
16#else
17#define zig_has_attribute(attribute) 0
18#endif
19
320#if __STDC_VERSION__ >= 201112L
4#define zig_noreturn _Noreturn
521#define zig_threadlocal thread_local
622#elif __GNUC__
7#define zig_noreturn __attribute__ ((noreturn))
823#define zig_threadlocal __thread
924#elif _MSC_VER
10#define zig_noreturn __declspec(noreturn)
1125#define zig_threadlocal __declspec(thread)
1226#else
13#define zig_noreturn
1427#define zig_threadlocal zig_threadlocal_unavailable
1528#endif
1629
17#if defined(_MSC_VER)
18#define ZIG_NAKED __declspec(naked)
30#if zig_has_attribute(naked)
31#define zig_naked __attribute__((naked))
32#elif defined(_MSC_VER)
33#define zig_naked __declspec(naked)
1934#else
20#define ZIG_NAKED __attribute__((naked))
35#define zig_naked zig_naked_unavailable
2136#endif
2237
23#if __GNUC__
24#define ZIG_COLD __attribute__ ((cold))
38#if zig_has_attribute(cold)
39#define zig_cold __attribute__((cold))
2540#else
26#define ZIG_COLD
41#define zig_cold
2742#endif
2843
2944#if __STDC_VERSION__ >= 199901L
30#define ZIG_RESTRICT restrict
45#define zig_restrict restrict
3146#elif defined(__GNUC__)
32#define ZIG_RESTRICT __restrict
47#define zig_restrict __restrict
3348#else
34#define ZIG_RESTRICT
49#define zig_restrict
3550#endif
3651
3752#if __STDC_VERSION__ >= 201112L
38#include <stdalign.h>
39#define ZIG_ALIGN(alignment) alignas(alignment)
40#elif defined(__GNUC__)
41#define ZIG_ALIGN(alignment) __attribute__((aligned(alignment)))
42#else
43#define ZIG_ALIGN(alignment) zig_compile_error("the C compiler being used does not support aligning variables")
44#endif
45
46#if __STDC_VERSION__ >= 199901L
47#include <stdbool.h>
53#define zig_align(alignment) _Alignas(alignment)
54#elif zig_has_attribute(aligned)
55#define zig_align(alignment) __attribute__((aligned(alignment)))
56#elif _MSC_VER
4857#else
49#define bool unsigned char
50#define true 1
51#define false 0
58#error the C compiler being used does not support aligning variables
5259#endif
5360
54#if defined(__GNUC__)
61#if zig_has_builtin(unreachable)
5562#define zig_unreachable() __builtin_unreachable()
5663#else
5764#define zig_unreachable()
5865#endif
5966
60#ifdef __cplusplus
61#define ZIG_EXTERN_C extern "C"
67#if defined(__cplusplus)
68#define zig_extern_c extern "C"
6269#else
63#define ZIG_EXTERN_C
70#define zig_extern_c
6471#endif
6572
66#if defined(_MSC_VER)
67#define zig_breakpoint() __debugbreak()
68#elif defined(__MINGW32__) || defined(__MINGW64__)
69#define zig_breakpoint() __debugbreak()
70#elif defined(__clang__)
73#if zig_has_builtin(debugtrap)
7174#define zig_breakpoint() __builtin_debugtrap()
72#elif defined(__GNUC__)
75#elif zig_has_builtin(trap)
7376#define zig_breakpoint() __builtin_trap()
77#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
78#define zig_breakpoint() __debugbreak()
7479#elif defined(__i386__) || defined(__x86_64__)
7580#define zig_breakpoint() __asm__ volatile("int $0x03");
7681#else
7782#define zig_breakpoint() raise(SIGTRAP)
7883#endif
7984
80#if defined(_MSC_VER)
81#define zig_return_address() _ReturnAddress()
82#elif defined(__GNUC__)
85#if zig_has_builtin(return_address)
8386#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))
87#elif defined(_MSC_VER)
88#define zig_return_address() _ReturnAddress()
8489#else
8590#define zig_return_address() 0
8691#endif
8792
88#if defined(__GNUC__)
93#if zig_has_builtin(frame_address)
8994#define zig_frame_address() __builtin_frame_address(0)
9095#else
9196#define zig_frame_address() 0
9297#endif
9398
94#if defined(__GNUC__)
99#if zig_has_builtin(prefetch)
95100#define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
96101#else
97102#define zig_prefetch(addr, rw, locality)
98103#endif
99104
100#if defined(__clang__)
105#if zig_has_builtin(memory_size) && zig_has_builtin(memory_grow)
101106#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)
102107#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)
103108#else
......@@ -130,8 +135,8 @@
130135#define memory_order_acq_rel __ATOMIC_ACQ_REL
131136#define memory_order_seq_cst __ATOMIC_SEQ_CST
132137#define zig_atomic(type) type
133#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, false, succ, fail)
134#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, true , succ, fail)
138#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, zig_false, succ, fail)
139#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, zig_true , succ, fail)
135140#define zig_atomicrmw_xchg(obj, arg, order) __atomic_exchange_n(obj, arg, order)
136141#define zig_atomicrmw_add(obj, arg, order) __atomic_fetch_add (obj, arg, order)
137142#define zig_atomicrmw_sub(obj, arg, order) __atomic_fetch_sub (obj, arg, order)
......@@ -168,1366 +173,1258 @@
168173#define zig_fence(order) zig_unimplemented()
169174#endif
170175
171#include <stdint.h>
172#include <stddef.h>
173#include <limits.h>
176#if __STDC_VERSION__ >= 201112L
177#define zig_noreturn _Noreturn void
178#define zig_threadlocal thread_local
179#elif __GNUC__
180#define zig_noreturn __attribute__ ((noreturn)) void
181#define zig_threadlocal __thread
182#elif _MSC_VER
183#define zig_noreturn __declspec(noreturn) void
184#define zig_threadlocal __declspec(thread)
185#else
186#define zig_noreturn void
187#define zig_threadlocal zig_threadlocal_unavailable
188#endif
174189
175#define int128_t __int128
176#define uint128_t unsigned __int128
177#define UINT128_MAX (((uint128_t)UINT64_MAX<<64|UINT64_MAX))
178ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);
179ZIG_EXTERN_C void *memset (void *, int, size_t);
180ZIG_EXTERN_C int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
181ZIG_EXTERN_C int128_t __addoti4(int128_t lhs, int128_t rhs, int *overflow);
182ZIG_EXTERN_C uint64_t __uaddodi4(uint64_t lhs, uint64_t rhs, int *overflow);
183ZIG_EXTERN_C uint128_t __uaddoti4(uint128_t lhs, uint128_t rhs, int *overflow);
184ZIG_EXTERN_C int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);
185ZIG_EXTERN_C int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);
186ZIG_EXTERN_C int128_t __suboti4(int128_t lhs, int128_t rhs, int *overflow);
187ZIG_EXTERN_C uint32_t __usubosi4(uint32_t lhs, uint32_t rhs, int *overflow);
188ZIG_EXTERN_C uint64_t __usubodi4(uint64_t lhs, uint64_t rhs, int *overflow);
189ZIG_EXTERN_C uint128_t __usuboti4(uint128_t lhs, uint128_t rhs, int *overflow);
190ZIG_EXTERN_C int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
191ZIG_EXTERN_C int128_t __muloti4(int128_t lhs, int128_t rhs, int *overflow);
192ZIG_EXTERN_C uint64_t __umulodi4(uint64_t lhs, uint64_t rhs, int *overflow);
193ZIG_EXTERN_C uint128_t __umuloti4(uint128_t lhs, uint128_t rhs, int *overflow);
194
195
196static inline uint8_t zig_addw_u8(uint8_t lhs, uint8_t rhs, uint8_t max) {
197 uint8_t thresh = max - rhs;
198 if (lhs > thresh) {
199 return lhs - thresh - 1;
200 } else {
201 return lhs + rhs;
202 }
190#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
191
192typedef void zig_void;
193
194#if defined(__cplusplus)
195typedef bool zig_bool;
196#define zig_false false
197#define zig_true true
198#else
199#if __STDC_VERSION__ >= 199901L
200typedef _Bool zig_bool;
201#else
202typedef char zig_bool;
203#endif
204#define zig_false ((zig_bool)0)
205#define zig_true ((zig_bool)1)
206#endif
207
208typedef uintptr_t zig_usize;
209typedef intptr_t zig_isize;
210typedef signed short int zig_c_short;
211typedef unsigned short int zig_c_ushort;
212typedef signed int zig_c_int;
213typedef unsigned int zig_c_uint;
214typedef signed long int zig_c_long;
215typedef unsigned long int zig_c_ulong;
216typedef signed long long int zig_c_longlong;
217typedef unsigned long long int zig_c_ulonglong;
218typedef long double zig_c_longdouble;
219
220typedef uint8_t zig_u8;
221typedef int8_t zig_i8;
222typedef uint16_t zig_u16;
223typedef int16_t zig_i16;
224typedef uint16_t zig_u16;
225typedef int16_t zig_i16;
226typedef uint32_t zig_u32;
227typedef int32_t zig_i32;
228typedef uint64_t zig_u64;
229typedef int64_t zig_i64;
230
231#define zig_as_u8(val) UINT8_C(val)
232#define zig_as_i8(val) INT8_C(val)
233#define zig_as_u16(val) UINT16_C(val)
234#define zig_as_i16(val) INT16_C(val)
235#define zig_as_u32(val) UINT32_C(val)
236#define zig_as_i32(val) INT32_C(val)
237#define zig_as_u64(val) UINT64_C(val)
238#define zig_as_i64(val) INT64_C(val)
239
240#define zig_minInt_u8 zig_as_u8(0)
241#define zig_maxInt_u8 UINT8_MAX
242#define zig_minInt_i8 INT8_MIN
243#define zig_maxInt_i8 INT8_MAX
244#define zig_minInt_u16 zig_as_u16(0)
245#define zig_maxInt_u16 UINT16_MAX
246#define zig_minInt_i16 INT16_MIN
247#define zig_maxInt_i16 INT16_MAX
248#define zig_minInt_u32 zig_as_u32(0)
249#define zig_maxInt_u32 UINT32_MAX
250#define zig_minInt_i32 INT32_MIN
251#define zig_maxInt_i32 INT32_MAX
252#define zig_minInt_u64 zig_as_u64(0)
253#define zig_maxInt_u64 UINT64_MAX
254#define zig_minInt_i64 INT64_MIN
255#define zig_maxInt_i64 INT64_MAX
256
257#if FLT_MANT_DIG == 11
258typedef float zig_f16;
259#elif DBL_MANT_DIG == 11
260typedef double zig_f16;
261#elif LDBL_MANT_DIG == 11
262typedef long double zig_f16;
263#elif FLT16_MANT_DIG == 11
264typedef _Float16 zig_f16;
265#endif
266
267#if FLT_MANT_DIG == 24
268typedef float zig_f32;
269#elif DBL_MANT_DIG == 24
270typedef double zig_f32;
271#elif LDBL_MANT_DIG == 24
272typedef long double zig_f32;
273#elif FLT32_MANT_DIG == 24
274typedef _Float32 zig_f32;
275#endif
276
277#if FLT_MANT_DIG == 53
278typedef float zig_f64;
279#elif DBL_MANT_DIG == 53
280typedef double zig_f64;
281#elif LDBL_MANT_DIG == 53
282typedef long double zig_f64;
283#elif FLT64_MANT_DIG == 53
284typedef _Float64 zig_f64;
285#endif
286
287#if FLT_MANT_DIG == 64
288typedef float zig_f80;
289#elif DBL_MANT_DIG == 64
290typedef double zig_f80;
291#elif LDBL_MANT_DIG == 64
292typedef long double zig_f80;
293#elif FLT80_MANT_DIG == 64
294typedef _Float80 zig_f80;
295#elif defined(__SIZEOF_FLOAT80__)
296typedef __float80 zig_f80;
297#endif
298
299#if FLT_MANT_DIG == 113
300typedef float zig_f128;
301#elif DBL_MANT_DIG == 113
302typedef double zig_f128;
303#elif LDBL_MANT_DIG == 113
304typedef long double zig_f128;
305#elif FLT128_MANT_DIG == 113
306typedef _Float128 zig_f128;
307#elif defined(__SIZEOF_FLOAT128__)
308typedef __float128 zig_f128;
309#endif
310
311zig_extern_c void *memcpy (void *zig_restrict, void const *zig_restrict, zig_usize);
312zig_extern_c void *memset (void *, int, zig_usize);
313
314/* ==================== 8/16/32/64-bit Integer Routines ===================== */
315
316#define zig_maxInt(Type, bits) zig_shr_##Type(zig_maxInt_##Type, (zig_bitSizeOf(zig_##Type) - bits))
317#define zig_minInt(Type, bits) zig_not_##Type(zig_maxInt(Type, bits), bits)
318
319#define zig_int_helpers(w) \
320 static inline zig_u##w zig_shl_u##w(zig_u##w lhs, zig_u8 rhs) { \
321 return lhs << rhs; \
322 } \
323\
324 static inline zig_i##w zig_shl_i##w(zig_i##w lhs, zig_u8 rhs) { \
325 return lhs << rhs; \
326 } \
327\
328 static inline zig_u##w zig_shr_u##w(zig_u##w lhs, zig_u8 rhs) { \
329 return lhs >> rhs; \
330 } \
331\
332 static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \
333 zig_i##w sign_mask = lhs < zig_as_i##w(0) ? zig_as_i##w(-1) : zig_as_i##w(0); \
334 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
335 } \
336\
337 static inline zig_u##w zig_not_u##w(zig_u##w val, zig_u8 bits) { \
338 return val ^ zig_maxInt(u##w, bits); \
339 } \
340\
341 static inline zig_i##w zig_not_i##w(zig_i##w val, zig_u8 bits) { \
342 (void)bits; \
343 return ~val; \
344 } \
345\
346 static inline zig_u##w zig_wrap_u##w(zig_u##w val, zig_u8 bits) { \
347 return val & zig_maxInt(u##w, bits); \
348 } \
349\
350 static inline zig_i##w zig_wrap_i##w(zig_i##w val, zig_u8 bits) { \
351 return (val & zig_as_u##w(1) << (bits - zig_as_u8(1))) != 0 \
352 ? val | zig_minInt(i##w, bits) : val & zig_maxInt(i##w, bits); \
353 } \
354\
355 static inline zig_u##w zig_div_floor_u##w(zig_u##w lhs, zig_u##w rhs) { \
356 return lhs / rhs; \
357 } \
358\
359 static inline zig_i##w zig_div_floor_i##w(zig_i##w lhs, zig_i##w rhs) { \
360 return lhs / rhs - (((lhs ^ rhs) & (lhs % rhs)) < zig_as_i##w(0)); \
361 } \
362\
363 static inline zig_u##w zig_mod_u##w(zig_u##w lhs, zig_u##w rhs) { \
364 return lhs % rhs; \
365 } \
366\
367 static inline zig_i##w zig_mod_i##w(zig_i##w lhs, zig_i##w rhs) { \
368 zig_i##w rem = lhs % rhs; \
369 return rem + (((lhs ^ rhs) & rem) < zig_as_i##w(0) ? rhs : zig_as_i##w(0)); \
370 }
371zig_int_helpers(8)
372zig_int_helpers(16)
373zig_int_helpers(32)
374zig_int_helpers(64)
375
376static inline zig_bool zig_addo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
377#if zig_has_builtin(add_overflow)
378 zig_u32 full_res;
379 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
380 *res = zig_wrap_u32(full_res, bits);
381 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
382#else
383 *res = zig_addw_u32(lhs, rhs, bits);
384 return *res < lhs;
385#endif
203386}
204387
205static inline int8_t zig_addw_i8(int8_t lhs, int8_t rhs, int8_t min, int8_t max) {
206 if ((lhs > 0) && (rhs > 0)) {
207 int8_t thresh = max - rhs;
208 if (lhs > thresh) {
209 return min + lhs - thresh - 1;
210 }
211 } else if ((lhs < 0) && (rhs < 0)) {
212 int8_t thresh = min - rhs;
213 if (lhs < thresh) {
214 return max + lhs - thresh + 1;
215 }
216 }
217 return lhs + rhs;
388zig_extern_c zig_i32 __addosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
389static inline zig_bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
390#if zig_has_builtin(add_overflow)
391 zig_i32 full_res;
392 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
393#else
394 zig_c_int overflow_int;
395 zig_u32 full_res = __addosi4(lhs, rhs, &overflow_int);
396 zig_bool overflow = overflow_int != 0;
397#endif
398 *res = zig_wrap_i32(full_res, bits);
399 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
218400}
219401
220static inline uint16_t zig_addw_u16(uint16_t lhs, uint16_t rhs, uint16_t max) {
221 uint16_t thresh = max - rhs;
222 if (lhs > thresh) {
223 return lhs - thresh - 1;
224 } else {
225 return lhs + rhs;
226 }
402static inline zig_bool zig_addo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
403#if zig_has_builtin(add_overflow)
404 zig_u64 full_res;
405 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
406 *res = zig_wrap_u64(full_res, bits);
407 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
408#else
409 *res = zig_addw_u64(lhs, rhs, bits);
410 return *res < lhs;
411#endif
227412}
228413
229static inline int16_t zig_addw_i16(int16_t lhs, int16_t rhs, int16_t min, int16_t max) {
230 if ((lhs > 0) && (rhs > 0)) {
231 int16_t thresh = max - rhs;
232 if (lhs > thresh) {
233 return min + lhs - thresh - 1;
234 }
235 } else if ((lhs < 0) && (rhs < 0)) {
236 int16_t thresh = min - rhs;
237 if (lhs < thresh) {
238 return max + lhs - thresh + 1;
239 }
240 }
241 return lhs + rhs;
414zig_extern_c zig_i64 __addodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
415static inline zig_bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
416#if zig_has_builtin(add_overflow)
417 zig_i64 full_res;
418 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
419#else
420 zig_c_int overflow_int;
421 zig_u64 full_res = __addodi4(lhs, rhs, &overflow_int);
422 zig_bool overflow = overflow_int != 0;
423#endif
424 *res = zig_wrap_i64(full_res, bits);
425 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
242426}
243427
244static inline uint32_t zig_addw_u32(uint32_t lhs, uint32_t rhs, uint32_t max) {
245 uint32_t thresh = max - rhs;
246 if (lhs > thresh) {
247 return lhs - thresh - 1;
248 } else {
249 return lhs + rhs;
250 }
428static inline zig_bool zig_addo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
429#if zig_has_builtin(add_overflow)
430 zig_u8 full_res;
431 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
432 *res = zig_wrap_u8(full_res, bits);
433 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
434#else
435 return zig_addo_u32(res, lhs, rhs, bits);
436#endif
251437}
252438
253static inline int32_t zig_addw_i32(int32_t lhs, int32_t rhs, int32_t min, int32_t max) {
254 if ((lhs > 0) && (rhs > 0)) {
255 int32_t thresh = max - rhs;
256 if (lhs > thresh) {
257 return min + lhs - thresh - 1;
258 }
259 } else if ((lhs < 0) && (rhs < 0)) {
260 int32_t thresh = min - rhs;
261 if (lhs < thresh) {
262 return max + lhs - thresh + 1;
263 }
264 }
265 return lhs + rhs;
439static inline zig_bool zig_addo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
440#if zig_has_builtin(add_overflow)
441 zig_i8 full_res;
442 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
443 *res = zig_wrap_i8(full_res, bits);
444 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
445#else
446 return zig_addo_i32(res, lhs, rhs, bits);
447#endif
266448}
267449
268static inline uint64_t zig_addw_u64(uint64_t lhs, uint64_t rhs, uint64_t max) {
269 uint64_t thresh = max - rhs;
270 if (lhs > thresh) {
271 return lhs - thresh - 1;
272 } else {
273 return lhs + rhs;
274 }
450static inline zig_bool zig_addo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
451#if zig_has_builtin(add_overflow)
452 zig_u16 full_res;
453 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
454 *res = zig_wrap_u16(full_res, bits);
455 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
456#else
457 return zig_addo_u32(res, lhs, rhs, bits);
458#endif
275459}
276460
277static inline int64_t zig_addw_i64(int64_t lhs, int64_t rhs, int64_t min, int64_t max) {
278 if ((lhs > 0) && (rhs > 0)) {
279 int64_t thresh = max - rhs;
280 if (lhs > thresh) {
281 return min + lhs - thresh - 1;
282 }
283 } else if ((lhs < 0) && (rhs < 0)) {
284 int64_t thresh = min - rhs;
285 if (lhs < thresh) {
286 return max + lhs - thresh + 1;
287 }
288 }
289 return lhs + rhs;
461static inline zig_bool zig_addo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
462#if zig_has_builtin(add_overflow)
463 zig_i16 full_res;
464 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
465 *res = zig_wrap_i16(full_res, bits);
466 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
467#else
468 return zig_addo_i32(res, lhs, rhs, bits);
469#endif
290470}
291471
292static inline intptr_t zig_addw_isize(intptr_t lhs, intptr_t rhs, intptr_t min, intptr_t max) {
293 return (intptr_t)(((uintptr_t)lhs) + ((uintptr_t)rhs));
472static inline zig_bool zig_subo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
473#if zig_has_builtin(sub_overflow)
474 zig_u32 full_res;
475 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
476 *res = zig_wrap_u32(full_res, bits);
477 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
478#else
479 *res = zig_subw_u32(lhs, rhs, bits);
480 return *res > lhs;
481#endif
294482}
295483
296static inline short zig_addw_short(short lhs, short rhs, short min, short max) {
297 return (short)(((unsigned short)lhs) + ((unsigned short)rhs));
484zig_extern_c zig_i32 __subosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
485static inline zig_bool zig_subo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
486#if zig_has_builtin(sub_overflow)
487 zig_i32 full_res;
488 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
489#else
490 zig_c_int overflow_int;
491 zig_u32 full_res = __subosi4(lhs, rhs, &overflow_int);
492 zig_bool overflow = overflow_int != 0;
493#endif
494 *res = zig_wrap_i32(full_res, bits);
495 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
298496}
299497
300static inline int zig_addw_int(int lhs, int rhs, int min, int max) {
301 return (int)(((unsigned)lhs) + ((unsigned)rhs));
498static inline zig_bool zig_subo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
499#if zig_has_builtin(sub_overflow)
500 zig_u64 full_res;
501 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
502 *res = zig_wrap_u64(full_res, bits);
503 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
504#else
505 *res = zig_subw_u64(lhs, rhs, bits);
506 return *res > lhs;
507#endif
302508}
303509
304static inline long zig_addw_long(long lhs, long rhs, long min, long max) {
305 return (long)(((unsigned long)lhs) + ((unsigned long)rhs));
510zig_extern_c zig_i64 __subodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
511static inline zig_bool zig_subo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
512#if zig_has_builtin(sub_overflow)
513 zig_i64 full_res;
514 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
515#else
516 zig_c_int overflow_int;
517 zig_u64 full_res = __subodi4(lhs, rhs, &overflow_int);
518 zig_bool overflow = overflow_int != 0;
519#endif
520 *res = zig_wrap_i64(full_res, bits);
521 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
306522}
307523
308static inline long long zig_addw_longlong(long long lhs, long long rhs, long long min, long long max) {
309 return (long long)(((unsigned long long)lhs) + ((unsigned long long)rhs));
524static inline zig_bool zig_subo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
525#if zig_has_builtin(sub_overflow)
526 zig_u8 full_res;
527 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
528 *res = zig_wrap_u8(full_res, bits);
529 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
530#else
531 return zig_subo_u32(res, lhs, rhs, bits);
532#endif
310533}
311534
312static inline uint8_t zig_subw_u8(uint8_t lhs, uint8_t rhs, uint8_t max) {
313 if (lhs < rhs) {
314 return max - rhs - lhs + 1;
315 } else {
316 return lhs - rhs;
317 }
535static inline zig_bool zig_subo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
536#if zig_has_builtin(sub_overflow)
537 zig_i8 full_res;
538 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
539 *res = zig_wrap_i8(full_res, bits);
540 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
541#else
542 return zig_subo_i32(res, lhs, rhs, bits);
543#endif
318544}
319545
320static inline int8_t zig_subw_i8(int8_t lhs, int8_t rhs, int8_t min, int8_t max) {
321 if ((lhs > 0) && (rhs < 0)) {
322 int8_t thresh = lhs - max;
323 if (rhs < thresh) {
324 return min + (thresh - rhs - 1);
325 }
326 } else if ((lhs < 0) && (rhs > 0)) {
327 int8_t thresh = lhs - min;
328 if (rhs > thresh) {
329 return max - (rhs - thresh - 1);
330 }
331 }
332 return lhs - rhs;
546static inline zig_bool zig_subo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
547#if zig_has_builtin(sub_overflow)
548 zig_u16 full_res;
549 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
550 *res = zig_wrap_u16(full_res, bits);
551 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
552#else
553 return zig_subo_u32(res, lhs, rhs, bits);
554#endif
333555}
334556
335static inline uint16_t zig_subw_u16(uint16_t lhs, uint16_t rhs, uint16_t max) {
336 if (lhs < rhs) {
337 return max - rhs - lhs + 1;
338 } else {
339 return lhs - rhs;
340 }
557static inline zig_bool zig_subo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
558#if zig_has_builtin(sub_overflow)
559 zig_i16 full_res;
560 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
561 *res = zig_wrap_i16(full_res, bits);
562 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
563#else
564 return zig_subo_i32(res, lhs, rhs, bits);
565#endif
341566}
342567
343static inline int16_t zig_subw_i16(int16_t lhs, int16_t rhs, int16_t min, int16_t max) {
344 if ((lhs > 0) && (rhs < 0)) {
345 int16_t thresh = lhs - max;
346 if (rhs < thresh) {
347 return min + (thresh - rhs - 1);
348 }
349 } else if ((lhs < 0) && (rhs > 0)) {
350 int16_t thresh = lhs - min;
351 if (rhs > thresh) {
352 return max - (rhs - thresh - 1);
353 }
354 }
355 return lhs - rhs;
568static inline zig_bool zig_mulo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
569#if zig_has_builtin(mul_overflow)
570 zig_u32 full_res;
571 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
572 *res = zig_wrap_u32(full_res, bits);
573 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
574#else
575 *res = zig_mulw_u32(lhs, rhs, bits);
576 return rhs != zig_as_u32(0) && lhs > zig_maxInt(u32, bits) / rhs;
577#endif
356578}
357579
358static inline uint32_t zig_subw_u32(uint32_t lhs, uint32_t rhs, uint32_t max) {
359 if (lhs < rhs) {
360 return max - rhs - lhs + 1;
361 } else {
362 return lhs - rhs;
363 }
580zig_extern_c zig_i32 __mulosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
581static inline zig_bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
582#if zig_has_builtin(mul_overflow)
583 zig_i32 full_res;
584 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
585#else
586 zig_c_int overflow_int;
587 zig_u32 full_res = __mulosi4(lhs, rhs, &overflow_int);
588 zig_bool overflow = overflow_int != 0;
589#endif
590 *res = zig_wrap_i32(full_res, bits);
591 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
364592}
365593
366static inline int32_t zig_subw_i32(int32_t lhs, int32_t rhs, int32_t min, int32_t max) {
367 if ((lhs > 0) && (rhs < 0)) {
368 int32_t thresh = lhs - max;
369 if (rhs < thresh) {
370 return min + (thresh - rhs - 1);
371 }
372 } else if ((lhs < 0) && (rhs > 0)) {
373 int32_t thresh = lhs - min;
374 if (rhs > thresh) {
375 return max - (rhs - thresh - 1);
376 }
377 }
378 return lhs - rhs;
594static inline zig_bool zig_mulo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
595#if zig_has_builtin(mul_overflow)
596 zig_u64 full_res;
597 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
598 *res = zig_wrap_u64(full_res, bits);
599 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
600#else
601 *res = zig_mulw_u64(lhs, rhs, bits);
602 return rhs != zig_as_u64(0) && lhs > zig_maxInt(u64, bits) / rhs;
603#endif
379604}
380605
381static inline uint64_t zig_subw_u64(uint64_t lhs, uint64_t rhs, uint64_t max) {
382 if (lhs < rhs) {
383 return max - rhs - lhs + 1;
384 } else {
385 return lhs - rhs;
386 }
606zig_extern_c zig_i64 __mulodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
607static inline zig_bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
608#if zig_has_builtin(mul_overflow)
609 zig_i64 full_res;
610 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
611#else
612 zig_c_int overflow_int;
613 zig_u64 full_res = __mulodi4(lhs, rhs, &overflow_int);
614 zig_bool overflow = overflow_int != 0;
615#endif
616 *res = zig_wrap_i64(full_res, bits);
617 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
387618}
388619
389static inline int64_t zig_subw_i64(int64_t lhs, int64_t rhs, int64_t min, int64_t max) {
390 if ((lhs > 0) && (rhs < 0)) {
391 int64_t thresh = lhs - max;
392 if (rhs < thresh) {
393 return min + (thresh - rhs - 1);
394 }
395 } else if ((lhs < 0) && (rhs > 0)) {
396 int64_t thresh = lhs - min;
397 if (rhs > thresh) {
398 return max - (rhs - thresh - 1);
399 }
400 }
401 return lhs - rhs;
620static inline zig_bool zig_mulo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
621#if zig_has_builtin(mul_overflow)
622 zig_u8 full_res;
623 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
624 *res = zig_wrap_u8(full_res, bits);
625 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
626#else
627 return zig_mulo_u32(res, lhs, rhs, bits);
628#endif
402629}
403630
404static inline intptr_t zig_subw_isize(intptr_t lhs, intptr_t rhs, intptr_t min, intptr_t max) {
405 return (intptr_t)(((uintptr_t)lhs) - ((uintptr_t)rhs));
631static inline zig_bool zig_mulo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
632#if zig_has_builtin(mul_overflow)
633 zig_i8 full_res;
634 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
635 *res = zig_wrap_i8(full_res, bits);
636 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
637#else
638 return zig_mulo_i32(res, lhs, rhs, bits);
639#endif
406640}
407641
408static inline short zig_subw_short(short lhs, short rhs, short min, short max) {
409 return (short)(((unsigned short)lhs) - ((unsigned short)rhs));
642static inline zig_bool zig_mulo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
643#if zig_has_builtin(mul_overflow)
644 zig_u16 full_res;
645 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
646 *res = zig_wrap_u16(full_res, bits);
647 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
648#else
649 return zig_mulo_u32(res, lhs, rhs, bits);
650#endif
410651}
411652
412static inline int zig_subw_int(int lhs, int rhs, int min, int max) {
413 return (int)(((unsigned)lhs) - ((unsigned)rhs));
653static inline zig_bool zig_mulo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
654#if zig_has_builtin(mul_overflow)
655 zig_i16 full_res;
656 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
657 *res = zig_wrap_i16(full_res, bits);
658 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
659#else
660 return zig_mulo_i32(res, lhs, rhs, bits);
661#endif
414662}
415663
416static inline long zig_subw_long(long lhs, long rhs, long min, long max) {
417 return (long)(((unsigned long)lhs) - ((unsigned long)rhs));
664#define zig_int_builtins(w) \
665 static inline zig_u##w zig_shlw_u##w(zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
666 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
667 } \
668\
669 static inline zig_i##w zig_shlw_i##w(zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
670 return zig_wrap_i##w((zig_i##w)zig_shl_u##w((zig_u##w)lhs, (zig_u##w)rhs), bits); \
671 } \
672\
673 static inline zig_u##w zig_addw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
674 return zig_wrap_u##w(lhs + rhs, bits); \
675 } \
676\
677 static inline zig_i##w zig_addw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
678 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs + (zig_u##w)rhs), bits); \
679 } \
680\
681 static inline zig_u##w zig_subw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
682 return zig_wrap_u##w(lhs - rhs, bits); \
683 } \
684\
685 static inline zig_i##w zig_subw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
686 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs - (zig_u##w)rhs), bits); \
687 } \
688\
689 static inline zig_u##w zig_mulw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
690 return zig_wrap_u##w(lhs * rhs, bits); \
691 } \
692\
693 static inline zig_i##w zig_mulw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
694 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs * (zig_u##w)rhs), bits); \
695 } \
696\
697 static inline zig_bool zig_shlo_u##w(zig_u##w *res, zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
698 *res = zig_shlw_u##w(lhs, rhs, bits); \
699 return (lhs & zig_maxInt_u##w << (bits - rhs)) != zig_as_u##w(0); \
700 } \
701\
702 static inline zig_bool zig_shlo_i##w(zig_i##w *res, zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
703 *res = zig_shlw_i##w(lhs, rhs, bits); \
704 zig_i##w mask = (zig_i##w)(zig_maxInt_u##w << (bits - rhs - 1)); \
705 return (lhs & mask) != zig_as_i##w(0) && (lhs & mask) != mask; \
706 } \
707\
708 static inline zig_u##w zig_shls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
709 zig_u##w res; \
710 if (rhs >= bits) return lhs != zig_as_u##w(0) ? zig_maxInt(u##w, bits) : lhs; \
711 return zig_shlo_u##w(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u##w, bits) : res; \
712 } \
713\
714 static inline zig_i##w zig_shls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
715 zig_i##w res; \
716 if ((zig_u##w)rhs < (zig_u##w)bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
717 return lhs < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
718 } \
719\
720 static inline zig_u##w zig_adds_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
721 zig_u##w res; \
722 return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
723 } \
724\
725 static inline zig_i##w zig_adds_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
726 zig_i##w res; \
727 if (!zig_addo_i##w(&res, lhs, rhs, bits)) return res; \
728 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
729 } \
730\
731 static inline zig_u##w zig_subs_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
732 zig_u##w res; \
733 return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt(u##w, bits) : res; \
734 } \
735\
736 static inline zig_i##w zig_subs_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
737 zig_i##w res; \
738 if (!zig_subo_i##w(&res, lhs, rhs, bits)) return res; \
739 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
740 } \
741\
742 static inline zig_u##w zig_muls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
743 zig_u##w res; \
744 return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
745 } \
746\
747 static inline zig_i##w zig_muls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
748 zig_i##w res; \
749 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
750 return (lhs ^ rhs) < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
751 }
752zig_int_builtins(8)
753zig_int_builtins(16)
754zig_int_builtins(32)
755zig_int_builtins(64)
756
757#define zig_builtin8(name, val) __builtin_##name(val)
758typedef zig_c_uint zig_Builtin8;
759
760#define zig_builtin16(name, val) __builtin_##name(val)
761typedef zig_c_uint zig_Builtin16;
762
763#if INT_MIN <= INT32_MIN
764#define zig_builtin32(name, val) __builtin_##name(val)
765typedef zig_c_uint zig_Builtin32;
766#elif LONG_MIN <= INT32_MIN
767#define zig_builtin32(name, val) __builtin_##name##l(val)
768typedef zig_c_ulong zig_Builtin32;
769#endif
770
771#if INT_MIN <= INT64_MIN
772#define zig_builtin64(name, val) __builtin_##name(val)
773typedef zig_c_uint zig_Builtin64;
774#elif LONG_MIN <= INT64_MIN
775#define zig_builtin64(name, val) __builtin_##name##l(val)
776typedef zig_c_ulong zig_Builtin64;
777#elif LLONG_MIN <= INT64_MIN
778#define zig_builtin64(name, val) __builtin_##name##ll(val)
779typedef zig_c_ulonglong zig_Builtin64;
780#endif
781
782#if zig_has_builtin(clz)
783#define zig_builtin_clz(w) \
784 static inline zig_u8 zig_clz_u##w(zig_u##w val, zig_u8 bits) { \
785 if (val == 0) return bits; \
786 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
787 } \
788\
789 static inline zig_u8 zig_clz_i##w(zig_i##w val, zig_u8 bits) { \
790 return zig_clz_u##w((zig_u##w)val, bits); \
791 }
792zig_builtin_clz(8)
793zig_builtin_clz(16)
794zig_builtin_clz(32)
795zig_builtin_clz(64)
796#endif
797
798#if zig_has_builtin(ctz)
799#define zig_builtin_ctz(w) \
800 static inline zig_u8 zig_ctz_u##w(zig_u##w val, zig_u8 bits) { \
801 if (val == 0) return bits; \
802 return zig_builtin##w(ctz, val); \
803 } \
804\
805 static inline zig_u8 zig_ctz_i##w(zig_i##w val, zig_u8 bits) { \
806 return zig_ctz_u##w((zig_u##w)val, bits); \
807 }
808zig_builtin_ctz(8)
809zig_builtin_ctz(16)
810zig_builtin_ctz(32)
811zig_builtin_ctz(64)
812#endif
813
814#if zig_has_builtin(popcount)
815#define zig_builtin_popcount(w) \
816 static inline zig_u8 zig_popcount_u##w(zig_u##w val, zig_u8 bits) { \
817 (void)bits; \
818 return zig_builtin##w(popcount, val); \
819 } \
820\
821 static inline zig_u8 zig_popcount_i##w(zig_i##w val, zig_u8 bits) { \
822 \
823 return zig_popcount_u##w((zig_u##w)val, bits); \
824 }
825zig_builtin_popcount(8)
826zig_builtin_popcount(16)
827zig_builtin_popcount(32)
828zig_builtin_popcount(64)
829#endif
830
831static inline zig_u8 zig_byte_swap_u8(zig_u8 val, zig_u8 bits) {
832 return zig_wrap_u8(val >> (8 - bits), bits);
418833}
419834
420static inline long long zig_subw_longlong(long long lhs, long long rhs, long long min, long long max) {
421 return (long long)(((unsigned long long)lhs) - ((unsigned long long)rhs));
835static inline zig_i8 zig_byte_swap_i8(zig_i8 val, zig_u8 bits) {
836 return zig_wrap_i8((zig_i8)zig_byte_swap_u8((zig_u8)val, bits), bits);
422837}
423838
424static inline bool zig_addo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {
425#if defined(__GNUC__) && INT8_MAX == INT_MAX
426 if (min == INT8_MIN && max == INT8_MAX) {
427 return __builtin_sadd_overflow(lhs, rhs, (int*)res);
428 }
429#elif defined(__GNUC__) && INT8_MAX == LONG_MAX
430 if (min == INT8_MIN && max == INT8_MAX) {
431 return __builtin_saddl_overflow(lhs, rhs, (long*)res);
432 }
433#elif defined(__GNUC__) && INT8_MAX == LLONG_MAX
434 if (min == INT8_MIN && max == INT8_MAX) {
435 return __builtin_saddll_overflow(lhs, rhs, (long long*)res);
436 }
839static inline zig_u16 zig_byte_swap_u16(zig_u16 val, zig_u8 bits) {
840 zig_u16 full_res;
841#if zig_has_builtin(bswap16)
842 full_res = __builtin_bswap16(val);
843#else
844 full_res = (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 0)) << 8 |
845 (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 8)) >> 0;
437846#endif
438 int16_t big_result = (int16_t)lhs + (int16_t)rhs;
439 if (big_result > max) {
440 *res = big_result - ((int16_t)max - (int16_t)min);
441 return true;
442 }
443 if (big_result < min) {
444 *res = big_result + ((int16_t)max - (int16_t)min);
445 return true;
446 }
447 *res = big_result;
448 return false;
847 return zig_wrap_u16(full_res >> (16 - bits), bits);
449848}
450849
451static inline bool zig_addo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {
452#if defined(__GNUC__) && INT16_MAX == INT_MAX
453 if (min == INT16_MIN && max == INT16_MAX) {
454 return __builtin_sadd_overflow(lhs, rhs, (int*)res);
455 }
456#elif defined(__GNUC__) && INT16_MAX == LONG_MAX
457 if (min == INT16_MIN && max == INT16_MAX) {
458 return __builtin_saddl_overflow(lhs, rhs, (long*)res);
459 }
460#elif defined(__GNUC__) && INT16_MAX == LLONG_MAX
461 if (min == INT16_MIN && max == INT16_MAX) {
462 return __builtin_saddll_overflow(lhs, rhs, (long long*)res);
463 }
464#endif
465 int32_t big_result = (int32_t)lhs + (int32_t)rhs;
466 if (big_result > max) {
467 *res = big_result - ((int32_t)max - (int32_t)min);
468 return true;
469 }
470 if (big_result < min) {
471 *res = big_result + ((int32_t)max - (int32_t)min);
472 return true;
473 }
474 *res = big_result;
475 return false;
850static inline zig_i16 zig_byte_swap_i16(zig_i16 val, zig_u8 bits) {
851 return zig_wrap_i16((zig_i16)zig_byte_swap_u16((zig_u16)val, bits), bits);
476852}
477853
478static inline bool zig_addo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {
479#if defined(__GNUC__) && INT32_MAX == INT_MAX
480 if (min == INT32_MIN && max == INT32_MAX) {
481 return __builtin_sadd_overflow(lhs, rhs, (int*)res);
482 }
483#elif defined(__GNUC__) && INT32_MAX == LONG_MAX
484 if (min == INT32_MIN && max == INT32_MAX) {
485 return __builtin_saddl_overflow(lhs, rhs, (long*)res);
486 }
487#elif defined(__GNUC__) && INT32_MAX == LLONG_MAX
488 if (min == INT32_MIN && max == INT32_MAX) {
489 return __builtin_saddll_overflow(lhs, rhs, (long long*)res);
490 }
491#endif
492 int64_t big_result = (int64_t)lhs + (int64_t)rhs;
493 if (big_result > max) {
494 *res = big_result - ((int64_t)max - (int64_t)min);
495 return true;
496 }
497 if (big_result < min) {
498 *res = big_result + ((int64_t)max - (int64_t)min);
499 return true;
500 }
501 *res = big_result;
502 return false;
503}
504
505static inline bool zig_addo_i64(int64_t lhs, int64_t rhs, int64_t *res, int64_t min, int64_t max) {
506 bool overflow;
507#if defined(__GNUC__) && INT64_MAX == INT_MAX
508 overflow = __builtin_sadd_overflow(lhs, rhs, (int*)res);
509#elif defined(__GNUC__) && INT64_MAX == LONG_MAX
510 overflow = __builtin_saddl_overflow(lhs, rhs, (long*)res);
511#elif defined(__GNUC__) && INT64_MAX == LLONG_MAX
512 overflow = __builtin_saddll_overflow(lhs, rhs, (long long*)res);
854static inline zig_u32 zig_byte_swap_u32(zig_u32 val, zig_u8 bits) {
855 zig_u32 full_res;
856#if zig_has_builtin(bswap32)
857 full_res = __builtin_bswap32(val);
513858#else
514 int int_overflow;
515 *res = __addodi4(lhs, rhs, &int_overflow);
516 overflow = int_overflow != 0;
517#endif
518 if (!overflow) {
519 if (*res > max) {
520 // TODO adjust the result to be the truncated bits
521 return true;
522 } else if (*res < min) {
523 // TODO adjust the result to be the truncated bits
524 return true;
525 }
526 }
527 return overflow;
859 full_res = (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 0)) << 16 |
860 (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 16)) >> 0;
861#endif
862 return zig_wrap_u32(full_res >> (32 - bits), bits);
528863}
529864
530static inline bool zig_addo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {
531 bool overflow;
532#if defined(__GNUC__) && INT128_MAX == INT_MAX
533 overflow = __builtin_sadd_overflow(lhs, rhs, (int*)res);
534#elif defined(__GNUC__) && INT128_MAX == LONG_MAX
535 overflow = __builtin_saddl_overflow(lhs, rhs, (long*)res);
536#elif defined(__GNUC__) && INT128_MAX == LLONG_MAX
537 overflow = __builtin_saddll_overflow(lhs, rhs, (long long*)res);
538#else
539 int int_overflow;
540 *res = __addoti4(lhs, rhs, &int_overflow);
541 overflow = int_overflow != 0;
542#endif
543 if (!overflow) {
544 if (*res > max) {
545 // TODO adjust the result to be the truncated bits
546 return true;
547 } else if (*res < min) {
548 // TODO adjust the result to be the truncated bits
549 return true;
550 }
551 }
552 return overflow;
865static inline zig_i32 zig_byte_swap_i32(zig_i32 val, zig_u8 bits) {
866 return zig_wrap_i32((zig_i32)zig_byte_swap_u32((zig_u32)val, bits), bits);
553867}
554868
555static inline bool zig_addo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {
556#if defined(__GNUC__) && UINT8_MAX == UINT_MAX
557 if (max == UINT8_MAX) {
558 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
559 }
560#elif defined(__GNUC__) && UINT8_MAX == ULONG_MAX
561 if (max == UINT8_MAX) {
562 return __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
563 }
564#elif defined(__GNUC__) && UINT8_MAX == ULLONG_MAX
565 if (max == UINT8_MAX) {
566 return __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
567 }
869static inline zig_u64 zig_byte_swap_u64(zig_u64 val, zig_u8 bits) {
870 zig_u64 full_res;
871#if zig_has_builtin(bswap64)
872 full_res = __builtin_bswap64(val);
873#else
874 full_res = (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 0)) << 32 |
875 (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 32)) >> 0;
568876#endif
569 uint16_t big_result = (uint16_t)lhs + (uint16_t)rhs;
570 if (big_result > max) {
571 *res = big_result - max - 1;
572 return true;
573 }
574 *res = big_result;
575 return false;
877 return zig_wrap_u64(full_res >> (64 - bits), bits);
576878}
577879
578static inline uint16_t zig_addo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {
579#if defined(__GNUC__) && UINT16_MAX == UINT_MAX
580 if (max == UINT16_MAX) {
581 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
582 }
583#elif defined(__GNUC__) && UINT16_MAX == ULONG_MAX
584 if (max == UINT16_MAX) {
585 return __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
586 }
587#elif defined(__GNUC__) && UINT16_MAX == ULLONG_MAX
588 if (max == UINT16_MAX) {
589 return __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
590 }
591#endif
592 uint32_t big_result = (uint32_t)lhs + (uint32_t)rhs;
593 if (big_result > max) {
594 *res = big_result - max - 1;
595 return true;
596 }
597 *res = big_result;
598 return false;
880static inline zig_i64 zig_byte_swap_i64(zig_i64 val, zig_u8 bits) {
881 return zig_wrap_i64((zig_i64)zig_byte_swap_u64((zig_u64)val, bits), bits);
599882}
600883
601static inline uint32_t zig_addo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {
602#if defined(__GNUC__) && UINT32_MAX == UINT_MAX
603 if (max == UINT32_MAX) {
604 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
605 }
606#elif defined(__GNUC__) && UINT32_MAX == ULONG_MAX
607 if (max == UINT32_MAX) {
608 return __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
609 }
610#elif defined(__GNUC__) && UINT32_MAX == ULLONG_MAX
611 if (max == UINT32_MAX) {
612 return __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
613 }
884static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
885 zig_u8 full_res;
886#if zig_has_builtin(bitreverse8)
887 full_res = __builtin_bitreverse8(val);
888#else
889 static zig_u8 const lut[0x10] = {
890 0b0000, 0b1000, 0b0100, 0b1100,
891 0b0010, 0b1010, 0b0110, 0b1110,
892 0b0001, 0b1001, 0b0101, 0b1101,
893 0b0011, 0b1011, 0b0111, 0b1111,
894 };
895 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
614896#endif
615 uint64_t big_result = (uint64_t)lhs + (uint64_t)rhs;
616 if (big_result > max) {
617 *res = big_result - max - 1;
618 return true;
619 }
620 *res = big_result;
621 return false;
622}
623
624static inline uint64_t zig_addo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {
625 bool overflow;
626#if defined(__GNUC__) && UINT64_MAX == UINT_MAX
627 overflow = __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
628#elif defined(__GNUC__) && UINT64_MAX == ULONG_MAX
629 overflow = __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
630#elif defined(__GNUC__) && UINT64_MAX == ULLONG_MAX
631 overflow = __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
897 return zig_wrap_u8(full_res >> (8 - bits), bits);
898}
899
900static inline zig_i8 zig_bit_reverse_i8(zig_i8 val, zig_u8 bits) {
901 return zig_wrap_i8((zig_i8)zig_bit_reverse_u8((zig_u8)val, bits), bits);
902}
903
904static inline zig_u16 zig_bit_reverse_u16(zig_u16 val, zig_u8 bits) {
905 zig_u16 full_res;
906#if zig_has_builtin(bitreverse16)
907 full_res = __builtin_bitreverse16(val);
632908#else
633 int int_overflow;
634 *res = __uaddodi4(lhs, rhs, &int_overflow);
635 overflow = int_overflow != 0;
909 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0)) << 8 |
910 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8)) >> 0;
636911#endif
637 if (*res > max && !overflow) {
638 *res -= max - 1;
639 return true;
640 }
641 return overflow;
912 return zig_wrap_u16(full_res >> (16 - bits), bits);
642913}
643914
644static inline uint128_t zig_addo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {
645 int overflow;
646 *res = __uaddoti4(lhs, rhs, &overflow);
647 if (*res > max && overflow == 0) {
648 *res -= max - 1;
649 return true;
650 }
651 return overflow != 0;
915static inline zig_i16 zig_bit_reverse_i16(zig_i16 val, zig_u8 bits) {
916 return zig_wrap_i16((zig_i16)zig_bit_reverse_u16((zig_u16)val, bits), bits);
652917}
653918
654static inline bool zig_subo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {
655#if defined(__GNUC__) && INT8_MAX == INT_MAX
656 if (min == INT8_MIN && max == INT8_MAX) {
657 return __builtin_ssub_overflow(lhs, rhs, (int*)res);
658 }
659#elif defined(__GNUC__) && INT8_MAX == LONG_MAX
660 if (min == INT8_MIN && max == INT8_MAX) {
661 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);
662 }
663#elif defined(__GNUC__) && INT8_MAX == LLONG_MAX
664 if (min == INT8_MIN && max == INT8_MAX) {
665 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
666 }
919static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) {
920 zig_u32 full_res;
921#if zig_has_builtin(bitreverse32)
922 full_res = __builtin_bitreverse32(val);
923#else
924 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0)) << 16 |
925 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16)) >> 0;
667926#endif
668 int16_t big_result = (int16_t)lhs - (int16_t)rhs;
669 if (big_result > max) {
670 *res = big_result - ((int16_t)max - (int16_t)min);
671 return true;
672 }
673 if (big_result < min) {
674 *res = big_result + ((int16_t)max - (int16_t)min);
675 return true;
676 }
677 *res = big_result;
678 return false;
927 return zig_wrap_u32(full_res >> (32 - bits), bits);
679928}
680929
681static inline bool zig_subo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {
682#if defined(__GNUC__) && INT16_MAX == INT_MAX
683 if (min == INT16_MIN && max == INT16_MAX) {
684 return __builtin_ssub_overflow(lhs, rhs, (int*)res);
685 }
686#elif defined(__GNUC__) && INT16_MAX == LONG_MAX
687 if (min == INT16_MIN && max == INT16_MAX) {
688 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);
689 }
690#elif defined(__GNUC__) && INT16_MAX == LLONG_MAX
691 if (min == INT16_MIN && max == INT16_MAX) {
692 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
693 }
930static inline zig_i32 zig_bit_reverse_i32(zig_i32 val, zig_u8 bits) {
931 return zig_wrap_i32((zig_i32)zig_bit_reverse_u32((zig_u32)val, bits), bits);
932}
933
934static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) {
935 zig_u64 full_res;
936#if zig_has_builtin(bitreverse64)
937 full_res = __builtin_bitreverse64(val);
938#else
939 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0)) << 32 |
940 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32)) >> 0;
694941#endif
695 int32_t big_result = (int32_t)lhs - (int32_t)rhs;
696 if (big_result > max) {
697 *res = big_result - ((int32_t)max - (int32_t)min);
698 return true;
699 }
700 if (big_result < min) {
701 *res = big_result + ((int32_t)max - (int32_t)min);
702 return true;
703 }
704 *res = big_result;
705 return false;
942 return zig_wrap_u64(full_res >> (64 - bits), bits);
706943}
707944
708static inline bool zig_subo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {
709#if defined(__GNUC__) && INT32_MAX == INT_MAX
710 if (min == INT32_MIN && max == INT32_MAX) {
711 return __builtin_ssub_overflow(lhs, rhs, (int*)res);
712 }
713#elif defined(__GNUC__) && INT32_MAX == LONG_MAX
714 if (min == INT32_MIN && max == INT32_MAX) {
715 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);
716 }
717#elif defined(__GNUC__) && INT32_MAX == LLONG_MAX
718 if (min == INT32_MIN && max == INT32_MAX) {
719 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
720 }
945static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {
946 return zig_wrap_i64((zig_i64)zig_bit_reverse_u64((zig_u64)val, bits), bits);
947}
948
949/* ======================== 128-bit Integer Routines ======================== */
950
951#if !defined(zig_has_int128)
952# if defined(__SIZEOF_INT128__)
953# define zig_has_int128 1
954# else
955# define zig_has_int128 0
956# endif
721957#endif
722 int64_t big_result = (int64_t)lhs - (int64_t)rhs;
723 if (big_result > max) {
724 *res = big_result - ((int64_t)max - (int64_t)min);
725 return true;
958
959#if zig_has_int128
960
961typedef unsigned __int128 zig_u128;
962typedef signed __int128 zig_i128;
963
964#define zig_as_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
965#define zig_as_i128(hi, lo) ((zig_i128)zig_as_u128(hi, lo))
966#define zig_hi_u128(val) ((zig_u64)((val) >> 64))
967#define zig_lo_u128(val) ((zig_u64)((val) >> 0))
968#define zig_hi_i128(val) ((zig_i64)((val) >> 64))
969#define zig_lo_i128(val) ((zig_u64)((val) >> 0))
970#define zig_bitcast_u128(val) ((zig_u128)(val))
971#define zig_bitcast_i128(val) ((zig_i128)(val))
972#define zig_cmp_int128(ZigType, CType) \
973 static inline zig_i8 zig_cmp_##ZigType(CType lhs, CType rhs) { \
974 return (lhs > rhs) - (lhs < rhs); \
726975 }
727 if (big_result < min) {
728 *res = big_result + ((int64_t)max - (int64_t)min);
729 return true;
976#define zig_bit_int128(ZigType, CType, operation, operator) \
977 static inline CType zig_##operation##_##ZigType(CType lhs, CType rhs) { \
978 return lhs operator rhs; \
730979 }
731 *res = big_result;
732 return false;
733}
734
735static inline bool zig_subo_i64(int64_t lhs, int64_t rhs, int64_t *res, int64_t min, int64_t max) {
736 bool overflow;
737#if defined(__GNUC__) && INT64_MAX == INT_MAX
738 overflow = __builtin_ssub_overflow(lhs, rhs, (int*)res);
739#elif defined(__GNUC__) && INT64_MAX == LONG_MAX
740 overflow = __builtin_ssubl_overflow(lhs, rhs, (long*)res);
741#elif defined(__GNUC__) && INT64_MAX == LLONG_MAX
742 overflow = __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
980
981#else /* zig_has_int128 */
982
983#if __LITTLE_ENDIAN__ || _MSC_VER
984typedef struct { zig_align(16) zig_u64 lo; zig_u64 hi; } zig_u128;
985typedef struct { zig_align(16) zig_u64 lo; zig_i64 hi; } zig_i128;
743986#else
744 int int_overflow;
745 *res = __subodi4(lhs, rhs, &int_overflow);
746 overflow = int_overflow != 0;
747#endif
748 if (!overflow) {
749 if (*res > max) {
750 // TODO adjust the result to be the truncated bits
751 return true;
752 } else if (*res < min) {
753 // TODO adjust the result to be the truncated bits
754 return true;
755 }
987typedef struct { zig_align(16) zig_u64 hi; zig_u64 lo; } zig_u128;
988typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
989#endif
990
991#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
992#define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
993#define zig_hi_u128(val) ((val).hi)
994#define zig_lo_u128(val) ((val).lo)
995#define zig_hi_i128(val) ((val).hi)
996#define zig_lo_i128(val) ((val).lo)
997#define zig_bitcast_u128(val) zig_as_u128((zig_u64)(val).hi, (val).lo)
998#define zig_bitcast_i128(val) zig_as_i128((zig_i64)(val).hi, (val).lo)
999#define zig_cmp_int128(ZigType, CType) \
1000 static inline zig_c_int zig_cmp_##ZigType(CType lhs, CType rhs) { \
1001 return (lhs.hi == rhs.hi) \
1002 ? (lhs.lo > rhs.lo) - (lhs.lo < rhs.lo) \
1003 : (lhs.hi > rhs.hi) - (lhs.hi < rhs.hi); \
1004 }
1005#define zig_bit_int128(ZigType, CType, operation, operator) \
1006 static inline CType zig_##operation##_##ZigType(CType lhs, CType rhs) { \
1007 return (CType){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
7561008 }
757 return overflow;
1009
1010#endif /* zig_has_int128 */
1011
1012#define zig_minInt_u128 zig_as_u128(zig_minInt_u64, zig_minInt_u64)
1013#define zig_maxInt_u128 zig_as_u128(zig_maxInt_u64, zig_maxInt_u64)
1014#define zig_minInt_i128 zig_as_i128(zig_minInt_i64, zig_minInt_u64)
1015#define zig_maxInt_i128 zig_as_i128(zig_maxInt_i64, zig_maxInt_u64)
1016
1017zig_cmp_int128(u128, zig_u128)
1018zig_cmp_int128(i128, zig_i128)
1019
1020zig_bit_int128(u128, zig_u128, and, &)
1021zig_bit_int128(i128, zig_i128, and, &)
1022
1023zig_bit_int128(u128, zig_u128, or, |)
1024zig_bit_int128(i128, zig_i128, or, |)
1025
1026zig_bit_int128(u128, zig_u128, xor, ^)
1027zig_bit_int128(i128, zig_i128, xor, ^)
1028
1029static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs);
1030
1031#if zig_has_int128
1032
1033static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1034 return val ^ zig_maxInt(u128, bits);
7581035}
7591036
760static inline bool zig_subo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {
761 bool overflow;
762#if defined(__GNUC__) && INT128_MAX == INT_MAX
763 overflow = __builtin_ssub_overflow(lhs, rhs, (int*)res);
764#elif defined(__GNUC__) && INT128_MAX == LONG_MAX
765 overflow = __builtin_ssubl_overflow(lhs, rhs, (long*)res);
766#elif defined(__GNUC__) && INT128_MAX == LLONG_MAX
767 overflow = __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
768#else
769 int int_overflow;
770 *res = __suboti4(lhs, rhs, &int_overflow);
771 overflow = int_overflow != 0;
772#endif
773 if (!overflow) {
774 if (*res > max) {
775 // TODO adjust the result to be the truncated bits
776 return true;
777 } else if (*res < min) {
778 // TODO adjust the result to be the truncated bits
779 return true;
780 }
781 }
782 return overflow;
1037static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1038 (void)bits;
1039 return ~val;
7831040}
7841041
785static inline bool zig_subo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {
786#if defined(__GNUC__) && UINT8_MAX == UINT_MAX
787 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
788#elif defined(__GNUC__) && UINT8_MAX == ULONG_MAX
789 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
790#elif defined(__GNUC__) && UINT8_MAX == ULLONG_MAX
791 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
792#endif
793 if (rhs > lhs) {
794 *res = max - (rhs - lhs - 1);
795 return true;
796 }
797 *res = lhs - rhs;
798 return false;
1042static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1043 return lhs >> rhs;
7991044}
8001045
801static inline uint16_t zig_subo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {
802#if defined(__GNUC__) && UINT16_MAX == UINT_MAX
803 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
804#elif defined(__GNUC__) && UINT16_MAX == ULONG_MAX
805 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
806#elif defined(__GNUC__) && UINT16_MAX == ULLONG_MAX
807 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
808#endif
809 if (rhs > lhs) {
810 *res = max - (rhs - lhs - 1);
811 return true;
812 }
813 *res = lhs - rhs;
814 return false;
815}
816
817static inline uint32_t zig_subo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {
818 if (max == UINT32_MAX) {
819#if defined(__GNUC__) && UINT32_MAX == UINT_MAX
820 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
821#elif defined(__GNUC__) && UINT32_MAX == ULONG_MAX
822 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
823#elif defined(__GNUC__) && UINT32_MAX == ULLONG_MAX
824 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
825#endif
826 int int_overflow;
827 *res = __usubosi4(lhs, rhs, &int_overflow);
828 return int_overflow != 0;
829 } else {
830 if (rhs > lhs) {
831 *res = max - (rhs - lhs - 1);
832 return true;
833 }
834 *res = lhs - rhs;
835 return false;
836 }
1046static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1047 return lhs << rhs;
8371048}
8381049
839static inline uint64_t zig_subo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {
840 if (max == UINT64_MAX) {
841#if defined(__GNUC__) && UINT64_MAX == UINT_MAX
842 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
843#elif defined(__GNUC__) && UINT64_MAX == ULONG_MAX
844 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
845#elif defined(__GNUC__) && UINT64_MAX == ULLONG_MAX
846 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
847#else
848 int int_overflow;
849 *res = __usubodi4(lhs, rhs, &int_overflow);
850 return int_overflow != 0;
851#endif
852 } else {
853 if (rhs > lhs) {
854 *res = max - (rhs - lhs - 1);
855 return true;
856 }
857 *res = lhs - rhs;
858 return false;
859 }
1050static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1051 return lhs << rhs;
8601052}
8611053
862static inline uint128_t zig_subo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {
863 if (max == UINT128_MAX) {
864 int int_overflow;
865 *res = __usuboti4(lhs, rhs, &int_overflow);
866 return int_overflow != 0;
867 } else {
868 if (rhs > lhs) {
869 *res = max - (rhs - lhs - 1);
870 return true;
871 }
872 *res = lhs - rhs;
873 return false;
874 }
1054static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
1055 return lhs + rhs;
8751056}
8761057
877static inline bool zig_mulo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {
878#if defined(__GNUC__) && INT8_MAX == INT_MAX
879 if (min == INT8_MIN && max == INT8_MAX) {
880 return __builtin_smul_overflow(lhs, rhs, (int*)res);
881 }
882#elif defined(__GNUC__) && INT8_MAX == LONG_MAX
883 if (min == INT8_MIN && max == INT8_MAX) {
884 return __builtin_smull_overflow(lhs, rhs, (long*)res);
885 }
886#elif defined(__GNUC__) && INT8_MAX == LLONG_MAX
887 if (min == INT8_MIN && max == INT8_MAX) {
888 return __builtin_smulll_overflow(lhs, rhs, (long long*)res);
889 }
890#endif
891 int16_t big_result = (int16_t)lhs * (int16_t)rhs;
892 if (big_result > max) {
893 *res = big_result - ((int16_t)max - (int16_t)min);
894 return true;
895 }
896 if (big_result < min) {
897 *res = big_result + ((int16_t)max - (int16_t)min);
898 return true;
899 }
900 *res = big_result;
901 return false;
1058static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
1059 return lhs + rhs;
9021060}
9031061
904static inline bool zig_mulo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {
905#if defined(__GNUC__) && INT16_MAX == INT_MAX
906 if (min == INT16_MIN && max == INT16_MAX) {
907 return __builtin_smul_overflow(lhs, rhs, (int*)res);
908 }
909#elif defined(__GNUC__) && INT16_MAX == LONG_MAX
910 if (min == INT16_MIN && max == INT16_MAX) {
911 return __builtin_smull_overflow(lhs, rhs, (long*)res);
912 }
913#elif defined(__GNUC__) && INT16_MAX == LLONG_MAX
914 if (min == INT16_MIN && max == INT16_MAX) {
915 return __builtin_smulll_overflow(lhs, rhs, (long long*)res);
916 }
917#endif
918 int32_t big_result = (int32_t)lhs * (int32_t)rhs;
919 if (big_result > max) {
920 *res = big_result - ((int32_t)max - (int32_t)min);
921 return true;
922 }
923 if (big_result < min) {
924 *res = big_result + ((int32_t)max - (int32_t)min);
925 return true;
926 }
927 *res = big_result;
928 return false;
1062static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
1063 return lhs - rhs;
9291064}
9301065
931static inline bool zig_mulo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {
932#if defined(__GNUC__) && INT32_MAX == INT_MAX
933 if (min == INT32_MIN && max == INT32_MAX) {
934 return __builtin_smul_overflow(lhs, rhs, (int*)res);
935 }
936#elif defined(__GNUC__) && INT32_MAX == LONG_MAX
937 if (min == INT32_MIN && max == INT32_MAX) {
938 return __builtin_smull_overflow(lhs, rhs, (long*)res);
939 }
940#elif defined(__GNUC__) && INT32_MAX == LLONG_MAX
941 if (min == INT32_MIN && max == INT32_MAX) {
942 return __builtin_smulll_overflow(lhs, rhs, (long long*)res);
943 }
944#endif
945 int64_t big_result = (int64_t)lhs * (int64_t)rhs;
946 if (big_result > max) {
947 *res = big_result - ((int64_t)max - (int64_t)min);
948 return true;
949 }
950 if (big_result < min) {
951 *res = big_result + ((int64_t)max - (int64_t)min);
952 return true;
953 }
954 *res = big_result;
955 return false;
956}
957
958static inline bool zig_mulo_i64(int64_t lhs, int64_t rhs, int64_t *res, int64_t min, int64_t max) {
959 bool overflow;
960#if defined(__GNUC__) && INT64_MAX == INT_MAX
961 overflow = __builtin_smul_overflow(lhs, rhs, (int*)res);
962#elif defined(__GNUC__) && INT64_MAX == LONG_MAX
963 overflow = __builtin_smull_overflow(lhs, rhs, (long*)res);
964#elif defined(__GNUC__) && INT64_MAX == LLONG_MAX
965 overflow = __builtin_smulll_overflow(lhs, rhs, (long long*)res);
966#else
967 int int_overflow;
968 *res = __mulodi4(lhs, rhs, &int_overflow);
969 overflow = int_overflow != 0;
970#endif
971 if (!overflow) {
972 if (*res > max) {
973 // TODO adjust the result to be the truncated bits
974 return true;
975 } else if (*res < min) {
976 // TODO adjust the result to be the truncated bits
977 return true;
978 }
979 }
980 return overflow;
1066static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1067 return lhs - rhs;
9811068}
9821069
983static inline bool zig_mulo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {
984 bool overflow;
985#if defined(__GNUC__) && INT128_MAX == INT_MAX
986 overflow = __builtin_smul_overflow(lhs, rhs, (int*)res);
987#elif defined(__GNUC__) && INT128_MAX == LONG_MAX
988 overflow = __builtin_smull_overflow(lhs, rhs, (long*)res);
989#elif defined(__GNUC__) && INT128_MAX == LLONG_MAX
990 overflow = __builtin_smulll_overflow(lhs, rhs, (long long*)res);
991#else
992 int int_overflow;
993 *res = __muloti4(lhs, rhs, &int_overflow);
994 overflow = int_overflow != 0;
995#endif
996 if (!overflow) {
997 if (*res > max) {
998 // TODO adjust the result to be the truncated bits
999 return true;
1000 } else if (*res < min) {
1001 // TODO adjust the result to be the truncated bits
1002 return true;
1003 }
1004 }
1005 return overflow;
1070static inline zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1071 return lhs * rhs;
10061072}
10071073
1008static inline bool zig_mulo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {
1009#if defined(__GNUC__) && UINT8_MAX == UINT_MAX
1010 if (max == UINT8_MAX) {
1011 return __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1012 }
1013#elif defined(__GNUC__) && UINT8_MAX == ULONG_MAX
1014 if (max == UINT8_MAX) {
1015 return __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1016 }
1017#elif defined(__GNUC__) && UINT8_MAX == ULLONG_MAX
1018 if (max == UINT8_MAX) {
1019 return __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1020 }
1021#endif
1022 uint16_t big_result = (uint16_t)lhs * (uint16_t)rhs;
1023 if (big_result > max) {
1024 *res = big_result - max - 1;
1025 return true;
1026 }
1027 *res = big_result;
1028 return false;
1074static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1075 return lhs * rhs;
10291076}
10301077
1031static inline uint16_t zig_mulo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {
1032#if defined(__GNUC__) && UINT16_MAX == UINT_MAX
1033 if (max == UINT16_MAX) {
1034 return __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1035 }
1036#elif defined(__GNUC__) && UINT16_MAX == ULONG_MAX
1037 if (max == UINT16_MAX) {
1038 return __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1039 }
1040#elif defined(__GNUC__) && UINT16_MAX == ULLONG_MAX
1041 if (max == UINT16_MAX) {
1042 return __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1043 }
1044#endif
1045 uint32_t big_result = (uint32_t)lhs * (uint32_t)rhs;
1046 if (big_result > max) {
1047 *res = big_result - max - 1;
1048 return true;
1049 }
1050 *res = big_result;
1051 return false;
1078static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
1079 return lhs / rhs;
10521080}
10531081
1054static inline uint32_t zig_mulo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {
1055#if defined(__GNUC__) && UINT32_MAX == UINT_MAX
1056 if (max == UINT32_MAX) {
1057 return __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1058 }
1059#elif defined(__GNUC__) && UINT32_MAX == ULONG_MAX
1060 if (max == UINT32_MAX) {
1061 return __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1062 }
1063#elif defined(__GNUC__) && UINT32_MAX == ULLONG_MAX
1064 if (max == UINT32_MAX) {
1065 return __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1066 }
1067#endif
1068 uint64_t big_result = (uint64_t)lhs * (uint64_t)rhs;
1069 if (big_result > max) {
1070 *res = big_result - max - 1;
1071 return true;
1072 }
1073 *res = big_result;
1074 return false;
1075}
1076
1077static inline uint64_t zig_mulo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {
1078 bool overflow;
1079#if defined(__GNUC__) && UINT64_MAX == UINT_MAX
1080 overflow = __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1081#elif defined(__GNUC__) && UINT64_MAX == ULONG_MAX
1082 overflow = __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1083#elif defined(__GNUC__) && UINT64_MAX == ULLONG_MAX
1084 overflow = __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1085#else
1086 int int_overflow;
1087 *res = __umulodi4(lhs, rhs, &int_overflow);
1088 overflow = int_overflow != 0;
1089#endif
1090 if (*res > max && !overflow) {
1091 *res -= max - 1;
1092 return true;
1093 }
1094 return overflow;
1082static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
1083 return lhs / rhs;
10951084}
10961085
1097static inline uint128_t zig_mulo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {
1098 int overflow;
1099 *res = __umuloti4(lhs, rhs, &overflow);
1100 if (*res > max && overflow == 0) {
1101 *res -= max - 1;
1102 return true;
1103 }
1104 return overflow != 0;
1086static inline zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
1087 return lhs % rhs;
11051088}
11061089
1107static inline float zig_bitcast_f32_u32(uint32_t arg) {
1108 float dest;
1109 memcpy(&dest, &arg, sizeof dest);
1110 return dest;
1090static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
1091 return lhs % rhs;
11111092}
11121093
1113static inline float zig_bitcast_f64_u64(uint64_t arg) {
1114 double dest;
1115 memcpy(&dest, &arg, sizeof dest);
1116 return dest;
1094static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1095 return zig_div_trunc_i128(lhs, rhs) - (((lhs ^ rhs) & zig_rem_i128(lhs, rhs)) < zig_as_i128(0, 0));
11171096}
11181097
1119#define zig_add_sat_u(ZT, T) static inline T zig_adds_##ZT(T x, T y, T max) { \
1120 return (x > max - y) ? max : x + y; \
1121}
1122
1123#define zig_add_sat_s(ZT, T, T2) static inline T zig_adds_##ZT(T2 x, T2 y, T2 min, T2 max) { \
1124 T2 res = x + y; \
1125 return (res < min) ? min : (res > max) ? max : res; \
1126}
1127
1128zig_add_sat_u( u8, uint8_t)
1129zig_add_sat_s( i8, int8_t, int16_t)
1130zig_add_sat_u(u16, uint16_t)
1131zig_add_sat_s(i16, int16_t, int32_t)
1132zig_add_sat_u(u32, uint32_t)
1133zig_add_sat_s(i32, int32_t, int64_t)
1134zig_add_sat_u(u64, uint64_t)
1135zig_add_sat_s(i64, int64_t, int128_t)
1136zig_add_sat_s(isize, intptr_t, int128_t)
1137zig_add_sat_s(short, short, int)
1138zig_add_sat_s(int, int, long)
1139zig_add_sat_s(long, long, long long)
1140
1141#define zig_sub_sat_u(ZT, T) static inline T zig_subs_##ZT(T x, T y, T max) { \
1142 return (x > max + y) ? max : x - y; \
1098static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1099 zig_i128 rem = zig_rem_i128(lhs, rhs);
1100 return rem + (((lhs ^ rhs) & rem) < zig_as_i128(0, 0) ? rhs : zig_as_i128(0, 0));
11431101}
11441102
1145#define zig_sub_sat_s(ZT, T, T2) static inline T zig_subs_##ZT(T2 x, T2 y, T2 min, T2 max) { \
1146 T2 res = x - y; \
1147 return (res < min) ? min : (res > max) ? max : res; \
1148}
1149
1150zig_sub_sat_u( u8, uint8_t)
1151zig_sub_sat_s( i8, int8_t, int16_t)
1152zig_sub_sat_u(u16, uint16_t)
1153zig_sub_sat_s(i16, int16_t, int32_t)
1154zig_sub_sat_u(u32, uint32_t)
1155zig_sub_sat_s(i32, int32_t, int64_t)
1156zig_sub_sat_u(u64, uint64_t)
1157zig_sub_sat_s(i64, int64_t, int128_t)
1158zig_sub_sat_s(isize, intptr_t, int128_t)
1159zig_sub_sat_s(short, short, int)
1160zig_sub_sat_s(int, int, long)
1161zig_sub_sat_s(long, long, long long)
1162
1103#else /* zig_has_int128 */
11631104
1164#define zig_mul_sat_u(ZT, T, T2) static inline T zig_muls_##ZT(T2 x, T2 y, T2 max) { \
1165 T2 res = x * y; \
1166 return (res > max) ? max : res; \
1105static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1106 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
11671107}
11681108
1169#define zig_mul_sat_s(ZT, T, T2) static inline T zig_muls_##ZT(T2 x, T2 y, T2 min, T2 max) { \
1170 T2 res = x * y; \
1171 return (res < min) ? min : (res > max) ? max : res; \
1109static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1110 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
11721111}
11731112
1174zig_mul_sat_u(u8, uint8_t, uint16_t)
1175zig_mul_sat_s(i8, int8_t, int16_t)
1176zig_mul_sat_u(u16, uint16_t, uint32_t)
1177zig_mul_sat_s(i16, int16_t, int32_t)
1178zig_mul_sat_u(u32, uint32_t, uint64_t)
1179zig_mul_sat_s(i32, int32_t, int64_t)
1180zig_mul_sat_u(u64, uint64_t, uint128_t)
1181zig_mul_sat_s(i64, int64_t, int128_t)
1182zig_mul_sat_s(isize, intptr_t, int128_t)
1183zig_mul_sat_s(short, short, int)
1184zig_mul_sat_s(int, int, long)
1185zig_mul_sat_s(long, long, long long)
1113static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1114 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1115 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1116}
11861117
1187#define zig_shl_sat_u(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T max) { \
1188 if(x == 0) return 0; \
1189 T bits_set = 64 - __builtin_clzll(x); \
1190 return (bits_set + y > bits) ? max : x << y; \
1118static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1119 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1120 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
11911121}
11921122
1193#define zig_shl_sat_s(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T min, T max) { \
1194 if(x == 0) return 0; \
1195 T x_twos_comp = x < 0 ? -x : x; \
1196 T bits_set = 64 - __builtin_clzll(x_twos_comp); \
1197 T min_or_max = (x < 0) ? min : max; \
1198 return (y + bits_set > bits ) ? min_or_max : x << y; \
1123static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1124 if (rhs >= zig_as_u8(64)) return (zig_i128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1125 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
11991126}
12001127
1201zig_shl_sat_u(u8, uint8_t, 8)
1202zig_shl_sat_s(i8, int8_t, 7)
1203zig_shl_sat_u(u16, uint16_t, 16)
1204zig_shl_sat_s(i16, int16_t, 15)
1205zig_shl_sat_u(u32, uint32_t, 32)
1206zig_shl_sat_s(i32, int32_t, 31)
1207zig_shl_sat_u(u64, uint64_t, 64)
1208zig_shl_sat_s(i64, int64_t, 63)
1209zig_shl_sat_s(isize, intptr_t, ((sizeof(intptr_t)) * CHAR_BIT - 1))
1210zig_shl_sat_s(short, short, ((sizeof(short )) * CHAR_BIT - 1))
1211zig_shl_sat_s(int, int, ((sizeof(int )) * CHAR_BIT - 1))
1212zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1))
1128static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
1129 zig_u128 res;
1130 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1131 return res;
1132}
12131133
1214#define zig_bitsizeof(T) (CHAR_BIT * sizeof(T))
1215#define zig_bit_mask(T, bit_width) \
1216 ((bit_width) == zig_bitsizeof(T) \
1217 ? ((T)-1) \
1218 : (((T)1 << (T)(bit_width)) - 1))
1134static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
1135 zig_i128 res;
1136 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1137 return res;
1138}
12191139
1220static inline int zig_clz(unsigned int value, uint8_t zig_type_bit_width) {
1221 if (value == 0) return zig_type_bit_width;
1222 return __builtin_clz(value) - zig_bitsizeof(unsigned int) + zig_type_bit_width;
1140static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
1141 zig_u128 res;
1142 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1143 return res;
12231144}
12241145
1225static inline int zig_clzl(unsigned long value, uint8_t zig_type_bit_width) {
1226 if (value == 0) return zig_type_bit_width;
1227 return __builtin_clzl(value) - zig_bitsizeof(unsigned long) + zig_type_bit_width;
1146static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1147 zig_i128 res;
1148 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1149 return res;
12281150}
12291151
1230static inline int zig_clzll(unsigned long long value, uint8_t zig_type_bit_width) {
1231 if (value == 0) return zig_type_bit_width;
1232 return __builtin_clzll(value) - zig_bitsizeof(unsigned long long) + zig_type_bit_width;
1152static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1153 return zig_sub_i128(zig_div_trunc_i128(lhs, rhs), (((lhs.hi ^ rhs.hi) & zig_rem_i128(lhs, rhs).hi) < zig_as_i64(0)) ? zig_as_i128(0, 1) : zig_as_i128(0, 0));
12331154}
12341155
1235#define zig_clz_u8 zig_clz
1236#define zig_clz_i8 zig_clz
1237#define zig_clz_u16 zig_clz
1238#define zig_clz_i16 zig_clz
1239#define zig_clz_u32 zig_clzl
1240#define zig_clz_i32 zig_clzl
1241#define zig_clz_u64 zig_clzll
1242#define zig_clz_i64 zig_clzll
1156static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1157 zig_i128 rem = zig_rem_i128(lhs, rhs);
1158 return rem + (((lhs.hi ^ rhs.hi) & rem.hi) < zig_as_i64(0) ? rhs : zig_as_i128(0, 0));
1159}
1160
1161#endif /* zig_has_int128 */
1162
1163#define zig_div_floor_u128 zig_div_trunc_u128
1164#define zig_mod_u128 zig_rem_u128
12431165
1244static inline int zig_clz_u128(uint128_t value, uint8_t zig_type_bit_width) {
1245 if (value == 0) return zig_type_bit_width;
1246 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1247 const uint64_t hi = (value & mask) >> 64;
1248 const uint64_t lo = (value & mask);
1249 const int leading_zeroes = (
1250 hi != 0 ? __builtin_clzll(hi) : 64 + (lo != 0 ? __builtin_clzll(lo) : 64));
1251 return leading_zeroes - zig_bitsizeof(uint128_t) + zig_type_bit_width;
1166static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
1167 zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < 0 ? zig_as_i128(-1, UINT64_MAX) : zig_as_i128(0, 0);
1168 return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
12521169}
12531170
1254#define zig_clz_i128 zig_clz_u128
1171static inline zig_u128 zig_wrap_u128(zig_u128 val, zig_u8 bits) {
1172 return zig_and_u128(val, zig_maxInt(u128, bits));
1173}
12551174
1256static inline int zig_ctz(unsigned int value, uint8_t zig_type_bit_width) {
1257 if (value == 0) return zig_type_bit_width;
1258 return __builtin_ctz(value & zig_bit_mask(unsigned int, zig_type_bit_width));
1175static inline zig_i128 zig_wrap_i128(zig_i128 val, zig_u8 bits) {
1176 return zig_as_i128(zig_wrap_i64(zig_hi_i128(val), bits - zig_as_u8(64)), zig_lo_i128(val));
12591177}
12601178
1261static inline int zig_ctzl(unsigned long value, uint8_t zig_type_bit_width) {
1262 if (value == 0) return zig_type_bit_width;
1263 return __builtin_ctzl(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1179static inline zig_u128 zig_shlw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1180 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
12641181}
12651182
1266static inline int zig_ctzll(unsigned long value, uint8_t zig_type_bit_width) {
1267 if (value == 0) return zig_type_bit_width;
1268 return __builtin_ctzll(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1183static inline zig_i128 zig_shlw_i128(zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1184 return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12691185}
12701186
1271#define zig_ctz_u8 zig_ctz
1272#define zig_ctz_i8 zig_ctz
1273#define zig_ctz_u16 zig_ctz
1274#define zig_ctz_i16 zig_ctz
1275#define zig_ctz_u32 zig_ctzl
1276#define zig_ctz_i32 zig_ctzl
1277#define zig_ctz_u64 zig_ctzll
1278#define zig_ctz_i64 zig_ctzll
1187static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1188 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
1189}
12791190
1280static inline int zig_ctz_u128(uint128_t value, uint8_t zig_type_bit_width) {
1281 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1282 const uint64_t hi = (value & mask) >> 64;
1283 const uint64_t lo = (value & mask);
1284 return (lo != 0 ? __builtin_ctzll(lo) : 64 + (hi != 0 ? __builtin_ctzll(hi) : 64));
1191static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1192 return zig_wrap_i128(zig_bitcast_i128(zig_add_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12851193}
12861194
1287#define zig_ctz_i128 zig_ctz_u128
1195static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1196 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
1197}
12881198
1289static inline int zig_popcount(unsigned int value, uint8_t zig_type_bit_width) {
1290 return __builtin_popcount(value & zig_bit_mask(unsigned int, zig_type_bit_width));
1199static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1200 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12911201}
12921202
1293static inline int zig_popcountl(unsigned long value, uint8_t zig_type_bit_width) {
1294 return __builtin_popcountl(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1203static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1204 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
12951205}
12961206
1297static inline int zig_popcountll(unsigned long value, uint8_t zig_type_bit_width) {
1298 return __builtin_popcountll(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1207static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1208 return zig_wrap_i128(zig_bitcast_i128(zig_mul_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12991209}
13001210
1301#define zig_popcount_u8 zig_popcount
1302#define zig_popcount_i8 zig_popcount
1303#define zig_popcount_u16 zig_popcount
1304#define zig_popcount_i16 zig_popcount
1305#define zig_popcount_u32 zig_popcountl
1306#define zig_popcount_i32 zig_popcountl
1307#define zig_popcount_u64 zig_popcountll
1308#define zig_popcount_i64 zig_popcountll
1211#if zig_has_int128
13091212
1310static inline int zig_popcount_u128(uint128_t value, uint8_t zig_type_bit_width) {
1311 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1312 const uint64_t hi = (value & mask) >> 64;
1313 const uint64_t lo = (value & mask);
1314 return __builtin_popcountll(hi) + __builtin_popcountll(lo);
1213static inline zig_bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1214 *res = zig_shlw_u128(lhs, rhs, bits);
1215 return zig_and_u128(lhs, zig_shl_u128(zig_maxInt_u128, bits - rhs)) != zig_as_u128(0, 0);
13151216}
13161217
1317#define zig_popcount_i128 zig_popcount_u128
1218static inline zig_bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1219 *res = zig_shlw_i128(lhs, rhs, bits);
1220 zig_i128 mask = zig_bitcast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - zig_as_u8(1)));
1221 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_as_i128(0, 0)) != 0 &&
1222 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != 0;
1223}
13181224
1319static inline bool zig_shlo_i8(int8_t lhs, int8_t rhs, int8_t *res, uint8_t bits) {
1320 *res = lhs << rhs;
1321 if (zig_clz_i8(lhs, bits) >= rhs) return false;
1322 *res &= UINT8_MAX >> (8 - bits);
1323 return true;
1225static inline zig_bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1226#if zig_has_builtin(add_overflow)
1227 zig_u128 full_res;
1228 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1229 *res = zig_wrap_u128(full_res, bits);
1230 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1231#else
1232 *res = zig_addw_u128(lhs, rhs, bits);
1233 return *res < lhs;
1234#endif
13241235}
13251236
1326static inline bool zig_shlo_i16(int16_t lhs, int16_t rhs, int16_t *res, uint8_t bits) {
1327 *res = lhs << rhs;
1328 if (zig_clz_i16(lhs, bits) >= rhs) return false;
1329 *res &= UINT16_MAX >> (16 - bits);
1330 return true;
1237zig_extern_c zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1238static inline zig_bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1239#if zig_has_builtin(add_overflow)
1240 zig_i128 full_res;
1241 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1242#else
1243 zig_c_int overflow_int;
1244 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
1245 zig_bool overflow = overflow_int != 0;
1246#endif
1247 *res = zig_wrap_i128(full_res, bits);
1248 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
13311249}
13321250
1333static inline bool zig_shlo_i32(int32_t lhs, int32_t rhs, int32_t *res, uint8_t bits) {
1334 *res = lhs << rhs;
1335 if (zig_clz_i32(lhs, bits) >= rhs) return false;
1336 *res &= UINT32_MAX >> (32 - bits);
1337 return true;
1251static inline zig_bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1252#if zig_has_builtin(sub_overflow)
1253 zig_u128 full_res;
1254 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1255 *res = zig_wrap_u128(full_res, bits);
1256 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1257#else
1258 *res = zig_subw_u128(lhs, rhs, bits);
1259 return *res > lhs;
1260#endif
13381261}
13391262
1340static inline bool zig_shlo_i64(int64_t lhs, int64_t rhs, int64_t *res, uint8_t bits) {
1341 *res = lhs << rhs;
1342 if (zig_clz_i64(lhs, bits) >= rhs) return false;
1343 *res &= UINT64_MAX >> (64 - bits);
1344 return true;
1263zig_extern_c zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1264static inline zig_bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1265#if zig_has_builtin(sub_overflow)
1266 zig_i128 full_res;
1267 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1268#else
1269 zig_c_int overflow_int;
1270 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
1271 zig_bool overflow = overflow_int != 0;
1272#endif
1273 *res = zig_wrap_i128(full_res, bits);
1274 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
13451275}
13461276
1347static inline bool zig_shlo_i128(int128_t lhs, int128_t rhs, int128_t *res, uint8_t bits) {
1348 *res = lhs << rhs;
1349 if (zig_clz_i128(lhs, bits) >= rhs) return false;
1350 *res &= UINT128_MAX >> (128 - bits);
1351 return true;
1277static inline zig_bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1278#if zig_has_builtin(mul_overflow)
1279 zig_u128 full_res;
1280 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1281 *res = zig_wrap_u128(full_res, bits);
1282 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1283#else
1284 *res = zig_mulw_u128(lhs, rhs, bits);
1285 return rhs != zig_as_u128(0, 0) && lhs > zig_maxInt(u128, bits) / rhs;
1286#endif
13521287}
13531288
1354static inline bool zig_shlo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t bits) {
1355 *res = lhs << rhs;
1356 if (zig_clz_u8(lhs, bits) >= rhs) return false;
1357 *res &= UINT8_MAX >> (8 - bits);
1358 return true;
1289zig_extern_c zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1290static inline zig_bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1291#if zig_has_builtin(mul_overflow)
1292 zig_i128 full_res;
1293 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1294#else
1295 zig_c_int overflow_int;
1296 zig_i128 full_res = __muloti4(lhs, rhs, &overflow);
1297 zig_bool overflow = overflow_int != 0;
1298#endif
1299 *res = zig_wrap_i128(full_res, bits);
1300 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
13591301}
13601302
1361static inline uint16_t zig_shlo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint8_t bits) {
1362 *res = lhs << rhs;
1363 if (zig_clz_u16(lhs, bits) >= rhs) return false;
1364 *res &= UINT16_MAX >> (16 - bits);
1365 return true;
1303#else /* zig_has_int128 */
1304
1305static inline zig_bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
1306 return zig_addo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
1307 zig_addo_u64(&res->hi, res->hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
13661308}
13671309
1368static inline uint32_t zig_shlo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint8_t bits) {
1369 *res = lhs << rhs;
1370 if (zig_clz_u32(lhs, bits) >= rhs) return false;
1371 *res &= UINT32_MAX >> (32 - bits);
1372 return true;
1310static inline zig_bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
1311 return zig_subo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
1312 zig_subo_u64(&res->hi, res->hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
13731313}
13741314
1375static inline uint64_t zig_shlo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint8_t bits) {
1376 *res = lhs << rhs;
1377 if (zig_clz_u64(lhs, bits) >= rhs) return false;
1378 *res &= UINT64_MAX >> (64 - bits);
1379 return true;
1315#endif /* zig_has_int128 */
1316
1317static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1318 zig_u128 res;
1319 if (zig_cmp_u128(rhs, zig_as_u128(0, bits)) >= 0)
1320 return zig_cmp_u128(lhs, zig_as_u128(0, 0)) != 0 ? zig_maxInt(u128, bits) : lhs;
1321 return zig_shlo_u128(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u128, bits) : res;
13801322}
13811323
1382static inline uint128_t zig_shlo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint8_t bits) {
1383 *res = lhs << rhs;
1384 if (zig_clz_u128(lhs, bits) >= rhs) return false;
1385 *res &= UINT128_MAX >> (128 - bits);
1386 return true;
1324static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1325 zig_i128 res;
1326 if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_as_u128(0, bits)) < 0 && !zig_shlo_i128(&res, lhs, rhs, bits)) return res;
1327 return zig_cmp_i128(lhs, zig_as_i128(0, 0)) < 0 ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
13871328}
13881329
1389#define zig_sign_extend(T) \
1390 static inline T zig_sign_extend_##T(T value, uint8_t zig_type_bit_width) { \
1391 const T m = (T)1 << (T)(zig_type_bit_width - 1); \
1392 return (value ^ m) - m; \
1393 }
1330static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1331 zig_u128 res;
1332 return zig_addo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1333}
13941334
1395zig_sign_extend(uint8_t)
1396zig_sign_extend(uint16_t)
1397zig_sign_extend(uint32_t)
1398zig_sign_extend(uint64_t)
1399zig_sign_extend(uint128_t)
1335static inline zig_i128 zig_adds_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1336 zig_i128 res;
1337 if (!zig_addo_i128(&res, lhs, rhs, bits)) return res;
1338 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= 0 ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1339}
14001340
1401#define zig_byte_swap_u(ZigTypeBits, CTypeBits) \
1402 static inline uint##CTypeBits##_t zig_byte_swap_u##ZigTypeBits(uint##CTypeBits##_t value, uint8_t zig_type_bit_width) { \
1403 return __builtin_bswap##CTypeBits(value) >> (CTypeBits - zig_type_bit_width); \
1404 }
1341static inline zig_u128 zig_subs_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1342 zig_u128 res;
1343 return zig_subo_u128(&res, lhs, rhs, bits) ? zig_minInt(u128, bits) : res;
1344}
14051345
1406#define zig_byte_swap_s(ZigTypeBits, CTypeBits) \
1407 static inline int##CTypeBits##_t zig_byte_swap_i##ZigTypeBits(int##CTypeBits##_t value, uint8_t zig_type_bit_width) { \
1408 const uint##CTypeBits##_t swapped = zig_byte_swap_u##ZigTypeBits(value, zig_type_bit_width); \
1409 return zig_sign_extend_uint##CTypeBits##_t(swapped, zig_type_bit_width); \
1410 }
1346static inline zig_i128 zig_subs_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1347 zig_i128 res;
1348 if (!zig_subo_i128(&res, lhs, rhs, bits)) return res;
1349 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= 0 ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1350}
1351
1352static inline zig_u128 zig_muls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1353 zig_u128 res;
1354 return zig_mulo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1355}
1356
1357static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1358 zig_i128 res;
1359 if (!zig_mulo_i128(&res, lhs, rhs, bits)) return res;
1360 return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_as_i128(0, 0)) < 0 ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1361}
1362
1363static inline zig_u8 zig_clz_u128(zig_u128 val, zig_u8 bits) {
1364 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - zig_as_u8(64));
1365 return zig_clz_u64(zig_lo_u128(val), zig_as_u8(64)) + zig_as_u8(64);
1366}
1367
1368static inline zig_u8 zig_clz_i128(zig_i128 val, zig_u8 bits) {
1369 return zig_clz_u128(zig_bitcast_u128(val), bits);
1370}
1371
1372static inline zig_u8 zig_ctz_u128(zig_u128 val, zig_u8 bits) {
1373 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), zig_as_u8(64));
1374 return zig_ctz_u64(zig_hi_u128(val), bits - zig_as_u8(64)) + zig_as_u8(64);
1375}
1376
1377static inline zig_u8 zig_ctz_i128(zig_i128 val, zig_u8 bits) {
1378 return zig_ctz_u128(zig_bitcast_u128(val), bits);
1379}
1380
1381static inline zig_u8 zig_popcount_u128(zig_u128 val, zig_u8 bits) {
1382 return zig_popcount_u64(zig_hi_u128(val), bits - zig_as_u8(64)) +
1383 zig_popcount_u64(zig_lo_u128(val), zig_as_u8(64));
1384}
1385
1386static inline zig_u8 zig_popcount_i128(zig_i128 val, zig_u8 bits) {
1387 return zig_popcount_u128(zig_bitcast_u128(val), bits);
1388}
1389
1390static inline zig_u128 zig_byte_swap_u128(zig_u128 val, zig_u8 bits) {
1391 zig_u128 full_res;
1392#if zig_has_builtin(bswap128)
1393 full_res = __builtin_bswap128(val);
1394#else
1395 full_res = zig_as_u128(zig_byte_swap_u64(zig_lo_u128(val), zig_as_u8(64)),
1396 zig_byte_swap_u64(zig_hi_u128(val), zig_as_u8(64)));
1397#endif
1398 return zig_shr_u128(full_res, zig_as_u8(128) - bits);
1399}
14111400
1412#define zig_byte_swap(ZigTypeBits, CTypeBits) \
1413 zig_byte_swap_u(ZigTypeBits, CTypeBits) \
1414 zig_byte_swap_s(ZigTypeBits, CTypeBits)
1415
1416zig_byte_swap( 8, 16)
1417zig_byte_swap(16, 16)
1418zig_byte_swap(32, 32)
1419zig_byte_swap(64, 64)
1420
1421static inline uint128_t zig_byte_swap_u128(uint128_t value, uint8_t zig_type_bit_width) {
1422 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1423 const uint128_t hi = __builtin_bswap64((uint64_t)(value >> 64));
1424 const uint128_t lo = __builtin_bswap64((uint64_t)value);
1425 return (((lo << 64 | hi) >> (128 - zig_type_bit_width))) & mask;
1426}
1427
1428zig_byte_swap_s(128, 128)
1429
1430static const uint8_t zig_bit_reverse_lut[256] = {
1431 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
1432 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1433 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
1434 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1435 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
1436 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1437 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
1438 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1439 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
1440 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1441 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
1442 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1443 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
1444 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1445 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
1446 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1447 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
1448 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1449 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
1450 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1451 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
1452 0x3f, 0xbf, 0x7f, 0xff
1453};
1454
1455static inline uint8_t zig_bit_reverse_u8(uint8_t value, uint8_t zig_type_bit_width) {
1456 const uint8_t reversed = zig_bit_reverse_lut[value] >> (8 - zig_type_bit_width);
1457 return zig_sign_extend_uint8_t(reversed, zig_type_bit_width);
1458}
1459
1460#define zig_bit_reverse_i8 zig_bit_reverse_u8
1461
1462static inline uint16_t zig_bit_reverse_u16(uint16_t value, uint8_t zig_type_bit_width) {
1463 const uint16_t swapped = zig_byte_swap_u16(value, zig_type_bit_width);
1464 const uint16_t reversed = (
1465 ((uint16_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1466 ((uint16_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1467 return zig_sign_extend_uint16_t(
1468 reversed & zig_bit_mask(uint16_t, zig_type_bit_width),
1469 zig_type_bit_width);
1470}
1471
1472#define zig_bit_reverse_i16 zig_bit_reverse_u16
1473
1474static inline uint32_t zig_bit_reverse_u32(uint32_t value, uint8_t zig_type_bit_width) {
1475 const uint32_t swapped = zig_byte_swap_u32(value, zig_type_bit_width);
1476 const uint32_t reversed = (
1477 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
1478 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
1479 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1480 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1481 return zig_sign_extend_uint32_t(
1482 reversed & zig_bit_mask(uint32_t, zig_type_bit_width),
1483 zig_type_bit_width);
1484}
1485
1486#define zig_bit_reverse_i32 zig_bit_reverse_u32
1487
1488static inline uint64_t zig_bit_reverse_u64(uint64_t value, uint8_t zig_type_bit_width) {
1489 const uint64_t swapped = zig_byte_swap_u64(value, zig_type_bit_width);
1490 const uint64_t reversed = (
1491 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x38) & 0xff] << 0x38) |
1492 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x30) & 0xff] << 0x30) |
1493 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x28) & 0xff] << 0x28) |
1494 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x20) & 0xff] << 0x20) |
1495 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
1496 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
1497 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1498 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1499 return zig_sign_extend_uint64_t(
1500 reversed & zig_bit_mask(uint64_t, zig_type_bit_width),
1501 zig_type_bit_width);
1502}
1503
1504#define zig_bit_reverse_i64 zig_bit_reverse_u64
1505
1506static inline uint128_t zig_bit_reverse_u128(uint128_t value, uint8_t zig_type_bit_width) {
1507 const uint128_t swapped = zig_byte_swap_u128(value, zig_type_bit_width);
1508 const uint128_t reversed = (
1509 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x78) & 0xff] << 0x78) |
1510 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x70) & 0xff] << 0x70) |
1511 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x68) & 0xff] << 0x68) |
1512 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x60) & 0xff] << 0x60) |
1513 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x58) & 0xff] << 0x58) |
1514 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x50) & 0xff] << 0x50) |
1515 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x48) & 0xff] << 0x48) |
1516 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x40) & 0xff] << 0x40) |
1517 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x38) & 0xff] << 0x38) |
1518 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x30) & 0xff] << 0x30) |
1519 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x28) & 0xff] << 0x28) |
1520 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x20) & 0xff] << 0x20) |
1521 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
1522 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
1523 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1524 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1525 return zig_sign_extend_uint128_t(
1526 reversed & zig_bit_mask(uint128_t, zig_type_bit_width),
1527 zig_type_bit_width);
1528}
1529
1530#define zig_bit_reverse_i128 zig_bit_reverse_u128
1401static inline zig_i128 zig_byte_swap_i128(zig_i128 val, zig_u8 bits) {
1402 return zig_byte_swap_u128(zig_bitcast_u128(val), bits);
1403}
1404
1405static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {
1406 return zig_shr_u128(zig_as_u128(zig_bit_reverse_u64(zig_lo_u128(val), zig_as_u8(64)),
1407 zig_bit_reverse_u64(zig_hi_u128(val), zig_as_u8(64))),
1408 zig_as_u8(128) - bits);
1409}
1410
1411static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
1412 return zig_bit_reverse_u128(zig_bitcast_u128(val), bits);
1413}
1414
1415/* ========================== Float Point Routines ========================== */
1416
1417static inline zig_f32 zig_bitcast_f32_u32(zig_u32 arg) {
1418 zig_f32 dest;
1419 memcpy(&dest, &arg, sizeof dest);
1420 return dest;
1421}
1422
1423static inline zig_f64 zig_bitcast_f64_u64(zig_u64 arg) {
1424 zig_f64 dest;
1425 memcpy(&dest, &arg, sizeof dest);
1426 return dest;
1427}
15311428
15321429static inline float zig_div_truncf(float numerator, float denominator) {
15331430 return __builtin_truncf(numerator / denominator);
......@@ -1562,17 +1459,6 @@ static inline long double zig_div_truncl(long double numerator, long double deno
15621459#define zig_div_floor_f80 zig_div_floorl
15631460#define zig_div_floor_f128 zig_div_floorl
15641461
1565#define zig_div_floor_u8 zig_div_floorf
1566#define zig_div_floor_i8 zig_div_floorf
1567#define zig_div_floor_u16 zig_div_floorf
1568#define zig_div_floor_i16 zig_div_floorf
1569#define zig_div_floor_u32 zig_div_floor
1570#define zig_div_floor_i32 zig_div_floor
1571#define zig_div_floor_u64 zig_div_floor
1572#define zig_div_floor_i64 zig_div_floor
1573#define zig_div_floor_u128 zig_div_floorl
1574#define zig_div_floor_i128 zig_div_floorl
1575
15761462static inline float zig_modf(float numerator, float denominator) {
15771463 return (numerator - (zig_div_floorf(numerator, denominator) * denominator));
15781464}
......@@ -1590,19 +1476,3 @@ static inline long double zig_modl(long double numerator, long double denominato
15901476#define zig_mod_f64 zig_mod
15911477#define zig_mod_f80 zig_modl
15921478#define zig_mod_f128 zig_modl
1593
1594#define zig_mod_int(ZigType, CType) \
1595 static inline CType zig_mod_##ZigType(CType numerator, CType denominator) { \
1596 return (numerator - (zig_div_floor_##ZigType(numerator, denominator) * denominator)); \
1597 }
1598
1599zig_mod_int( u8, uint8_t)
1600zig_mod_int( i8, int8_t)
1601zig_mod_int( u16, uint16_t)
1602zig_mod_int( i16, int16_t)
1603zig_mod_int( u32, uint32_t)
1604zig_mod_int( i32, int32_t)
1605zig_mod_int( u64, uint64_t)
1606zig_mod_int( i64, int64_t)
1607zig_mod_int(u128, uint128_t)
1608zig_mod_int(i128, int128_t)
src/codegen/c.zig+525-590
......@@ -72,6 +72,12 @@ const ValueRenderLocation = enum {
7272 Other,
7373};
7474
75const BuiltinInfo = enum {
76 None,
77 Range,
78 Bits,
79};
80
7581/// TODO make this not cut off at 128 bytes
7682fn formatTypeAsCIdentifier(
7783 data: FormatTypeAsCIdentContext,
......@@ -323,6 +329,33 @@ pub const Function = struct {
323329 }
324330 }
325331
332 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
333 switch (c_value) {
334 .constant => |inst| {
335 const ty = f.air.typeOf(inst);
336 const val = f.air.value(inst).?;
337 try f.object.dg.renderValue(w, ty, val, .Other);
338 try w.writeByte('.');
339 return f.writeCValue(w, member, .Other);
340 },
341 else => return f.object.dg.writeCValueMember(w, c_value, member),
342 }
343 }
344
345 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
346 switch (c_value) {
347 .constant => |inst| {
348 const ty = f.air.typeOf(inst);
349 const val = f.air.value(inst).?;
350 try w.writeByte('(');
351 try f.object.dg.renderValue(w, ty, val, .Other);
352 try w.writeAll(")->");
353 return f.writeCValue(w, member, .Other);
354 },
355 else => return f.object.dg.writeCValueDerefMember(w, c_value, member),
356 }
357 }
358
326359 fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
327360 return f.object.dg.fail(format, args);
328361 }
......@@ -339,16 +372,63 @@ pub const Function = struct {
339372 return f.object.dg.fmtIntLiteral(ty, val);
340373 }
341374
342 fn renderFloatFnName(f: *Function, fn_name: []const u8, float_ty: Type) !void {
375 fn renderTypeForBuiltinFnName(f: *Function, writer: anytype, ty: Type) !void {
376 const target = f.object.dg.module.getTarget();
377 const c_bits = if (ty.isInt()) c_bits: {
378 const int_info = ty.intInfo(target);
379 try writer.writeByte(signAbbrev(int_info.signedness));
380 break :c_bits toCIntBits(int_info.bits) orelse
381 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
382 } else if (ty.isRuntimeFloat()) c_bits: {
383 try writer.writeByte('f');
384 break :c_bits ty.floatBits(target);
385 } else return f.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
386 ty.fmt(f.object.dg.module),
387 });
388 try writer.print("{d}", .{c_bits});
389 }
390
391 fn renderBuiltinInfo(f: *Function, writer: anytype, ty: Type, info: BuiltinInfo) !void {
392 const target = f.object.dg.module.getTarget();
393 switch (info) {
394 .None => {},
395 .Range => {
396 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
397 defer arena.deinit();
398
399 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
400 var stack align(@alignOf(expected_contents)) =
401 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
402
403 const int_info = ty.intInfo(target);
404 if (int_info.signedness == .signed) {
405 const min_val = try ty.minInt(stack.get(), target);
406 try writer.print(", {x}", .{try f.fmtIntLiteral(ty, min_val)});
407 }
408
409 const max_val = try ty.maxInt(stack.get(), target);
410 try writer.print(", {x}", .{try f.fmtIntLiteral(ty, max_val)});
411 },
412 .Bits => {
413 var bits_pl = Value.Payload.U64{
414 .base = .{ .tag = .int_u64 },
415 .data = ty.bitSize(target),
416 };
417 const bits_val = Value.initPayload(&bits_pl.base);
418 try writer.print(", {}", .{try f.fmtIntLiteral(Type.u8, bits_val)});
419 },
420 }
421 }
422
423 fn renderFloatFnName(f: *Function, writer: anytype, operation: []const u8, float_ty: Type) !void {
343424 const target = f.object.dg.module.getTarget();
344425 const float_bits = float_ty.floatBits(target);
345426 const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
346 const writer = f.object.writer();
347427 try writer.writeAll("__");
348428 if (is_longdouble or float_bits != 80) {
349429 try writer.writeAll("builtin_");
350430 }
351 try writer.writeAll(fn_name);
431 try writer.writeAll(operation);
352432 if (is_longdouble) {
353433 try writer.writeByte('l');
354434 } else switch (float_bits) {
......@@ -558,9 +638,8 @@ pub const DeclGen = struct {
558638 const target = dg.module.getTarget();
559639 if (val.isUndefDeep()) {
560640 switch (ty.zigTypeTag()) {
561 // Using '{}' for integer and floats seemed to error C compilers (both GCC and Clang)
562 // with 'error: expected expression' (including when built with 'zig cc')
563 .Bool => return writer.writeAll("false"),
641 // bool b = 0xaa; evals to true, but memcpy(&b, 0xaa, 1); evals to false.
642 .Bool => return dg.renderValue(writer, ty, Value.@"false", location),
564643 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),
565644 .Float => switch (ty.tag()) {
566645 .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{
......@@ -839,15 +918,14 @@ pub const DeclGen = struct {
839918 },
840919 }
841920 },
842 .Bool => return writer.print("{}", .{val.toBool()}),
921 .Bool => return writer.print("zig_{}", .{val.toBool()}),
843922 .Optional => {
844923 var opt_buf: Type.Payload.ElemType = undefined;
845924 const payload_ty = ty.optionalChild(&opt_buf);
846925
847 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
848 const is_null = val.castTag(.opt_payload) == null;
849 return writer.print("{}", .{is_null});
850 }
926 const is_null_val = Value.makeBool(val.tag() == .null_value);
927 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
928 return dg.renderValue(writer, Type.bool, is_null_val, location);
851929
852930 if (ty.optionalReprIsPayload()) {
853931 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val;
......@@ -864,21 +942,17 @@ pub const DeclGen = struct {
864942
865943 try writer.writeAll("{ .payload = ");
866944 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);
867 try writer.print(", .is_null = {} }}", .{val.tag() == .null_value});
945 try writer.writeAll(", .is_null = ");
946 try dg.renderValue(writer, Type.bool, is_null_val, .Initializer);
947 try writer.writeAll(" }");
868948 },
869949 .ErrorSet => {
870 switch (val.tag()) {
871 .@"error" => {
872 const payload = val.castTag(.@"error").?;
873 // error values will be #defined at the top of the file
874 return writer.print("zig_error_{s}", .{fmtIdent(payload.data.name)});
875 },
876 else => {
877 // In this case we are rendering an error union which has a
878 // 0 bits payload.
879 return writer.writeByte('0');
880 },
881 }
950 const error_name = if (val.castTag(.@"error")) |error_pl|
951 error_pl.data.name
952 else
953 dg.module.error_name_list.items[0];
954 // Error values are already defined by genErrDecls.
955 try writer.print("zig_error_{}", .{fmtIdent(error_name)});
882956 },
883957 .ErrorUnion => {
884958 const error_ty = ty.errorUnionSet();
......@@ -897,7 +971,7 @@ pub const DeclGen = struct {
897971 }
898972
899973 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
900 const error_val = if (val.tag() == .eu_payload) Value.zero else val;
974 const error_val = if (val.errorUnionIsPayload()) Value.zero else val;
901975
902976 try writer.writeAll("{ .payload = ");
903977 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);
......@@ -1026,24 +1100,14 @@ pub const DeclGen = struct {
10261100
10271101 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void {
10281102 const fn_info = dg.decl.ty.fnInfo();
1029 if (fn_info.cc == .Naked) {
1030 try w.writeAll("ZIG_NAKED ");
1031 }
1032 if (dg.decl.val.castTag(.function)) |func_payload| {
1033 const func: *Module.Fn = func_payload.data;
1034 if (func.is_cold) {
1035 try w.writeAll("ZIG_COLD ");
1036 }
1037 }
1038 if (fn_info.return_type.hasRuntimeBits()) {
1039 try dg.renderType(w, fn_info.return_type, kind);
1040 } else if (fn_info.return_type.isError()) {
1041 try dg.renderType(w, Type.anyerror, kind);
1042 } else if (fn_info.return_type.zigTypeTag() == .NoReturn) {
1043 try w.writeAll("zig_noreturn void");
1044 } else {
1045 try w.writeAll("void");
1046 }
1103 if (fn_info.cc == .Naked) try w.writeAll("zig_naked ");
1104 if (dg.decl.val.castTag(.function)) |func_payload|
1105 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1106 const ret_ty = fn_info.return_type;
1107 try dg.renderType(w, if (ret_ty.tag() == .noreturn or ret_ty.hasRuntimeBitsIgnoreComptime())
1108 ret_ty
1109 else
1110 Type.void, kind);
10471111 try w.writeByte(' ');
10481112 try dg.renderDeclName(w, dg.decl_index);
10491113 try w.writeByte('(');
......@@ -1051,9 +1115,7 @@ pub const DeclGen = struct {
10511115 var index: usize = 0;
10521116 for (fn_info.param_types) |param_type| {
10531117 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1054 if (index > 0) {
1055 try w.writeAll(", ");
1056 }
1118 if (index > 0) try w.writeAll(", ");
10571119 const name = CValue{ .arg = index };
10581120 try dg.renderTypeAndName(w, param_type, name, .Const, 0, kind);
10591121 index += 1;
......@@ -1063,7 +1125,7 @@ pub const DeclGen = struct {
10631125 if (index > 0) try w.writeAll(", ");
10641126 try w.writeAll("...");
10651127 } else if (index == 0) {
1066 try w.writeAll("void");
1128 try dg.renderType(w, Type.void, kind);
10671129 }
10681130 try w.writeByte(')');
10691131 }
......@@ -1102,7 +1164,7 @@ pub const DeclGen = struct {
11021164 if (params_written != 0) try bw.writeAll(", ");
11031165 try bw.writeAll("...");
11041166 } else if (params_written == 0) {
1105 try bw.writeAll("void");
1167 try dg.renderType(bw, Type.void, .Forward);
11061168 }
11071169 try bw.writeAll(");\n");
11081170
......@@ -1126,14 +1188,18 @@ pub const DeclGen = struct {
11261188 defer buffer.deinit();
11271189 const bw = buffer.writer();
11281190
1129 try bw.writeAll("typedef struct { ");
1191 var ptr_ty_buf: Type.SlicePtrFieldTypeBuffer = undefined;
1192 const ptr_ty = t.slicePtrFieldType(&ptr_ty_buf);
1193 const ptr_name = CValue{ .identifier = "ptr" };
1194 const len_ty = Type.usize;
1195 const len_name = CValue{ .identifier = "len" };
11301196
1131 var ptr_type_buf: Type.SlicePtrFieldTypeBuffer = undefined;
1132 const ptr_type = t.slicePtrFieldType(&ptr_type_buf);
1133 const ptr_name = CValue{ .bytes = "ptr" };
1134 try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0, .Complete);
1197 try bw.writeAll("typedef struct {\n ");
1198 try dg.renderTypeAndName(bw, ptr_ty, ptr_name, .Mut, 0, .Complete);
1199 try bw.writeAll(";\n ");
1200 try dg.renderTypeAndName(bw, len_ty, len_name, .Mut, 0, .Complete);
11351201
1136 try bw.writeAll("; size_t len; } ");
1202 try bw.writeAll(";\n} ");
11371203 const name_begin = buffer.items.len;
11381204 try bw.print("zig_{c}_{}", .{
11391205 @as(u8, if (t.isConstPtr()) 'L' else 'M'),
......@@ -1339,27 +1405,31 @@ pub const DeclGen = struct {
13391405 }
13401406
13411407 fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1342 const payload_ty = t.errorUnionPayload();
13431408 assert(t.errorUnionSet().tag() == .anyerror);
13441409
13451410 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
13461411 defer buffer.deinit();
13471412 const bw = buffer.writer();
13481413
1349 const payload_name = CValue{ .bytes = "payload" };
1414 const payload_ty = t.errorUnionPayload();
1415 const payload_name = CValue{ .identifier = "payload" };
1416 const error_ty = t.errorUnionSet();
1417 const error_name = CValue{ .identifier = "error" };
1418
13501419 const target = dg.module.getTarget();
13511420 const payload_align = payload_ty.abiAlignment(target);
1352 const error_align = Type.anyerror.abiAlignment(target);
1421 const error_align = error_ty.abiAlignment(target);
1422 try bw.writeAll("typedef struct {\n ");
13531423 if (error_align > payload_align) {
1354 try bw.writeAll("typedef struct { ");
13551424 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1356 try bw.writeAll("; uint16_t error; } ");
1425 try bw.writeAll(";\n ");
1426 try dg.renderTypeAndName(bw, error_ty, error_name, .Mut, 0, .Complete);
13571427 } else {
1358 try bw.writeAll("typedef struct { uint16_t error; ");
1428 try dg.renderTypeAndName(bw, error_ty, error_name, .Mut, 0, .Complete);
1429 try bw.writeAll(";\n ");
13591430 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1360 try bw.writeAll("; } ");
13611431 }
1362
1432 try bw.writeAll(";\n} ");
13631433 const name_begin = buffer.items.len;
13641434 try bw.print("zig_E_{}", .{typeToCIdentifier(payload_ty, dg.module)});
13651435 const name_end = buffer.items.len;
......@@ -1413,11 +1483,11 @@ pub const DeclGen = struct {
14131483 defer buffer.deinit();
14141484 const bw = buffer.writer();
14151485
1416 try bw.writeAll("typedef struct { ");
1417 const payload_name = CValue{ .bytes = "payload" };
1418 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0, .Complete);
1419 try bw.writeAll("; bool is_null; } ");
1420
1486 try bw.writeAll("typedef struct {\n ");
1487 try dg.renderTypeAndName(bw, child_type, .{ .identifier = "payload" }, .Mut, 0, .Complete);
1488 try bw.writeAll(";\n ");
1489 try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete);
1490 try bw.writeAll("; } ");
14211491 const name_begin = buffer.items.len;
14221492 try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)});
14231493 const name_end = buffer.items.len;
......@@ -1486,51 +1556,20 @@ pub const DeclGen = struct {
14861556 const target = dg.module.getTarget();
14871557
14881558 switch (t.zigTypeTag()) {
1489 .NoReturn, .Void => try w.writeAll("void"),
1490 .Bool => try w.writeAll("bool"),
1491 .Int => {
1492 switch (t.tag()) {
1493 .u1, .u8 => try w.writeAll("uint8_t"),
1494 .i8 => try w.writeAll("int8_t"),
1495 .u16 => try w.writeAll("uint16_t"),
1496 .i16 => try w.writeAll("int16_t"),
1497 .u32 => try w.writeAll("uint32_t"),
1498 .i32 => try w.writeAll("int32_t"),
1499 .u64 => try w.writeAll("uint64_t"),
1500 .i64 => try w.writeAll("int64_t"),
1501 .u128 => try w.writeAll("uint128_t"),
1502 .i128 => try w.writeAll("int128_t"),
1503 .usize => try w.writeAll("uintptr_t"),
1504 .isize => try w.writeAll("intptr_t"),
1505 .c_short => try w.writeAll("short"),
1506 .c_ushort => try w.writeAll("unsigned short"),
1507 .c_int => try w.writeAll("int"),
1508 .c_uint => try w.writeAll("unsigned int"),
1509 .c_long => try w.writeAll("long"),
1510 .c_ulong => try w.writeAll("unsigned long"),
1511 .c_longlong => try w.writeAll("long long"),
1512 .c_ulonglong => try w.writeAll("unsigned long long"),
1513 .u29, .int_signed, .int_unsigned => {
1514 const info = t.intInfo(target);
1515 const sign_prefix = switch (info.signedness) {
1516 .signed => "",
1517 .unsigned => "u",
1518 };
1519 const c_bits = toCIntBits(info.bits) orelse
1520 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
1521 try w.print("{s}int{d}_t", .{ sign_prefix, c_bits });
1522 },
1523 else => unreachable,
1524 }
1525 },
1526 .Float => {
1527 switch (t.tag()) {
1528 .f32 => try w.writeAll("float"),
1529 .f64 => try w.writeAll("double"),
1530 .c_longdouble => try w.writeAll("long double"),
1531 .f16 => return dg.fail("TODO: C backend: implement float type f16", .{}),
1532 .f128 => return dg.fail("TODO: C backend: implement float type f128", .{}),
1533 else => unreachable,
1559 .NoReturn, .Void, .Bool, .Int, .Float, .ErrorSet => |tag| {
1560 const is_named = switch (tag) {
1561 .Int => t.isNamedInt(),
1562 .ErrorSet => false,
1563 else => true,
1564 };
1565 if (is_named) {
1566 try w.writeAll("zig_");
1567 try t.print(w, dg.module);
1568 } else {
1569 const info = t.intInfo(target);
1570 const c_bits = toCIntBits(info.bits) orelse
1571 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
1572 try w.print("zig_{c}{d}", .{ signAbbrev(info.signedness), c_bits });
15341573 }
15351574 },
15361575 .Pointer => {
......@@ -1564,9 +1603,10 @@ pub const DeclGen = struct {
15641603 // u8 and i8 produce unsigned char and signed char respectively,
15651604 // which in C are (not very usefully) different than char.
15661605 try w.writeAll("char");
1567 } else {
1568 try dg.renderType(w, child_ty, .Forward);
1569 }
1606 } else try dg.renderType(w, switch (child_ty.tag()) {
1607 .anyopaque => Type.void,
1608 else => child_ty,
1609 }, .Forward);
15701610 if (t.isConstPtr()) try w.writeAll(" const");
15711611 if (t.isVolatilePtr()) try w.writeAll(" volatile");
15721612 return w.writeAll(" *");
......@@ -1587,29 +1627,22 @@ pub const DeclGen = struct {
15871627 var opt_buf: Type.Payload.ElemType = undefined;
15881628 const child_type = t.optionalChild(&opt_buf);
15891629
1590 if (!child_type.hasRuntimeBitsIgnoreComptime()) {
1591 return w.writeAll("bool");
1592 }
1630 if (!child_type.hasRuntimeBitsIgnoreComptime())
1631 return dg.renderType(w, Type.bool, kind);
15931632
1594 if (t.optionalReprIsPayload()) {
1595 return dg.renderType(w, child_type, .Complete);
1596 }
1633 if (t.optionalReprIsPayload())
1634 return dg.renderType(w, child_type, kind);
15971635
15981636 const name = dg.getTypedefName(t) orelse
15991637 try dg.renderOptionalTypedef(t, child_type);
16001638
16011639 return w.writeAll(name);
16021640 },
1603 .ErrorSet => {
1604 comptime assert(Type.anyerror.abiSize(builtin.target) == 2);
1605 return w.writeAll("uint16_t");
1606 },
16071641 .ErrorUnion => {
16081642 const payload_ty = t.errorUnionPayload();
16091643
1610 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1611 return dg.renderType(w, Type.anyerror, .Complete);
1612 }
1644 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
1645 return dg.renderType(w, Type.anyerror, kind);
16131646
16141647 var error_union_pl = Type.Payload.ErrorUnion{
16151648 .data = .{ .error_set = Type.anyerror, .payload = payload_ty },
......@@ -1652,7 +1685,6 @@ pub const DeclGen = struct {
16521685 try dg.renderType(w, int_tag_ty, kind);
16531686 },
16541687 .Opaque => switch (t.tag()) {
1655 .anyopaque => try w.writeAll("void"),
16561688 .@"opaque" => {
16571689 const name = dg.getTypedefName(t) orelse
16581690 try dg.renderOpaqueTypedef(t);
......@@ -1695,13 +1727,8 @@ pub const DeclGen = struct {
16951727 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
16961728 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
16971729 ///
1698 fn renderTypecast(
1699 dg: *DeclGen,
1700 w: anytype,
1701 ty: Type,
1702 ) error{ OutOfMemory, AnalysisFail }!void {
1703 const name = CValue{ .bytes = "" };
1704 return renderTypeAndName(dg, w, ty, name, .Mut, 0, .Complete);
1730 fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void {
1731 return renderTypeAndName(dg, w, ty, .{ .bytes = "" }, .Mut, 0, .Complete);
17051732 }
17061733
17071734 /// Renders a type and name in field declaration/definition format.
......@@ -1735,8 +1762,9 @@ pub const DeclGen = struct {
17351762 render_ty = render_ty.elemType();
17361763 }
17371764
1738 if (alignment != 0)
1739 try w.print("ZIG_ALIGN({}) ", .{alignment});
1765 if (alignment != 0 and alignment > ty.abiAlignment(dg.module.getTarget())) {
1766 try w.print("zig_align({}) ", .{alignment});
1767 }
17401768 try dg.renderType(w, render_ty, kind);
17411769
17421770 const const_prefix = switch (mutability) {
......@@ -1792,13 +1820,16 @@ pub const DeclGen = struct {
17921820 try buffer.appendSlice(";\n return (");
17931821 try dg.renderTypecast(bw, name_slice_ty);
17941822 try bw.print("){{{}, {}}};\n", .{
1795 fmtIdent("name"),
1796 try dg.fmtIntLiteral(Type.usize, len_val),
1823 fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val),
17971824 });
17981825
17991826 try buffer.appendSlice(" }\n");
18001827 }
1801 try buffer.appendSlice(" }\n while (true) zig_breakpoint();\n}\n");
1828 try buffer.appendSlice(" }\n while (");
1829 try dg.renderValue(bw, Type.bool, Value.@"true", .Other);
1830 try buffer.appendSlice(") ");
1831 _ = try airBreakpoint(bw);
1832 try buffer.appendSlice("}\n");
18021833
18031834 const rendered = buffer.toOwnedSlice();
18041835 errdefer dg.typedefs.allocator.free(rendered);
......@@ -1874,6 +1905,27 @@ pub const DeclGen = struct {
18741905 }
18751906 }
18761907
1908 fn writeCValueMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
1909 try dg.writeCValue(writer, c_value);
1910 try writer.writeByte('.');
1911 try dg.writeCValue(writer, member);
1912 }
1913
1914 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
1915 switch (c_value) {
1916 .none, .constant, .undef => unreachable,
1917 .local, .arg, .decl, .identifier, .bytes => {
1918 try dg.writeCValue(writer, c_value);
1919 try writer.writeAll("->");
1920 },
1921 .local_ref, .decl_ref => {
1922 try dg.writeCValueDeref(writer, c_value);
1923 try writer.writeByte('.');
1924 },
1925 }
1926 try dg.writeCValue(writer, member);
1927 }
1928
18771929 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index) !void {
18781930 const decl = dg.module.declPtr(decl_index);
18791931 dg.module.markDeclAlive(decl);
......@@ -1971,8 +2023,7 @@ pub fn genErrDecls(o: *Object) !void {
19712023 const len_val = Value.initPayload(&len_pl.base);
19722024
19732025 try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{
1974 fmtIdent(name),
1975 try o.dg.fmtIntLiteral(Type.usize, len_val),
2026 fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val),
19762027 });
19772028 }
19782029 try writer.writeAll("};\n");
......@@ -1989,7 +2040,7 @@ pub fn genFunc(f: *Function) !void {
19892040
19902041 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);
19912042 const fwd_decl_writer = o.dg.fwd_decl.writer();
1992 try fwd_decl_writer.writeAll(if (is_global) "ZIG_EXTERN_C " else "static ");
2043 try fwd_decl_writer.writeAll(if (is_global) "zig_extern_c " else "static ");
19932044 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
19942045 try fwd_decl_writer.writeAll(";\n");
19952046
......@@ -2028,7 +2079,7 @@ pub fn genDecl(o: *Object) !void {
20282079 };
20292080 if (tv.val.tag() == .extern_fn) {
20302081 const fwd_decl_writer = o.dg.fwd_decl.writer();
2031 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
2082 try fwd_decl_writer.writeAll("zig_extern_c ");
20322083 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
20332084 try fwd_decl_writer.writeAll(";\n");
20342085 } else if (tv.val.castTag(.variable)) |var_payload| {
......@@ -2036,7 +2087,7 @@ pub fn genDecl(o: *Object) !void {
20362087 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
20372088 const fwd_decl_writer = o.dg.fwd_decl.writer();
20382089 if (is_global) {
2039 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
2090 try fwd_decl_writer.writeAll("zig_extern_c ");
20402091 }
20412092 if (variable.is_threadlocal) {
20422093 try fwd_decl_writer.writeAll("zig_threadlocal ");
......@@ -2096,7 +2147,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
20962147 .Fn => {
20972148 const is_global = dg.declIsGlobal(tv);
20982149 if (is_global) {
2099 try writer.writeAll("ZIG_EXTERN_C ");
2150 try writer.writeAll("zig_extern_c ");
21002151 try dg.renderFunctionSignature(writer, .Complete);
21012152 try dg.fwd_decl.appendSlice(";\n");
21022153 }
......@@ -2124,7 +2175,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21242175 .const_ty => unreachable, // excluded from function bodies
21252176 .arg => airArg(f),
21262177
2127 .breakpoint => try airBreakpoint(f),
2178 .breakpoint => try airBreakpoint(f.object.writer()),
21282179 .ret_addr => try airRetAddr(f, inst),
21292180 .frame_addr => try airFrameAddress(f, inst),
21302181 .unreach => try airUnreach(f),
......@@ -2135,10 +2186,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21352186
21362187 // TODO use a different strategy for add, sub, mul, div
21372188 // that communicates to the optimizer that wrapping is UB.
2138 .add => try airBinOp(f, inst, "+"),
2139 .sub => try airBinOp(f, inst, "-"),
2140 .mul => try airBinOp(f, inst, "*"),
2141 .div_float, .div_exact => try airBinOp(f, inst, "/"),
2189 .add => try airBinOp(f, inst, "+", "add", .None),
2190 .sub => try airBinOp(f, inst, "-", "sub", .None),
2191 .mul => try airBinOp(f, inst, "*", "mul", .None),
2192 .div_float, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
21422193
21432194 .rem => blk: {
21442195 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
......@@ -2146,9 +2197,9 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21462197 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
21472198 // so we only check one.
21482199 break :blk if (lhs_ty.isInt())
2149 try airBinOp(f, inst, "%")
2200 try airBinOp(f, inst, "%", "rem", .None)
21502201 else
2151 try airBinFloatOp(f, inst, "fmod"); // yes, @rem() => fmod()
2202 try airBinFloatOp(f, inst, "fmod");
21522203 },
21532204 .div_trunc => blk: {
21542205 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
......@@ -2156,21 +2207,21 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21562207 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
21572208 // so we only check one.
21582209 break :blk if (lhs_ty.isInt())
2159 try airBinOp(f, inst, "/")
2210 try airBinOp(f, inst, "/", "div_trunc", .None)
21602211 else
2161 try airBinOpBuiltinCall(f, inst, "div_trunc");
2212 try airBinBuiltinCall(f, inst, "div_trunc", .None);
21622213 },
2163 .div_floor => try airBinOpBuiltinCall(f, inst, "div_floor"),
2164 .mod => try airBinOpBuiltinCall(f, inst, "mod"),
2214 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
2215 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
21652216
2166 .addwrap => try airWrapOp(f, inst, "+", "add"),
2167 .subwrap => try airWrapOp(f, inst, "-", "sub"),
2168 .mulwrap => try airWrapOp(f, inst, "*", "mul"),
2217 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),
2218 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),
2219 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),
21692220
2170 .add_sat => try airSatOp(f, inst, "add"),
2171 .sub_sat => try airSatOp(f, inst, "sub"),
2172 .mul_sat => try airSatOp(f, inst, "mul"),
2173 .shl_sat => try airSatOp(f, inst, "shl"),
2221 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),
2222 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),
2223 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
2224 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
21742225
21752226 .neg => try airNeg(f, inst),
21762227
......@@ -2192,20 +2243,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21922243
21932244 .mul_add => try airMulAdd(f, inst),
21942245
2195 .add_with_overflow => try airOverflow(f, inst, "add", .range),
2196 .sub_with_overflow => try airOverflow(f, inst, "sub", .range),
2197 .mul_with_overflow => try airOverflow(f, inst, "mul", .range),
2198 .shl_with_overflow => try airOverflow(f, inst, "shl", .bits),
2246 .add_with_overflow => try airOverflow(f, inst, "add", .Bits),
2247 .sub_with_overflow => try airOverflow(f, inst, "sub", .Bits),
2248 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),
2249 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),
21992250
22002251 .min => try airMinMax(f, inst, '<'),
22012252 .max => try airMinMax(f, inst, '>'),
22022253
22032254 .slice => try airSlice(f, inst),
22042255
2205 .cmp_gt => try airBinOp(f, inst, ">"),
2206 .cmp_gte => try airBinOp(f, inst, ">="),
2207 .cmp_lt => try airBinOp(f, inst, "<"),
2208 .cmp_lte => try airBinOp(f, inst, "<="),
2256 .cmp_gt => try airCmpOp(f, inst, ">"),
2257 .cmp_gte => try airCmpOp(f, inst, ">="),
2258 .cmp_lt => try airCmpOp(f, inst, "<"),
2259 .cmp_lte => try airCmpOp(f, inst, "<="),
22092260
22102261 .cmp_eq => try airEquality(f, inst, "((", "=="),
22112262 .cmp_neq => try airEquality(f, inst, "!((", "!="),
......@@ -2214,12 +2265,13 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
22142265 .cmp_lt_errors_len => return f.fail("TODO: C backend: implement cmp_lt_errors_len", .{}),
22152266
22162267 // bool_and and bool_or are non-short-circuit operations
2217 .bool_and, .bit_and => try airBinOp(f, inst, "&"),
2218 .bool_or, .bit_or => try airBinOp(f, inst, "|"),
2219 .xor => try airBinOp(f, inst, "^"),
2220 .shr, .shr_exact => try airBinOp(f, inst, ">>"),
2221 .shl, .shl_exact => try airBinOp(f, inst, "<<"),
2222 .not => try airNot (f, inst),
2268 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),
2269 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),
2270 .xor => try airBinOp(f, inst, "^", "xor", .None),
2271 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),
2272 .shl, => try airBinBuiltinCall(f, inst, "shl", .None),
2273 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),
2274 .not => try airNot (f, inst),
22232275
22242276 .optional_payload => try airOptionalPayload(f, inst),
22252277 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),
......@@ -2263,11 +2315,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
22632315 .memcpy => try airMemcpy(f, inst),
22642316 .set_union_tag => try airSetUnionTag(f, inst),
22652317 .get_union_tag => try airGetUnionTag(f, inst),
2266 .clz => try airBuiltinCall(f, inst, "clz"),
2267 .ctz => try airBuiltinCall(f, inst, "ctz"),
2268 .popcount => try airBuiltinCall(f, inst, "popcount"),
2269 .byte_swap => try airBuiltinCall(f, inst, "byte_swap"),
2270 .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"),
2318 .clz => try airUnBuiltinCall(f, inst, "clz", .Bits),
2319 .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits),
2320 .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits),
2321 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits),
2322 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits),
22712323 .tag_name => try airTagName(f, inst),
22722324 .error_name => try airErrorName(f, inst),
22732325 .splat => try airSplat(f, inst),
......@@ -2393,10 +2445,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
23932445 const writer = f.object.writer();
23942446 const local = try f.allocLocal(inst_ty, .Const);
23952447 try writer.writeAll(" = ");
2396 if (is_ptr) try writer.writeByte('&');
2397 try f.writeCValue(writer, operand, .Other);
2398 try if (is_ptr) writer.writeAll("->") else writer.writeByte('.');
2399 try writer.writeAll(field_name);
2448 if (is_ptr) {
2449 try writer.writeByte('&');
2450 try f.writeCValueDerefMember(writer, operand, .{ .identifier = field_name });
2451 } else try f.writeCValueMember(writer, operand, .{ .identifier = field_name });
24002452 try writer.writeAll(";\n");
24012453 return local;
24022454}
......@@ -2752,138 +2804,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
27522804 return CValue.none;
27532805}
27542806
2755fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name: []const u8) !CValue {
2756 if (f.liveness.isUnused(inst)) return CValue.none;
2757
2758 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2759 const inst_ty = f.air.typeOfIndex(inst);
2760 const target = f.object.dg.module.getTarget();
2761 const int_info = inst_ty.intInfo(target);
2762 const bits = int_info.bits;
2763
2764 // if it's an unsigned int with non-arbitrary bit size then we can just add
2765 if (toCIntBits(bits)) |c_bits| {
2766 if (int_info.signedness == .unsigned and bits == c_bits) {
2767 return try airBinOp(f, inst, operator);
2768 }
2769 }
2770
2771 if (bits > 64) return f.fail("TODO: C backend: airWrapOp for large integers", .{});
2772
2773 const lhs = try f.resolveInst(bin_op.lhs);
2774 const rhs = try f.resolveInst(bin_op.rhs);
2775 const w = f.object.writer();
2776
2777 const local = try f.allocLocal(inst_ty, .Mut);
2778 try w.print(" = zig_{s}w_", .{fn_name});
2779
2780 switch (inst_ty.tag()) {
2781 .isize => try w.writeAll("isize"),
2782 .c_short => try w.writeAll("short"),
2783 .c_int => try w.writeAll("int"),
2784 .c_long => try w.writeAll("long"),
2785 .c_longlong => try w.writeAll("longlong"),
2786 else => {
2787 const prefix_byte: u8 = signAbbrev(int_info.signedness);
2788 for ([_]u8{ 8, 16, 32, 64 }) |nbits| {
2789 if (bits <= nbits) {
2790 try w.print("{c}{d}", .{ prefix_byte, nbits });
2791 break;
2792 }
2793 } else {
2794 unreachable;
2795 }
2796 },
2797 }
2798
2799 try w.writeByte('(');
2800 try f.writeCValue(w, lhs, .FunctionArgument);
2801 try w.writeAll(", ");
2802 try f.writeCValue(w, rhs, .FunctionArgument);
2803 {
2804 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
2805 defer arena.deinit();
2806
2807 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2808 var stack align(@alignOf(expected_contents)) =
2809 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
2810
2811 if (int_info.signedness == .signed) {
2812 const min_val = try inst_ty.minInt(stack.get(), target);
2813 try w.print(", {}", .{try f.fmtIntLiteral(inst_ty, min_val)});
2814 }
2815
2816 const max_val = try inst_ty.maxInt(stack.get(), target);
2817 try w.print(", {});", .{try f.fmtIntLiteral(inst_ty, max_val)});
2818 }
2819 try f.object.indent_writer.insertNewline();
2820
2821 return local;
2822}
2823
2824fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
2825 if (f.liveness.isUnused(inst)) return CValue.none;
2826
2827 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2828 const inst_ty = f.air.typeOfIndex(inst);
2829 const target = f.object.dg.module.getTarget();
2830 const int_info = inst_ty.intInfo(target);
2831 const bits = int_info.bits;
2832
2833 if (bits > 64) return f.object.dg.fail("TODO: C backend: airSatOp for large integers", .{});
2834
2835 const lhs = try f.resolveInst(bin_op.lhs);
2836 const rhs = try f.resolveInst(bin_op.rhs);
2837 const w = f.object.writer();
2838
2839 const local = try f.allocLocal(inst_ty, .Mut);
2840 try w.print(" = zig_{s}s_", .{fn_name});
2841
2842 switch (inst_ty.tag()) {
2843 .isize => try w.writeAll("isize"),
2844 .c_short => try w.writeAll("short"),
2845 .c_int => try w.writeAll("int"),
2846 .c_long => try w.writeAll("long"),
2847 .c_longlong => try w.writeAll("longlong"),
2848 else => {
2849 const prefix_byte: u8 = signAbbrev(int_info.signedness);
2850 for ([_]u8{ 8, 16, 32, 64 }) |nbits| {
2851 if (bits <= nbits) {
2852 try w.print("{c}{d}", .{ prefix_byte, nbits });
2853 break;
2854 }
2855 } else {
2856 unreachable;
2857 }
2858 },
2859 }
2860
2861 try w.writeByte('(');
2862 try f.writeCValue(w, lhs, .FunctionArgument);
2863 try w.writeAll(", ");
2864 try f.writeCValue(w, rhs, .FunctionArgument);
2865 {
2866 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
2867 defer arena.deinit();
2868
2869 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2870 var stack align(@alignOf(expected_contents)) =
2871 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
2872
2873 if (int_info.signedness == .signed) {
2874 const min_val = try inst_ty.minInt(stack.get(), target);
2875 try w.print(", {}", .{try f.fmtIntLiteral(inst_ty, min_val)});
2876 }
2877
2878 const max_val = try inst_ty.maxInt(stack.get(), target);
2879 try w.print(", {});", .{try f.fmtIntLiteral(inst_ty, max_val)});
2880 }
2881 try f.object.indent_writer.insertNewline();
2882
2883 return local;
2884}
2885
2886fn airOverflow(f: *Function, inst: Air.Inst.Index, fn_name: []const u8, kind: enum { range, bits }) !CValue {
2807fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
28872808 if (f.liveness.isUnused(inst))
28882809 return CValue.none;
28892810
......@@ -2895,54 +2816,29 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, fn_name: []const u8, kind: en
28952816
28962817 const inst_ty = f.air.typeOfIndex(inst);
28972818 const scalar_ty = f.air.typeOf(bin_op.lhs).scalarType();
2898 const target = f.object.dg.module.getTarget();
2899 const int_info = scalar_ty.intInfo(target);
29002819 const w = f.object.writer();
2901 const c_bits = toCIntBits(int_info.bits) orelse
2902 return f.fail("TODO: C backend: implement integer arithmetic larger than 128 bits", .{});
29032820
29042821 const local = try f.allocLocal(inst_ty, .Mut);
29052822 try w.writeAll(";\n");
29062823
29072824 try f.writeCValue(w, local, .Other);
2908 try w.print(".field_1 = zig_{s}o_{c}{d}(", .{
2909 fn_name, signAbbrev(int_info.signedness), c_bits,
2910 });
2825 try w.writeAll(".field_1 = zig_");
2826 try w.writeAll(operation);
2827 try w.writeAll("o_");
2828 try f.renderTypeForBuiltinFnName(w, scalar_ty);
2829 try w.writeAll("(&");
2830 try f.writeCValueMember(w, local, .{ .identifier = "field_0" });
2831 try w.writeAll(", ");
29112832 try f.writeCValue(w, lhs, .FunctionArgument);
29122833 try w.writeAll(", ");
29132834 try f.writeCValue(w, rhs, .FunctionArgument);
2914 try w.writeAll(", &");
2915 try f.writeCValue(w, local, .Other);
2916 try w.writeAll(".field_0, ");
2917 switch (kind) {
2918 .range => {
2919 var arena = std.heap.ArenaAllocator.init(f.object.dg.module.gpa);
2920 defer arena.deinit();
2921
2922 const expected_contents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2923 var stack align(@alignOf(expected_contents)) =
2924 std.heap.stackFallback(@sizeOf(expected_contents), arena.allocator());
2925
2926 if (int_info.signedness == .signed) {
2927 const min_val = try scalar_ty.minInt(stack.get(), target);
2928 try w.print("{}, ", .{try f.fmtIntLiteral(scalar_ty, min_val)});
2929 }
2930
2931 const max_val = try scalar_ty.maxInt(stack.get(), target);
2932 try w.print("{});\n", .{try f.fmtIntLiteral(scalar_ty, max_val)});
2933 },
2934 .bits => {
2935 var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };
2936 const bits_val = Value.initPayload(&bits_pl.base);
2937 try w.print("{x});\n", .{try f.fmtIntLiteral(Type.u8, bits_val)});
2938 },
2939 }
2835 try f.renderBuiltinInfo(w, scalar_ty, info);
2836 try w.writeAll(");\n");
29402837 return local;
29412838}
29422839
29432840fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
2944 if (f.liveness.isUnused(inst))
2945 return CValue.none;
2841 if (f.liveness.isUnused(inst)) return CValue.none;
29462842
29472843 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
29482844 const op = try f.resolveInst(ty_op.operand);
......@@ -2951,6 +2847,9 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
29512847 const inst_ty = f.air.typeOfIndex(inst);
29522848 const local = try f.allocLocal(inst_ty, .Const);
29532849
2850 const target = f.object.dg.module.getTarget();
2851 if (inst_ty.bitSize(target) > 64) {}
2852
29542853 try writer.writeAll(" = ");
29552854 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');
29562855 try f.writeCValue(writer, op, .Other);
......@@ -2959,16 +2858,53 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
29592858 return local;
29602859}
29612860
2962fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
2963 if (f.liveness.isUnused(inst))
2964 return CValue.none;
2861fn airBinOp(
2862 f: *Function,
2863 inst: Air.Inst.Index,
2864 operator: []const u8,
2865 operation: []const u8,
2866 info: BuiltinInfo,
2867) !CValue {
2868 if (f.liveness.isUnused(inst)) return CValue.none;
29652869
29662870 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2871
2872 const operand_ty = f.air.typeOf(bin_op.lhs);
2873 const target = f.object.dg.module.getTarget();
2874 if (operand_ty.bitSize(target) > 64) return try airBinBuiltinCall(f, inst, operation, info);
2875
2876 const inst_ty = f.air.typeOfIndex(inst);
29672877 const lhs = try f.resolveInst(bin_op.lhs);
29682878 const rhs = try f.resolveInst(bin_op.rhs);
29692879
29702880 const writer = f.object.writer();
2881 const local = try f.allocLocal(inst_ty, .Const);
2882
2883 try writer.writeAll(" = ");
2884 try f.writeCValue(writer, lhs, .Other);
2885 try writer.writeByte(' ');
2886 try writer.writeAll(operator);
2887 try writer.writeByte(' ');
2888 try f.writeCValue(writer, rhs, .Other);
2889 try writer.writeAll(";\n");
2890
2891 return local;
2892}
2893
2894fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
2895 if (f.liveness.isUnused(inst)) return CValue.none;
2896
2897 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2898
2899 const operand_ty = f.air.typeOf(bin_op.lhs);
2900 const target = f.object.dg.module.getTarget();
2901 if (operand_ty.bitSize(target) > 64) return try airCmpBuiltinCall(f, inst, operator);
2902
29712903 const inst_ty = f.air.typeOfIndex(inst);
2904 const lhs = try f.resolveInst(bin_op.lhs);
2905 const rhs = try f.resolveInst(bin_op.rhs);
2906
2907 const writer = f.object.writer();
29722908 const local = try f.allocLocal(inst_ty, .Const);
29732909
29742910 try writer.writeAll(" = ");
......@@ -3301,27 +3237,19 @@ fn lowerTry(
33013237 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
33023238
33033239 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
3304 err: {
3305 if (!payload_has_bits) {
3306 if (operand_is_ptr) {
3307 try writer.writeAll("if(*");
3308 } else {
3309 try writer.writeAll("if(");
3310 }
3311 try f.writeCValue(writer, err_union, .Other);
3312 try writer.writeByte(')');
3313 break :err;
3314 }
3315 if (operand_is_ptr or isByRef(err_union_ty)) {
3316 try writer.writeAll("if(");
3240 try writer.writeAll("if (");
3241 if (!payload_has_bits) {
3242 if (operand_is_ptr)
3243 try f.writeCValueDeref(writer, err_union)
3244 else
33173245 try f.writeCValue(writer, err_union, .Other);
3318 try writer.writeAll("->error)");
3319 break :err;
3320 }
3321 try writer.writeAll("if(");
3322 try f.writeCValue(writer, err_union, .Other);
3323 try writer.writeAll(".error)");
3246 } else {
3247 if (operand_is_ptr or isByRef(err_union_ty))
3248 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "error" })
3249 else
3250 try f.writeCValueMember(writer, err_union, .{ .identifier = "error" });
33243251 }
3252 try writer.writeByte(')');
33253253
33263254 try genBody(f, body);
33273255 try f.object.indent_writer.insertNewline();
......@@ -3342,20 +3270,17 @@ fn lowerTry(
33423270 try writer.writeAll("memcpy(");
33433271 try f.writeCValue(writer, local, .FunctionArgument);
33443272 try writer.writeAll(", ");
3345 try f.writeCValue(writer, err_union, .Other);
3346 try writer.writeAll(".payload, sizeof(");
3273 try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
3274 try writer.writeAll(", sizeof(");
33473275 try f.renderTypecast(writer, payload_ty);
33483276 try writer.writeAll("));\n");
33493277 } else {
3278 try writer.writeAll(" = ");
33503279 if (operand_is_ptr or isByRef(payload_ty)) {
3351 try writer.writeAll(" = &");
3352 try f.writeCValue(writer, err_union, .Other);
3353 try writer.writeAll("->payload;\n");
3354 } else {
3355 try writer.writeAll(" = ");
3356 try f.writeCValue(writer, err_union, .Other);
3357 try writer.writeAll(".payload;\n");
3358 }
3280 try writer.writeByte('&');
3281 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" });
3282 } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
3283 try writer.writeAll(";\n");
33593284 }
33603285 return local;
33613286}
......@@ -3415,8 +3340,8 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
34153340 return local;
34163341}
34173342
3418fn airBreakpoint(f: *Function) !CValue {
3419 try f.object.writer().writeAll("zig_breakpoint();\n");
3343fn airBreakpoint(writer: anytype) !CValue {
3344 try writer.writeAll("zig_breakpoint();\n");
34203345 return CValue.none;
34213346}
34223347
......@@ -3463,9 +3388,12 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {
34633388 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
34643389 const loop = f.air.extraData(Air.Block, ty_pl.payload);
34653390 const body = f.air.extra[loop.end..][0..loop.data.body_len];
3466 try f.object.writer().writeAll("while (true) ");
3391 const writer = f.object.writer();
3392 try writer.writeAll("while (");
3393 try f.object.dg.renderValue(writer, Type.bool, Value.@"true", .Other);
3394 try writer.writeAll(") ");
34673395 try genBody(f, body);
3468 try f.object.indent_writer.insertNewline();
3396 try writer.writeByte('\n');
34693397 return CValue.none;
34703398}
34713399
......@@ -3496,7 +3424,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
34963424 const writer = f.object.writer();
34973425
34983426 try writer.writeAll("switch (");
3499 if (condition_ty.tag() == .bool) try writer.writeAll("(int)");
3427 if (condition_ty.tag() == .bool) {
3428 try writer.writeByte('(');
3429 try f.renderTypecast(writer, Type.u1);
3430 try writer.writeByte(')');
3431 }
35003432 try f.writeCValue(writer, condition, .Other);
35013433 try writer.writeAll(") {");
35023434 f.object.indent_writer.pushIndent();
......@@ -3751,16 +3683,22 @@ fn airIsNull(
37513683 var payload_buf: Type.Payload.ElemType = undefined;
37523684 const payload_ty = optional_ty.optionalChild(&payload_buf);
37533685
3754 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3755 try writer.print(" {s} true;\n", .{operator});
3756 } else if (operand_ty.isPtrLikeOptional()) {
3686 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime())
3687 TypedValue{ .ty = Type.bool, .val = Value.@"true" }
3688 else if (operand_ty.isPtrLikeOptional())
37573689 // operand is a regular pointer, test `operand !=/== NULL`
3758 try writer.print(" {s} NULL;\n", .{operator});
3759 } else if (payload_ty.zigTypeTag() == .ErrorSet) {
3760 try writer.print(" {s} 0;\n", .{operator});
3761 } else {
3762 try writer.print(".is_null {s} true;\n", .{operator});
3763 }
3690 TypedValue{ .ty = operand_ty, .val = Value.@"null" }
3691 else if (payload_ty.zigTypeTag() == .ErrorSet)
3692 TypedValue{ .ty = payload_ty, .val = Value.zero }
3693 else rhs: {
3694 try writer.writeAll(".is_null");
3695 break :rhs TypedValue{ .ty = Type.bool, .val = Value.@"true" };
3696 };
3697 try writer.writeByte(' ');
3698 try writer.writeAll(operator);
3699 try writer.writeByte(' ');
3700 try f.object.dg.renderValue(writer, rhs.ty, rhs.val, .Other);
3701 try writer.writeAll(";\n");
37643702 return local;
37653703}
37663704
......@@ -3812,9 +3750,9 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
38123750 }
38133751
38143752 const local = try f.allocLocal(inst_ty, .Const);
3815 try writer.writeAll(" = &(");
3816 try f.writeCValue(writer, operand, .Other);
3817 try writer.writeAll(")->payload;\n");
3753 try writer.writeAll(" = &");
3754 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
3755 try writer.writeAll(";\n");
38183756 return local;
38193757}
38203758
......@@ -3833,7 +3771,9 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
38333771 }
38343772
38353773 try f.writeCValueDeref(writer, operand);
3836 try writer.writeAll(".is_null = false;\n");
3774 try writer.writeAll(".is_null = ");
3775 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
3776 try writer.writeAll(";\n");
38373777
38383778 const inst_ty = f.air.typeOfIndex(inst);
38393779 const local = try f.allocLocal(inst_ty, .Const);
......@@ -3974,44 +3914,30 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
39743914/// *(E!T) -> E
39753915/// Note that the result is never a pointer.
39763916fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
3977 if (f.liveness.isUnused(inst))
3978 return CValue.none;
3917 if (f.liveness.isUnused(inst)) return CValue.none;
39793918
39803919 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
39813920 const inst_ty = f.air.typeOfIndex(inst);
3982 const writer = f.object.writer();
39833921 const operand = try f.resolveInst(ty_op.operand);
39843922 const operand_ty = f.air.typeOf(ty_op.operand);
39853923
3986 if (operand_ty.zigTypeTag() == .Pointer) {
3987 const err_union_ty = operand_ty.childType();
3988 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
3989 return CValue{ .bytes = "0" };
3990 }
3991 if (!err_union_ty.errorUnionPayload().hasRuntimeBits()) {
3992 return operand;
3993 }
3994 const local = try f.allocLocal(inst_ty, .Const);
3995 try writer.writeAll(" = *");
3996 try f.writeCValue(writer, operand, .Other);
3997 try writer.writeAll(";\n");
3998 return local;
3999 }
4000 if (operand_ty.errorUnionSet().errorSetIsEmpty()) {
4001 return CValue{ .bytes = "0" };
4002 }
4003 if (!operand_ty.errorUnionPayload().hasRuntimeBits()) {
4004 return operand;
4005 }
3924 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
3925 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
3926 const error_ty = error_union_ty.errorUnionSet();
3927 const payload_ty = error_union_ty.errorUnionPayload();
3928 if (!payload_ty.hasRuntimeBits()) return operand;
40063929
3930 const writer = f.object.writer();
40073931 const local = try f.allocLocal(inst_ty, .Const);
40083932 try writer.writeAll(" = ");
4009 if (operand_ty.zigTypeTag() == .Pointer) {
4010 try f.writeCValueDeref(writer, operand);
4011 } else {
4012 try f.writeCValue(writer, operand, .Other);
4013 }
4014 try writer.writeAll(".error;\n");
3933 if (!error_ty.errorSetIsEmpty())
3934 if (operand_is_ptr)
3935 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
3936 else
3937 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
3938 else
3939 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
3940 try writer.writeAll(";\n");
40153941 return local;
40163942}
40173943
......@@ -4020,26 +3946,23 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
40203946 return CValue.none;
40213947
40223948 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4023 const writer = f.object.writer();
3949 const inst_ty = f.air.typeOfIndex(inst);
40243950 const operand = try f.resolveInst(ty_op.operand);
40253951 const operand_ty = f.air.typeOf(ty_op.operand);
40263952 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
40273953 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
40283954
4029 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {
4030 return CValue.none;
4031 }
4032
4033 const inst_ty = f.air.typeOfIndex(inst);
3955 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) return CValue.none;
40343956
3957 const writer = f.object.writer();
40353958 const local = try f.allocLocal(inst_ty, .Const);
40363959 try writer.writeAll(" = ");
40373960 if (is_ptr) try writer.writeByte('&');
4038 try writer.writeByte('(');
4039 try f.writeCValue(writer, operand, .Other);
4040 try writer.writeByte(')');
4041 try if (operand_is_ptr) writer.writeAll("->") else writer.writeByte('.');
4042 try writer.writeAll("payload;\n");
3961 if (operand_is_ptr)
3962 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" })
3963 else
3964 try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
3965 try writer.writeAll(";\n");
40433966 return local;
40443967}
40453968
......@@ -4060,7 +3983,9 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
40603983 const local = try f.allocLocal(inst_ty, .Const);
40613984 try writer.writeAll(" = { .payload = ");
40623985 try f.writeCValue(writer, operand, .Initializer);
4063 try writer.writeAll(", .is_null = false };\n");
3986 try writer.writeAll(", .is_null = ");
3987 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
3988 try writer.writeAll(" };\n");
40643989 return local;
40653990}
40663991
......@@ -4070,13 +3995,11 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
40703995 const writer = f.object.writer();
40713996 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
40723997 const operand = try f.resolveInst(ty_op.operand);
4073 const err_un_ty = f.air.typeOfIndex(inst);
4074 const payload_ty = err_un_ty.errorUnionPayload();
4075 if (!payload_ty.hasRuntimeBits()) {
4076 return operand;
4077 }
3998 const error_union_ty = f.air.typeOfIndex(inst);
3999 const payload_ty = error_union_ty.errorUnionPayload();
4000 if (!payload_ty.hasRuntimeBits()) return operand;
40784001
4079 const local = try f.allocLocal(err_un_ty, .Const);
4002 const local = try f.allocLocal(error_union_ty, .Const);
40804003 try writer.writeAll(" = { .payload = ");
40814004 try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer);
40824005 try writer.writeAll(", .error = ");
......@@ -4180,18 +4103,21 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
41804103
41814104 try writer.writeAll(" = ");
41824105
4183 if (error_ty.errorSetIsEmpty()) {
4184 try writer.writeByte('0');
4185 } else {
4186 try f.writeCValue(writer, operand, .Other);
4187 if (payload_ty.hasRuntimeBits()) {
4188 try if (is_ptr) writer.writeAll("->") else writer.writeByte('.');
4189 try writer.writeAll("error");
4190 }
4191 }
4106 if (!error_ty.errorSetIsEmpty())
4107 if (payload_ty.hasRuntimeBits())
4108 if (is_ptr)
4109 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
4110 else
4111 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
4112 else
4113 try f.writeCValue(writer, operand, .Other)
4114 else
4115 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
41924116 try writer.writeByte(' ');
41934117 try writer.writeAll(operator);
4194 try writer.writeAll(" 0;\n");
4118 try writer.writeByte(' ');
4119 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
4120 try writer.writeAll(";\n");
41954121 return local;
41964122}
41974123
......@@ -4258,55 +4184,74 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
42584184 return local;
42594185}
42604186
4261fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
4187fn airUnBuiltinCall(
4188 f: *Function,
4189 inst: Air.Inst.Index,
4190 operation: []const u8,
4191 info: BuiltinInfo,
4192) !CValue {
42624193 if (f.liveness.isUnused(inst)) return CValue.none;
42634194
42644195 const inst_ty = f.air.typeOfIndex(inst);
4265 const local = try f.allocLocal(inst_ty, .Const);
42664196 const operand = f.air.instructions.items(.data)[inst].ty_op.operand;
42674197 const operand_ty = f.air.typeOf(operand);
4268 const target = f.object.dg.module.getTarget();
4269 const writer = f.object.writer();
4270
4271 const int_info = operand_ty.intInfo(target);
4272 const c_bits = toCIntBits(int_info.bits) orelse
4273 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
42744198
4275 try writer.print(" = zig_{s}_", .{fn_name});
4276 try writer.print("{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
4199 const local = try f.allocLocal(inst_ty, .Const);
4200 const writer = f.object.writer();
4201 try writer.writeAll(" = zig_");
4202 try writer.writeAll(operation);
4203 try writer.writeByte('_');
4204 try f.renderTypeForBuiltinFnName(writer, operand_ty);
4205 try writer.writeByte('(');
42774206 try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument);
4278 try writer.print(", {d});\n", .{int_info.bits});
4207 try f.renderBuiltinInfo(writer, operand_ty, info);
4208 try writer.writeAll(");\n");
42794209 return local;
42804210}
42814211
4282fn airBinOpBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
4212fn airBinBuiltinCall(
4213 f: *Function,
4214 inst: Air.Inst.Index,
4215 operation: []const u8,
4216 info: BuiltinInfo,
4217) !CValue {
42834218 if (f.liveness.isUnused(inst)) return CValue.none;
42844219
42854220 const inst_ty = f.air.typeOfIndex(inst);
4286 const local = try f.allocLocal(inst_ty, .Const);
42874221 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4288 const lhs_ty = f.air.typeOf(bin_op.lhs);
4289 const target = f.object.dg.module.getTarget();
4222 const operand_ty = f.air.typeOf(bin_op.lhs);
4223
4224 const local = try f.allocLocal(inst_ty, .Const);
42904225 const writer = f.object.writer();
4226 try writer.writeAll(" = zig_");
4227 try writer.writeAll(operation);
4228 try writer.writeByte('_');
4229 try f.renderTypeForBuiltinFnName(writer, operand_ty);
4230 try writer.writeByte('(');
4231 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
4232 try writer.writeAll(", ");
4233 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
4234 try f.renderBuiltinInfo(writer, operand_ty, info);
4235 try writer.writeAll(");\n");
4236 return local;
4237}
42914238
4292 // For binary operations @TypeOf(lhs)==@TypeOf(rhs), so we only check one.
4293 if (lhs_ty.isInt()) {
4294 const int_info = lhs_ty.intInfo(target);
4295 const c_bits = toCIntBits(int_info.bits) orelse
4296 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
4297 try writer.print(" = zig_{s}_{c}{d}", .{ fn_name, signAbbrev(int_info.signedness), c_bits });
4298 } else if (lhs_ty.isRuntimeFloat()) {
4299 const c_bits = lhs_ty.floatBits(target);
4300 try writer.print(" = zig_{s}_f{d}", .{ fn_name, c_bits });
4301 } else {
4302 return f.fail("TODO: C backend: implement airBinOpBuiltinCall for type {s}", .{@tagName(lhs_ty.tag())});
4303 }
4239fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
4240 if (f.liveness.isUnused(inst)) return CValue.none;
4241
4242 const inst_ty = f.air.typeOfIndex(inst);
4243 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4244 const operand_ty = f.air.typeOf(bin_op.lhs);
43044245
4246 const local = try f.allocLocal(inst_ty, .Const);
4247 const writer = f.object.writer();
4248 try writer.writeAll(" = zig_cmp_");
4249 try f.renderTypeForBuiltinFnName(writer, operand_ty);
43054250 try writer.writeByte('(');
43064251 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
43074252 try writer.writeAll(", ");
43084253 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
4309 try writer.writeAll(");\n");
4254 try writer.print(") {s} {};\n", .{ operator, try f.fmtIntLiteral(Type.initTag(.i8), Value.zero) });
43104255 return local;
43114256}
43124257
......@@ -4325,7 +4270,11 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
43254270 try writer.writeAll(" = ");
43264271 if (is_struct) try writer.writeAll("{ .payload = ");
43274272 try f.writeCValue(writer, expected_value, .Initializer);
4328 if (is_struct) try writer.writeAll(", .is_null = false }");
4273 if (is_struct) {
4274 try writer.writeAll(", .is_null = ");
4275 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
4276 try writer.writeAll(" }");
4277 }
43294278 try writer.writeAll(";\n");
43304279
43314280 if (is_struct) {
......@@ -4341,10 +4290,10 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
43414290 try writer.writeAll(" *)");
43424291 try f.writeCValue(writer, ptr, .Other);
43434292 try writer.writeAll(", ");
4344 try f.writeCValue(writer, local, .FunctionArgument);
4345 if (is_struct) {
4346 try writer.writeAll(".payload");
4347 }
4293 if (is_struct)
4294 try f.writeCValueMember(writer, local, .{ .identifier = "payload" })
4295 else
4296 try f.writeCValue(writer, local, .FunctionArgument);
43484297 try writer.writeAll(", ");
43494298 try f.writeCValue(writer, new_value, .FunctionArgument);
43504299 try writer.writeAll(", ");
......@@ -4537,8 +4486,6 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
45374486 try f.writeCValue(writer, operand, .Other);
45384487 try writer.writeAll(");\n");
45394488
4540 try f.object.dg.fwd_decl.writer().writeAll("// This is where the fwd decl for tagName ended up\n");
4541
45424489 return local;
45434490}
45444491
......@@ -4804,7 +4751,7 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
48044751 return local;
48054752}
48064753
4807fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
4754fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
48084755 if (f.liveness.isUnused(inst)) return CValue.none;
48094756 const un_op = f.air.instructions.items(.data)[inst].un_op;
48104757 const writer = f.object.writer();
......@@ -4812,14 +4759,14 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue
48124759 const operand = try f.resolveInst(un_op);
48134760 const local = try f.allocLocal(inst_ty, .Const);
48144761 try writer.writeAll(" = ");
4815 try f.renderFloatFnName(fn_name, inst_ty);
4762 try f.renderFloatFnName(writer, operation, inst_ty);
48164763 try writer.writeByte('(');
48174764 try f.writeCValue(writer, operand, .FunctionArgument);
48184765 try writer.writeAll(");\n");
48194766 return local;
48204767}
48214768
4822fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue {
4769fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
48234770 if (f.liveness.isUnused(inst)) return CValue.none;
48244771 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
48254772 const writer = f.object.writer();
......@@ -4828,7 +4775,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValu
48284775 const rhs = try f.resolveInst(bin_op.rhs);
48294776 const local = try f.allocLocal(inst_ty, .Const);
48304777 try writer.writeAll(" = ");
4831 try f.renderFloatFnName(fn_name, inst_ty);
4778 try f.renderFloatFnName(writer, operation, inst_ty);
48324779 try writer.writeByte('(');
48334780 try f.writeCValue(writer, lhs, .FunctionArgument);
48344781 try writer.writeAll(", ");
......@@ -4848,7 +4795,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
48484795 const writer = f.object.writer();
48494796 const local = try f.allocLocal(inst_ty, .Const);
48504797 try writer.writeAll(" = ");
4851 try f.renderFloatFnName("fma", inst_ty);
4798 try f.renderFloatFnName(writer, "fma", inst_ty);
48524799 try writer.writeByte('(');
48534800 try f.writeCValue(writer, mulend1, .FunctionArgument);
48544801 try writer.writeAll(", ");
......@@ -5010,8 +4957,7 @@ fn formatIntLiteral(
50104957 };
50114958
50124959 undef_limbs: [limbs_count_128]Limb,
5013 str: [worst_case_int.sizeInBaseUpperBound(base)]u8,
5014 limbs_limbs: [expected_needed_limbs_count]Limb,
4960 wrap_limbs: [limbs_count_128]Limb,
50154961 };
50164962 var stack align(@alignOf(expected_contents)) =
50174963 std.heap.stackFallback(@sizeOf(expected_contents), data.mod.gpa);
......@@ -5037,35 +4983,89 @@ fn formatIntLiteral(
50374983 } else data.val.toBigInt(&int_buf, target);
50384984 assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));
50394985
5040 const limbs_count_64 = @divExact(64, @bitSizeOf(Limb));
50414986 const c_bits = toCIntBits(int_info.bits) orelse unreachable;
5042 if (c_bits == 128) {
5043 // Clang and GCC don't support 128-bit integer constants but
5044 // will hopefully unfold them if we construct one manually.
5045 //std.debug.todo("128-bit is unimplemented");
5046 try writer.writeByte('(');
5047 if (int_info.signedness == .signed) {
5048 try writer.writeAll("(int128_t)");
5049 if (!int.positive) try writer.writeByte('-');
4987 var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined;
4988 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
4989
4990 const wrap_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(c_bits));
4991 defer allocator.free(wrap_limbs);
4992 var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined };
4993 if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
4994 int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits))
4995 {
4996 const abbrev = switch (data.ty.tag()) {
4997 .c_short, .c_ushort => "SHRT",
4998 .c_int, .c_uint => "INT",
4999 .c_long, .c_ulong => "LONG",
5000 .c_longlong, .c_ulonglong => "LLONG",
5001 .isize, .usize => "INTPTR",
5002 else => return writer.print("zig_{s}Int_{c}{d}", .{
5003 if (int.positive) "max" else "min", signAbbrev(int_info.signedness), c_bits,
5004 }),
5005 };
5006 if (int_info.signedness == .unsigned) try writer.writeByte('U');
5007 return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" });
5008 }
5009
5010 if (!int.positive) try writer.writeByte('-');
5011 switch (data.ty.tag()) {
5012 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
5013 else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }),
5014 }
5015
5016 const limbs_count_64 = @divExact(64, @bitSizeOf(Limb));
5017 if (c_bits <= 64) {
5018 var base: u8 = undefined;
5019 var case: std.fmt.Case = undefined;
5020 switch (fmt.len) {
5021 0 => base = 10,
5022 1 => switch (fmt[0]) {
5023 'b' => {
5024 base = 2;
5025 try writer.writeAll("0b");
5026 },
5027 'o' => {
5028 base = 8;
5029 try writer.writeByte('0');
5030 },
5031 'd' => base = 10,
5032 'x' => {
5033 base = 16;
5034 case = .lower;
5035 try writer.writeAll("0x");
5036 },
5037 'X' => {
5038 base = 16;
5039 case = .upper;
5040 try writer.writeAll("0x");
5041 },
5042 else => @compileError("Invalid fmt: " ++ fmt),
5043 },
5044 else => @compileError("Invalid fmt: " ++ fmt),
50505045 }
50515046
5047 var str: [64]u8 = undefined;
5048 var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined;
5049 try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]);
5050 } else {
5051 assert(c_bits == 128);
50525052 const split = std.math.min(int.limbs.len, limbs_count_64);
5053
50535054 var upper_pl = Value.Payload.BigInt{
50545055 .base = .{ .tag = .int_big_positive },
50555056 .data = int.limbs[split..],
50565057 };
5057 const have_upper = !upper_pl.asBigInt().eqZero();
5058 if (have_upper) try writer.writeByte('(');
5059 if (have_upper or !int.positive) try writer.writeAll("(uint128_t)");
5060 if (have_upper) {
5061 const upper_val = Value.initPayload(&upper_pl.base);
5062 try formatIntLiteral(.{
5063 .ty = Type.u64,
5064 .val = upper_val,
5065 .mod = data.mod,
5066 }, fmt, options, writer);
5067 try writer.writeAll("<<64|");
5068 }
5058 const upper_val = Value.initPayload(&upper_pl.base);
5059 try formatIntLiteral(.{
5060 .ty = switch (int_info.signedness) {
5061 .unsigned => Type.u64,
5062 .signed => Type.i64,
5063 },
5064 .val = upper_val,
5065 .mod = data.mod,
5066 }, fmt, options, writer);
5067
5068 try writer.writeAll(", ");
50695069
50705070 var lower_pl = Value.Payload.BigInt{
50715071 .base = .{ .tag = .int_big_positive },
......@@ -5078,74 +5078,9 @@ fn formatIntLiteral(
50785078 .mod = data.mod,
50795079 }, fmt, options, writer);
50805080
5081 if (have_upper) try writer.writeByte(')');
50825081 return writer.writeByte(')');
50835082 }
50845083
5085 assert(c_bits <= 64);
5086 var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined;
5087 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
5088
5089 var wrap_limbs: [BigInt.calcTwosCompLimbCount(64)]Limb = undefined;
5090 var wrap = BigInt.Mutable{ .limbs = &wrap_limbs, .len = undefined, .positive = undefined };
5091 if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
5092 int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits))
5093 {
5094 if (int_info.signedness == .unsigned) try writer.writeByte('U');
5095 switch (data.ty.tag()) {
5096 .c_short, .c_ushort => try writer.writeAll("SHRT"),
5097 .c_int, .c_uint => try writer.writeAll("INT"),
5098 .c_long, .c_ulong => try writer.writeAll("LONG"),
5099 .c_longlong, .c_ulonglong => try writer.writeAll("LLONG"),
5100 .isize, .usize => try writer.writeAll("INTPTR"),
5101 else => try writer.print("INT{d}", .{c_bits}),
5102 }
5103 try writer.writeAll(if (int.positive) "_MAX" else "_MIN");
5104 return;
5105 }
5106
5107 if (!int.positive) try writer.writeByte('-');
5108 switch (data.ty.tag()) {
5109 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
5110 else => {
5111 if (int_info.signedness == .unsigned) try writer.writeByte('U');
5112 try writer.print("INT{d}_C(", .{c_bits});
5113 },
5114 }
5115
5116 var base: u8 = undefined;
5117 var case: std.fmt.Case = undefined;
5118 switch (fmt.len) {
5119 0 => base = 10,
5120 1 => switch (fmt[0]) {
5121 'b' => {
5122 base = 2;
5123 try writer.writeAll("0b");
5124 },
5125 'o' => {
5126 base = 8;
5127 try writer.writeByte('0');
5128 },
5129 'd' => base = 10,
5130 'x' => {
5131 base = 16;
5132 case = .lower;
5133 try writer.writeAll("0x");
5134 },
5135 'X' => {
5136 base = 16;
5137 case = .upper;
5138 try writer.writeAll("0x");
5139 },
5140 else => @compileError("Invalid fmt: " ++ fmt),
5141 },
5142 else => @compileError("Invalid fmt: " ++ fmt),
5143 }
5144
5145 var str: [64]u8 = undefined;
5146 var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined;
5147 try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]);
5148
51495084 switch (data.ty.tag()) {
51505085 .c_short, .c_ushort, .c_int => {},
51515086 .c_uint => try writer.writeAll("u"),
test/behavior/align.zig-2
......@@ -393,8 +393,6 @@ test "function callconv expression depends on generic parameter" {
393393}
394394
395395test "runtime-known array index has best alignment possible" {
396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
397
398396 // take full advantage of over-alignment
399397 var array align(4) = [_]u8{ 1, 2, 3, 4 };
400398 comptime assert(@TypeOf(&array[0]) == *align(4) u8);
test/behavior/bugs/2114.zig-1
......@@ -12,7 +12,6 @@ test "fixed" {
1212 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1615
1716 try testCtz();
1817 comptime try testCtz();
test/behavior/cast.zig-2
......@@ -119,7 +119,6 @@ test "@intToFloat(f80)" {
119119 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
120120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
121121 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
122 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
123122
124123 const S = struct {
125124 fn doTheTest(comptime Int: type) !void {
......@@ -1157,7 +1156,6 @@ fn castToOptionalSlice() ?[]const u8 {
11571156
11581157test "cast u128 to f128 and back" {
11591158 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1160 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11611159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11621160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11631161 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig-3
......@@ -54,7 +54,6 @@ fn testFloatComparisons() !void {
5454
5555test "different sized float comparisons" {
5656 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5857 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5958 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6059 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -303,7 +302,6 @@ test "@log" {
303302 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
304303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
305304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
306 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
307305
308306 comptime try testLog();
309307 try testLog();
......@@ -543,7 +541,6 @@ fn testTrunc() !void {
543541
544542test "negation f16" {
545543 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
546 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
547544 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
548545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
549546 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/int128.zig-1
......@@ -43,7 +43,6 @@ test "int128" {
4343 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
4444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
4545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4746
4847 var buff: i128 = -1;
4948 try expect(buff < 0 and (buff + 1) == 0);
test/behavior/math.zig-10
......@@ -452,7 +452,6 @@ fn testDivision() !void {
452452}
453453
454454test "division half-precision floats" {
455 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
456455 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
457456 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
458457 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -685,7 +684,6 @@ test "basic @mulWithOverflow" {
685684
686685// TODO migrate to this for all backends once they handle more cases
687686test "extensive @mulWithOverflow" {
688 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
689687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
690688
691689 {
......@@ -835,7 +833,6 @@ test "extensive @mulWithOverflow" {
835833}
836834
837835test "@mulWithOverflow bitsize > 32" {
838 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
839836 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
840837 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
841838
......@@ -923,8 +920,6 @@ test "@subWithOverflow" {
923920}
924921
925922test "@shlWithOverflow" {
926 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
927
928923 {
929924 var result: u4 = undefined;
930925 var a: u4 = 2;
......@@ -1274,7 +1269,6 @@ test "@sqrt" {
12741269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12751270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12761271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1277 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12781272
12791273 try testSqrt(f64, 12.0);
12801274 comptime try testSqrt(f64, 12.0);
......@@ -1339,7 +1333,6 @@ test "@floor" {
13391333 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13401334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13411335 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1342 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13431336
13441337 try testFloor(f64, 12.0);
13451338 comptime try testFloor(f64, 12.0);
......@@ -1388,7 +1381,6 @@ test "@ceil" {
13881381 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13891382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13901383 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1391 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13921384
13931385 try testCeil(f64, 12.0);
13941386 comptime try testCeil(f64, 12.0);
......@@ -1437,7 +1429,6 @@ test "@trunc" {
14371429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14381430 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14391431 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14411432
14421433 try testTrunc(f64, 12.0);
14431434 comptime try testTrunc(f64, 12.0);
......@@ -1500,7 +1491,6 @@ test "@round" {
15001491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15011492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15021493 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1503 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15041494
15051495 try testRound(f64, 12.0);
15061496 comptime try testRound(f64, 12.0);
test/behavior/muladd.zig-1
......@@ -27,7 +27,6 @@ fn testMulAdd() !void {
2727
2828test "@mulAdd f16" {
2929 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3130 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3231 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3332 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/packed-struct.zig-1
......@@ -448,7 +448,6 @@ test "optional pointer in packed struct" {
448448}
449449
450450test "nested packed struct field access test" {
451 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
452451 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
453452 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
454453 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/ptrcast.zig-1
......@@ -133,7 +133,6 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
133133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
134134 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
135135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: CBE does not yet support under-aligned fields
137136
138137 // Test lowering a field ptr
139138 comptime var bytes align(2) = [_]u8{ 1, 2, 3, 4, 5, 6 };
test/behavior/saturating_arithmetic.zig-5
......@@ -54,7 +54,6 @@ test "saturating add 128bit" {
5454 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5555 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5656 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5857 const S = struct {
5958 fn doTheTest() !void {
6059 try testSatAdd(i128, maxInt(i128), -maxInt(i128), 0);
......@@ -78,7 +77,6 @@ test "saturating subtraction" {
7877 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7978 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8079 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
8280
8381 const S = struct {
8482 fn doTheTest() !void {
......@@ -124,7 +122,6 @@ test "saturating subtraction 128bit" {
124122 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
125123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
126124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
127 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
128125
129126 const S = struct {
130127 fn doTheTest() !void {
......@@ -151,7 +148,6 @@ test "saturating multiplication" {
151148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
152149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
153150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
154 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
155151
156152 if (builtin.zig_backend == .stage1 and builtin.cpu.arch == .wasm32) {
157153 // https://github.com/ziglang/zig/issues/9660
......@@ -199,7 +195,6 @@ test "saturating shift-left" {
199195 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
200196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
201197 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
203198
204199 const S = struct {
205200 fn doTheTest() !void {
test/behavior/sizeof_and_typeof.zig-1
......@@ -19,7 +19,6 @@ test "@sizeOf on compile-time types" {
1919
2020test "@TypeOf() with multiple arguments" {
2121 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2322 {
2423 var var_1: u32 = undefined;
2524 var var_2: u8 = undefined;
test/behavior/widening.zig-2
......@@ -40,7 +40,6 @@ test "float widening" {
4040 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
4141 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
4242 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4443
4544 var a: f16 = 12.34;
4645 var b: f32 = a;
......@@ -60,7 +59,6 @@ test "float widening f16 to f128" {
6059 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
6261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
63 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
6462
6563 // TODO https://github.com/ziglang/zig/issues/3282
6664 if (builtin.cpu.arch == .aarch64) return error.SkipZigTest;