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 @@...@@ -1,103 +1,108 @@
1#undef linux1#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
3#if __STDC_VERSION__ >= 201112L20#if __STDC_VERSION__ >= 201112L
4#define zig_noreturn _Noreturn
5#define zig_threadlocal thread_local21#define zig_threadlocal thread_local
6#elif __GNUC__22#elif __GNUC__
7#define zig_noreturn __attribute__ ((noreturn))
8#define zig_threadlocal __thread23#define zig_threadlocal __thread
9#elif _MSC_VER24#elif _MSC_VER
10#define zig_noreturn __declspec(noreturn)
11#define zig_threadlocal __declspec(thread)25#define zig_threadlocal __declspec(thread)
12#else26#else
13#define zig_noreturn
14#define zig_threadlocal zig_threadlocal_unavailable27#define zig_threadlocal zig_threadlocal_unavailable
15#endif28#endif
1629
17#if defined(_MSC_VER)30#if zig_has_attribute(naked)
18#define ZIG_NAKED __declspec(naked)31#define zig_naked __attribute__((naked))
32#elif defined(_MSC_VER)
33#define zig_naked __declspec(naked)
19#else34#else
20#define ZIG_NAKED __attribute__((naked))35#define zig_naked zig_naked_unavailable
21#endif36#endif
2237
23#if __GNUC__38#if zig_has_attribute(cold)
24#define ZIG_COLD __attribute__ ((cold))39#define zig_cold __attribute__((cold))
25#else40#else
26#define ZIG_COLD41#define zig_cold
27#endif42#endif
2843
29#if __STDC_VERSION__ >= 199901L44#if __STDC_VERSION__ >= 199901L
30#define ZIG_RESTRICT restrict45#define zig_restrict restrict
31#elif defined(__GNUC__)46#elif defined(__GNUC__)
32#define ZIG_RESTRICT __restrict47#define zig_restrict __restrict
33#else48#else
34#define ZIG_RESTRICT49#define zig_restrict
35#endif50#endif
3651
37#if __STDC_VERSION__ >= 201112L52#if __STDC_VERSION__ >= 201112L
38#include <stdalign.h>53#define zig_align(alignment) _Alignas(alignment)
39#define ZIG_ALIGN(alignment) alignas(alignment)54#elif zig_has_attribute(aligned)
40#elif defined(__GNUC__)55#define zig_align(alignment) __attribute__((aligned(alignment)))
41#define ZIG_ALIGN(alignment) __attribute__((aligned(alignment)))56#elif _MSC_VER
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>
48#else57#else
49#define bool unsigned char58#error the C compiler being used does not support aligning variables
50#define true 1
51#define false 0
52#endif59#endif
5360
54#if defined(__GNUC__)61#if zig_has_builtin(unreachable)
55#define zig_unreachable() __builtin_unreachable()62#define zig_unreachable() __builtin_unreachable()
56#else63#else
57#define zig_unreachable()64#define zig_unreachable()
58#endif65#endif
5966
60#ifdef __cplusplus67#if defined(__cplusplus)
61#define ZIG_EXTERN_C extern "C"68#define zig_extern_c extern "C"
62#else69#else
63#define ZIG_EXTERN_C70#define zig_extern_c
64#endif71#endif
6572
66#if defined(_MSC_VER)73#if zig_has_builtin(debugtrap)
67#define zig_breakpoint() __debugbreak()
68#elif defined(__MINGW32__) || defined(__MINGW64__)
69#define zig_breakpoint() __debugbreak()
70#elif defined(__clang__)
71#define zig_breakpoint() __builtin_debugtrap()74#define zig_breakpoint() __builtin_debugtrap()
72#elif defined(__GNUC__)75#elif zig_has_builtin(trap)
73#define zig_breakpoint() __builtin_trap()76#define zig_breakpoint() __builtin_trap()
77#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
78#define zig_breakpoint() __debugbreak()
74#elif defined(__i386__) || defined(__x86_64__)79#elif defined(__i386__) || defined(__x86_64__)
75#define zig_breakpoint() __asm__ volatile("int $0x03");80#define zig_breakpoint() __asm__ volatile("int $0x03");
76#else81#else
77#define zig_breakpoint() raise(SIGTRAP)82#define zig_breakpoint() raise(SIGTRAP)
78#endif83#endif
7984
80#if defined(_MSC_VER)85#if zig_has_builtin(return_address)
81#define zig_return_address() _ReturnAddress()
82#elif defined(__GNUC__)
83#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))86#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))
87#elif defined(_MSC_VER)
88#define zig_return_address() _ReturnAddress()
84#else89#else
85#define zig_return_address() 090#define zig_return_address() 0
86#endif91#endif
8792
88#if defined(__GNUC__)93#if zig_has_builtin(frame_address)
89#define zig_frame_address() __builtin_frame_address(0)94#define zig_frame_address() __builtin_frame_address(0)
90#else95#else
91#define zig_frame_address() 096#define zig_frame_address() 0
92#endif97#endif
9398
94#if defined(__GNUC__)99#if zig_has_builtin(prefetch)
95#define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality)100#define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
96#else101#else
97#define zig_prefetch(addr, rw, locality)102#define zig_prefetch(addr, rw, locality)
98#endif103#endif
99104
100#if defined(__clang__)105#if zig_has_builtin(memory_size) && zig_has_builtin(memory_grow)
101#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)106#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)
102#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)107#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)
103#else108#else
...@@ -130,8 +135,8 @@...@@ -130,8 +135,8 @@
130#define memory_order_acq_rel __ATOMIC_ACQ_REL135#define memory_order_acq_rel __ATOMIC_ACQ_REL
131#define memory_order_seq_cst __ATOMIC_SEQ_CST136#define memory_order_seq_cst __ATOMIC_SEQ_CST
132#define zig_atomic(type) type137#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)138#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, zig_false, succ, fail)
134#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, true , succ, fail)139#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, zig_true , succ, fail)
135#define zig_atomicrmw_xchg(obj, arg, order) __atomic_exchange_n(obj, arg, order)140#define zig_atomicrmw_xchg(obj, arg, order) __atomic_exchange_n(obj, arg, order)
136#define zig_atomicrmw_add(obj, arg, order) __atomic_fetch_add (obj, arg, order)141#define zig_atomicrmw_add(obj, arg, order) __atomic_fetch_add (obj, arg, order)
137#define zig_atomicrmw_sub(obj, arg, order) __atomic_fetch_sub (obj, arg, order)142#define zig_atomicrmw_sub(obj, arg, order) __atomic_fetch_sub (obj, arg, order)
...@@ -168,1366 +173,1258 @@...@@ -168,1366 +173,1258 @@
168#define zig_fence(order) zig_unimplemented()173#define zig_fence(order) zig_unimplemented()
169#endif174#endif
170175
171#include <stdint.h>176#if __STDC_VERSION__ >= 201112L
172#include <stddef.h>177#define zig_noreturn _Noreturn void
173#include <limits.h>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 __int128190#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
176#define uint128_t unsigned __int128191
177#define UINT128_MAX (((uint128_t)UINT64_MAX<<64|UINT64_MAX))192typedef void zig_void;
178ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);193
179ZIG_EXTERN_C void *memset (void *, int, size_t);194#if defined(__cplusplus)
180ZIG_EXTERN_C int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);195typedef bool zig_bool;
181ZIG_EXTERN_C int128_t __addoti4(int128_t lhs, int128_t rhs, int *overflow);196#define zig_false false
182ZIG_EXTERN_C uint64_t __uaddodi4(uint64_t lhs, uint64_t rhs, int *overflow);197#define zig_true true
183ZIG_EXTERN_C uint128_t __uaddoti4(uint128_t lhs, uint128_t rhs, int *overflow);198#else
184ZIG_EXTERN_C int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);199#if __STDC_VERSION__ >= 199901L
185ZIG_EXTERN_C int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);200typedef _Bool zig_bool;
186ZIG_EXTERN_C int128_t __suboti4(int128_t lhs, int128_t rhs, int *overflow);201#else
187ZIG_EXTERN_C uint32_t __usubosi4(uint32_t lhs, uint32_t rhs, int *overflow);202typedef char zig_bool;
188ZIG_EXTERN_C uint64_t __usubodi4(uint64_t lhs, uint64_t rhs, int *overflow);203#endif
189ZIG_EXTERN_C uint128_t __usuboti4(uint128_t lhs, uint128_t rhs, int *overflow);204#define zig_false ((zig_bool)0)
190ZIG_EXTERN_C int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);205#define zig_true ((zig_bool)1)
191ZIG_EXTERN_C int128_t __muloti4(int128_t lhs, int128_t rhs, int *overflow);206#endif
192ZIG_EXTERN_C uint64_t __umulodi4(uint64_t lhs, uint64_t rhs, int *overflow);207
193ZIG_EXTERN_C uint128_t __umuloti4(uint128_t lhs, uint128_t rhs, int *overflow);208typedef uintptr_t zig_usize;
194209typedef intptr_t zig_isize;
195210typedef signed short int zig_c_short;
196static inline uint8_t zig_addw_u8(uint8_t lhs, uint8_t rhs, uint8_t max) {211typedef unsigned short int zig_c_ushort;
197 uint8_t thresh = max - rhs;212typedef signed int zig_c_int;
198 if (lhs > thresh) {213typedef unsigned int zig_c_uint;
199 return lhs - thresh - 1;214typedef signed long int zig_c_long;
200 } else {215typedef unsigned long int zig_c_ulong;
201 return lhs + rhs;216typedef signed long long int zig_c_longlong;
202 }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
203}386}
204387
205static inline int8_t zig_addw_i8(int8_t lhs, int8_t rhs, int8_t min, int8_t max) {388zig_extern_c zig_i32 __addosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
206 if ((lhs > 0) && (rhs > 0)) {389static inline zig_bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
207 int8_t thresh = max - rhs;390#if zig_has_builtin(add_overflow)
208 if (lhs > thresh) {391 zig_i32 full_res;
209 return min + lhs - thresh - 1;392 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
210 }393#else
211 } else if ((lhs < 0) && (rhs < 0)) {394 zig_c_int overflow_int;
212 int8_t thresh = min - rhs;395 zig_u32 full_res = __addosi4(lhs, rhs, &overflow_int);
213 if (lhs < thresh) {396 zig_bool overflow = overflow_int != 0;
214 return max + lhs - thresh + 1;397#endif
215 }398 *res = zig_wrap_i32(full_res, bits);
216 }399 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
217 return lhs + rhs;
218}400}
219401
220static inline uint16_t zig_addw_u16(uint16_t lhs, uint16_t rhs, uint16_t max) {402static inline zig_bool zig_addo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
221 uint16_t thresh = max - rhs;403#if zig_has_builtin(add_overflow)
222 if (lhs > thresh) {404 zig_u64 full_res;
223 return lhs - thresh - 1;405 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
224 } else {406 *res = zig_wrap_u64(full_res, bits);
225 return lhs + rhs;407 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
226 }408#else
409 *res = zig_addw_u64(lhs, rhs, bits);
410 return *res < lhs;
411#endif
227}412}
228413
229static inline int16_t zig_addw_i16(int16_t lhs, int16_t rhs, int16_t min, int16_t max) {414zig_extern_c zig_i64 __addodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
230 if ((lhs > 0) && (rhs > 0)) {415static inline zig_bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
231 int16_t thresh = max - rhs;416#if zig_has_builtin(add_overflow)
232 if (lhs > thresh) {417 zig_i64 full_res;
233 return min + lhs - thresh - 1;418 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
234 }419#else
235 } else if ((lhs < 0) && (rhs < 0)) {420 zig_c_int overflow_int;
236 int16_t thresh = min - rhs;421 zig_u64 full_res = __addodi4(lhs, rhs, &overflow_int);
237 if (lhs < thresh) {422 zig_bool overflow = overflow_int != 0;
238 return max + lhs - thresh + 1;423#endif
239 }424 *res = zig_wrap_i64(full_res, bits);
240 }425 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
241 return lhs + rhs;
242}426}
243427
244static inline uint32_t zig_addw_u32(uint32_t lhs, uint32_t rhs, uint32_t max) {428static inline zig_bool zig_addo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
245 uint32_t thresh = max - rhs;429#if zig_has_builtin(add_overflow)
246 if (lhs > thresh) {430 zig_u8 full_res;
247 return lhs - thresh - 1;431 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
248 } else {432 *res = zig_wrap_u8(full_res, bits);
249 return lhs + rhs;433 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
250 }434#else
435 return zig_addo_u32(res, lhs, rhs, bits);
436#endif
251}437}
252438
253static inline int32_t zig_addw_i32(int32_t lhs, int32_t rhs, int32_t min, int32_t max) {439static inline zig_bool zig_addo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
254 if ((lhs > 0) && (rhs > 0)) {440#if zig_has_builtin(add_overflow)
255 int32_t thresh = max - rhs;441 zig_i8 full_res;
256 if (lhs > thresh) {442 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
257 return min + lhs - thresh - 1;443 *res = zig_wrap_i8(full_res, bits);
258 }444 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
259 } else if ((lhs < 0) && (rhs < 0)) {445#else
260 int32_t thresh = min - rhs;446 return zig_addo_i32(res, lhs, rhs, bits);
261 if (lhs < thresh) {447#endif
262 return max + lhs - thresh + 1;
263 }
264 }
265 return lhs + rhs;
266}448}
267449
268static inline uint64_t zig_addw_u64(uint64_t lhs, uint64_t rhs, uint64_t max) {450static inline zig_bool zig_addo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
269 uint64_t thresh = max - rhs;451#if zig_has_builtin(add_overflow)
270 if (lhs > thresh) {452 zig_u16 full_res;
271 return lhs - thresh - 1;453 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
272 } else {454 *res = zig_wrap_u16(full_res, bits);
273 return lhs + rhs;455 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
274 }456#else
457 return zig_addo_u32(res, lhs, rhs, bits);
458#endif
275}459}
276460
277static inline int64_t zig_addw_i64(int64_t lhs, int64_t rhs, int64_t min, int64_t max) {461static inline zig_bool zig_addo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
278 if ((lhs > 0) && (rhs > 0)) {462#if zig_has_builtin(add_overflow)
279 int64_t thresh = max - rhs;463 zig_i16 full_res;
280 if (lhs > thresh) {464 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
281 return min + lhs - thresh - 1;465 *res = zig_wrap_i16(full_res, bits);
282 }466 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
283 } else if ((lhs < 0) && (rhs < 0)) {467#else
284 int64_t thresh = min - rhs;468 return zig_addo_i32(res, lhs, rhs, bits);
285 if (lhs < thresh) {469#endif
286 return max + lhs - thresh + 1;
287 }
288 }
289 return lhs + rhs;
290}470}
291471
292static inline intptr_t zig_addw_isize(intptr_t lhs, intptr_t rhs, intptr_t min, intptr_t max) {472static inline zig_bool zig_subo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
293 return (intptr_t)(((uintptr_t)lhs) + ((uintptr_t)rhs));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
294}482}
295483
296static inline short zig_addw_short(short lhs, short rhs, short min, short max) {484zig_extern_c zig_i32 __subosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
297 return (short)(((unsigned short)lhs) + ((unsigned short)rhs));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);
298}496}
299497
300static inline int zig_addw_int(int lhs, int rhs, int min, int max) {498static inline zig_bool zig_subo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
301 return (int)(((unsigned)lhs) + ((unsigned)rhs));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
302}508}
303509
304static inline long zig_addw_long(long lhs, long rhs, long min, long max) {510zig_extern_c zig_i64 __subodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
305 return (long)(((unsigned long)lhs) + ((unsigned long)rhs));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);
306}522}
307523
308static inline long long zig_addw_longlong(long long lhs, long long rhs, long long min, long long max) {524static inline zig_bool zig_subo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
309 return (long long)(((unsigned long long)lhs) + ((unsigned long long)rhs));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
310}533}
311534
312static inline uint8_t zig_subw_u8(uint8_t lhs, uint8_t rhs, uint8_t max) {535static inline zig_bool zig_subo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
313 if (lhs < rhs) {536#if zig_has_builtin(sub_overflow)
314 return max - rhs - lhs + 1;537 zig_i8 full_res;
315 } else {538 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
316 return lhs - rhs;539 *res = zig_wrap_i8(full_res, bits);
317 }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
318}544}
319545
320static inline int8_t zig_subw_i8(int8_t lhs, int8_t rhs, int8_t min, int8_t max) {546static inline zig_bool zig_subo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
321 if ((lhs > 0) && (rhs < 0)) {547#if zig_has_builtin(sub_overflow)
322 int8_t thresh = lhs - max;548 zig_u16 full_res;
323 if (rhs < thresh) {549 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
324 return min + (thresh - rhs - 1);550 *res = zig_wrap_u16(full_res, bits);
325 }551 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
326 } else if ((lhs < 0) && (rhs > 0)) {552#else
327 int8_t thresh = lhs - min;553 return zig_subo_u32(res, lhs, rhs, bits);
328 if (rhs > thresh) {554#endif
329 return max - (rhs - thresh - 1);
330 }
331 }
332 return lhs - rhs;
333}555}
334556
335static inline uint16_t zig_subw_u16(uint16_t lhs, uint16_t rhs, uint16_t max) {557static inline zig_bool zig_subo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
336 if (lhs < rhs) {558#if zig_has_builtin(sub_overflow)
337 return max - rhs - lhs + 1;559 zig_i16 full_res;
338 } else {560 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
339 return lhs - rhs;561 *res = zig_wrap_i16(full_res, bits);
340 }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
341}566}
342567
343static inline int16_t zig_subw_i16(int16_t lhs, int16_t rhs, int16_t min, int16_t max) {568static inline zig_bool zig_mulo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
344 if ((lhs > 0) && (rhs < 0)) {569#if zig_has_builtin(mul_overflow)
345 int16_t thresh = lhs - max;570 zig_u32 full_res;
346 if (rhs < thresh) {571 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
347 return min + (thresh - rhs - 1);572 *res = zig_wrap_u32(full_res, bits);
348 }573 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
349 } else if ((lhs < 0) && (rhs > 0)) {574#else
350 int16_t thresh = lhs - min;575 *res = zig_mulw_u32(lhs, rhs, bits);
351 if (rhs > thresh) {576 return rhs != zig_as_u32(0) && lhs > zig_maxInt(u32, bits) / rhs;
352 return max - (rhs - thresh - 1);577#endif
353 }
354 }
355 return lhs - rhs;
356}578}
357579
358static inline uint32_t zig_subw_u32(uint32_t lhs, uint32_t rhs, uint32_t max) {580zig_extern_c zig_i32 __mulosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
359 if (lhs < rhs) {581static inline zig_bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
360 return max - rhs - lhs + 1;582#if zig_has_builtin(mul_overflow)
361 } else {583 zig_i32 full_res;
362 return lhs - rhs;584 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
363 }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);
364}592}
365593
366static inline int32_t zig_subw_i32(int32_t lhs, int32_t rhs, int32_t min, int32_t max) {594static inline zig_bool zig_mulo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
367 if ((lhs > 0) && (rhs < 0)) {595#if zig_has_builtin(mul_overflow)
368 int32_t thresh = lhs - max;596 zig_u64 full_res;
369 if (rhs < thresh) {597 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
370 return min + (thresh - rhs - 1);598 *res = zig_wrap_u64(full_res, bits);
371 }599 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
372 } else if ((lhs < 0) && (rhs > 0)) {600#else
373 int32_t thresh = lhs - min;601 *res = zig_mulw_u64(lhs, rhs, bits);
374 if (rhs > thresh) {602 return rhs != zig_as_u64(0) && lhs > zig_maxInt(u64, bits) / rhs;
375 return max - (rhs - thresh - 1);603#endif
376 }
377 }
378 return lhs - rhs;
379}604}
380605
381static inline uint64_t zig_subw_u64(uint64_t lhs, uint64_t rhs, uint64_t max) {606zig_extern_c zig_i64 __mulodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
382 if (lhs < rhs) {607static inline zig_bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
383 return max - rhs - lhs + 1;608#if zig_has_builtin(mul_overflow)
384 } else {609 zig_i64 full_res;
385 return lhs - rhs;610 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
386 }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);
387}618}
388619
389static inline int64_t zig_subw_i64(int64_t lhs, int64_t rhs, int64_t min, int64_t max) {620static inline zig_bool zig_mulo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
390 if ((lhs > 0) && (rhs < 0)) {621#if zig_has_builtin(mul_overflow)
391 int64_t thresh = lhs - max;622 zig_u8 full_res;
392 if (rhs < thresh) {623 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
393 return min + (thresh - rhs - 1);624 *res = zig_wrap_u8(full_res, bits);
394 }625 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
395 } else if ((lhs < 0) && (rhs > 0)) {626#else
396 int64_t thresh = lhs - min;627 return zig_mulo_u32(res, lhs, rhs, bits);
397 if (rhs > thresh) {628#endif
398 return max - (rhs - thresh - 1);
399 }
400 }
401 return lhs - rhs;
402}629}
403630
404static inline intptr_t zig_subw_isize(intptr_t lhs, intptr_t rhs, intptr_t min, intptr_t max) {631static inline zig_bool zig_mulo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
405 return (intptr_t)(((uintptr_t)lhs) - ((uintptr_t)rhs));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
406}640}
407641
408static inline short zig_subw_short(short lhs, short rhs, short min, short max) {642static inline zig_bool zig_mulo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
409 return (short)(((unsigned short)lhs) - ((unsigned short)rhs));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
410}651}
411652
412static inline int zig_subw_int(int lhs, int rhs, int min, int max) {653static inline zig_bool zig_mulo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
413 return (int)(((unsigned)lhs) - ((unsigned)rhs));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
414}662}
415663
416static inline long zig_subw_long(long lhs, long rhs, long min, long max) {664#define zig_int_builtins(w) \
417 return (long)(((unsigned long)lhs) - ((unsigned long)rhs));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);
418}833}
419834
420static inline long long zig_subw_longlong(long long lhs, long long rhs, long long min, long long max) {835static inline zig_i8 zig_byte_swap_i8(zig_i8 val, zig_u8 bits) {
421 return (long long)(((unsigned long long)lhs) - ((unsigned long long)rhs));836 return zig_wrap_i8((zig_i8)zig_byte_swap_u8((zig_u8)val, bits), bits);
422}837}
423838
424static inline bool zig_addo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {839static inline zig_u16 zig_byte_swap_u16(zig_u16 val, zig_u8 bits) {
425#if defined(__GNUC__) && INT8_MAX == INT_MAX840 zig_u16 full_res;
426 if (min == INT8_MIN && max == INT8_MAX) {841#if zig_has_builtin(bswap16)
427 return __builtin_sadd_overflow(lhs, rhs, (int*)res);842 full_res = __builtin_bswap16(val);
428 }843#else
429#elif defined(__GNUC__) && INT8_MAX == LONG_MAX844 full_res = (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 0)) << 8 |
430 if (min == INT8_MIN && max == INT8_MAX) {845 (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 8)) >> 0;
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 }
437#endif846#endif
438 int16_t big_result = (int16_t)lhs + (int16_t)rhs;847 return zig_wrap_u16(full_res >> (16 - bits), bits);
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;
449}848}
450849
451static inline bool zig_addo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {850static inline zig_i16 zig_byte_swap_i16(zig_i16 val, zig_u8 bits) {
452#if defined(__GNUC__) && INT16_MAX == INT_MAX851 return zig_wrap_i16((zig_i16)zig_byte_swap_u16((zig_u16)val, bits), bits);
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;
476}852}
477853
478static inline bool zig_addo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {854static inline zig_u32 zig_byte_swap_u32(zig_u32 val, zig_u8 bits) {
479#if defined(__GNUC__) && INT32_MAX == INT_MAX855 zig_u32 full_res;
480 if (min == INT32_MIN && max == INT32_MAX) {856#if zig_has_builtin(bswap32)
481 return __builtin_sadd_overflow(lhs, rhs, (int*)res);857 full_res = __builtin_bswap32(val);
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);
513#else858#else
514 int int_overflow;859 full_res = (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 0)) << 16 |
515 *res = __addodi4(lhs, rhs, &int_overflow);860 (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 16)) >> 0;
516 overflow = int_overflow != 0;861#endif
517#endif862 return zig_wrap_u32(full_res >> (32 - bits), bits);
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;
528}863}
529864
530static inline bool zig_addo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {865static inline zig_i32 zig_byte_swap_i32(zig_i32 val, zig_u8 bits) {
531 bool overflow;866 return zig_wrap_i32((zig_i32)zig_byte_swap_u32((zig_u32)val, bits), bits);
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;
553}867}
554868
555static inline bool zig_addo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {869static inline zig_u64 zig_byte_swap_u64(zig_u64 val, zig_u8 bits) {
556#if defined(__GNUC__) && UINT8_MAX == UINT_MAX870 zig_u64 full_res;
557 if (max == UINT8_MAX) {871#if zig_has_builtin(bswap64)
558 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);872 full_res = __builtin_bswap64(val);
559 }873#else
560#elif defined(__GNUC__) && UINT8_MAX == ULONG_MAX874 full_res = (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 0)) << 32 |
561 if (max == UINT8_MAX) {875 (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 32)) >> 0;
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 }
568#endif876#endif
569 uint16_t big_result = (uint16_t)lhs + (uint16_t)rhs;877 return zig_wrap_u64(full_res >> (64 - bits), bits);
570 if (big_result > max) {
571 *res = big_result - max - 1;
572 return true;
573 }
574 *res = big_result;
575 return false;
576}878}
577879
578static inline uint16_t zig_addo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {880static inline zig_i64 zig_byte_swap_i64(zig_i64 val, zig_u8 bits) {
579#if defined(__GNUC__) && UINT16_MAX == UINT_MAX881 return zig_wrap_i64((zig_i64)zig_byte_swap_u64((zig_u64)val, bits), bits);
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;
599}882}
600883
601static inline uint32_t zig_addo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {884static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
602#if defined(__GNUC__) && UINT32_MAX == UINT_MAX885 zig_u8 full_res;
603 if (max == UINT32_MAX) {886#if zig_has_builtin(bitreverse8)
604 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);887 full_res = __builtin_bitreverse8(val);
605 }888#else
606#elif defined(__GNUC__) && UINT32_MAX == ULONG_MAX889 static zig_u8 const lut[0x10] = {
607 if (max == UINT32_MAX) {890 0b0000, 0b1000, 0b0100, 0b1100,
608 return __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);891 0b0010, 0b1010, 0b0110, 0b1110,
609 }892 0b0001, 0b1001, 0b0101, 0b1101,
610#elif defined(__GNUC__) && UINT32_MAX == ULLONG_MAX893 0b0011, 0b1011, 0b0111, 0b1111,
611 if (max == UINT32_MAX) {894 };
612 return __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);895 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
613 }
614#endif896#endif
615 uint64_t big_result = (uint64_t)lhs + (uint64_t)rhs;897 return zig_wrap_u8(full_res >> (8 - bits), bits);
616 if (big_result > max) {898}
617 *res = big_result - max - 1;899
618 return true;900static inline zig_i8 zig_bit_reverse_i8(zig_i8 val, zig_u8 bits) {
619 }901 return zig_wrap_i8((zig_i8)zig_bit_reverse_u8((zig_u8)val, bits), bits);
620 *res = big_result;902}
621 return false;903
622}904static inline zig_u16 zig_bit_reverse_u16(zig_u16 val, zig_u8 bits) {
623905 zig_u16 full_res;
624static inline uint64_t zig_addo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {906#if zig_has_builtin(bitreverse16)
625 bool overflow;907 full_res = __builtin_bitreverse16(val);
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);
632#else908#else
633 int int_overflow;909 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0)) << 8 |
634 *res = __uaddodi4(lhs, rhs, &int_overflow);910 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8)) >> 0;
635 overflow = int_overflow != 0;
636#endif911#endif
637 if (*res > max && !overflow) {912 return zig_wrap_u16(full_res >> (16 - bits), bits);
638 *res -= max - 1;
639 return true;
640 }
641 return overflow;
642}913}
643914
644static inline uint128_t zig_addo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {915static inline zig_i16 zig_bit_reverse_i16(zig_i16 val, zig_u8 bits) {
645 int overflow;916 return zig_wrap_i16((zig_i16)zig_bit_reverse_u16((zig_u16)val, bits), bits);
646 *res = __uaddoti4(lhs, rhs, &overflow);
647 if (*res > max && overflow == 0) {
648 *res -= max - 1;
649 return true;
650 }
651 return overflow != 0;
652}917}
653918
654static inline bool zig_subo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {919static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) {
655#if defined(__GNUC__) && INT8_MAX == INT_MAX920 zig_u32 full_res;
656 if (min == INT8_MIN && max == INT8_MAX) {921#if zig_has_builtin(bitreverse32)
657 return __builtin_ssub_overflow(lhs, rhs, (int*)res);922 full_res = __builtin_bitreverse32(val);
658 }923#else
659#elif defined(__GNUC__) && INT8_MAX == LONG_MAX924 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0)) << 16 |
660 if (min == INT8_MIN && max == INT8_MAX) {925 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16)) >> 0;
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 }
667#endif926#endif
668 int16_t big_result = (int16_t)lhs - (int16_t)rhs;927 return zig_wrap_u32(full_res >> (32 - bits), bits);
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;
679}928}
680929
681static inline bool zig_subo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {930static inline zig_i32 zig_bit_reverse_i32(zig_i32 val, zig_u8 bits) {
682#if defined(__GNUC__) && INT16_MAX == INT_MAX931 return zig_wrap_i32((zig_i32)zig_bit_reverse_u32((zig_u32)val, bits), bits);
683 if (min == INT16_MIN && max == INT16_MAX) {932}
684 return __builtin_ssub_overflow(lhs, rhs, (int*)res);933
685 }934static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) {
686#elif defined(__GNUC__) && INT16_MAX == LONG_MAX935 zig_u64 full_res;
687 if (min == INT16_MIN && max == INT16_MAX) {936#if zig_has_builtin(bitreverse64)
688 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);937 full_res = __builtin_bitreverse64(val);
689 }938#else
690#elif defined(__GNUC__) && INT16_MAX == LLONG_MAX939 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0)) << 32 |
691 if (min == INT16_MIN && max == INT16_MAX) {940 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32)) >> 0;
692 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
693 }
694#endif941#endif
695 int32_t big_result = (int32_t)lhs - (int32_t)rhs;942 return zig_wrap_u64(full_res >> (64 - bits), bits);
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;
706}943}
707944
708static inline bool zig_subo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {945static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {
709#if defined(__GNUC__) && INT32_MAX == INT_MAX946 return zig_wrap_i64((zig_i64)zig_bit_reverse_u64((zig_u64)val, bits), bits);
710 if (min == INT32_MIN && max == INT32_MAX) {947}
711 return __builtin_ssub_overflow(lhs, rhs, (int*)res);948
712 }949/* ======================== 128-bit Integer Routines ======================== */
713#elif defined(__GNUC__) && INT32_MAX == LONG_MAX950
714 if (min == INT32_MIN && max == INT32_MAX) {951#if !defined(zig_has_int128)
715 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);952# if defined(__SIZEOF_INT128__)
716 }953# define zig_has_int128 1
717#elif defined(__GNUC__) && INT32_MAX == LLONG_MAX954# else
718 if (min == INT32_MIN && max == INT32_MAX) {955# define zig_has_int128 0
719 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);956# endif
720 }
721#endif957#endif
722 int64_t big_result = (int64_t)lhs - (int64_t)rhs;958
723 if (big_result > max) {959#if zig_has_int128
724 *res = big_result - ((int64_t)max - (int64_t)min);960
725 return true;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); \
726 }975 }
727 if (big_result < min) {976#define zig_bit_int128(ZigType, CType, operation, operator) \
728 *res = big_result + ((int64_t)max - (int64_t)min);977 static inline CType zig_##operation##_##ZigType(CType lhs, CType rhs) { \
729 return true;978 return lhs operator rhs; \
730 }979 }
731 *res = big_result;980
732 return false;981#else /* zig_has_int128 */
733}982
734983#if __LITTLE_ENDIAN__ || _MSC_VER
735static inline bool zig_subo_i64(int64_t lhs, int64_t rhs, int64_t *res, int64_t min, int64_t max) {984typedef struct { zig_align(16) zig_u64 lo; zig_u64 hi; } zig_u128;
736 bool overflow;985typedef struct { zig_align(16) zig_u64 lo; zig_i64 hi; } zig_i128;
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);
743#else986#else
744 int int_overflow;987typedef struct { zig_align(16) zig_u64 hi; zig_u64 lo; } zig_u128;
745 *res = __subodi4(lhs, rhs, &int_overflow);988typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
746 overflow = int_overflow != 0;989#endif
747#endif990
748 if (!overflow) {991#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
749 if (*res > max) {992#define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
750 // TODO adjust the result to be the truncated bits993#define zig_hi_u128(val) ((val).hi)
751 return true;994#define zig_lo_u128(val) ((val).lo)
752 } else if (*res < min) {995#define zig_hi_i128(val) ((val).hi)
753 // TODO adjust the result to be the truncated bits996#define zig_lo_i128(val) ((val).lo)
754 return true;997#define zig_bitcast_u128(val) zig_as_u128((zig_u64)(val).hi, (val).lo)
755 }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 }; \
756 }1008 }
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);
758}1035}
7591036
760static inline bool zig_subo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {1037static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
761 bool overflow;1038 (void)bits;
762#if defined(__GNUC__) && INT128_MAX == INT_MAX1039 return ~val;
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;
783}1040}
7841041
785static inline bool zig_subo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {1042static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
786#if defined(__GNUC__) && UINT8_MAX == UINT_MAX1043 return lhs >> rhs;
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;
799}1044}
8001045
801static inline uint16_t zig_subo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {1046static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
802#if defined(__GNUC__) && UINT16_MAX == UINT_MAX1047 return lhs << rhs;
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 }
837}1048}
8381049
839static inline uint64_t zig_subo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {1050static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
840 if (max == UINT64_MAX) {1051 return lhs << rhs;
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 }
860}1052}
8611053
862static inline uint128_t zig_subo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {1054static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
863 if (max == UINT128_MAX) {1055 return lhs + rhs;
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 }
875}1056}
8761057
877static inline bool zig_mulo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {1058static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
878#if defined(__GNUC__) && INT8_MAX == INT_MAX1059 return lhs + rhs;
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;
902}1060}
9031061
904static inline bool zig_mulo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {1062static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
905#if defined(__GNUC__) && INT16_MAX == INT_MAX1063 return lhs - rhs;
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;
929}1064}
9301065
931static inline bool zig_mulo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {1066static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
932#if defined(__GNUC__) && INT32_MAX == INT_MAX1067 return lhs - rhs;
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;
981}1068}
9821069
983static inline bool zig_mulo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {1070static inline zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
984 bool overflow;1071 return lhs * rhs;
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;
1006}1072}
10071073
1008static inline bool zig_mulo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {1074static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1009#if defined(__GNUC__) && UINT8_MAX == UINT_MAX1075 return lhs * rhs;
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;
1029}1076}
10301077
1031static inline uint16_t zig_mulo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {1078static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
1032#if defined(__GNUC__) && UINT16_MAX == UINT_MAX1079 return lhs / rhs;
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;
1052}1080}
10531081
1054static inline uint32_t zig_mulo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {1082static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
1055#if defined(__GNUC__) && UINT32_MAX == UINT_MAX1083 return lhs / rhs;
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;
1095}1084}
10961085
1097static inline uint128_t zig_mulo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {1086static inline zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
1098 int overflow;1087 return lhs % rhs;
1099 *res = __umuloti4(lhs, rhs, &overflow);
1100 if (*res > max && overflow == 0) {
1101 *res -= max - 1;
1102 return true;
1103 }
1104 return overflow != 0;
1105}1088}
11061089
1107static inline float zig_bitcast_f32_u32(uint32_t arg) {1090static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
1108 float dest;1091 return lhs % rhs;
1109 memcpy(&dest, &arg, sizeof dest);
1110 return dest;
1111}1092}
11121093
1113static inline float zig_bitcast_f64_u64(uint64_t arg) {1094static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1114 double dest;1095 return zig_div_trunc_i128(lhs, rhs) - (((lhs ^ rhs) & zig_rem_i128(lhs, rhs)) < zig_as_i128(0, 0));
1115 memcpy(&dest, &arg, sizeof dest);
1116 return dest;
1117}1096}
11181097
1119#define zig_add_sat_u(ZT, T) static inline T zig_adds_##ZT(T x, T y, T max) { \1098static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1120 return (x > max - y) ? max : x + y; \1099 zig_i128 rem = zig_rem_i128(lhs, rhs);
1121}1100 return rem + (((lhs ^ rhs) & rem) < zig_as_i128(0, 0) ? rhs : zig_as_i128(0, 0));
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; \
1143}1101}
11441102
1145#define zig_sub_sat_s(ZT, T, T2) static inline T zig_subs_##ZT(T2 x, T2 y, T2 min, T2 max) { \1103#else /* zig_has_int128 */
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
11631104
1164#define zig_mul_sat_u(ZT, T, T2) static inline T zig_muls_##ZT(T2 x, T2 y, T2 max) { \1105static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1165 T2 res = x * y; \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)) };
1166 return (res > max) ? max : res; \
1167}1107}
11681108
1169#define zig_mul_sat_s(ZT, T, T2) static inline T zig_muls_##ZT(T2 x, T2 y, T2 min, T2 max) { \1109static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1170 T2 res = x * y; \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)) };
1171 return (res < min) ? min : (res > max) ? max : res; \
1172}1111}
11731112
1174zig_mul_sat_u(u8, uint8_t, uint16_t)1113static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1175zig_mul_sat_s(i8, int8_t, int16_t)1114 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1176zig_mul_sat_u(u16, uint16_t, uint32_t)1115 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1177zig_mul_sat_s(i16, int16_t, int32_t)1116}
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)
11861117
1187#define zig_shl_sat_u(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T max) { \1118static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1188 if(x == 0) return 0; \1119 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1189 T bits_set = 64 - __builtin_clzll(x); \1120 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1190 return (bits_set + y > bits) ? max : x << y; \
1191}1121}
11921122
1193#define zig_shl_sat_s(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T min, T max) { \1123static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1194 if(x == 0) return 0; \1124 if (rhs >= zig_as_u8(64)) return (zig_i128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1195 T x_twos_comp = x < 0 ? -x : x; \1125 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
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; \
1199}1126}
12001127
1201zig_shl_sat_u(u8, uint8_t, 8)1128static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
1202zig_shl_sat_s(i8, int8_t, 7)1129 zig_u128 res;
1203zig_shl_sat_u(u16, uint16_t, 16)1130 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1204zig_shl_sat_s(i16, int16_t, 15)1131 return res;
1205zig_shl_sat_u(u32, uint32_t, 32)1132}
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))
12131133
1214#define zig_bitsizeof(T) (CHAR_BIT * sizeof(T))1134static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
1215#define zig_bit_mask(T, bit_width) \1135 zig_i128 res;
1216 ((bit_width) == zig_bitsizeof(T) \1136 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1217 ? ((T)-1) \1137 return res;
1218 : (((T)1 << (T)(bit_width)) - 1))1138}
12191139
1220static inline int zig_clz(unsigned int value, uint8_t zig_type_bit_width) {1140static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
1221 if (value == 0) return zig_type_bit_width;1141 zig_u128 res;
1222 return __builtin_clz(value) - zig_bitsizeof(unsigned int) + zig_type_bit_width;1142 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1143 return res;
1223}1144}
12241145
1225static inline int zig_clzl(unsigned long value, uint8_t zig_type_bit_width) {1146static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1226 if (value == 0) return zig_type_bit_width;1147 zig_i128 res;
1227 return __builtin_clzl(value) - zig_bitsizeof(unsigned long) + zig_type_bit_width;1148 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1149 return res;
1228}1150}
12291151
1230static inline int zig_clzll(unsigned long long value, uint8_t zig_type_bit_width) {1152static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1231 if (value == 0) return zig_type_bit_width;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));
1232 return __builtin_clzll(value) - zig_bitsizeof(unsigned long long) + zig_type_bit_width;
1233}1154}
12341155
1235#define zig_clz_u8 zig_clz1156static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1236#define zig_clz_i8 zig_clz1157 zig_i128 rem = zig_rem_i128(lhs, rhs);
1237#define zig_clz_u16 zig_clz1158 return rem + (((lhs.hi ^ rhs.hi) & rem.hi) < zig_as_i64(0) ? rhs : zig_as_i128(0, 0));
1238#define zig_clz_i16 zig_clz1159}
1239#define zig_clz_u32 zig_clzl1160
1240#define zig_clz_i32 zig_clzl1161#endif /* zig_has_int128 */
1241#define zig_clz_u64 zig_clzll1162
1242#define zig_clz_i64 zig_clzll1163#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) {1166static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
1245 if (value == 0) return zig_type_bit_width;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);
1246 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);1168 return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
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;
1252}1169}
12531170
1254#define zig_clz_i128 zig_clz_u1281171static 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) {1175static inline zig_i128 zig_wrap_i128(zig_i128 val, zig_u8 bits) {
1257 if (value == 0) return zig_type_bit_width;1176 return zig_as_i128(zig_wrap_i64(zig_hi_i128(val), bits - zig_as_u8(64)), zig_lo_i128(val));
1258 return __builtin_ctz(value & zig_bit_mask(unsigned int, zig_type_bit_width));
1259}1177}
12601178
1261static inline int zig_ctzl(unsigned long value, uint8_t zig_type_bit_width) {1179static inline zig_u128 zig_shlw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1262 if (value == 0) return zig_type_bit_width;1180 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
1263 return __builtin_ctzl(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1264}1181}
12651182
1266static inline int zig_ctzll(unsigned long value, uint8_t zig_type_bit_width) {1183static inline zig_i128 zig_shlw_i128(zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1267 if (value == 0) return zig_type_bit_width;1184 return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1268 return __builtin_ctzll(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1269}1185}
12701186
1271#define zig_ctz_u8 zig_ctz1187static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1272#define zig_ctz_i8 zig_ctz1188 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
1273#define zig_ctz_u16 zig_ctz1189}
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
12791190
1280static inline int zig_ctz_u128(uint128_t value, uint8_t zig_type_bit_width) {1191static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1281 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);1192 return zig_wrap_i128(zig_bitcast_i128(zig_add_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
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));
1285}1193}
12861194
1287#define zig_ctz_i128 zig_ctz_u1281195static 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) {1199static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1290 return __builtin_popcount(value & zig_bit_mask(unsigned int, zig_type_bit_width));1200 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1291}1201}
12921202
1293static inline int zig_popcountl(unsigned long value, uint8_t zig_type_bit_width) {1203static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1294 return __builtin_popcountl(value & zig_bit_mask(unsigned long, zig_type_bit_width));1204 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
1295}1205}
12961206
1297static inline int zig_popcountll(unsigned long value, uint8_t zig_type_bit_width) {1207static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1298 return __builtin_popcountll(value & zig_bit_mask(unsigned long, zig_type_bit_width));1208 return zig_wrap_i128(zig_bitcast_i128(zig_mul_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1299}1209}
13001210
1301#define zig_popcount_u8 zig_popcount1211#if zig_has_int128
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
13091212
1310static inline int zig_popcount_u128(uint128_t value, uint8_t zig_type_bit_width) {1213static inline zig_bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1311 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);1214 *res = zig_shlw_u128(lhs, rhs, bits);
1312 const uint64_t hi = (value & mask) >> 64;1215 return zig_and_u128(lhs, zig_shl_u128(zig_maxInt_u128, bits - rhs)) != zig_as_u128(0, 0);
1313 const uint64_t lo = (value & mask);
1314 return __builtin_popcountll(hi) + __builtin_popcountll(lo);
1315}1216}
13161217
1317#define zig_popcount_i128 zig_popcount_u1281218static 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) {1225static inline zig_bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1320 *res = lhs << rhs;1226#if zig_has_builtin(add_overflow)
1321 if (zig_clz_i8(lhs, bits) >= rhs) return false;1227 zig_u128 full_res;
1322 *res &= UINT8_MAX >> (8 - bits);1228 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1323 return true;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
1324}1235}
13251236
1326static inline bool zig_shlo_i16(int16_t lhs, int16_t rhs, int16_t *res, uint8_t bits) {1237zig_extern_c zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1327 *res = lhs << rhs;1238static inline zig_bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1328 if (zig_clz_i16(lhs, bits) >= rhs) return false;1239#if zig_has_builtin(add_overflow)
1329 *res &= UINT16_MAX >> (16 - bits);1240 zig_i128 full_res;
1330 return true;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);
1331}1249}
13321250
1333static inline bool zig_shlo_i32(int32_t lhs, int32_t rhs, int32_t *res, uint8_t bits) {1251static inline zig_bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1334 *res = lhs << rhs;1252#if zig_has_builtin(sub_overflow)
1335 if (zig_clz_i32(lhs, bits) >= rhs) return false;1253 zig_u128 full_res;
1336 *res &= UINT32_MAX >> (32 - bits);1254 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1337 return true;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
1338}1261}
13391262
1340static inline bool zig_shlo_i64(int64_t lhs, int64_t rhs, int64_t *res, uint8_t bits) {1263zig_extern_c zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1341 *res = lhs << rhs;1264static inline zig_bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1342 if (zig_clz_i64(lhs, bits) >= rhs) return false;1265#if zig_has_builtin(sub_overflow)
1343 *res &= UINT64_MAX >> (64 - bits);1266 zig_i128 full_res;
1344 return true;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);
1345}1275}
13461276
1347static inline bool zig_shlo_i128(int128_t lhs, int128_t rhs, int128_t *res, uint8_t bits) {1277static inline zig_bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1348 *res = lhs << rhs;1278#if zig_has_builtin(mul_overflow)
1349 if (zig_clz_i128(lhs, bits) >= rhs) return false;1279 zig_u128 full_res;
1350 *res &= UINT128_MAX >> (128 - bits);1280 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1351 return true;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
1352}1287}
13531288
1354static inline bool zig_shlo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t bits) {1289zig_extern_c zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1355 *res = lhs << rhs;1290static inline zig_bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1356 if (zig_clz_u8(lhs, bits) >= rhs) return false;1291#if zig_has_builtin(mul_overflow)
1357 *res &= UINT8_MAX >> (8 - bits);1292 zig_i128 full_res;
1358 return true;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);
1359}1301}
13601302
1361static inline uint16_t zig_shlo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint8_t bits) {1303#else /* zig_has_int128 */
1362 *res = lhs << rhs;1304
1363 if (zig_clz_u16(lhs, bits) >= rhs) return false;1305static inline zig_bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
1364 *res &= UINT16_MAX >> (16 - bits);1306 return zig_addo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
1365 return true;1307 zig_addo_u64(&res->hi, res->hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
1366}1308}
13671309
1368static inline uint32_t zig_shlo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint8_t bits) {1310static inline zig_bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
1369 *res = lhs << rhs;1311 return zig_subo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
1370 if (zig_clz_u32(lhs, bits) >= rhs) return false;1312 zig_subo_u64(&res->hi, res->hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
1371 *res &= UINT32_MAX >> (32 - bits);
1372 return true;
1373}1313}
13741314
1375static inline uint64_t zig_shlo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint8_t bits) {1315#endif /* zig_has_int128 */
1376 *res = lhs << rhs;1316
1377 if (zig_clz_u64(lhs, bits) >= rhs) return false;1317static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1378 *res &= UINT64_MAX >> (64 - bits);1318 zig_u128 res;
1379 return true;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;
1380}1322}
13811323
1382static inline uint128_t zig_shlo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint8_t bits) {1324static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1383 *res = lhs << rhs;1325 zig_i128 res;
1384 if (zig_clz_u128(lhs, bits) >= rhs) return false;1326 if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_as_u128(0, bits)) < 0 && !zig_shlo_i128(&res, lhs, rhs, bits)) return res;
1385 *res &= UINT128_MAX >> (128 - bits);1327 return zig_cmp_i128(lhs, zig_as_i128(0, 0)) < 0 ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1386 return true;
1387}1328}
13881329
1389#define zig_sign_extend(T) \1330static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1390 static inline T zig_sign_extend_##T(T value, uint8_t zig_type_bit_width) { \1331 zig_u128 res;
1391 const T m = (T)1 << (T)(zig_type_bit_width - 1); \1332 return zig_addo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1392 return (value ^ m) - m; \1333}
1393 }
13941334
1395zig_sign_extend(uint8_t)1335static inline zig_i128 zig_adds_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1396zig_sign_extend(uint16_t)1336 zig_i128 res;
1397zig_sign_extend(uint32_t)1337 if (!zig_addo_i128(&res, lhs, rhs, bits)) return res;
1398zig_sign_extend(uint64_t)1338 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= 0 ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1399zig_sign_extend(uint128_t)1339}
14001340
1401#define zig_byte_swap_u(ZigTypeBits, CTypeBits) \1341static inline zig_u128 zig_subs_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1402 static inline uint##CTypeBits##_t zig_byte_swap_u##ZigTypeBits(uint##CTypeBits##_t value, uint8_t zig_type_bit_width) { \1342 zig_u128 res;
1403 return __builtin_bswap##CTypeBits(value) >> (CTypeBits - zig_type_bit_width); \1343 return zig_subo_u128(&res, lhs, rhs, bits) ? zig_minInt(u128, bits) : res;
1404 }1344}
14051345
1406#define zig_byte_swap_s(ZigTypeBits, CTypeBits) \1346static inline zig_i128 zig_subs_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1407 static inline int##CTypeBits##_t zig_byte_swap_i##ZigTypeBits(int##CTypeBits##_t value, uint8_t zig_type_bit_width) { \1347 zig_i128 res;
1408 const uint##CTypeBits##_t swapped = zig_byte_swap_u##ZigTypeBits(value, zig_type_bit_width); \1348 if (!zig_subo_i128(&res, lhs, rhs, bits)) return res;
1409 return zig_sign_extend_uint##CTypeBits##_t(swapped, zig_type_bit_width); \1349 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= 0 ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1410 }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) \1401static inline zig_i128 zig_byte_swap_i128(zig_i128 val, zig_u8 bits) {
1413 zig_byte_swap_u(ZigTypeBits, CTypeBits) \1402 return zig_byte_swap_u128(zig_bitcast_u128(val), bits);
1414 zig_byte_swap_s(ZigTypeBits, CTypeBits)1403}
14151404
1416zig_byte_swap( 8, 16)1405static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {
1417zig_byte_swap(16, 16)1406 return zig_shr_u128(zig_as_u128(zig_bit_reverse_u64(zig_lo_u128(val), zig_as_u8(64)),
1418zig_byte_swap(32, 32)1407 zig_bit_reverse_u64(zig_hi_u128(val), zig_as_u8(64))),
1419zig_byte_swap(64, 64)1408 zig_as_u8(128) - bits);
14201409}
1421static inline uint128_t zig_byte_swap_u128(uint128_t value, uint8_t zig_type_bit_width) {1410
1422 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);1411static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
1423 const uint128_t hi = __builtin_bswap64((uint64_t)(value >> 64));1412 return zig_bit_reverse_u128(zig_bitcast_u128(val), bits);
1424 const uint128_t lo = __builtin_bswap64((uint64_t)value);1413}
1425 return (((lo << 64 | hi) >> (128 - zig_type_bit_width))) & mask;1414
1426}1415/* ========================== Float Point Routines ========================== */
14271416
1428zig_byte_swap_s(128, 128)1417static inline zig_f32 zig_bitcast_f32_u32(zig_u32 arg) {
14291418 zig_f32 dest;
1430static const uint8_t zig_bit_reverse_lut[256] = {1419 memcpy(&dest, &arg, sizeof dest);
1431 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,1420 return dest;
1432 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,1421}
1433 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,1422
1434 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,1423static inline zig_f64 zig_bitcast_f64_u64(zig_u64 arg) {
1435 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,1424 zig_f64 dest;
1436 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,1425 memcpy(&dest, &arg, sizeof dest);
1437 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,1426 return dest;
1438 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,1427}
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
15311428
1532static inline float zig_div_truncf(float numerator, float denominator) {1429static inline float zig_div_truncf(float numerator, float denominator) {
1533 return __builtin_truncf(numerator / denominator);1430 return __builtin_truncf(numerator / denominator);
...@@ -1562,17 +1459,6 @@ static inline long double zig_div_truncl(long double numerator, long double deno...@@ -1562,17 +1459,6 @@ static inline long double zig_div_truncl(long double numerator, long double deno
1562#define zig_div_floor_f80 zig_div_floorl1459#define zig_div_floor_f80 zig_div_floorl
1563#define zig_div_floor_f128 zig_div_floorl1460#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
1576static inline float zig_modf(float numerator, float denominator) {1462static inline float zig_modf(float numerator, float denominator) {
1577 return (numerator - (zig_div_floorf(numerator, denominator) * denominator));1463 return (numerator - (zig_div_floorf(numerator, denominator) * denominator));
1578}1464}
...@@ -1590,19 +1476,3 @@ static inline long double zig_modl(long double numerator, long double denominato...@@ -1590,19 +1476,3 @@ static inline long double zig_modl(long double numerator, long double denominato
1590#define zig_mod_f64 zig_mod1476#define zig_mod_f64 zig_mod
1591#define zig_mod_f80 zig_modl1477#define zig_mod_f80 zig_modl
1592#define zig_mod_f128 zig_modl1478#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 {...@@ -72,6 +72,12 @@ const ValueRenderLocation = enum {
72 Other,72 Other,
73};73};
7474
75const BuiltinInfo = enum {
76 None,
77 Range,
78 Bits,
79};
80
75/// TODO make this not cut off at 128 bytes81/// TODO make this not cut off at 128 bytes
76fn formatTypeAsCIdentifier(82fn formatTypeAsCIdentifier(
77 data: FormatTypeAsCIdentContext,83 data: FormatTypeAsCIdentContext,
...@@ -323,6 +329,33 @@ pub const Function = struct {...@@ -323,6 +329,33 @@ pub const Function = struct {
323 }329 }
324 }330 }
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
326 fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {359 fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
327 return f.object.dg.fail(format, args);360 return f.object.dg.fail(format, args);
328 }361 }
...@@ -339,16 +372,63 @@ pub const Function = struct {...@@ -339,16 +372,63 @@ pub const Function = struct {
339 return f.object.dg.fmtIntLiteral(ty, val);372 return f.object.dg.fmtIntLiteral(ty, val);
340 }373 }
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 {
343 const target = f.object.dg.module.getTarget();424 const target = f.object.dg.module.getTarget();
344 const float_bits = float_ty.floatBits(target);425 const float_bits = float_ty.floatBits(target);
345 const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);426 const is_longdouble = float_bits == CType.longdouble.sizeInBits(target);
346 const writer = f.object.writer();
347 try writer.writeAll("__");427 try writer.writeAll("__");
348 if (is_longdouble or float_bits != 80) {428 if (is_longdouble or float_bits != 80) {
349 try writer.writeAll("builtin_");429 try writer.writeAll("builtin_");
350 }430 }
351 try writer.writeAll(fn_name);431 try writer.writeAll(operation);
352 if (is_longdouble) {432 if (is_longdouble) {
353 try writer.writeByte('l');433 try writer.writeByte('l');
354 } else switch (float_bits) {434 } else switch (float_bits) {
...@@ -558,9 +638,8 @@ pub const DeclGen = struct {...@@ -558,9 +638,8 @@ pub const DeclGen = struct {
558 const target = dg.module.getTarget();638 const target = dg.module.getTarget();
559 if (val.isUndefDeep()) {639 if (val.isUndefDeep()) {
560 switch (ty.zigTypeTag()) {640 switch (ty.zigTypeTag()) {
561 // Using '{}' for integer and floats seemed to error C compilers (both GCC and Clang)641 // bool b = 0xaa; evals to true, but memcpy(&b, 0xaa, 1); evals to false.
562 // with 'error: expected expression' (including when built with 'zig cc')642 .Bool => return dg.renderValue(writer, ty, Value.@"false", location),
563 .Bool => return writer.writeAll("false"),
564 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),643 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),
565 .Float => switch (ty.tag()) {644 .Float => switch (ty.tag()) {
566 .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{645 .f32 => return writer.print("zig_bitcast_f32_u32({x})", .{
...@@ -839,15 +918,14 @@ pub const DeclGen = struct {...@@ -839,15 +918,14 @@ pub const DeclGen = struct {
839 },918 },
840 }919 }
841 },920 },
842 .Bool => return writer.print("{}", .{val.toBool()}),921 .Bool => return writer.print("zig_{}", .{val.toBool()}),
843 .Optional => {922 .Optional => {
844 var opt_buf: Type.Payload.ElemType = undefined;923 var opt_buf: Type.Payload.ElemType = undefined;
845 const payload_ty = ty.optionalChild(&opt_buf);924 const payload_ty = ty.optionalChild(&opt_buf);
846925
847 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {926 const is_null_val = Value.makeBool(val.tag() == .null_value);
848 const is_null = val.castTag(.opt_payload) == null;927 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
849 return writer.print("{}", .{is_null});928 return dg.renderValue(writer, Type.bool, is_null_val, location);
850 }
851929
852 if (ty.optionalReprIsPayload()) {930 if (ty.optionalReprIsPayload()) {
853 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val;931 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val;
...@@ -864,21 +942,17 @@ pub const DeclGen = struct {...@@ -864,21 +942,17 @@ pub const DeclGen = struct {
864942
865 try writer.writeAll("{ .payload = ");943 try writer.writeAll("{ .payload = ");
866 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);944 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(" }");
868 },948 },
869 .ErrorSet => {949 .ErrorSet => {
870 switch (val.tag()) {950 const error_name = if (val.castTag(.@"error")) |error_pl|
871 .@"error" => {951 error_pl.data.name
872 const payload = val.castTag(.@"error").?;952 else
873 // error values will be #defined at the top of the file953 dg.module.error_name_list.items[0];
874 return writer.print("zig_error_{s}", .{fmtIdent(payload.data.name)});954 // Error values are already defined by genErrDecls.
875 },955 try writer.print("zig_error_{}", .{fmtIdent(error_name)});
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 }
882 },956 },
883 .ErrorUnion => {957 .ErrorUnion => {
884 const error_ty = ty.errorUnionSet();958 const error_ty = ty.errorUnionSet();
...@@ -897,7 +971,7 @@ pub const DeclGen = struct {...@@ -897,7 +971,7 @@ pub const DeclGen = struct {
897 }971 }
898972
899 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;973 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
902 try writer.writeAll("{ .payload = ");976 try writer.writeAll("{ .payload = ");
903 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);977 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);
...@@ -1026,24 +1100,14 @@ pub const DeclGen = struct {...@@ -1026,24 +1100,14 @@ pub const DeclGen = struct {
10261100
1027 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void {1101 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void {
1028 const fn_info = dg.decl.ty.fnInfo();1102 const fn_info = dg.decl.ty.fnInfo();
1029 if (fn_info.cc == .Naked) {1103 if (fn_info.cc == .Naked) try w.writeAll("zig_naked ");
1030 try w.writeAll("ZIG_NAKED ");1104 if (dg.decl.val.castTag(.function)) |func_payload|
1031 }1105 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1032 if (dg.decl.val.castTag(.function)) |func_payload| {1106 const ret_ty = fn_info.return_type;
1033 const func: *Module.Fn = func_payload.data;1107 try dg.renderType(w, if (ret_ty.tag() == .noreturn or ret_ty.hasRuntimeBitsIgnoreComptime())
1034 if (func.is_cold) {1108 ret_ty
1035 try w.writeAll("ZIG_COLD ");1109 else
1036 }1110 Type.void, kind);
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 }
1047 try w.writeByte(' ');1111 try w.writeByte(' ');
1048 try dg.renderDeclName(w, dg.decl_index);1112 try dg.renderDeclName(w, dg.decl_index);
1049 try w.writeByte('(');1113 try w.writeByte('(');
...@@ -1051,9 +1115,7 @@ pub const DeclGen = struct {...@@ -1051,9 +1115,7 @@ pub const DeclGen = struct {
1051 var index: usize = 0;1115 var index: usize = 0;
1052 for (fn_info.param_types) |param_type| {1116 for (fn_info.param_types) |param_type| {
1053 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;1117 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1054 if (index > 0) {1118 if (index > 0) try w.writeAll(", ");
1055 try w.writeAll(", ");
1056 }
1057 const name = CValue{ .arg = index };1119 const name = CValue{ .arg = index };
1058 try dg.renderTypeAndName(w, param_type, name, .Const, 0, kind);1120 try dg.renderTypeAndName(w, param_type, name, .Const, 0, kind);
1059 index += 1;1121 index += 1;
...@@ -1063,7 +1125,7 @@ pub const DeclGen = struct {...@@ -1063,7 +1125,7 @@ pub const DeclGen = struct {
1063 if (index > 0) try w.writeAll(", ");1125 if (index > 0) try w.writeAll(", ");
1064 try w.writeAll("...");1126 try w.writeAll("...");
1065 } else if (index == 0) {1127 } else if (index == 0) {
1066 try w.writeAll("void");1128 try dg.renderType(w, Type.void, kind);
1067 }1129 }
1068 try w.writeByte(')');1130 try w.writeByte(')');
1069 }1131 }
...@@ -1102,7 +1164,7 @@ pub const DeclGen = struct {...@@ -1102,7 +1164,7 @@ pub const DeclGen = struct {
1102 if (params_written != 0) try bw.writeAll(", ");1164 if (params_written != 0) try bw.writeAll(", ");
1103 try bw.writeAll("...");1165 try bw.writeAll("...");
1104 } else if (params_written == 0) {1166 } else if (params_written == 0) {
1105 try bw.writeAll("void");1167 try dg.renderType(bw, Type.void, .Forward);
1106 }1168 }
1107 try bw.writeAll(");\n");1169 try bw.writeAll(");\n");
11081170
...@@ -1126,14 +1188,18 @@ pub const DeclGen = struct {...@@ -1126,14 +1188,18 @@ pub const DeclGen = struct {
1126 defer buffer.deinit();1188 defer buffer.deinit();
1127 const bw = buffer.writer();1189 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;1197 try bw.writeAll("typedef struct {\n ");
1132 const ptr_type = t.slicePtrFieldType(&ptr_type_buf);1198 try dg.renderTypeAndName(bw, ptr_ty, ptr_name, .Mut, 0, .Complete);
1133 const ptr_name = CValue{ .bytes = "ptr" };1199 try bw.writeAll(";\n ");
1134 try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0, .Complete);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} ");
1137 const name_begin = buffer.items.len;1203 const name_begin = buffer.items.len;
1138 try bw.print("zig_{c}_{}", .{1204 try bw.print("zig_{c}_{}", .{
1139 @as(u8, if (t.isConstPtr()) 'L' else 'M'),1205 @as(u8, if (t.isConstPtr()) 'L' else 'M'),
...@@ -1339,27 +1405,31 @@ pub const DeclGen = struct {...@@ -1339,27 +1405,31 @@ pub const DeclGen = struct {
1339 }1405 }
13401406
1341 fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1407 fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1342 const payload_ty = t.errorUnionPayload();
1343 assert(t.errorUnionSet().tag() == .anyerror);1408 assert(t.errorUnionSet().tag() == .anyerror);
13441409
1345 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);1410 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1346 defer buffer.deinit();1411 defer buffer.deinit();
1347 const bw = buffer.writer();1412 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
1350 const target = dg.module.getTarget();1419 const target = dg.module.getTarget();
1351 const payload_align = payload_ty.abiAlignment(target);1420 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 ");
1353 if (error_align > payload_align) {1423 if (error_align > payload_align) {
1354 try bw.writeAll("typedef struct { ");
1355 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);1424 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);
1357 } else {1427 } 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 ");
1359 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);1430 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1360 try bw.writeAll("; } ");
1361 }1431 }
13621432 try bw.writeAll(";\n} ");
1363 const name_begin = buffer.items.len;1433 const name_begin = buffer.items.len;
1364 try bw.print("zig_E_{}", .{typeToCIdentifier(payload_ty, dg.module)});1434 try bw.print("zig_E_{}", .{typeToCIdentifier(payload_ty, dg.module)});
1365 const name_end = buffer.items.len;1435 const name_end = buffer.items.len;
...@@ -1413,11 +1483,11 @@ pub const DeclGen = struct {...@@ -1413,11 +1483,11 @@ pub const DeclGen = struct {
1413 defer buffer.deinit();1483 defer buffer.deinit();
1414 const bw = buffer.writer();1484 const bw = buffer.writer();
14151485
1416 try bw.writeAll("typedef struct { ");1486 try bw.writeAll("typedef struct {\n ");
1417 const payload_name = CValue{ .bytes = "payload" };1487 try dg.renderTypeAndName(bw, child_type, .{ .identifier = "payload" }, .Mut, 0, .Complete);
1418 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0, .Complete);1488 try bw.writeAll(";\n ");
1419 try bw.writeAll("; bool is_null; } ");1489 try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete);
14201490 try bw.writeAll("; } ");
1421 const name_begin = buffer.items.len;1491 const name_begin = buffer.items.len;
1422 try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)});1492 try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)});
1423 const name_end = buffer.items.len;1493 const name_end = buffer.items.len;
...@@ -1486,51 +1556,20 @@ pub const DeclGen = struct {...@@ -1486,51 +1556,20 @@ pub const DeclGen = struct {
1486 const target = dg.module.getTarget();1556 const target = dg.module.getTarget();
14871557
1488 switch (t.zigTypeTag()) {1558 switch (t.zigTypeTag()) {
1489 .NoReturn, .Void => try w.writeAll("void"),1559 .NoReturn, .Void, .Bool, .Int, .Float, .ErrorSet => |tag| {
1490 .Bool => try w.writeAll("bool"),1560 const is_named = switch (tag) {
1491 .Int => {1561 .Int => t.isNamedInt(),
1492 switch (t.tag()) {1562 .ErrorSet => false,
1493 .u1, .u8 => try w.writeAll("uint8_t"),1563 else => true,
1494 .i8 => try w.writeAll("int8_t"),1564 };
1495 .u16 => try w.writeAll("uint16_t"),1565 if (is_named) {
1496 .i16 => try w.writeAll("int16_t"),1566 try w.writeAll("zig_");
1497 .u32 => try w.writeAll("uint32_t"),1567 try t.print(w, dg.module);
1498 .i32 => try w.writeAll("int32_t"),1568 } else {
1499 .u64 => try w.writeAll("uint64_t"),1569 const info = t.intInfo(target);
1500 .i64 => try w.writeAll("int64_t"),1570 const c_bits = toCIntBits(info.bits) orelse
1501 .u128 => try w.writeAll("uint128_t"),1571 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
1502 .i128 => try w.writeAll("int128_t"),1572 try w.print("zig_{c}{d}", .{ signAbbrev(info.signedness), c_bits });
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,
1534 }1573 }
1535 },1574 },
1536 .Pointer => {1575 .Pointer => {
...@@ -1564,9 +1603,10 @@ pub const DeclGen = struct {...@@ -1564,9 +1603,10 @@ pub const DeclGen = struct {
1564 // u8 and i8 produce unsigned char and signed char respectively,1603 // u8 and i8 produce unsigned char and signed char respectively,
1565 // which in C are (not very usefully) different than char.1604 // which in C are (not very usefully) different than char.
1566 try w.writeAll("char");1605 try w.writeAll("char");
1567 } else {1606 } else try dg.renderType(w, switch (child_ty.tag()) {
1568 try dg.renderType(w, child_ty, .Forward);1607 .anyopaque => Type.void,
1569 }1608 else => child_ty,
1609 }, .Forward);
1570 if (t.isConstPtr()) try w.writeAll(" const");1610 if (t.isConstPtr()) try w.writeAll(" const");
1571 if (t.isVolatilePtr()) try w.writeAll(" volatile");1611 if (t.isVolatilePtr()) try w.writeAll(" volatile");
1572 return w.writeAll(" *");1612 return w.writeAll(" *");
...@@ -1587,29 +1627,22 @@ pub const DeclGen = struct {...@@ -1587,29 +1627,22 @@ pub const DeclGen = struct {
1587 var opt_buf: Type.Payload.ElemType = undefined;1627 var opt_buf: Type.Payload.ElemType = undefined;
1588 const child_type = t.optionalChild(&opt_buf);1628 const child_type = t.optionalChild(&opt_buf);
15891629
1590 if (!child_type.hasRuntimeBitsIgnoreComptime()) {1630 if (!child_type.hasRuntimeBitsIgnoreComptime())
1591 return w.writeAll("bool");1631 return dg.renderType(w, Type.bool, kind);
1592 }
15931632
1594 if (t.optionalReprIsPayload()) {1633 if (t.optionalReprIsPayload())
1595 return dg.renderType(w, child_type, .Complete);1634 return dg.renderType(w, child_type, kind);
1596 }
15971635
1598 const name = dg.getTypedefName(t) orelse1636 const name = dg.getTypedefName(t) orelse
1599 try dg.renderOptionalTypedef(t, child_type);1637 try dg.renderOptionalTypedef(t, child_type);
16001638
1601 return w.writeAll(name);1639 return w.writeAll(name);
1602 },1640 },
1603 .ErrorSet => {
1604 comptime assert(Type.anyerror.abiSize(builtin.target) == 2);
1605 return w.writeAll("uint16_t");
1606 },
1607 .ErrorUnion => {1641 .ErrorUnion => {
1608 const payload_ty = t.errorUnionPayload();1642 const payload_ty = t.errorUnionPayload();
16091643
1610 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {1644 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
1611 return dg.renderType(w, Type.anyerror, .Complete);1645 return dg.renderType(w, Type.anyerror, kind);
1612 }
16131646
1614 var error_union_pl = Type.Payload.ErrorUnion{1647 var error_union_pl = Type.Payload.ErrorUnion{
1615 .data = .{ .error_set = Type.anyerror, .payload = payload_ty },1648 .data = .{ .error_set = Type.anyerror, .payload = payload_ty },
...@@ -1652,7 +1685,6 @@ pub const DeclGen = struct {...@@ -1652,7 +1685,6 @@ pub const DeclGen = struct {
1652 try dg.renderType(w, int_tag_ty, kind);1685 try dg.renderType(w, int_tag_ty, kind);
1653 },1686 },
1654 .Opaque => switch (t.tag()) {1687 .Opaque => switch (t.tag()) {
1655 .anyopaque => try w.writeAll("void"),
1656 .@"opaque" => {1688 .@"opaque" => {
1657 const name = dg.getTypedefName(t) orelse1689 const name = dg.getTypedefName(t) orelse
1658 try dg.renderOpaqueTypedef(t);1690 try dg.renderOpaqueTypedef(t);
...@@ -1695,13 +1727,8 @@ pub const DeclGen = struct {...@@ -1695,13 +1727,8 @@ pub const DeclGen = struct {
1695 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |1727 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
1696 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |1728 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
1697 ///1729 ///
1698 fn renderTypecast(1730 fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void {
1699 dg: *DeclGen,1731 return renderTypeAndName(dg, w, ty, .{ .bytes = "" }, .Mut, 0, .Complete);
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);
1705 }1732 }
17061733
1707 /// Renders a type and name in field declaration/definition format.1734 /// Renders a type and name in field declaration/definition format.
...@@ -1735,8 +1762,9 @@ pub const DeclGen = struct {...@@ -1735,8 +1762,9 @@ pub const DeclGen = struct {
1735 render_ty = render_ty.elemType();1762 render_ty = render_ty.elemType();
1736 }1763 }
17371764
1738 if (alignment != 0)1765 if (alignment != 0 and alignment > ty.abiAlignment(dg.module.getTarget())) {
1739 try w.print("ZIG_ALIGN({}) ", .{alignment});1766 try w.print("zig_align({}) ", .{alignment});
1767 }
1740 try dg.renderType(w, render_ty, kind);1768 try dg.renderType(w, render_ty, kind);
17411769
1742 const const_prefix = switch (mutability) {1770 const const_prefix = switch (mutability) {
...@@ -1792,13 +1820,16 @@ pub const DeclGen = struct {...@@ -1792,13 +1820,16 @@ pub const DeclGen = struct {
1792 try buffer.appendSlice(";\n return (");1820 try buffer.appendSlice(";\n return (");
1793 try dg.renderTypecast(bw, name_slice_ty);1821 try dg.renderTypecast(bw, name_slice_ty);
1794 try bw.print("){{{}, {}}};\n", .{1822 try bw.print("){{{}, {}}};\n", .{
1795 fmtIdent("name"),1823 fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val),
1796 try dg.fmtIntLiteral(Type.usize, len_val),
1797 });1824 });
17981825
1799 try buffer.appendSlice(" }\n");1826 try buffer.appendSlice(" }\n");
1800 }1827 }
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
1803 const rendered = buffer.toOwnedSlice();1834 const rendered = buffer.toOwnedSlice();
1804 errdefer dg.typedefs.allocator.free(rendered);1835 errdefer dg.typedefs.allocator.free(rendered);
...@@ -1874,6 +1905,27 @@ pub const DeclGen = struct {...@@ -1874,6 +1905,27 @@ pub const DeclGen = struct {
1874 }1905 }
1875 }1906 }
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
1877 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index) !void {1929 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index) !void {
1878 const decl = dg.module.declPtr(decl_index);1930 const decl = dg.module.declPtr(decl_index);
1879 dg.module.markDeclAlive(decl);1931 dg.module.markDeclAlive(decl);
...@@ -1971,8 +2023,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -1971,8 +2023,7 @@ pub fn genErrDecls(o: *Object) !void {
1971 const len_val = Value.initPayload(&len_pl.base);2023 const len_val = Value.initPayload(&len_pl.base);
19722024
1973 try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{2025 try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{
1974 fmtIdent(name),2026 fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val),
1975 try o.dg.fmtIntLiteral(Type.usize, len_val),
1976 });2027 });
1977 }2028 }
1978 try writer.writeAll("};\n");2029 try writer.writeAll("};\n");
...@@ -1989,7 +2040,7 @@ pub fn genFunc(f: *Function) !void {...@@ -1989,7 +2040,7 @@ pub fn genFunc(f: *Function) !void {
19892040
1990 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);2041 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);
1991 const fwd_decl_writer = o.dg.fwd_decl.writer();2042 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 ");
1993 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);2044 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
1994 try fwd_decl_writer.writeAll(";\n");2045 try fwd_decl_writer.writeAll(";\n");
19952046
...@@ -2028,7 +2079,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2028,7 +2079,7 @@ pub fn genDecl(o: *Object) !void {
2028 };2079 };
2029 if (tv.val.tag() == .extern_fn) {2080 if (tv.val.tag() == .extern_fn) {
2030 const fwd_decl_writer = o.dg.fwd_decl.writer();2081 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 ");
2032 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);2083 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
2033 try fwd_decl_writer.writeAll(";\n");2084 try fwd_decl_writer.writeAll(";\n");
2034 } else if (tv.val.castTag(.variable)) |var_payload| {2085 } else if (tv.val.castTag(.variable)) |var_payload| {
...@@ -2036,7 +2087,7 @@ pub fn genDecl(o: *Object) !void {...@@ -2036,7 +2087,7 @@ pub fn genDecl(o: *Object) !void {
2036 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;2087 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
2037 const fwd_decl_writer = o.dg.fwd_decl.writer();2088 const fwd_decl_writer = o.dg.fwd_decl.writer();
2038 if (is_global) {2089 if (is_global) {
2039 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");2090 try fwd_decl_writer.writeAll("zig_extern_c ");
2040 }2091 }
2041 if (variable.is_threadlocal) {2092 if (variable.is_threadlocal) {
2042 try fwd_decl_writer.writeAll("zig_threadlocal ");2093 try fwd_decl_writer.writeAll("zig_threadlocal ");
...@@ -2096,7 +2147,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -2096,7 +2147,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
2096 .Fn => {2147 .Fn => {
2097 const is_global = dg.declIsGlobal(tv);2148 const is_global = dg.declIsGlobal(tv);
2098 if (is_global) {2149 if (is_global) {
2099 try writer.writeAll("ZIG_EXTERN_C ");2150 try writer.writeAll("zig_extern_c ");
2100 try dg.renderFunctionSignature(writer, .Complete);2151 try dg.renderFunctionSignature(writer, .Complete);
2101 try dg.fwd_decl.appendSlice(";\n");2152 try dg.fwd_decl.appendSlice(";\n");
2102 }2153 }
...@@ -2124,7 +2175,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2124,7 +2175,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2124 .const_ty => unreachable, // excluded from function bodies2175 .const_ty => unreachable, // excluded from function bodies
2125 .arg => airArg(f),2176 .arg => airArg(f),
21262177
2127 .breakpoint => try airBreakpoint(f),2178 .breakpoint => try airBreakpoint(f.object.writer()),
2128 .ret_addr => try airRetAddr(f, inst),2179 .ret_addr => try airRetAddr(f, inst),
2129 .frame_addr => try airFrameAddress(f, inst),2180 .frame_addr => try airFrameAddress(f, inst),
2130 .unreach => try airUnreach(f),2181 .unreach => try airUnreach(f),
...@@ -2135,10 +2186,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2135,10 +2186,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21352186
2136 // TODO use a different strategy for add, sub, mul, div2187 // TODO use a different strategy for add, sub, mul, div
2137 // that communicates to the optimizer that wrapping is UB.2188 // that communicates to the optimizer that wrapping is UB.
2138 .add => try airBinOp(f, inst, "+"),2189 .add => try airBinOp(f, inst, "+", "add", .None),
2139 .sub => try airBinOp(f, inst, "-"),2190 .sub => try airBinOp(f, inst, "-", "sub", .None),
2140 .mul => try airBinOp(f, inst, "*"),2191 .mul => try airBinOp(f, inst, "*", "mul", .None),
2141 .div_float, .div_exact => try airBinOp(f, inst, "/"),2192 .div_float, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
21422193
2143 .rem => blk: {2194 .rem => blk: {
2144 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2195 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...@@ -2146,9 +2197,9 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2146 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),2197 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2147 // so we only check one.2198 // so we only check one.
2148 break :blk if (lhs_ty.isInt())2199 break :blk if (lhs_ty.isInt())
2149 try airBinOp(f, inst, "%")2200 try airBinOp(f, inst, "%", "rem", .None)
2150 else2201 else
2151 try airBinFloatOp(f, inst, "fmod"); // yes, @rem() => fmod()2202 try airBinFloatOp(f, inst, "fmod");
2152 },2203 },
2153 .div_trunc => blk: {2204 .div_trunc => blk: {
2154 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2205 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...@@ -2156,21 +2207,21 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2156 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),2207 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2157 // so we only check one.2208 // so we only check one.
2158 break :blk if (lhs_ty.isInt())2209 break :blk if (lhs_ty.isInt())
2159 try airBinOp(f, inst, "/")2210 try airBinOp(f, inst, "/", "div_trunc", .None)
2160 else2211 else
2161 try airBinOpBuiltinCall(f, inst, "div_trunc");2212 try airBinBuiltinCall(f, inst, "div_trunc", .None);
2162 },2213 },
2163 .div_floor => try airBinOpBuiltinCall(f, inst, "div_floor"),2214 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
2164 .mod => try airBinOpBuiltinCall(f, inst, "mod"),2215 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
21652216
2166 .addwrap => try airWrapOp(f, inst, "+", "add"),2217 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),
2167 .subwrap => try airWrapOp(f, inst, "-", "sub"),2218 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),
2168 .mulwrap => try airWrapOp(f, inst, "*", "mul"),2219 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),
21692220
2170 .add_sat => try airSatOp(f, inst, "add"),2221 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),
2171 .sub_sat => try airSatOp(f, inst, "sub"),2222 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),
2172 .mul_sat => try airSatOp(f, inst, "mul"),2223 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
2173 .shl_sat => try airSatOp(f, inst, "shl"),2224 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
21742225
2175 .neg => try airNeg(f, inst),2226 .neg => try airNeg(f, inst),
21762227
...@@ -2192,20 +2243,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2192,20 +2243,20 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
21922243
2193 .mul_add => try airMulAdd(f, inst),2244 .mul_add => try airMulAdd(f, inst),
21942245
2195 .add_with_overflow => try airOverflow(f, inst, "add", .range),2246 .add_with_overflow => try airOverflow(f, inst, "add", .Bits),
2196 .sub_with_overflow => try airOverflow(f, inst, "sub", .range),2247 .sub_with_overflow => try airOverflow(f, inst, "sub", .Bits),
2197 .mul_with_overflow => try airOverflow(f, inst, "mul", .range),2248 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),
2198 .shl_with_overflow => try airOverflow(f, inst, "shl", .bits),2249 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),
21992250
2200 .min => try airMinMax(f, inst, '<'),2251 .min => try airMinMax(f, inst, '<'),
2201 .max => try airMinMax(f, inst, '>'),2252 .max => try airMinMax(f, inst, '>'),
22022253
2203 .slice => try airSlice(f, inst),2254 .slice => try airSlice(f, inst),
22042255
2205 .cmp_gt => try airBinOp(f, inst, ">"),2256 .cmp_gt => try airCmpOp(f, inst, ">"),
2206 .cmp_gte => try airBinOp(f, inst, ">="),2257 .cmp_gte => try airCmpOp(f, inst, ">="),
2207 .cmp_lt => try airBinOp(f, inst, "<"),2258 .cmp_lt => try airCmpOp(f, inst, "<"),
2208 .cmp_lte => try airBinOp(f, inst, "<="),2259 .cmp_lte => try airCmpOp(f, inst, "<="),
22092260
2210 .cmp_eq => try airEquality(f, inst, "((", "=="),2261 .cmp_eq => try airEquality(f, inst, "((", "=="),
2211 .cmp_neq => try airEquality(f, inst, "!((", "!="),2262 .cmp_neq => try airEquality(f, inst, "!((", "!="),
...@@ -2214,12 +2265,13 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2214,12 +2265,13 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2214 .cmp_lt_errors_len => return f.fail("TODO: C backend: implement cmp_lt_errors_len", .{}),2265 .cmp_lt_errors_len => return f.fail("TODO: C backend: implement cmp_lt_errors_len", .{}),
22152266
2216 // bool_and and bool_or are non-short-circuit operations2267 // bool_and and bool_or are non-short-circuit operations
2217 .bool_and, .bit_and => try airBinOp(f, inst, "&"),2268 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),
2218 .bool_or, .bit_or => try airBinOp(f, inst, "|"),2269 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),
2219 .xor => try airBinOp(f, inst, "^"),2270 .xor => try airBinOp(f, inst, "^", "xor", .None),
2220 .shr, .shr_exact => try airBinOp(f, inst, ">>"),2271 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),
2221 .shl, .shl_exact => try airBinOp(f, inst, "<<"),2272 .shl, => try airBinBuiltinCall(f, inst, "shl", .None),
2222 .not => try airNot (f, inst),2273 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),
2274 .not => try airNot (f, inst),
22232275
2224 .optional_payload => try airOptionalPayload(f, inst),2276 .optional_payload => try airOptionalPayload(f, inst),
2225 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),2277 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),
...@@ -2263,11 +2315,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -2263,11 +2315,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
2263 .memcpy => try airMemcpy(f, inst),2315 .memcpy => try airMemcpy(f, inst),
2264 .set_union_tag => try airSetUnionTag(f, inst),2316 .set_union_tag => try airSetUnionTag(f, inst),
2265 .get_union_tag => try airGetUnionTag(f, inst),2317 .get_union_tag => try airGetUnionTag(f, inst),
2266 .clz => try airBuiltinCall(f, inst, "clz"),2318 .clz => try airUnBuiltinCall(f, inst, "clz", .Bits),
2267 .ctz => try airBuiltinCall(f, inst, "ctz"),2319 .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits),
2268 .popcount => try airBuiltinCall(f, inst, "popcount"),2320 .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits),
2269 .byte_swap => try airBuiltinCall(f, inst, "byte_swap"),2321 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits),
2270 .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"),2322 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits),
2271 .tag_name => try airTagName(f, inst),2323 .tag_name => try airTagName(f, inst),
2272 .error_name => try airErrorName(f, inst),2324 .error_name => try airErrorName(f, inst),
2273 .splat => try airSplat(f, inst),2325 .splat => try airSplat(f, inst),
...@@ -2393,10 +2445,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [...@@ -2393,10 +2445,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
2393 const writer = f.object.writer();2445 const writer = f.object.writer();
2394 const local = try f.allocLocal(inst_ty, .Const);2446 const local = try f.allocLocal(inst_ty, .Const);
2395 try writer.writeAll(" = ");2447 try writer.writeAll(" = ");
2396 if (is_ptr) try writer.writeByte('&');2448 if (is_ptr) {
2397 try f.writeCValue(writer, operand, .Other);2449 try writer.writeByte('&');
2398 try if (is_ptr) writer.writeAll("->") else writer.writeByte('.');2450 try f.writeCValueDerefMember(writer, operand, .{ .identifier = field_name });
2399 try writer.writeAll(field_name);2451 } else try f.writeCValueMember(writer, operand, .{ .identifier = field_name });
2400 try writer.writeAll(";\n");2452 try writer.writeAll(";\n");
2401 return local;2453 return local;
2402}2454}
...@@ -2752,138 +2804,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2752,138 +2804,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
2752 return CValue.none;2804 return CValue.none;
2753}2805}
27542806
2755fn airWrapOp(f: *Function, inst: Air.Inst.Index, operator: []const u8, fn_name: []const u8) !CValue {2807fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !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 {
2887 if (f.liveness.isUnused(inst))2808 if (f.liveness.isUnused(inst))
2888 return CValue.none;2809 return CValue.none;
28892810
...@@ -2895,54 +2816,29 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, fn_name: []const u8, kind: en...@@ -2895,54 +2816,29 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, fn_name: []const u8, kind: en
28952816
2896 const inst_ty = f.air.typeOfIndex(inst);2817 const inst_ty = f.air.typeOfIndex(inst);
2897 const scalar_ty = f.air.typeOf(bin_op.lhs).scalarType();2818 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);
2900 const w = f.object.writer();2819 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
2904 const local = try f.allocLocal(inst_ty, .Mut);2821 const local = try f.allocLocal(inst_ty, .Mut);
2905 try w.writeAll(";\n");2822 try w.writeAll(";\n");
29062823
2907 try f.writeCValue(w, local, .Other);2824 try f.writeCValue(w, local, .Other);
2908 try w.print(".field_1 = zig_{s}o_{c}{d}(", .{2825 try w.writeAll(".field_1 = zig_");
2909 fn_name, signAbbrev(int_info.signedness), c_bits,2826 try w.writeAll(operation);
2910 });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(", ");
2911 try f.writeCValue(w, lhs, .FunctionArgument);2832 try f.writeCValue(w, lhs, .FunctionArgument);
2912 try w.writeAll(", ");2833 try w.writeAll(", ");
2913 try f.writeCValue(w, rhs, .FunctionArgument);2834 try f.writeCValue(w, rhs, .FunctionArgument);
2914 try w.writeAll(", &");2835 try f.renderBuiltinInfo(w, scalar_ty, info);
2915 try f.writeCValue(w, local, .Other);2836 try w.writeAll(");\n");
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 }
2940 return local;2837 return local;
2941}2838}
29422839
2943fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {2840fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
2944 if (f.liveness.isUnused(inst))2841 if (f.liveness.isUnused(inst)) return CValue.none;
2945 return CValue.none;
29462842
2947 const ty_op = f.air.instructions.items(.data)[inst].ty_op;2843 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
2948 const op = try f.resolveInst(ty_op.operand);2844 const op = try f.resolveInst(ty_op.operand);
...@@ -2951,6 +2847,9 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2951,6 +2847,9 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
2951 const inst_ty = f.air.typeOfIndex(inst);2847 const inst_ty = f.air.typeOfIndex(inst);
2952 const local = try f.allocLocal(inst_ty, .Const);2848 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
2954 try writer.writeAll(" = ");2853 try writer.writeAll(" = ");
2955 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');2854 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');
2956 try f.writeCValue(writer, op, .Other);2855 try f.writeCValue(writer, op, .Other);
...@@ -2959,16 +2858,53 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -2959,16 +2858,53 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
2959 return local;2858 return local;
2960}2859}
29612860
2962fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {2861fn airBinOp(
2963 if (f.liveness.isUnused(inst))2862 f: *Function,
2964 return CValue.none;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
2966 const bin_op = f.air.instructions.items(.data)[inst].bin_op;2870 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);
2967 const lhs = try f.resolveInst(bin_op.lhs);2877 const lhs = try f.resolveInst(bin_op.lhs);
2968 const rhs = try f.resolveInst(bin_op.rhs);2878 const rhs = try f.resolveInst(bin_op.rhs);
29692879
2970 const writer = f.object.writer();2880 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
2971 const inst_ty = f.air.typeOfIndex(inst);2903 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();
2972 const local = try f.allocLocal(inst_ty, .Const);2908 const local = try f.allocLocal(inst_ty, .Const);
29732909
2974 try writer.writeAll(" = ");2910 try writer.writeAll(" = ");
...@@ -3301,27 +3237,19 @@ fn lowerTry(...@@ -3301,27 +3237,19 @@ fn lowerTry(
3301 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();3237 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
33023238
3303 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {3239 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
3304 err: {3240 try writer.writeAll("if (");
3305 if (!payload_has_bits) {3241 if (!payload_has_bits) {
3306 if (operand_is_ptr) {3242 if (operand_is_ptr)
3307 try writer.writeAll("if(*");3243 try f.writeCValueDeref(writer, err_union)
3308 } else {3244 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(");
3317 try f.writeCValue(writer, err_union, .Other);3245 try f.writeCValue(writer, err_union, .Other);
3318 try writer.writeAll("->error)");3246 } else {
3319 break :err;3247 if (operand_is_ptr or isByRef(err_union_ty))
3320 }3248 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "error" })
3321 try writer.writeAll("if(");3249 else
3322 try f.writeCValue(writer, err_union, .Other);3250 try f.writeCValueMember(writer, err_union, .{ .identifier = "error" });
3323 try writer.writeAll(".error)");
3324 }3251 }
3252 try writer.writeByte(')');
33253253
3326 try genBody(f, body);3254 try genBody(f, body);
3327 try f.object.indent_writer.insertNewline();3255 try f.object.indent_writer.insertNewline();
...@@ -3342,20 +3270,17 @@ fn lowerTry(...@@ -3342,20 +3270,17 @@ fn lowerTry(
3342 try writer.writeAll("memcpy(");3270 try writer.writeAll("memcpy(");
3343 try f.writeCValue(writer, local, .FunctionArgument);3271 try f.writeCValue(writer, local, .FunctionArgument);
3344 try writer.writeAll(", ");3272 try writer.writeAll(", ");
3345 try f.writeCValue(writer, err_union, .Other);3273 try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
3346 try writer.writeAll(".payload, sizeof(");3274 try writer.writeAll(", sizeof(");
3347 try f.renderTypecast(writer, payload_ty);3275 try f.renderTypecast(writer, payload_ty);
3348 try writer.writeAll("));\n");3276 try writer.writeAll("));\n");
3349 } else {3277 } else {
3278 try writer.writeAll(" = ");
3350 if (operand_is_ptr or isByRef(payload_ty)) {3279 if (operand_is_ptr or isByRef(payload_ty)) {
3351 try writer.writeAll(" = &");3280 try writer.writeByte('&');
3352 try f.writeCValue(writer, err_union, .Other);3281 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" });
3353 try writer.writeAll("->payload;\n");3282 } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
3354 } else {3283 try writer.writeAll(";\n");
3355 try writer.writeAll(" = ");
3356 try f.writeCValue(writer, err_union, .Other);
3357 try writer.writeAll(".payload;\n");
3358 }
3359 }3284 }
3360 return local;3285 return local;
3361}3286}
...@@ -3415,8 +3340,8 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3415,8 +3340,8 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
3415 return local;3340 return local;
3416}3341}
34173342
3418fn airBreakpoint(f: *Function) !CValue {3343fn airBreakpoint(writer: anytype) !CValue {
3419 try f.object.writer().writeAll("zig_breakpoint();\n");3344 try writer.writeAll("zig_breakpoint();\n");
3420 return CValue.none;3345 return CValue.none;
3421}3346}
34223347
...@@ -3463,9 +3388,12 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3463,9 +3388,12 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {
3463 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;3388 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
3464 const loop = f.air.extraData(Air.Block, ty_pl.payload);3389 const loop = f.air.extraData(Air.Block, ty_pl.payload);
3465 const body = f.air.extra[loop.end..][0..loop.data.body_len];3390 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(") ");
3467 try genBody(f, body);3395 try genBody(f, body);
3468 try f.object.indent_writer.insertNewline();3396 try writer.writeByte('\n');
3469 return CValue.none;3397 return CValue.none;
3470}3398}
34713399
...@@ -3496,7 +3424,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3496,7 +3424,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
3496 const writer = f.object.writer();3424 const writer = f.object.writer();
34973425
3498 try writer.writeAll("switch (");3426 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 }
3500 try f.writeCValue(writer, condition, .Other);3432 try f.writeCValue(writer, condition, .Other);
3501 try writer.writeAll(") {");3433 try writer.writeAll(") {");
3502 f.object.indent_writer.pushIndent();3434 f.object.indent_writer.pushIndent();
...@@ -3751,16 +3683,22 @@ fn airIsNull(...@@ -3751,16 +3683,22 @@ fn airIsNull(
3751 var payload_buf: Type.Payload.ElemType = undefined;3683 var payload_buf: Type.Payload.ElemType = undefined;
3752 const payload_ty = optional_ty.optionalChild(&payload_buf);3684 const payload_ty = optional_ty.optionalChild(&payload_buf);
37533685
3754 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {3686 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime())
3755 try writer.print(" {s} true;\n", .{operator});3687 TypedValue{ .ty = Type.bool, .val = Value.@"true" }
3756 } else if (operand_ty.isPtrLikeOptional()) {3688 else if (operand_ty.isPtrLikeOptional())
3757 // operand is a regular pointer, test `operand !=/== NULL`3689 // operand is a regular pointer, test `operand !=/== NULL`
3758 try writer.print(" {s} NULL;\n", .{operator});3690 TypedValue{ .ty = operand_ty, .val = Value.@"null" }
3759 } else if (payload_ty.zigTypeTag() == .ErrorSet) {3691 else if (payload_ty.zigTypeTag() == .ErrorSet)
3760 try writer.print(" {s} 0;\n", .{operator});3692 TypedValue{ .ty = payload_ty, .val = Value.zero }
3761 } else {3693 else rhs: {
3762 try writer.print(".is_null {s} true;\n", .{operator});3694 try writer.writeAll(".is_null");
3763 }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");
3764 return local;3702 return local;
3765}3703}
37663704
...@@ -3812,9 +3750,9 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3812,9 +3750,9 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3812 }3750 }
38133751
3814 const local = try f.allocLocal(inst_ty, .Const);3752 const local = try f.allocLocal(inst_ty, .Const);
3815 try writer.writeAll(" = &(");3753 try writer.writeAll(" = &");
3816 try f.writeCValue(writer, operand, .Other);3754 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
3817 try writer.writeAll(")->payload;\n");3755 try writer.writeAll(";\n");
3818 return local;3756 return local;
3819}3757}
38203758
...@@ -3833,7 +3771,9 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3833,7 +3771,9 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
3833 }3771 }
38343772
3835 try f.writeCValueDeref(writer, operand);3773 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
3838 const inst_ty = f.air.typeOfIndex(inst);3778 const inst_ty = f.air.typeOfIndex(inst);
3839 const local = try f.allocLocal(inst_ty, .Const);3779 const local = try f.allocLocal(inst_ty, .Const);
...@@ -3974,44 +3914,30 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3974,44 +3914,30 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
3974/// *(E!T) -> E3914/// *(E!T) -> E
3975/// Note that the result is never a pointer.3915/// Note that the result is never a pointer.
3976fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {3916fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
3977 if (f.liveness.isUnused(inst))3917 if (f.liveness.isUnused(inst)) return CValue.none;
3978 return CValue.none;
39793918
3980 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3919 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3981 const inst_ty = f.air.typeOfIndex(inst);3920 const inst_ty = f.air.typeOfIndex(inst);
3982 const writer = f.object.writer();
3983 const operand = try f.resolveInst(ty_op.operand);3921 const operand = try f.resolveInst(ty_op.operand);
3984 const operand_ty = f.air.typeOf(ty_op.operand);3922 const operand_ty = f.air.typeOf(ty_op.operand);
39853923
3986 if (operand_ty.zigTypeTag() == .Pointer) {3924 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
3987 const err_union_ty = operand_ty.childType();3925 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
3988 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {3926 const error_ty = error_union_ty.errorUnionSet();
3989 return CValue{ .bytes = "0" };3927 const payload_ty = error_union_ty.errorUnionPayload();
3990 }3928 if (!payload_ty.hasRuntimeBits()) return operand;
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 }
40063929
3930 const writer = f.object.writer();
4007 const local = try f.allocLocal(inst_ty, .Const);3931 const local = try f.allocLocal(inst_ty, .Const);
4008 try writer.writeAll(" = ");3932 try writer.writeAll(" = ");
4009 if (operand_ty.zigTypeTag() == .Pointer) {3933 if (!error_ty.errorSetIsEmpty())
4010 try f.writeCValueDeref(writer, operand);3934 if (operand_is_ptr)
4011 } else {3935 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
4012 try f.writeCValue(writer, operand, .Other);3936 else
4013 }3937 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
4014 try writer.writeAll(".error;\n");3938 else
3939 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
3940 try writer.writeAll(";\n");
4015 return local;3941 return local;
4016}3942}
40173943
...@@ -4020,26 +3946,23 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu...@@ -4020,26 +3946,23 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
4020 return CValue.none;3946 return CValue.none;
40213947
4022 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3948 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);
4024 const operand = try f.resolveInst(ty_op.operand);3950 const operand = try f.resolveInst(ty_op.operand);
4025 const operand_ty = f.air.typeOf(ty_op.operand);3951 const operand_ty = f.air.typeOf(ty_op.operand);
4026 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;3952 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
4027 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;3953 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
40283954
4029 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {3955 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) return CValue.none;
4030 return CValue.none;
4031 }
4032
4033 const inst_ty = f.air.typeOfIndex(inst);
40343956
3957 const writer = f.object.writer();
4035 const local = try f.allocLocal(inst_ty, .Const);3958 const local = try f.allocLocal(inst_ty, .Const);
4036 try writer.writeAll(" = ");3959 try writer.writeAll(" = ");
4037 if (is_ptr) try writer.writeByte('&');3960 if (is_ptr) try writer.writeByte('&');
4038 try writer.writeByte('(');3961 if (operand_is_ptr)
4039 try f.writeCValue(writer, operand, .Other);3962 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" })
4040 try writer.writeByte(')');3963 else
4041 try if (operand_is_ptr) writer.writeAll("->") else writer.writeByte('.');3964 try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
4042 try writer.writeAll("payload;\n");3965 try writer.writeAll(";\n");
4043 return local;3966 return local;
4044}3967}
40453968
...@@ -4060,7 +3983,9 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4060,7 +3983,9 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
4060 const local = try f.allocLocal(inst_ty, .Const);3983 const local = try f.allocLocal(inst_ty, .Const);
4061 try writer.writeAll(" = { .payload = ");3984 try writer.writeAll(" = { .payload = ");
4062 try f.writeCValue(writer, operand, .Initializer);3985 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");
4064 return local;3989 return local;
4065}3990}
40663991
...@@ -4070,13 +3995,11 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4070,13 +3995,11 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
4070 const writer = f.object.writer();3995 const writer = f.object.writer();
4071 const ty_op = f.air.instructions.items(.data)[inst].ty_op;3996 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4072 const operand = try f.resolveInst(ty_op.operand);3997 const operand = try f.resolveInst(ty_op.operand);
4073 const err_un_ty = f.air.typeOfIndex(inst);3998 const error_union_ty = f.air.typeOfIndex(inst);
4074 const payload_ty = err_un_ty.errorUnionPayload();3999 const payload_ty = error_union_ty.errorUnionPayload();
4075 if (!payload_ty.hasRuntimeBits()) {4000 if (!payload_ty.hasRuntimeBits()) return operand;
4076 return operand;
4077 }
40784001
4079 const local = try f.allocLocal(err_un_ty, .Const);4002 const local = try f.allocLocal(error_union_ty, .Const);
4080 try writer.writeAll(" = { .payload = ");4003 try writer.writeAll(" = { .payload = ");
4081 try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer);4004 try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer);
4082 try writer.writeAll(", .error = ");4005 try writer.writeAll(", .error = ");
...@@ -4180,18 +4103,21 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const...@@ -4180,18 +4103,21 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
41804103
4181 try writer.writeAll(" = ");4104 try writer.writeAll(" = ");
41824105
4183 if (error_ty.errorSetIsEmpty()) {4106 if (!error_ty.errorSetIsEmpty())
4184 try writer.writeByte('0');4107 if (payload_ty.hasRuntimeBits())
4185 } else {4108 if (is_ptr)
4186 try f.writeCValue(writer, operand, .Other);4109 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
4187 if (payload_ty.hasRuntimeBits()) {4110 else
4188 try if (is_ptr) writer.writeAll("->") else writer.writeByte('.');4111 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
4189 try writer.writeAll("error");4112 else
4190 }4113 try f.writeCValue(writer, operand, .Other)
4191 }4114 else
4115 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
4192 try writer.writeByte(' ');4116 try writer.writeByte(' ');
4193 try writer.writeAll(operator);4117 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");
4195 return local;4121 return local;
4196}4122}
41974123
...@@ -4258,55 +4184,74 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4258,55 +4184,74 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
4258 return local;4184 return local;
4259}4185}
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 {
4262 if (f.liveness.isUnused(inst)) return CValue.none;4193 if (f.liveness.isUnused(inst)) return CValue.none;
42634194
4264 const inst_ty = f.air.typeOfIndex(inst);4195 const inst_ty = f.air.typeOfIndex(inst);
4265 const local = try f.allocLocal(inst_ty, .Const);
4266 const operand = f.air.instructions.items(.data)[inst].ty_op.operand;4196 const operand = f.air.instructions.items(.data)[inst].ty_op.operand;
4267 const operand_ty = f.air.typeOf(operand);4197 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});4199 const local = try f.allocLocal(inst_ty, .Const);
4276 try writer.print("{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });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('(');
4277 try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument);4206 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");
4279 return local;4209 return local;
4280}4210}
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 {
4283 if (f.liveness.isUnused(inst)) return CValue.none;4218 if (f.liveness.isUnused(inst)) return CValue.none;
42844219
4285 const inst_ty = f.air.typeOfIndex(inst);4220 const inst_ty = f.air.typeOfIndex(inst);
4286 const local = try f.allocLocal(inst_ty, .Const);
4287 const bin_op = f.air.instructions.items(.data)[inst].bin_op;4221 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4288 const lhs_ty = f.air.typeOf(bin_op.lhs);4222 const operand_ty = f.air.typeOf(bin_op.lhs);
4289 const target = f.object.dg.module.getTarget();4223
4224 const local = try f.allocLocal(inst_ty, .Const);
4290 const writer = f.object.writer();4225 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.4239fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
4293 if (lhs_ty.isInt()) {4240 if (f.liveness.isUnused(inst)) return CValue.none;
4294 const int_info = lhs_ty.intInfo(target);4241
4295 const c_bits = toCIntBits(int_info.bits) orelse4242 const inst_ty = f.air.typeOfIndex(inst);
4296 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});4243 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4297 try writer.print(" = zig_{s}_{c}{d}", .{ fn_name, signAbbrev(int_info.signedness), c_bits });4244 const operand_ty = f.air.typeOf(bin_op.lhs);
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 }
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);
4305 try writer.writeByte('(');4250 try writer.writeByte('(');
4306 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);4251 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
4307 try writer.writeAll(", ");4252 try writer.writeAll(", ");
4308 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);4253 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) });
4310 return local;4255 return local;
4311}4256}
43124257
...@@ -4325,7 +4270,11 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -4325,7 +4270,11 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
4325 try writer.writeAll(" = ");4270 try writer.writeAll(" = ");
4326 if (is_struct) try writer.writeAll("{ .payload = ");4271 if (is_struct) try writer.writeAll("{ .payload = ");
4327 try f.writeCValue(writer, expected_value, .Initializer);4272 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 }
4329 try writer.writeAll(";\n");4278 try writer.writeAll(";\n");
43304279
4331 if (is_struct) {4280 if (is_struct) {
...@@ -4341,10 +4290,10 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -4341,10 +4290,10 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
4341 try writer.writeAll(" *)");4290 try writer.writeAll(" *)");
4342 try f.writeCValue(writer, ptr, .Other);4291 try f.writeCValue(writer, ptr, .Other);
4343 try writer.writeAll(", ");4292 try writer.writeAll(", ");
4344 try f.writeCValue(writer, local, .FunctionArgument);4293 if (is_struct)
4345 if (is_struct) {4294 try f.writeCValueMember(writer, local, .{ .identifier = "payload" })
4346 try writer.writeAll(".payload");4295 else
4347 }4296 try f.writeCValue(writer, local, .FunctionArgument);
4348 try writer.writeAll(", ");4297 try writer.writeAll(", ");
4349 try f.writeCValue(writer, new_value, .FunctionArgument);4298 try f.writeCValue(writer, new_value, .FunctionArgument);
4350 try writer.writeAll(", ");4299 try writer.writeAll(", ");
...@@ -4537,8 +4486,6 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4537,8 +4486,6 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
4537 try f.writeCValue(writer, operand, .Other);4486 try f.writeCValue(writer, operand, .Other);
4538 try writer.writeAll(");\n");4487 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
4542 return local;4489 return local;
4543}4490}
45444491
...@@ -4804,7 +4751,7 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4804,7 +4751,7 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
4804 return local;4751 return local;
4805}4752}
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 {
4808 if (f.liveness.isUnused(inst)) return CValue.none;4755 if (f.liveness.isUnused(inst)) return CValue.none;
4809 const un_op = f.air.instructions.items(.data)[inst].un_op;4756 const un_op = f.air.instructions.items(.data)[inst].un_op;
4810 const writer = f.object.writer();4757 const writer = f.object.writer();
...@@ -4812,14 +4759,14 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue...@@ -4812,14 +4759,14 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValue
4812 const operand = try f.resolveInst(un_op);4759 const operand = try f.resolveInst(un_op);
4813 const local = try f.allocLocal(inst_ty, .Const);4760 const local = try f.allocLocal(inst_ty, .Const);
4814 try writer.writeAll(" = ");4761 try writer.writeAll(" = ");
4815 try f.renderFloatFnName(fn_name, inst_ty);4762 try f.renderFloatFnName(writer, operation, inst_ty);
4816 try writer.writeByte('(');4763 try writer.writeByte('(');
4817 try f.writeCValue(writer, operand, .FunctionArgument);4764 try f.writeCValue(writer, operand, .FunctionArgument);
4818 try writer.writeAll(");\n");4765 try writer.writeAll(");\n");
4819 return local;4766 return local;
4820}4767}
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 {
4823 if (f.liveness.isUnused(inst)) return CValue.none;4770 if (f.liveness.isUnused(inst)) return CValue.none;
4824 const bin_op = f.air.instructions.items(.data)[inst].bin_op;4771 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4825 const writer = f.object.writer();4772 const writer = f.object.writer();
...@@ -4828,7 +4775,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValu...@@ -4828,7 +4775,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, fn_name: []const u8) !CValu
4828 const rhs = try f.resolveInst(bin_op.rhs);4775 const rhs = try f.resolveInst(bin_op.rhs);
4829 const local = try f.allocLocal(inst_ty, .Const);4776 const local = try f.allocLocal(inst_ty, .Const);
4830 try writer.writeAll(" = ");4777 try writer.writeAll(" = ");
4831 try f.renderFloatFnName(fn_name, inst_ty);4778 try f.renderFloatFnName(writer, operation, inst_ty);
4832 try writer.writeByte('(');4779 try writer.writeByte('(');
4833 try f.writeCValue(writer, lhs, .FunctionArgument);4780 try f.writeCValue(writer, lhs, .FunctionArgument);
4834 try writer.writeAll(", ");4781 try writer.writeAll(", ");
...@@ -4848,7 +4795,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4848,7 +4795,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
4848 const writer = f.object.writer();4795 const writer = f.object.writer();
4849 const local = try f.allocLocal(inst_ty, .Const);4796 const local = try f.allocLocal(inst_ty, .Const);
4850 try writer.writeAll(" = ");4797 try writer.writeAll(" = ");
4851 try f.renderFloatFnName("fma", inst_ty);4798 try f.renderFloatFnName(writer, "fma", inst_ty);
4852 try writer.writeByte('(');4799 try writer.writeByte('(');
4853 try f.writeCValue(writer, mulend1, .FunctionArgument);4800 try f.writeCValue(writer, mulend1, .FunctionArgument);
4854 try writer.writeAll(", ");4801 try writer.writeAll(", ");
...@@ -5010,8 +4957,7 @@ fn formatIntLiteral(...@@ -5010,8 +4957,7 @@ fn formatIntLiteral(
5010 };4957 };
50114958
5012 undef_limbs: [limbs_count_128]Limb,4959 undef_limbs: [limbs_count_128]Limb,
5013 str: [worst_case_int.sizeInBaseUpperBound(base)]u8,4960 wrap_limbs: [limbs_count_128]Limb,
5014 limbs_limbs: [expected_needed_limbs_count]Limb,
5015 };4961 };
5016 var stack align(@alignOf(expected_contents)) =4962 var stack align(@alignOf(expected_contents)) =
5017 std.heap.stackFallback(@sizeOf(expected_contents), data.mod.gpa);4963 std.heap.stackFallback(@sizeOf(expected_contents), data.mod.gpa);
...@@ -5037,35 +4983,89 @@ fn formatIntLiteral(...@@ -5037,35 +4983,89 @@ fn formatIntLiteral(
5037 } else data.val.toBigInt(&int_buf, target);4983 } else data.val.toBigInt(&int_buf, target);
5038 assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));4984 assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));
50394985
5040 const limbs_count_64 = @divExact(64, @bitSizeOf(Limb));
5041 const c_bits = toCIntBits(int_info.bits) orelse unreachable;4986 const c_bits = toCIntBits(int_info.bits) orelse unreachable;
5042 if (c_bits == 128) {4987 var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined;
5043 // Clang and GCC don't support 128-bit integer constants but4988 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
5044 // will hopefully unfold them if we construct one manually.4989
5045 //std.debug.todo("128-bit is unimplemented");4990 const wrap_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(c_bits));
5046 try writer.writeByte('(');4991 defer allocator.free(wrap_limbs);
5047 if (int_info.signedness == .signed) {4992 var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined };
5048 try writer.writeAll("(int128_t)");4993 if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
5049 if (!int.positive) try writer.writeByte('-');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),
5050 }5045 }
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);
5052 const split = std.math.min(int.limbs.len, limbs_count_64);5052 const split = std.math.min(int.limbs.len, limbs_count_64);
5053
5053 var upper_pl = Value.Payload.BigInt{5054 var upper_pl = Value.Payload.BigInt{
5054 .base = .{ .tag = .int_big_positive },5055 .base = .{ .tag = .int_big_positive },
5055 .data = int.limbs[split..],5056 .data = int.limbs[split..],
5056 };5057 };
5057 const have_upper = !upper_pl.asBigInt().eqZero();5058 const upper_val = Value.initPayload(&upper_pl.base);
5058 if (have_upper) try writer.writeByte('(');5059 try formatIntLiteral(.{
5059 if (have_upper or !int.positive) try writer.writeAll("(uint128_t)");5060 .ty = switch (int_info.signedness) {
5060 if (have_upper) {5061 .unsigned => Type.u64,
5061 const upper_val = Value.initPayload(&upper_pl.base);5062 .signed => Type.i64,
5062 try formatIntLiteral(.{5063 },
5063 .ty = Type.u64,5064 .val = upper_val,
5064 .val = upper_val,5065 .mod = data.mod,
5065 .mod = data.mod,5066 }, fmt, options, writer);
5066 }, fmt, options, writer);5067
5067 try writer.writeAll("<<64|");5068 try writer.writeAll(", ");
5068 }
50695069
5070 var lower_pl = Value.Payload.BigInt{5070 var lower_pl = Value.Payload.BigInt{
5071 .base = .{ .tag = .int_big_positive },5071 .base = .{ .tag = .int_big_positive },
...@@ -5078,74 +5078,9 @@ fn formatIntLiteral(...@@ -5078,74 +5078,9 @@ fn formatIntLiteral(
5078 .mod = data.mod,5078 .mod = data.mod,
5079 }, fmt, options, writer);5079 }, fmt, options, writer);
50805080
5081 if (have_upper) try writer.writeByte(')');
5082 return writer.writeByte(')');5081 return writer.writeByte(')');
5083 }5082 }
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
5149 switch (data.ty.tag()) {5084 switch (data.ty.tag()) {
5150 .c_short, .c_ushort, .c_int => {},5085 .c_short, .c_ushort, .c_int => {},
5151 .c_uint => try writer.writeAll("u"),5086 .c_uint => try writer.writeAll("u"),
test/behavior/align.zig-2
...@@ -393,8 +393,6 @@ test "function callconv expression depends on generic parameter" {...@@ -393,8 +393,6 @@ test "function callconv expression depends on generic parameter" {
393}393}
394394
395test "runtime-known array index has best alignment possible" {395test "runtime-known array index has best alignment possible" {
396 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
397
398 // take full advantage of over-alignment396 // take full advantage of over-alignment
399 var array align(4) = [_]u8{ 1, 2, 3, 4 };397 var array align(4) = [_]u8{ 1, 2, 3, 4 };
400 comptime assert(@TypeOf(&array[0]) == *align(4) u8);398 comptime assert(@TypeOf(&array[0]) == *align(4) u8);
test/behavior/bugs/2114.zig-1
...@@ -12,7 +12,6 @@ test "fixed" {...@@ -12,7 +12,6 @@ test "fixed" {
12 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO12 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO13 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO14 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1615
17 try testCtz();16 try testCtz();
18 comptime try testCtz();17 comptime try testCtz();
test/behavior/cast.zig-2
...@@ -119,7 +119,6 @@ test "@intToFloat(f80)" {...@@ -119,7 +119,6 @@ test "@intToFloat(f80)" {
119 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO119 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
121 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO121 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
122 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
123122
124 const S = struct {123 const S = struct {
125 fn doTheTest(comptime Int: type) !void {124 fn doTheTest(comptime Int: type) !void {
...@@ -1157,7 +1156,6 @@ fn castToOptionalSlice() ?[]const u8 {...@@ -1157,7 +1156,6 @@ fn castToOptionalSlice() ?[]const u8 {
11571156
1158test "cast u128 to f128 and back" {1157test "cast u128 to f128 and back" {
1159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;1158 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1160 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1162 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1163 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1161 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
test/behavior/floatop.zig-3
...@@ -54,7 +54,6 @@ fn testFloatComparisons() !void {...@@ -54,7 +54,6 @@ fn testFloatComparisons() !void {
5454
55test "different sized float comparisons" {55test "different sized float comparisons" {
56 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO58 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
...@@ -303,7 +302,6 @@ test "@log" {...@@ -303,7 +302,6 @@ test "@log" {
303 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO302 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
305 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
306 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
307305
308 comptime try testLog();306 comptime try testLog();
309 try testLog();307 try testLog();
...@@ -543,7 +541,6 @@ fn testTrunc() !void {...@@ -543,7 +541,6 @@ fn testTrunc() !void {
543541
544test "negation f16" {542test "negation f16" {
545 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO543 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
546 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
547 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO544 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
548 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
549 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO546 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/int128.zig-1
...@@ -43,7 +43,6 @@ test "int128" {...@@ -43,7 +43,6 @@ test "int128" {
43 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO43 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
44 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO44 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO45 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4746
48 var buff: i128 = -1;47 var buff: i128 = -1;
49 try expect(buff < 0 and (buff + 1) == 0);48 try expect(buff < 0 and (buff + 1) == 0);
test/behavior/math.zig-10
...@@ -452,7 +452,6 @@ fn testDivision() !void {...@@ -452,7 +452,6 @@ fn testDivision() !void {
452}452}
453453
454test "division half-precision floats" {454test "division half-precision floats" {
455 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
456 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO455 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
457 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO456 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
458 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO457 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
...@@ -685,7 +684,6 @@ test "basic @mulWithOverflow" {...@@ -685,7 +684,6 @@ test "basic @mulWithOverflow" {
685684
686// TODO migrate to this for all backends once they handle more cases685// TODO migrate to this for all backends once they handle more cases
687test "extensive @mulWithOverflow" {686test "extensive @mulWithOverflow" {
688 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
689 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
690688
691 {689 {
...@@ -835,7 +833,6 @@ test "extensive @mulWithOverflow" {...@@ -835,7 +833,6 @@ test "extensive @mulWithOverflow" {
835}833}
836834
837test "@mulWithOverflow bitsize > 32" {835test "@mulWithOverflow bitsize > 32" {
838 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
839 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO836 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
840 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO837 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
841838
...@@ -923,8 +920,6 @@ test "@subWithOverflow" {...@@ -923,8 +920,6 @@ test "@subWithOverflow" {
923}920}
924921
925test "@shlWithOverflow" {922test "@shlWithOverflow" {
926 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
927
928 {923 {
929 var result: u4 = undefined;924 var result: u4 = undefined;
930 var a: u4 = 2;925 var a: u4 = 2;
...@@ -1274,7 +1269,6 @@ test "@sqrt" {...@@ -1274,7 +1269,6 @@ test "@sqrt" {
1274 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1269 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1275 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1270 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1276 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1277 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12781272
1279 try testSqrt(f64, 12.0);1273 try testSqrt(f64, 12.0);
1280 comptime try testSqrt(f64, 12.0);1274 comptime try testSqrt(f64, 12.0);
...@@ -1339,7 +1333,6 @@ test "@floor" {...@@ -1339,7 +1333,6 @@ test "@floor" {
1339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1333 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1340 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1341 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1335 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1342 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13431336
1344 try testFloor(f64, 12.0);1337 try testFloor(f64, 12.0);
1345 comptime try testFloor(f64, 12.0);1338 comptime try testFloor(f64, 12.0);
...@@ -1388,7 +1381,6 @@ test "@ceil" {...@@ -1388,7 +1381,6 @@ test "@ceil" {
1388 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1381 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1389 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1382 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1390 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1383 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1391 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13921384
1393 try testCeil(f64, 12.0);1385 try testCeil(f64, 12.0);
1394 comptime try testCeil(f64, 12.0);1386 comptime try testCeil(f64, 12.0);
...@@ -1437,7 +1429,6 @@ test "@trunc" {...@@ -1437,7 +1429,6 @@ test "@trunc" {
1437 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1438 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1430 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1439 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1431 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1440 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14411432
1442 try testTrunc(f64, 12.0);1433 try testTrunc(f64, 12.0);
1443 comptime try testTrunc(f64, 12.0);1434 comptime try testTrunc(f64, 12.0);
...@@ -1500,7 +1491,6 @@ test "@round" {...@@ -1500,7 +1491,6 @@ test "@round" {
1500 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1491 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1501 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1492 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1502 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1493 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1503 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15041494
1505 try testRound(f64, 12.0);1495 try testRound(f64, 12.0);
1506 comptime try testRound(f64, 12.0);1496 comptime try testRound(f64, 12.0);
test/behavior/muladd.zig-1
...@@ -27,7 +27,6 @@ fn testMulAdd() !void {...@@ -27,7 +27,6 @@ fn testMulAdd() !void {
2727
28test "@mulAdd f16" {28test "@mulAdd f16" {
29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
32 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO32 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" {...@@ -448,7 +448,6 @@ test "optional pointer in packed struct" {
448}448}
449449
450test "nested packed struct field access test" {450test "nested packed struct field access test" {
451 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
452 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO451 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
453 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO452 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
454 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO453 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)" {...@@ -133,7 +133,6 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
134 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO134 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO135 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
138 // Test lowering a field ptr137 // Test lowering a field ptr
139 comptime var bytes align(2) = [_]u8{ 1, 2, 3, 4, 5, 6 };138 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" {...@@ -54,7 +54,6 @@ test "saturating add 128bit" {
54 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO54 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
58 const S = struct {57 const S = struct {
59 fn doTheTest() !void {58 fn doTheTest() !void {
60 try testSatAdd(i128, maxInt(i128), -maxInt(i128), 0);59 try testSatAdd(i128, maxInt(i128), -maxInt(i128), 0);
...@@ -78,7 +77,6 @@ test "saturating subtraction" {...@@ -78,7 +77,6 @@ test "saturating subtraction" {
78 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
80 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
81 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
8280
83 const S = struct {81 const S = struct {
84 fn doTheTest() !void {82 fn doTheTest() !void {
...@@ -124,7 +122,6 @@ test "saturating subtraction 128bit" {...@@ -124,7 +122,6 @@ test "saturating subtraction 128bit" {
124 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO122 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
127 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
128125
129 const S = struct {126 const S = struct {
130 fn doTheTest() !void {127 fn doTheTest() !void {
...@@ -151,7 +148,6 @@ test "saturating multiplication" {...@@ -151,7 +148,6 @@ test "saturating multiplication" {
151 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
154 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
155151
156 if (builtin.zig_backend == .stage1 and builtin.cpu.arch == .wasm32) {152 if (builtin.zig_backend == .stage1 and builtin.cpu.arch == .wasm32) {
157 // https://github.com/ziglang/zig/issues/9660153 // https://github.com/ziglang/zig/issues/9660
...@@ -199,7 +195,6 @@ test "saturating shift-left" {...@@ -199,7 +195,6 @@ test "saturating shift-left" {
199 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO195 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
201 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO197 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
203198
204 const S = struct {199 const S = struct {
205 fn doTheTest() !void {200 fn doTheTest() !void {
test/behavior/sizeof_and_typeof.zig-1
...@@ -19,7 +19,6 @@ test "@sizeOf on compile-time types" {...@@ -19,7 +19,6 @@ test "@sizeOf on compile-time types" {
1919
20test "@TypeOf() with multiple arguments" {20test "@TypeOf() with multiple arguments" {
21 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;21 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
23 {22 {
24 var var_1: u32 = undefined;23 var var_1: u32 = undefined;
25 var var_2: u8 = undefined;24 var var_2: u8 = undefined;
test/behavior/widening.zig-2
...@@ -40,7 +40,6 @@ test "float widening" {...@@ -40,7 +40,6 @@ test "float widening" {
40 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO41 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO42 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
43 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4443
45 var a: f16 = 12.34;44 var a: f16 = 12.34;
46 var b: f32 = a;45 var b: f32 = a;
...@@ -60,7 +59,6 @@ test "float widening f16 to f128" {...@@ -60,7 +59,6 @@ test "float widening f16 to f128" {
60 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO59 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO60 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
62 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO61 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
63 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
6462
65 // TODO https://github.com/ziglang/zig/issues/328263 // TODO https://github.com/ziglang/zig/issues/3282
66 if (builtin.cpu.arch == .aarch64) return error.SkipZigTest;64 if (builtin.cpu.arch == .aarch64) return error.SkipZigTest;