authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-29 23:06:59-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-29 23:06:59-04:00
log5f5a20ebaf646fe629da370ec56ad86dd2761290
tree07153eefc0a6441ae3306202590ff93d21d475a6
parent09a96cdfce0540e4c02dd3b0917de6b59edbc95c
parent4364f5147697f3c6a9147efd74eec82586cf568c
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #13093 from jacobly0/backend-fixes

C backend fixes

99 files changed, 4277 insertions(+), 3390 deletions(-)

lib/include/zig.h+1219-1319
......@@ -1,97 +1,109 @@
11#undef linux
22
3#define __STDC_WANT_IEC_60559_TYPES_EXT__
4#include <float.h>
5#include <limits.h>
6#include <stddef.h>
7#include <stdint.h>
8
9#if defined(__has_builtin)
10#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)
11#else
12#define zig_has_builtin(builtin) 0
13#endif
14
15#if defined(__has_attribute)
16#define zig_has_attribute(attribute) __has_attribute(attribute)
17#else
18#define zig_has_attribute(attribute) 0
19#endif
20
321#if __STDC_VERSION__ >= 201112L
4#define zig_noreturn _Noreturn
522#define zig_threadlocal thread_local
623#elif __GNUC__
7#define zig_noreturn __attribute__ ((noreturn))
824#define zig_threadlocal __thread
925#elif _MSC_VER
10#define zig_noreturn __declspec(noreturn)
1126#define zig_threadlocal __declspec(thread)
1227#else
13#define zig_noreturn
1428#define zig_threadlocal zig_threadlocal_unavailable
1529#endif
1630
17#if __GNUC__
18#define ZIG_COLD __attribute__ ((cold))
31#if zig_has_attribute(naked)
32#define zig_naked __attribute__((naked))
33#elif defined(_MSC_VER)
34#define zig_naked __declspec(naked)
1935#else
20#define ZIG_COLD
36#define zig_naked zig_naked_unavailable
2137#endif
2238
23#if __STDC_VERSION__ >= 199901L
24#define ZIG_RESTRICT restrict
25#elif defined(__GNUC__)
26#define ZIG_RESTRICT __restrict
39#if zig_has_attribute(cold)
40#define zig_cold __attribute__((cold))
2741#else
28#define ZIG_RESTRICT
42#define zig_cold
2943#endif
3044
31#if __STDC_VERSION__ >= 201112L
32#include <stdalign.h>
33#define ZIG_ALIGN(alignment) alignas(alignment)
45#if __STDC_VERSION__ >= 199901L
46#define zig_restrict restrict
3447#elif defined(__GNUC__)
35#define ZIG_ALIGN(alignment) __attribute__((aligned(alignment)))
48#define zig_restrict __restrict
3649#else
37#define ZIG_ALIGN(alignment) zig_compile_error("the C compiler being used does not support aligning variables")
50#define zig_restrict
3851#endif
3952
40#if __STDC_VERSION__ >= 199901L
41#include <stdbool.h>
53#if __STDC_VERSION__ >= 201112L
54#define zig_align(alignment) _Alignas(alignment)
55#elif zig_has_attribute(aligned)
56#define zig_align(alignment) __attribute__((aligned(alignment)))
57#elif _MSC_VER
4258#else
43#define bool unsigned char
44#define true 1
45#define false 0
59#error the C compiler being used does not support aligning variables
4660#endif
4761
48#if defined(__GNUC__)
62#if zig_has_builtin(unreachable)
4963#define zig_unreachable() __builtin_unreachable()
5064#else
5165#define zig_unreachable()
5266#endif
5367
54#ifdef __cplusplus
55#define ZIG_EXTERN_C extern "C"
68#if defined(__cplusplus)
69#define zig_extern_c extern "C"
5670#else
57#define ZIG_EXTERN_C
71#define zig_extern_c
5872#endif
5973
60#if defined(_MSC_VER)
61#define zig_breakpoint() __debugbreak()
62#elif defined(__MINGW32__) || defined(__MINGW64__)
63#define zig_breakpoint() __debugbreak()
64#elif defined(__clang__)
74#if zig_has_builtin(debugtrap)
6575#define zig_breakpoint() __builtin_debugtrap()
66#elif defined(__GNUC__)
76#elif zig_has_builtin(trap)
6777#define zig_breakpoint() __builtin_trap()
78#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
79#define zig_breakpoint() __debugbreak()
6880#elif defined(__i386__) || defined(__x86_64__)
6981#define zig_breakpoint() __asm__ volatile("int $0x03");
7082#else
7183#define zig_breakpoint() raise(SIGTRAP)
7284#endif
7385
74#if defined(_MSC_VER)
75#define zig_return_address() _ReturnAddress()
76#elif defined(__GNUC__)
86#if zig_has_builtin(return_address)
7787#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))
88#elif defined(_MSC_VER)
89#define zig_return_address() _ReturnAddress()
7890#else
7991#define zig_return_address() 0
8092#endif
8193
82#if defined(__GNUC__)
94#if zig_has_builtin(frame_address)
8395#define zig_frame_address() __builtin_frame_address(0)
8496#else
8597#define zig_frame_address() 0
8698#endif
8799
88#if defined(__GNUC__)
100#if zig_has_builtin(prefetch)
89101#define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
90102#else
91103#define zig_prefetch(addr, rw, locality)
92104#endif
93105
94#if defined(__clang__)
106#if zig_has_builtin(memory_size) && zig_has_builtin(memory_grow)
95107#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)
96108#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)
97109#else
......@@ -101,19 +113,20 @@
101113
102114#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
103115#include <stdatomic.h>
116#define zig_atomic(type) _Atomic(type)
104117#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
105#define zig_cmpxchg_weak (obj, expected, desired, succ, fail) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
118#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
106119#define zig_atomicrmw_xchg(obj, arg, order) atomic_exchange_explicit (obj, arg, order)
107#define zig_atomicrmw_add (obj, arg, order) atomic_fetch_add_explicit (obj, arg, order)
108#define zig_atomicrmw_sub (obj, arg, order) atomic_fetch_sub_explicit (obj, arg, order)
109#define zig_atomicrmw_or (obj, arg, order) atomic_fetch_or_explicit (obj, arg, order)
110#define zig_atomicrmw_xor (obj, arg, order) atomic_fetch_xor_explicit (obj, arg, order)
111#define zig_atomicrmw_and (obj, arg, order) atomic_fetch_and_explicit (obj, arg, order)
112#define zig_atomicrmw_nand(obj, arg, order) atomic_fetch_nand_explicit(obj, arg, order)
113#define zig_atomicrmw_min (obj, arg, order) atomic_fetch_min_explicit (obj, arg, order)
114#define zig_atomicrmw_max (obj, arg, order) atomic_fetch_max_explicit (obj, arg, order)
115#define zig_atomic_store (obj, arg, order) atomic_store_explicit (obj, arg, order)
116#define zig_atomic_load (obj, order) atomic_load_explicit (obj, order)
120#define zig_atomicrmw_add(obj, arg, order) atomic_fetch_add_explicit (obj, arg, order)
121#define zig_atomicrmw_sub(obj, arg, order) atomic_fetch_sub_explicit (obj, arg, order)
122#define zig_atomicrmw_or(obj, arg, order) atomic_fetch_or_explicit (obj, arg, order)
123#define zig_atomicrmw_xor(obj, arg, order) atomic_fetch_xor_explicit (obj, arg, order)
124#define zig_atomicrmw_and(obj, arg, order) atomic_fetch_and_explicit (obj, arg, order)
125#define zig_atomicrmw_nand(obj, arg, order) __atomic_fetch_nand (obj, arg, order)
126#define zig_atomicrmw_min(obj, arg, order) __atomic_fetch_min (obj, arg, order)
127#define zig_atomicrmw_max(obj, arg, order) __atomic_fetch_max (obj, arg, order)
128#define zig_atomic_store(obj, arg, order) atomic_store_explicit (obj, arg, order)
129#define zig_atomic_load(obj, order) atomic_load_explicit (obj, order)
117130#define zig_fence(order) atomic_thread_fence(order)
118131#elif __GNUC__
119132#define memory_order_relaxed __ATOMIC_RELAXED
......@@ -122,19 +135,20 @@
122135#define memory_order_release __ATOMIC_RELEASE
123136#define memory_order_acq_rel __ATOMIC_ACQ_REL
124137#define memory_order_seq_cst __ATOMIC_SEQ_CST
125#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, false, succ, fail)
126#define zig_cmpxchg_weak (obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, true , succ, fail)
138#define zig_atomic(type) type
139#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, zig_false, succ, fail)
140#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) __atomic_compare_exchange_n(obj, &(expected), desired, zig_true , succ, fail)
127141#define zig_atomicrmw_xchg(obj, arg, order) __atomic_exchange_n(obj, arg, order)
128#define zig_atomicrmw_add (obj, arg, order) __atomic_fetch_add (obj, arg, order)
129#define zig_atomicrmw_sub (obj, arg, order) __atomic_fetch_sub (obj, arg, order)
130#define zig_atomicrmw_or (obj, arg, order) __atomic_fetch_or (obj, arg, order)
131#define zig_atomicrmw_xor (obj, arg, order) __atomic_fetch_xor (obj, arg, order)
132#define zig_atomicrmw_and (obj, arg, order) __atomic_fetch_and (obj, arg, order)
142#define zig_atomicrmw_add(obj, arg, order) __atomic_fetch_add (obj, arg, order)
143#define zig_atomicrmw_sub(obj, arg, order) __atomic_fetch_sub (obj, arg, order)
144#define zig_atomicrmw_or(obj, arg, order) __atomic_fetch_or (obj, arg, order)
145#define zig_atomicrmw_xor(obj, arg, order) __atomic_fetch_xor (obj, arg, order)
146#define zig_atomicrmw_and(obj, arg, order) __atomic_fetch_and (obj, arg, order)
133147#define zig_atomicrmw_nand(obj, arg, order) __atomic_fetch_nand(obj, arg, order)
134#define zig_atomicrmw_min (obj, arg, order) __atomic_fetch_min (obj, arg, order)
135#define zig_atomicrmw_max (obj, arg, order) __atomic_fetch_max (obj, arg, order)
136#define zig_atomic_store (obj, arg, order) __atomic_store (obj, arg, order)
137#define zig_atomic_load (obj, order) __atomic_load (obj, order)
148#define zig_atomicrmw_min(obj, arg, order) __atomic_fetch_min (obj, arg, order)
149#define zig_atomicrmw_max(obj, arg, order) __atomic_fetch_max (obj, arg, order)
150#define zig_atomic_store(obj, arg, order) __atomic_store_n (obj, arg, order)
151#define zig_atomic_load(obj, order) __atomic_load_n (obj, order)
138152#define zig_fence(order) __atomic_thread_fence(order)
139153#else
140154#define memory_order_relaxed 0
......@@ -143,1457 +157,1343 @@
143157#define memory_order_release 3
144158#define memory_order_acq_rel 4
145159#define memory_order_seq_cst 5
160#define zig_atomic(type) type
146161#define zig_cmpxchg_strong(obj, expected, desired, succ, fail) zig_unimplemented()
147#define zig_cmpxchg_weak (obj, expected, desired, succ, fail) zig_unimplemented()
162#define zig_cmpxchg_weak(obj, expected, desired, succ, fail) zig_unimplemented()
148163#define zig_atomicrmw_xchg(obj, arg, order) zig_unimplemented()
149#define zig_atomicrmw_add (obj, arg, order) zig_unimplemented()
150#define zig_atomicrmw_sub (obj, arg, order) zig_unimplemented()
151#define zig_atomicrmw_or (obj, arg, order) zig_unimplemented()
152#define zig_atomicrmw_xor (obj, arg, order) zig_unimplemented()
153#define zig_atomicrmw_and (obj, arg, order) zig_unimplemented()
164#define zig_atomicrmw_add(obj, arg, order) zig_unimplemented()
165#define zig_atomicrmw_sub(obj, arg, order) zig_unimplemented()
166#define zig_atomicrmw_or(obj, arg, order) zig_unimplemented()
167#define zig_atomicrmw_xor(obj, arg, order) zig_unimplemented()
168#define zig_atomicrmw_and(obj, arg, order) zig_unimplemented()
154169#define zig_atomicrmw_nand(obj, arg, order) zig_unimplemented()
155#define zig_atomicrmw_min (obj, arg, order) zig_unimplemented()
156#define zig_atomicrmw_max (obj, arg, order) zig_unimplemented()
157#define zig_atomic_store (obj, arg, order) zig_unimplemented()
158#define zig_atomic_load (obj, order) zig_unimplemented()
170#define zig_atomicrmw_min(obj, arg, order) zig_unimplemented()
171#define zig_atomicrmw_max(obj, arg, order) zig_unimplemented()
172#define zig_atomic_store(obj, arg, order) zig_unimplemented()
173#define zig_atomic_load(obj, order) zig_unimplemented()
159174#define zig_fence(order) zig_unimplemented()
160175#endif
161176
162#include <stdint.h>
163#include <stddef.h>
164#include <limits.h>
177#if __STDC_VERSION__ >= 201112L
178#define zig_noreturn _Noreturn void
179#elif zig_has_attribute(noreturn)
180#define zig_noreturn __attribute__((noreturn)) void
181#elif _MSC_VER
182#define zig_noreturn __declspec(noreturn) void
183#else
184#define zig_noreturn void
185#endif
165186
166#define int128_t __int128
167#define uint128_t unsigned __int128
168#define UINT128_MAX ((uint128_t)(0xffffffffffffffffull) | 0xffffffffffffffffull)
169ZIG_EXTERN_C void *memcpy (void *ZIG_RESTRICT, const void *ZIG_RESTRICT, size_t);
170ZIG_EXTERN_C void *memset (void *, int, size_t);
171ZIG_EXTERN_C int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
172ZIG_EXTERN_C int128_t __addoti4(int128_t lhs, int128_t rhs, int *overflow);
173ZIG_EXTERN_C uint64_t __uaddodi4(uint64_t lhs, uint64_t rhs, int *overflow);
174ZIG_EXTERN_C uint128_t __uaddoti4(uint128_t lhs, uint128_t rhs, int *overflow);
175ZIG_EXTERN_C int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);
176ZIG_EXTERN_C int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);
177ZIG_EXTERN_C int128_t __suboti4(int128_t lhs, int128_t rhs, int *overflow);
178ZIG_EXTERN_C uint32_t __usubosi4(uint32_t lhs, uint32_t rhs, int *overflow);
179ZIG_EXTERN_C uint64_t __usubodi4(uint64_t lhs, uint64_t rhs, int *overflow);
180ZIG_EXTERN_C uint128_t __usuboti4(uint128_t lhs, uint128_t rhs, int *overflow);
181ZIG_EXTERN_C int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
182ZIG_EXTERN_C int128_t __muloti4(int128_t lhs, int128_t rhs, int *overflow);
183ZIG_EXTERN_C uint64_t __umulodi4(uint64_t lhs, uint64_t rhs, int *overflow);
184ZIG_EXTERN_C uint128_t __umuloti4(uint128_t lhs, uint128_t rhs, int *overflow);
185
186
187static inline uint8_t zig_addw_u8(uint8_t lhs, uint8_t rhs, uint8_t max) {
188 uint8_t thresh = max - rhs;
189 if (lhs > thresh) {
190 return lhs - thresh - 1;
191 } else {
192 return lhs + rhs;
193 }
187#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
188
189typedef void zig_void;
190
191#if defined(__cplusplus)
192typedef bool zig_bool;
193#define zig_false false
194#define zig_true true
195#else
196#if __STDC_VERSION__ >= 199901L
197typedef _Bool zig_bool;
198#else
199typedef char zig_bool;
200#endif
201#define zig_false ((zig_bool)0)
202#define zig_true ((zig_bool)1)
203#endif
204
205typedef uintptr_t zig_usize;
206typedef intptr_t zig_isize;
207typedef signed short int zig_c_short;
208typedef unsigned short int zig_c_ushort;
209typedef signed int zig_c_int;
210typedef unsigned int zig_c_uint;
211typedef signed long int zig_c_long;
212typedef unsigned long int zig_c_ulong;
213typedef signed long long int zig_c_longlong;
214typedef unsigned long long int zig_c_ulonglong;
215
216typedef uint8_t zig_u8;
217typedef int8_t zig_i8;
218typedef uint16_t zig_u16;
219typedef int16_t zig_i16;
220typedef uint16_t zig_u16;
221typedef int16_t zig_i16;
222typedef uint32_t zig_u32;
223typedef int32_t zig_i32;
224typedef uint64_t zig_u64;
225typedef int64_t zig_i64;
226
227#define zig_as_u8(val) UINT8_C(val)
228#define zig_as_i8(val) INT8_C(val)
229#define zig_as_u16(val) UINT16_C(val)
230#define zig_as_i16(val) INT16_C(val)
231#define zig_as_u32(val) UINT32_C(val)
232#define zig_as_i32(val) INT32_C(val)
233#define zig_as_u64(val) UINT64_C(val)
234#define zig_as_i64(val) INT64_C(val)
235
236#define zig_minInt_u8 zig_as_u8(0)
237#define zig_maxInt_u8 UINT8_MAX
238#define zig_minInt_i8 INT8_MIN
239#define zig_maxInt_i8 INT8_MAX
240#define zig_minInt_u16 zig_as_u16(0)
241#define zig_maxInt_u16 UINT16_MAX
242#define zig_minInt_i16 INT16_MIN
243#define zig_maxInt_i16 INT16_MAX
244#define zig_minInt_u32 zig_as_u32(0)
245#define zig_maxInt_u32 UINT32_MAX
246#define zig_minInt_i32 INT32_MIN
247#define zig_maxInt_i32 INT32_MAX
248#define zig_minInt_u64 zig_as_u64(0)
249#define zig_maxInt_u64 UINT64_MAX
250#define zig_minInt_i64 INT64_MIN
251#define zig_maxInt_i64 INT64_MAX
252
253#define zig_builtin_f16(name) __##name##h
254#define zig_builtin_constant_f16(name) zig_suffix_f16(__builtin_##name)
255#if FLT_MANT_DIG == 11
256typedef float zig_f16;
257#define zig_suffix_f16(x) x##f
258#elif DBL_MANT_DIG == 11
259typedef double zig_f16;
260#define zig_suffix_f16(x) x
261#elif LDBL_MANT_DIG == 11
262typedef long double zig_f16;
263#define zig_suffix_f16(x) x##l
264#elif FLT16_MANT_DIG == 11
265typedef _Float16 zig_f16;
266#define zig_suffix_f16(x) x##f16
267#elif defined(__SIZEOF_FP16__)
268typedef __fp16 zig_f16;
269#define zig_suffix_f16(x) x##f16
270#endif
271
272#define zig_builtin_f32(name) name##f
273#define zig_builtin_constant_f32(name) zig_suffix_f32(__builtin_##name)
274#if FLT_MANT_DIG == 24
275typedef float zig_f32;
276#define zig_suffix_f32(x) x##f
277#elif DBL_MANT_DIG == 24
278typedef double zig_f32;
279#define zig_suffix_f32(x) x
280#elif LDBL_MANT_DIG == 24
281typedef long double zig_f32;
282#define zig_suffix_f32(x) x##l
283#elif FLT32_MANT_DIG == 24
284typedef _Float32 zig_f32;
285#define zig_suffix_f32(x) x##f32
286#endif
287
288#define zig_builtin_f64(name) name
289#define zig_builtin_constant_f64(name) zig_suffix_f64(__builtin_##name)
290#if FLT_MANT_DIG == 53
291typedef float zig_f64;
292#define zig_suffix_f64(x) x##f
293#elif DBL_MANT_DIG == 53
294typedef double zig_f64;
295#define zig_suffix_f64(x) x
296#elif LDBL_MANT_DIG == 53
297typedef long double zig_f64;
298#define zig_suffix_f64(x) x##l
299#elif FLT64_MANT_DIG == 53
300typedef _Float64 zig_f64;
301#define zig_suffix_f64(x) x##f64
302#elif FLT32X_MANT_DIG == 53
303typedef _Float32x zig_f64;
304#define zig_suffix_f64(x) x##f32x
305#endif
306
307#define zig_builtin_f80(name) __##name##x
308#define zig_builtin_constant_f80(name) zig_suffix_f80(__builtin_##name)
309#if FLT_MANT_DIG == 64
310typedef float zig_f80;
311#define zig_suffix_f80(x) x##f
312#elif DBL_MANT_DIG == 64
313typedef double zig_f80;
314#define zig_suffix_f80(x) x
315#elif LDBL_MANT_DIG == 64
316typedef long double zig_f80;
317#define zig_suffix_f80(x) x##l
318#elif FLT80_MANT_DIG == 64
319typedef _Float80 zig_f80;
320#define zig_suffix_f80(x) x##f80
321#elif FLT64X_MANT_DIG == 64
322typedef _Float64x zig_f80;
323#define zig_suffix_f80(x) x##f64x
324#elif defined(__SIZEOF_FLOAT80__)
325typedef __float80 zig_f80;
326#define zig_suffix_f80(x) x##l
327#endif
328
329#define zig_builtin_f128(name) name##q
330#define zig_builtin_constant_f128(name) zig_suffix_f80(__builtin_##name)
331#if FLT_MANT_DIG == 113
332typedef float zig_f128;
333#define zig_suffix_f128(x) x##f
334#elif DBL_MANT_DIG == 113
335typedef double zig_f128;
336#define zig_suffix_f128(x) x
337#elif LDBL_MANT_DIG == 113
338typedef long double zig_f128;
339#define zig_suffix_f128(x) x##l
340#elif FLT128_MANT_DIG == 113
341typedef _Float128 zig_f128;
342#define zig_suffix_f128(x) x##f128
343#elif FLT64X_MANT_DIG == 113
344typedef _Float64x zig_f128;
345#define zig_suffix_f128(x) x##f64x
346#elif defined(__SIZEOF_FLOAT128__)
347typedef __float128 zig_f128;
348#define zig_suffix_f128(x) x##q
349#undef zig_builtin_constant_f128
350#define zig_builtin_constant_f128(name) __builtin_##name##f128
351#endif
352
353typedef long double zig_c_longdouble;
354#define zig_suffix_c_longdouble(x) x##l
355#define zig_builtin_c_longdouble(name) zig_suffix_c_longdouble(name)
356#define zig_builtin_constant_c_longdouble(name) zig_suffix_c_longdouble(__builtin_##name)
357
358zig_extern_c void *memcpy (void *zig_restrict, void const *zig_restrict, zig_usize);
359zig_extern_c void *memset (void *, int, zig_usize);
360
361/* ==================== 8/16/32/64-bit Integer Routines ===================== */
362
363#define zig_maxInt(Type, bits) zig_shr_##Type(zig_maxInt_##Type, (zig_bitSizeOf(zig_##Type) - bits))
364#define zig_minInt(Type, bits) zig_not_##Type(zig_maxInt(Type, bits), bits)
365
366#define zig_int_operator(Type, RhsType, operation, operator) \
367 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##RhsType rhs) { \
368 return lhs operator rhs; \
369 }
370#define zig_int_operators(w) \
371 zig_int_operator(u##w, u##w, and, &) \
372 zig_int_operator(i##w, i##w, and, &) \
373 zig_int_operator(u##w, u##w, or, |) \
374 zig_int_operator(i##w, i##w, or, |) \
375 zig_int_operator(u##w, u##w, xor, ^) \
376 zig_int_operator(i##w, i##w, xor, ^) \
377 zig_int_operator(u##w, u8, shl, <<) \
378 zig_int_operator(i##w, u8, shl, <<) \
379 zig_int_operator(u##w, u8, shr, >>) \
380 zig_int_operator(u##w, u##w, div_floor, /) \
381 zig_int_operator(u##w, u##w, mod, %)
382zig_int_operators(8)
383zig_int_operators(16)
384zig_int_operators(32)
385zig_int_operators(64)
386
387#define zig_int_helpers(w) \
388 static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \
389 zig_i##w sign_mask = lhs < zig_as_i##w(0) ? -zig_as_i##w(1) : zig_as_i##w(0); \
390 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
391 } \
392\
393 static inline zig_u##w zig_not_u##w(zig_u##w val, zig_u8 bits) { \
394 return val ^ zig_maxInt(u##w, bits); \
395 } \
396\
397 static inline zig_i##w zig_not_i##w(zig_i##w val, zig_u8 bits) { \
398 (void)bits; \
399 return ~val; \
400 } \
401\
402 static inline zig_u##w zig_wrap_u##w(zig_u##w val, zig_u8 bits) { \
403 return val & zig_maxInt(u##w, bits); \
404 } \
405\
406 static inline zig_i##w zig_wrap_i##w(zig_i##w val, zig_u8 bits) { \
407 return (val & zig_as_u##w(1) << (bits - zig_as_u8(1))) != 0 \
408 ? val | zig_minInt(i##w, bits) : val & zig_maxInt(i##w, bits); \
409 } \
410\
411 static inline zig_i##w zig_div_floor_i##w(zig_i##w lhs, zig_i##w rhs) { \
412 return lhs / rhs - (((lhs ^ rhs) & (lhs % rhs)) < zig_as_i##w(0)); \
413 } \
414\
415 static inline zig_i##w zig_mod_i##w(zig_i##w lhs, zig_i##w rhs) { \
416 zig_i##w rem = lhs % rhs; \
417 return rem + (((lhs ^ rhs) & rem) < zig_as_i##w(0) ? rhs : zig_as_i##w(0)); \
418 }
419zig_int_helpers(8)
420zig_int_helpers(16)
421zig_int_helpers(32)
422zig_int_helpers(64)
423
424static inline zig_bool zig_addo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
425#if zig_has_builtin(add_overflow)
426 zig_u32 full_res;
427 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
428 *res = zig_wrap_u32(full_res, bits);
429 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
430#else
431 *res = zig_addw_u32(lhs, rhs, bits);
432 return *res < lhs;
433#endif
194434}
195435
196static inline int8_t zig_addw_i8(int8_t lhs, int8_t rhs, int8_t min, int8_t max) {
197 if ((lhs > 0) && (rhs > 0)) {
198 int8_t thresh = max - rhs;
199 if (lhs > thresh) {
200 return min + lhs - thresh - 1;
201 }
202 } else if ((lhs < 0) && (rhs < 0)) {
203 int8_t thresh = min - rhs;
204 if (lhs < thresh) {
205 return max + lhs - thresh + 1;
206 }
207 }
208 return lhs + rhs;
436zig_extern_c zig_i32 __addosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
437static inline zig_bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
438#if zig_has_builtin(add_overflow)
439 zig_i32 full_res;
440 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
441#else
442 zig_c_int overflow_int;
443 zig_u32 full_res = __addosi4(lhs, rhs, &overflow_int);
444 zig_bool overflow = overflow_int != 0;
445#endif
446 *res = zig_wrap_i32(full_res, bits);
447 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
209448}
210449
211static inline uint16_t zig_addw_u16(uint16_t lhs, uint16_t rhs, uint16_t max) {
212 uint16_t thresh = max - rhs;
213 if (lhs > thresh) {
214 return lhs - thresh - 1;
215 } else {
216 return lhs + rhs;
217 }
450static inline zig_bool zig_addo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
451#if zig_has_builtin(add_overflow)
452 zig_u64 full_res;
453 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
454 *res = zig_wrap_u64(full_res, bits);
455 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
456#else
457 *res = zig_addw_u64(lhs, rhs, bits);
458 return *res < lhs;
459#endif
218460}
219461
220static inline int16_t zig_addw_i16(int16_t lhs, int16_t rhs, int16_t min, int16_t max) {
221 if ((lhs > 0) && (rhs > 0)) {
222 int16_t thresh = max - rhs;
223 if (lhs > thresh) {
224 return min + lhs - thresh - 1;
225 }
226 } else if ((lhs < 0) && (rhs < 0)) {
227 int16_t thresh = min - rhs;
228 if (lhs < thresh) {
229 return max + lhs - thresh + 1;
230 }
231 }
232 return lhs + rhs;
462zig_extern_c zig_i64 __addodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
463static inline zig_bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
464#if zig_has_builtin(add_overflow)
465 zig_i64 full_res;
466 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
467#else
468 zig_c_int overflow_int;
469 zig_u64 full_res = __addodi4(lhs, rhs, &overflow_int);
470 zig_bool overflow = overflow_int != 0;
471#endif
472 *res = zig_wrap_i64(full_res, bits);
473 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
233474}
234475
235static inline uint32_t zig_addw_u32(uint32_t lhs, uint32_t rhs, uint32_t max) {
236 uint32_t thresh = max - rhs;
237 if (lhs > thresh) {
238 return lhs - thresh - 1;
239 } else {
240 return lhs + rhs;
241 }
476static inline zig_bool zig_addo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
477#if zig_has_builtin(add_overflow)
478 zig_u8 full_res;
479 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
480 *res = zig_wrap_u8(full_res, bits);
481 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
482#else
483 return zig_addo_u32(res, lhs, rhs, bits);
484#endif
242485}
243486
244static inline int32_t zig_addw_i32(int32_t lhs, int32_t rhs, int32_t min, int32_t max) {
245 if ((lhs > 0) && (rhs > 0)) {
246 int32_t thresh = max - rhs;
247 if (lhs > thresh) {
248 return min + lhs - thresh - 1;
249 }
250 } else if ((lhs < 0) && (rhs < 0)) {
251 int32_t thresh = min - rhs;
252 if (lhs < thresh) {
253 return max + lhs - thresh + 1;
254 }
255 }
256 return lhs + rhs;
487static inline zig_bool zig_addo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
488#if zig_has_builtin(add_overflow)
489 zig_i8 full_res;
490 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
491 *res = zig_wrap_i8(full_res, bits);
492 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
493#else
494 return zig_addo_i32(res, lhs, rhs, bits);
495#endif
257496}
258497
259static inline uint64_t zig_addw_u64(uint64_t lhs, uint64_t rhs, uint64_t max) {
260 uint64_t thresh = max - rhs;
261 if (lhs > thresh) {
262 return lhs - thresh - 1;
263 } else {
264 return lhs + rhs;
265 }
498static inline zig_bool zig_addo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
499#if zig_has_builtin(add_overflow)
500 zig_u16 full_res;
501 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
502 *res = zig_wrap_u16(full_res, bits);
503 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
504#else
505 return zig_addo_u32(res, lhs, rhs, bits);
506#endif
266507}
267508
268static inline int64_t zig_addw_i64(int64_t lhs, int64_t rhs, int64_t min, int64_t max) {
269 if ((lhs > 0) && (rhs > 0)) {
270 int64_t thresh = max - rhs;
271 if (lhs > thresh) {
272 return min + lhs - thresh - 1;
273 }
274 } else if ((lhs < 0) && (rhs < 0)) {
275 int64_t thresh = min - rhs;
276 if (lhs < thresh) {
277 return max + lhs - thresh + 1;
278 }
279 }
280 return lhs + rhs;
509static inline zig_bool zig_addo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
510#if zig_has_builtin(add_overflow)
511 zig_i16 full_res;
512 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
513 *res = zig_wrap_i16(full_res, bits);
514 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
515#else
516 return zig_addo_i32(res, lhs, rhs, bits);
517#endif
281518}
282519
283static inline intptr_t zig_addw_isize(intptr_t lhs, intptr_t rhs, intptr_t min, intptr_t max) {
284 return (intptr_t)(((uintptr_t)lhs) + ((uintptr_t)rhs));
520static inline zig_bool zig_subo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
521#if zig_has_builtin(sub_overflow)
522 zig_u32 full_res;
523 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
524 *res = zig_wrap_u32(full_res, bits);
525 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
526#else
527 *res = zig_subw_u32(lhs, rhs, bits);
528 return *res > lhs;
529#endif
285530}
286531
287static inline short zig_addw_short(short lhs, short rhs, short min, short max) {
288 return (short)(((unsigned short)lhs) + ((unsigned short)rhs));
532zig_extern_c zig_i32 __subosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
533static inline zig_bool zig_subo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
534#if zig_has_builtin(sub_overflow)
535 zig_i32 full_res;
536 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
537#else
538 zig_c_int overflow_int;
539 zig_u32 full_res = __subosi4(lhs, rhs, &overflow_int);
540 zig_bool overflow = overflow_int != 0;
541#endif
542 *res = zig_wrap_i32(full_res, bits);
543 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
289544}
290545
291static inline int zig_addw_int(int lhs, int rhs, int min, int max) {
292 return (int)(((unsigned)lhs) + ((unsigned)rhs));
546static inline zig_bool zig_subo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
547#if zig_has_builtin(sub_overflow)
548 zig_u64 full_res;
549 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
550 *res = zig_wrap_u64(full_res, bits);
551 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
552#else
553 *res = zig_subw_u64(lhs, rhs, bits);
554 return *res > lhs;
555#endif
293556}
294557
295static inline long zig_addw_long(long lhs, long rhs, long min, long max) {
296 return (long)(((unsigned long)lhs) + ((unsigned long)rhs));
558zig_extern_c zig_i64 __subodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
559static inline zig_bool zig_subo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
560#if zig_has_builtin(sub_overflow)
561 zig_i64 full_res;
562 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
563#else
564 zig_c_int overflow_int;
565 zig_u64 full_res = __subodi4(lhs, rhs, &overflow_int);
566 zig_bool overflow = overflow_int != 0;
567#endif
568 *res = zig_wrap_i64(full_res, bits);
569 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
297570}
298571
299static inline long long zig_addw_longlong(long long lhs, long long rhs, long long min, long long max) {
300 return (long long)(((unsigned long long)lhs) + ((unsigned long long)rhs));
572static inline zig_bool zig_subo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
573#if zig_has_builtin(sub_overflow)
574 zig_u8 full_res;
575 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
576 *res = zig_wrap_u8(full_res, bits);
577 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
578#else
579 return zig_subo_u32(res, lhs, rhs, bits);
580#endif
301581}
302582
303static inline uint8_t zig_subw_u8(uint8_t lhs, uint8_t rhs, uint8_t max) {
304 if (lhs < rhs) {
305 return max - rhs - lhs + 1;
306 } else {
307 return lhs - rhs;
308 }
583static inline zig_bool zig_subo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
584#if zig_has_builtin(sub_overflow)
585 zig_i8 full_res;
586 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
587 *res = zig_wrap_i8(full_res, bits);
588 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
589#else
590 return zig_subo_i32(res, lhs, rhs, bits);
591#endif
309592}
310593
311static inline int8_t zig_subw_i8(int8_t lhs, int8_t rhs, int8_t min, int8_t max) {
312 if ((lhs > 0) && (rhs < 0)) {
313 int8_t thresh = lhs - max;
314 if (rhs < thresh) {
315 return min + (thresh - rhs - 1);
316 }
317 } else if ((lhs < 0) && (rhs > 0)) {
318 int8_t thresh = lhs - min;
319 if (rhs > thresh) {
320 return max - (rhs - thresh - 1);
321 }
322 }
323 return lhs - rhs;
594static inline zig_bool zig_subo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
595#if zig_has_builtin(sub_overflow)
596 zig_u16 full_res;
597 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
598 *res = zig_wrap_u16(full_res, bits);
599 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
600#else
601 return zig_subo_u32(res, lhs, rhs, bits);
602#endif
324603}
325604
326static inline uint16_t zig_subw_u16(uint16_t lhs, uint16_t rhs, uint16_t max) {
327 if (lhs < rhs) {
328 return max - rhs - lhs + 1;
329 } else {
330 return lhs - rhs;
331 }
605static inline zig_bool zig_subo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
606#if zig_has_builtin(sub_overflow)
607 zig_i16 full_res;
608 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
609 *res = zig_wrap_i16(full_res, bits);
610 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
611#else
612 return zig_subo_i32(res, lhs, rhs, bits);
613#endif
332614}
333615
334static inline int16_t zig_subw_i16(int16_t lhs, int16_t rhs, int16_t min, int16_t max) {
335 if ((lhs > 0) && (rhs < 0)) {
336 int16_t thresh = lhs - max;
337 if (rhs < thresh) {
338 return min + (thresh - rhs - 1);
339 }
340 } else if ((lhs < 0) && (rhs > 0)) {
341 int16_t thresh = lhs - min;
342 if (rhs > thresh) {
343 return max - (rhs - thresh - 1);
344 }
345 }
346 return lhs - rhs;
616static inline zig_bool zig_mulo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
617#if zig_has_builtin(mul_overflow)
618 zig_u32 full_res;
619 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
620 *res = zig_wrap_u32(full_res, bits);
621 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
622#else
623 *res = zig_mulw_u32(lhs, rhs, bits);
624 return rhs != zig_as_u32(0) && lhs > zig_maxInt(u32, bits) / rhs;
625#endif
347626}
348627
349static inline uint32_t zig_subw_u32(uint32_t lhs, uint32_t rhs, uint32_t max) {
350 if (lhs < rhs) {
351 return max - rhs - lhs + 1;
352 } else {
353 return lhs - rhs;
354 }
628zig_extern_c zig_i32 __mulosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
629static inline zig_bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
630#if zig_has_builtin(mul_overflow)
631 zig_i32 full_res;
632 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
633#else
634 zig_c_int overflow_int;
635 zig_u32 full_res = __mulosi4(lhs, rhs, &overflow_int);
636 zig_bool overflow = overflow_int != 0;
637#endif
638 *res = zig_wrap_i32(full_res, bits);
639 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
355640}
356641
357static inline int32_t zig_subw_i32(int32_t lhs, int32_t rhs, int32_t min, int32_t max) {
358 if ((lhs > 0) && (rhs < 0)) {
359 int32_t thresh = lhs - max;
360 if (rhs < thresh) {
361 return min + (thresh - rhs - 1);
362 }
363 } else if ((lhs < 0) && (rhs > 0)) {
364 int32_t thresh = lhs - min;
365 if (rhs > thresh) {
366 return max - (rhs - thresh - 1);
367 }
368 }
369 return lhs - rhs;
642static inline zig_bool zig_mulo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
643#if zig_has_builtin(mul_overflow)
644 zig_u64 full_res;
645 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
646 *res = zig_wrap_u64(full_res, bits);
647 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
648#else
649 *res = zig_mulw_u64(lhs, rhs, bits);
650 return rhs != zig_as_u64(0) && lhs > zig_maxInt(u64, bits) / rhs;
651#endif
370652}
371653
372static inline uint64_t zig_subw_u64(uint64_t lhs, uint64_t rhs, uint64_t max) {
373 if (lhs < rhs) {
374 return max - rhs - lhs + 1;
375 } else {
376 return lhs - rhs;
377 }
654zig_extern_c zig_i64 __mulodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
655static inline zig_bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
656#if zig_has_builtin(mul_overflow)
657 zig_i64 full_res;
658 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
659#else
660 zig_c_int overflow_int;
661 zig_u64 full_res = __mulodi4(lhs, rhs, &overflow_int);
662 zig_bool overflow = overflow_int != 0;
663#endif
664 *res = zig_wrap_i64(full_res, bits);
665 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
378666}
379667
380static inline int64_t zig_subw_i64(int64_t lhs, int64_t rhs, int64_t min, int64_t max) {
381 if ((lhs > 0) && (rhs < 0)) {
382 int64_t thresh = lhs - max;
383 if (rhs < thresh) {
384 return min + (thresh - rhs - 1);
385 }
386 } else if ((lhs < 0) && (rhs > 0)) {
387 int64_t thresh = lhs - min;
388 if (rhs > thresh) {
389 return max - (rhs - thresh - 1);
390 }
391 }
392 return lhs - rhs;
668static inline zig_bool zig_mulo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
669#if zig_has_builtin(mul_overflow)
670 zig_u8 full_res;
671 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
672 *res = zig_wrap_u8(full_res, bits);
673 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
674#else
675 return zig_mulo_u32(res, lhs, rhs, bits);
676#endif
393677}
394678
395static inline intptr_t zig_subw_isize(intptr_t lhs, intptr_t rhs, intptr_t min, intptr_t max) {
396 return (intptr_t)(((uintptr_t)lhs) - ((uintptr_t)rhs));
679static inline zig_bool zig_mulo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
680#if zig_has_builtin(mul_overflow)
681 zig_i8 full_res;
682 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
683 *res = zig_wrap_i8(full_res, bits);
684 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
685#else
686 return zig_mulo_i32(res, lhs, rhs, bits);
687#endif
397688}
398689
399static inline short zig_subw_short(short lhs, short rhs, short min, short max) {
400 return (short)(((unsigned short)lhs) - ((unsigned short)rhs));
690static inline zig_bool zig_mulo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
691#if zig_has_builtin(mul_overflow)
692 zig_u16 full_res;
693 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
694 *res = zig_wrap_u16(full_res, bits);
695 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
696#else
697 return zig_mulo_u32(res, lhs, rhs, bits);
698#endif
401699}
402700
403static inline int zig_subw_int(int lhs, int rhs, int min, int max) {
404 return (int)(((unsigned)lhs) - ((unsigned)rhs));
701static inline zig_bool zig_mulo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
702#if zig_has_builtin(mul_overflow)
703 zig_i16 full_res;
704 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
705 *res = zig_wrap_i16(full_res, bits);
706 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
707#else
708 return zig_mulo_i32(res, lhs, rhs, bits);
709#endif
405710}
406711
407static inline long zig_subw_long(long lhs, long rhs, long min, long max) {
408 return (long)(((unsigned long)lhs) - ((unsigned long)rhs));
712#define zig_int_builtins(w) \
713 static inline zig_u##w zig_shlw_u##w(zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
714 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
715 } \
716\
717 static inline zig_i##w zig_shlw_i##w(zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
718 return zig_wrap_i##w((zig_i##w)zig_shl_u##w((zig_u##w)lhs, (zig_u##w)rhs), bits); \
719 } \
720\
721 static inline zig_u##w zig_addw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
722 return zig_wrap_u##w(lhs + rhs, bits); \
723 } \
724\
725 static inline zig_i##w zig_addw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
726 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs + (zig_u##w)rhs), bits); \
727 } \
728\
729 static inline zig_u##w zig_subw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
730 return zig_wrap_u##w(lhs - rhs, bits); \
731 } \
732\
733 static inline zig_i##w zig_subw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
734 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs - (zig_u##w)rhs), bits); \
735 } \
736\
737 static inline zig_u##w zig_mulw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
738 return zig_wrap_u##w(lhs * rhs, bits); \
739 } \
740\
741 static inline zig_i##w zig_mulw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
742 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs * (zig_u##w)rhs), bits); \
743 } \
744\
745 static inline zig_bool zig_shlo_u##w(zig_u##w *res, zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
746 *res = zig_shlw_u##w(lhs, rhs, bits); \
747 return (lhs & zig_maxInt_u##w << (bits - rhs)) != zig_as_u##w(0); \
748 } \
749\
750 static inline zig_bool zig_shlo_i##w(zig_i##w *res, zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
751 *res = zig_shlw_i##w(lhs, rhs, bits); \
752 zig_i##w mask = (zig_i##w)(zig_maxInt_u##w << (bits - rhs - 1)); \
753 return (lhs & mask) != zig_as_i##w(0) && (lhs & mask) != mask; \
754 } \
755\
756 static inline zig_u##w zig_shls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
757 zig_u##w res; \
758 if (rhs >= bits) return lhs != zig_as_u##w(0) ? zig_maxInt(u##w, bits) : lhs; \
759 return zig_shlo_u##w(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u##w, bits) : res; \
760 } \
761\
762 static inline zig_i##w zig_shls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
763 zig_i##w res; \
764 if ((zig_u##w)rhs < (zig_u##w)bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
765 return lhs < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
766 } \
767\
768 static inline zig_u##w zig_adds_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
769 zig_u##w res; \
770 return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
771 } \
772\
773 static inline zig_i##w zig_adds_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
774 zig_i##w res; \
775 if (!zig_addo_i##w(&res, lhs, rhs, bits)) return res; \
776 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
777 } \
778\
779 static inline zig_u##w zig_subs_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
780 zig_u##w res; \
781 return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt(u##w, bits) : res; \
782 } \
783\
784 static inline zig_i##w zig_subs_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
785 zig_i##w res; \
786 if (!zig_subo_i##w(&res, lhs, rhs, bits)) return res; \
787 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
788 } \
789\
790 static inline zig_u##w zig_muls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
791 zig_u##w res; \
792 return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
793 } \
794\
795 static inline zig_i##w zig_muls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
796 zig_i##w res; \
797 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
798 return (lhs ^ rhs) < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
799 }
800zig_int_builtins(8)
801zig_int_builtins(16)
802zig_int_builtins(32)
803zig_int_builtins(64)
804
805#define zig_builtin8(name, val) __builtin_##name(val)
806typedef zig_c_uint zig_Builtin8;
807
808#define zig_builtin16(name, val) __builtin_##name(val)
809typedef zig_c_uint zig_Builtin16;
810
811#if INT_MIN <= INT32_MIN
812#define zig_builtin32(name, val) __builtin_##name(val)
813typedef zig_c_uint zig_Builtin32;
814#elif LONG_MIN <= INT32_MIN
815#define zig_builtin32(name, val) __builtin_##name##l(val)
816typedef zig_c_ulong zig_Builtin32;
817#endif
818
819#if INT_MIN <= INT64_MIN
820#define zig_builtin64(name, val) __builtin_##name(val)
821typedef zig_c_uint zig_Builtin64;
822#elif LONG_MIN <= INT64_MIN
823#define zig_builtin64(name, val) __builtin_##name##l(val)
824typedef zig_c_ulong zig_Builtin64;
825#elif LLONG_MIN <= INT64_MIN
826#define zig_builtin64(name, val) __builtin_##name##ll(val)
827typedef zig_c_ulonglong zig_Builtin64;
828#endif
829
830#if zig_has_builtin(clz)
831#define zig_builtin_clz(w) \
832 static inline zig_u8 zig_clz_u##w(zig_u##w val, zig_u8 bits) { \
833 if (val == 0) return bits; \
834 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
835 } \
836\
837 static inline zig_u8 zig_clz_i##w(zig_i##w val, zig_u8 bits) { \
838 return zig_clz_u##w((zig_u##w)val, bits); \
839 }
840zig_builtin_clz(8)
841zig_builtin_clz(16)
842zig_builtin_clz(32)
843zig_builtin_clz(64)
844#endif
845
846#if zig_has_builtin(ctz)
847#define zig_builtin_ctz(w) \
848 static inline zig_u8 zig_ctz_u##w(zig_u##w val, zig_u8 bits) { \
849 if (val == 0) return bits; \
850 return zig_builtin##w(ctz, val); \
851 } \
852\
853 static inline zig_u8 zig_ctz_i##w(zig_i##w val, zig_u8 bits) { \
854 return zig_ctz_u##w((zig_u##w)val, bits); \
855 }
856zig_builtin_ctz(8)
857zig_builtin_ctz(16)
858zig_builtin_ctz(32)
859zig_builtin_ctz(64)
860#endif
861
862#if zig_has_builtin(popcount)
863#define zig_builtin_popcount(w) \
864 static inline zig_u8 zig_popcount_u##w(zig_u##w val, zig_u8 bits) { \
865 (void)bits; \
866 return zig_builtin##w(popcount, val); \
867 } \
868\
869 static inline zig_u8 zig_popcount_i##w(zig_i##w val, zig_u8 bits) { \
870 \
871 return zig_popcount_u##w((zig_u##w)val, bits); \
872 }
873zig_builtin_popcount(8)
874zig_builtin_popcount(16)
875zig_builtin_popcount(32)
876zig_builtin_popcount(64)
877#endif
878
879static inline zig_u8 zig_byte_swap_u8(zig_u8 val, zig_u8 bits) {
880 return zig_wrap_u8(val >> (8 - bits), bits);
409881}
410882
411static inline long long zig_subw_longlong(long long lhs, long long rhs, long long min, long long max) {
412 return (long long)(((unsigned long long)lhs) - ((unsigned long long)rhs));
883static inline zig_i8 zig_byte_swap_i8(zig_i8 val, zig_u8 bits) {
884 return zig_wrap_i8((zig_i8)zig_byte_swap_u8((zig_u8)val, bits), bits);
413885}
414886
415static inline bool zig_addo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {
416#if defined(__GNUC__) && INT8_MAX == INT_MAX
417 if (min == INT8_MIN && max == INT8_MAX) {
418 return __builtin_sadd_overflow(lhs, rhs, (int*)res);
419 }
420#elif defined(__GNUC__) && INT8_MAX == LONG_MAX
421 if (min == INT8_MIN && max == INT8_MAX) {
422 return __builtin_saddl_overflow(lhs, rhs, (long*)res);
423 }
424#elif defined(__GNUC__) && INT8_MAX == LLONG_MAX
425 if (min == INT8_MIN && max == INT8_MAX) {
426 return __builtin_saddll_overflow(lhs, rhs, (long long*)res);
427 }
887static inline zig_u16 zig_byte_swap_u16(zig_u16 val, zig_u8 bits) {
888 zig_u16 full_res;
889#if zig_has_builtin(bswap16)
890 full_res = __builtin_bswap16(val);
891#else
892 full_res = (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 0)) << 8 |
893 (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 8)) >> 0;
428894#endif
429 int16_t big_result = (int16_t)lhs + (int16_t)rhs;
430 if (big_result > max) {
431 *res = big_result - ((int16_t)max - (int16_t)min);
432 return true;
433 }
434 if (big_result < min) {
435 *res = big_result + ((int16_t)max - (int16_t)min);
436 return true;
437 }
438 *res = big_result;
439 return false;
895 return zig_wrap_u16(full_res >> (16 - bits), bits);
440896}
441897
442static inline bool zig_addo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {
443#if defined(__GNUC__) && INT16_MAX == INT_MAX
444 if (min == INT16_MIN && max == INT16_MAX) {
445 return __builtin_sadd_overflow(lhs, rhs, (int*)res);
446 }
447#elif defined(__GNUC__) && INT16_MAX == LONG_MAX
448 if (min == INT16_MIN && max == INT16_MAX) {
449 return __builtin_saddl_overflow(lhs, rhs, (long*)res);
450 }
451#elif defined(__GNUC__) && INT16_MAX == LLONG_MAX
452 if (min == INT16_MIN && max == INT16_MAX) {
453 return __builtin_saddll_overflow(lhs, rhs, (long long*)res);
454 }
455#endif
456 int32_t big_result = (int32_t)lhs + (int32_t)rhs;
457 if (big_result > max) {
458 *res = big_result - ((int32_t)max - (int32_t)min);
459 return true;
460 }
461 if (big_result < min) {
462 *res = big_result + ((int32_t)max - (int32_t)min);
463 return true;
464 }
465 *res = big_result;
466 return false;
898static inline zig_i16 zig_byte_swap_i16(zig_i16 val, zig_u8 bits) {
899 return zig_wrap_i16((zig_i16)zig_byte_swap_u16((zig_u16)val, bits), bits);
467900}
468901
469static inline bool zig_addo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {
470#if defined(__GNUC__) && INT32_MAX == INT_MAX
471 if (min == INT32_MIN && max == INT32_MAX) {
472 return __builtin_sadd_overflow(lhs, rhs, (int*)res);
473 }
474#elif defined(__GNUC__) && INT32_MAX == LONG_MAX
475 if (min == INT32_MIN && max == INT32_MAX) {
476 return __builtin_saddl_overflow(lhs, rhs, (long*)res);
477 }
478#elif defined(__GNUC__) && INT32_MAX == LLONG_MAX
479 if (min == INT32_MIN && max == INT32_MAX) {
480 return __builtin_saddll_overflow(lhs, rhs, (long long*)res);
481 }
482#endif
483 int64_t big_result = (int64_t)lhs + (int64_t)rhs;
484 if (big_result > max) {
485 *res = big_result - ((int64_t)max - (int64_t)min);
486 return true;
487 }
488 if (big_result < min) {
489 *res = big_result + ((int64_t)max - (int64_t)min);
490 return true;
491 }
492 *res = big_result;
493 return false;
494}
495
496static inline bool zig_addo_i64(int64_t lhs, int64_t rhs, int64_t *res, int64_t min, int64_t max) {
497 bool overflow;
498#if defined(__GNUC__) && INT64_MAX == INT_MAX
499 overflow = __builtin_sadd_overflow(lhs, rhs, (int*)res);
500#elif defined(__GNUC__) && INT64_MAX == LONG_MAX
501 overflow = __builtin_saddl_overflow(lhs, rhs, (long*)res);
502#elif defined(__GNUC__) && INT64_MAX == LLONG_MAX
503 overflow = __builtin_saddll_overflow(lhs, rhs, (long long*)res);
902static inline zig_u32 zig_byte_swap_u32(zig_u32 val, zig_u8 bits) {
903 zig_u32 full_res;
904#if zig_has_builtin(bswap32)
905 full_res = __builtin_bswap32(val);
504906#else
505 int int_overflow;
506 *res = __addodi4(lhs, rhs, &int_overflow);
507 overflow = int_overflow != 0;
508#endif
509 if (!overflow) {
510 if (*res > max) {
511 // TODO adjust the result to be the truncated bits
512 return true;
513 } else if (*res < min) {
514 // TODO adjust the result to be the truncated bits
515 return true;
516 }
517 }
518 return overflow;
907 full_res = (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 0)) << 16 |
908 (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 16)) >> 0;
909#endif
910 return zig_wrap_u32(full_res >> (32 - bits), bits);
519911}
520912
521static inline bool zig_addo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {
522 bool overflow;
523#if defined(__GNUC__) && INT128_MAX == INT_MAX
524 overflow = __builtin_sadd_overflow(lhs, rhs, (int*)res);
525#elif defined(__GNUC__) && INT128_MAX == LONG_MAX
526 overflow = __builtin_saddl_overflow(lhs, rhs, (long*)res);
527#elif defined(__GNUC__) && INT128_MAX == LLONG_MAX
528 overflow = __builtin_saddll_overflow(lhs, rhs, (long long*)res);
529#else
530 int int_overflow;
531 *res = __addoti4(lhs, rhs, &int_overflow);
532 overflow = int_overflow != 0;
533#endif
534 if (!overflow) {
535 if (*res > max) {
536 // TODO adjust the result to be the truncated bits
537 return true;
538 } else if (*res < min) {
539 // TODO adjust the result to be the truncated bits
540 return true;
541 }
542 }
543 return overflow;
913static inline zig_i32 zig_byte_swap_i32(zig_i32 val, zig_u8 bits) {
914 return zig_wrap_i32((zig_i32)zig_byte_swap_u32((zig_u32)val, bits), bits);
544915}
545916
546static inline bool zig_addo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {
547#if defined(__GNUC__) && UINT8_MAX == UINT_MAX
548 if (max == UINT8_MAX) {
549 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
550 }
551#elif defined(__GNUC__) && UINT8_MAX == ULONG_MAX
552 if (max == UINT8_MAX) {
553 return __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
554 }
555#elif defined(__GNUC__) && UINT8_MAX == ULLONG_MAX
556 if (max == UINT8_MAX) {
557 return __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
558 }
917static inline zig_u64 zig_byte_swap_u64(zig_u64 val, zig_u8 bits) {
918 zig_u64 full_res;
919#if zig_has_builtin(bswap64)
920 full_res = __builtin_bswap64(val);
921#else
922 full_res = (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 0)) << 32 |
923 (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 32)) >> 0;
559924#endif
560 uint16_t big_result = (uint16_t)lhs + (uint16_t)rhs;
561 if (big_result > max) {
562 *res = big_result - max - 1;
563 return true;
564 }
565 *res = big_result;
566 return false;
925 return zig_wrap_u64(full_res >> (64 - bits), bits);
567926}
568927
569static inline uint16_t zig_addo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {
570#if defined(__GNUC__) && UINT16_MAX == UINT_MAX
571 if (max == UINT16_MAX) {
572 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
573 }
574#elif defined(__GNUC__) && UINT16_MAX == ULONG_MAX
575 if (max == UINT16_MAX) {
576 return __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
577 }
578#elif defined(__GNUC__) && UINT16_MAX == ULLONG_MAX
579 if (max == UINT16_MAX) {
580 return __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
581 }
582#endif
583 uint32_t big_result = (uint32_t)lhs + (uint32_t)rhs;
584 if (big_result > max) {
585 *res = big_result - max - 1;
586 return true;
587 }
588 *res = big_result;
589 return false;
928static inline zig_i64 zig_byte_swap_i64(zig_i64 val, zig_u8 bits) {
929 return zig_wrap_i64((zig_i64)zig_byte_swap_u64((zig_u64)val, bits), bits);
590930}
591931
592static inline uint32_t zig_addo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {
593#if defined(__GNUC__) && UINT32_MAX == UINT_MAX
594 if (max == UINT32_MAX) {
595 return __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
596 }
597#elif defined(__GNUC__) && UINT32_MAX == ULONG_MAX
598 if (max == UINT32_MAX) {
599 return __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
600 }
601#elif defined(__GNUC__) && UINT32_MAX == ULLONG_MAX
602 if (max == UINT32_MAX) {
603 return __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
604 }
932static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
933 zig_u8 full_res;
934#if zig_has_builtin(bitreverse8)
935 full_res = __builtin_bitreverse8(val);
936#else
937 static zig_u8 const lut[0x10] = {
938 0b0000, 0b1000, 0b0100, 0b1100,
939 0b0010, 0b1010, 0b0110, 0b1110,
940 0b0001, 0b1001, 0b0101, 0b1101,
941 0b0011, 0b1011, 0b0111, 0b1111,
942 };
943 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
605944#endif
606 uint64_t big_result = (uint64_t)lhs + (uint64_t)rhs;
607 if (big_result > max) {
608 *res = big_result - max - 1;
609 return true;
610 }
611 *res = big_result;
612 return false;
613}
614
615static inline uint64_t zig_addo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {
616 bool overflow;
617#if defined(__GNUC__) && UINT64_MAX == UINT_MAX
618 overflow = __builtin_uadd_overflow(lhs, rhs, (unsigned int*)res);
619#elif defined(__GNUC__) && UINT64_MAX == ULONG_MAX
620 overflow = __builtin_uaddl_overflow(lhs, rhs, (unsigned long*)res);
621#elif defined(__GNUC__) && UINT64_MAX == ULLONG_MAX
622 overflow = __builtin_uaddll_overflow(lhs, rhs, (unsigned long long*)res);
945 return zig_wrap_u8(full_res >> (8 - bits), bits);
946}
947
948static inline zig_i8 zig_bit_reverse_i8(zig_i8 val, zig_u8 bits) {
949 return zig_wrap_i8((zig_i8)zig_bit_reverse_u8((zig_u8)val, bits), bits);
950}
951
952static inline zig_u16 zig_bit_reverse_u16(zig_u16 val, zig_u8 bits) {
953 zig_u16 full_res;
954#if zig_has_builtin(bitreverse16)
955 full_res = __builtin_bitreverse16(val);
623956#else
624 int int_overflow;
625 *res = __uaddodi4(lhs, rhs, &int_overflow);
626 overflow = int_overflow != 0;
957 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0)) << 8 |
958 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8)) >> 0;
627959#endif
628 if (*res > max && !overflow) {
629 *res -= max - 1;
630 return true;
631 }
632 return overflow;
960 return zig_wrap_u16(full_res >> (16 - bits), bits);
633961}
634962
635static inline uint128_t zig_addo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {
636 int overflow;
637 *res = __uaddoti4(lhs, rhs, &overflow);
638 if (*res > max && overflow == 0) {
639 *res -= max - 1;
640 return true;
641 }
642 return overflow != 0;
963static inline zig_i16 zig_bit_reverse_i16(zig_i16 val, zig_u8 bits) {
964 return zig_wrap_i16((zig_i16)zig_bit_reverse_u16((zig_u16)val, bits), bits);
643965}
644966
645static inline bool zig_subo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {
646#if defined(__GNUC__) && INT8_MAX == INT_MAX
647 if (min == INT8_MIN && max == INT8_MAX) {
648 return __builtin_ssub_overflow(lhs, rhs, (int*)res);
649 }
650#elif defined(__GNUC__) && INT8_MAX == LONG_MAX
651 if (min == INT8_MIN && max == INT8_MAX) {
652 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);
653 }
654#elif defined(__GNUC__) && INT8_MAX == LLONG_MAX
655 if (min == INT8_MIN && max == INT8_MAX) {
656 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
657 }
967static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) {
968 zig_u32 full_res;
969#if zig_has_builtin(bitreverse32)
970 full_res = __builtin_bitreverse32(val);
971#else
972 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0)) << 16 |
973 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16)) >> 0;
658974#endif
659 int16_t big_result = (int16_t)lhs - (int16_t)rhs;
660 if (big_result > max) {
661 *res = big_result - ((int16_t)max - (int16_t)min);
662 return true;
663 }
664 if (big_result < min) {
665 *res = big_result + ((int16_t)max - (int16_t)min);
666 return true;
667 }
668 *res = big_result;
669 return false;
975 return zig_wrap_u32(full_res >> (32 - bits), bits);
670976}
671977
672static inline bool zig_subo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {
673#if defined(__GNUC__) && INT16_MAX == INT_MAX
674 if (min == INT16_MIN && max == INT16_MAX) {
675 return __builtin_ssub_overflow(lhs, rhs, (int*)res);
676 }
677#elif defined(__GNUC__) && INT16_MAX == LONG_MAX
678 if (min == INT16_MIN && max == INT16_MAX) {
679 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);
680 }
681#elif defined(__GNUC__) && INT16_MAX == LLONG_MAX
682 if (min == INT16_MIN && max == INT16_MAX) {
683 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
684 }
978static inline zig_i32 zig_bit_reverse_i32(zig_i32 val, zig_u8 bits) {
979 return zig_wrap_i32((zig_i32)zig_bit_reverse_u32((zig_u32)val, bits), bits);
980}
981
982static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) {
983 zig_u64 full_res;
984#if zig_has_builtin(bitreverse64)
985 full_res = __builtin_bitreverse64(val);
986#else
987 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0)) << 32 |
988 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32)) >> 0;
685989#endif
686 int32_t big_result = (int32_t)lhs - (int32_t)rhs;
687 if (big_result > max) {
688 *res = big_result - ((int32_t)max - (int32_t)min);
689 return true;
690 }
691 if (big_result < min) {
692 *res = big_result + ((int32_t)max - (int32_t)min);
693 return true;
694 }
695 *res = big_result;
696 return false;
990 return zig_wrap_u64(full_res >> (64 - bits), bits);
697991}
698992
699static inline bool zig_subo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {
700#if defined(__GNUC__) && INT32_MAX == INT_MAX
701 if (min == INT32_MIN && max == INT32_MAX) {
702 return __builtin_ssub_overflow(lhs, rhs, (int*)res);
703 }
704#elif defined(__GNUC__) && INT32_MAX == LONG_MAX
705 if (min == INT32_MIN && max == INT32_MAX) {
706 return __builtin_ssubl_overflow(lhs, rhs, (long*)res);
707 }
708#elif defined(__GNUC__) && INT32_MAX == LLONG_MAX
709 if (min == INT32_MIN && max == INT32_MAX) {
710 return __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
711 }
993static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {
994 return zig_wrap_i64((zig_i64)zig_bit_reverse_u64((zig_u64)val, bits), bits);
995}
996
997/* ======================== 128-bit Integer Routines ======================== */
998
999#if !defined(zig_has_int128)
1000# if defined(__SIZEOF_INT128__)
1001# define zig_has_int128 1
1002# else
1003# define zig_has_int128 0
1004# endif
7121005#endif
713 int64_t big_result = (int64_t)lhs - (int64_t)rhs;
714 if (big_result > max) {
715 *res = big_result - ((int64_t)max - (int64_t)min);
716 return true;
1006
1007#if zig_has_int128
1008
1009typedef unsigned __int128 zig_u128;
1010typedef signed __int128 zig_i128;
1011
1012#define zig_as_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1013#define zig_as_i128(hi, lo) ((zig_i128)zig_as_u128(hi, lo))
1014#define zig_hi_u128(val) ((zig_u64)((val) >> 64))
1015#define zig_lo_u128(val) ((zig_u64)((val) >> 0))
1016#define zig_hi_i128(val) ((zig_i64)((val) >> 64))
1017#define zig_lo_i128(val) ((zig_u64)((val) >> 0))
1018#define zig_bitcast_u128(val) ((zig_u128)(val))
1019#define zig_bitcast_i128(val) ((zig_i128)(val))
1020#define zig_cmp_int128(Type) \
1021 static inline zig_i8 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1022 return (lhs > rhs) - (lhs < rhs); \
7171023 }
718 if (big_result < min) {
719 *res = big_result + ((int64_t)max - (int64_t)min);
720 return true;
1024#define zig_bit_int128(Type, operation, operator) \
1025 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1026 return lhs operator rhs; \
7211027 }
722 *res = big_result;
723 return false;
724}
725
726static inline bool zig_subo_i64(int64_t lhs, int64_t rhs, int64_t *res, int64_t min, int64_t max) {
727 bool overflow;
728#if defined(__GNUC__) && INT64_MAX == INT_MAX
729 overflow = __builtin_ssub_overflow(lhs, rhs, (int*)res);
730#elif defined(__GNUC__) && INT64_MAX == LONG_MAX
731 overflow = __builtin_ssubl_overflow(lhs, rhs, (long*)res);
732#elif defined(__GNUC__) && INT64_MAX == LLONG_MAX
733 overflow = __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
1028
1029#else /* zig_has_int128 */
1030
1031#if __LITTLE_ENDIAN__ || _MSC_VER
1032typedef struct { zig_align(16) zig_u64 lo; zig_u64 hi; } zig_u128;
1033typedef struct { zig_align(16) zig_u64 lo; zig_i64 hi; } zig_i128;
7341034#else
735 int int_overflow;
736 *res = __subodi4(lhs, rhs, &int_overflow);
737 overflow = int_overflow != 0;
738#endif
739 if (!overflow) {
740 if (*res > max) {
741 // TODO adjust the result to be the truncated bits
742 return true;
743 } else if (*res < min) {
744 // TODO adjust the result to be the truncated bits
745 return true;
746 }
1035typedef struct { zig_align(16) zig_u64 hi; zig_u64 lo; } zig_u128;
1036typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
1037#endif
1038
1039#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1040#define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
1041#define zig_hi_u128(val) ((val).hi)
1042#define zig_lo_u128(val) ((val).lo)
1043#define zig_hi_i128(val) ((val).hi)
1044#define zig_lo_i128(val) ((val).lo)
1045#define zig_bitcast_u128(val) zig_as_u128((zig_u64)(val).hi, (val).lo)
1046#define zig_bitcast_i128(val) zig_as_i128((zig_i64)(val).hi, (val).lo)
1047#define zig_cmp_int128(Type) \
1048 static inline zig_i8 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1049 return (lhs.hi == rhs.hi) \
1050 ? (lhs.lo > rhs.lo) - (lhs.lo < rhs.lo) \
1051 : (lhs.hi > rhs.hi) - (lhs.hi < rhs.hi); \
7471052 }
748 return overflow;
1053#define zig_bit_int128(Type, operation, operator) \
1054 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1055 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
1056 }
1057
1058#endif /* zig_has_int128 */
1059
1060#define zig_minInt_u128 zig_as_u128(zig_minInt_u64, zig_minInt_u64)
1061#define zig_maxInt_u128 zig_as_u128(zig_maxInt_u64, zig_maxInt_u64)
1062#define zig_minInt_i128 zig_as_i128(zig_minInt_i64, zig_minInt_u64)
1063#define zig_maxInt_i128 zig_as_i128(zig_maxInt_i64, zig_maxInt_u64)
1064
1065zig_cmp_int128(u128)
1066zig_cmp_int128(i128)
1067
1068zig_bit_int128(u128, and, &)
1069zig_bit_int128(i128, and, &)
1070
1071zig_bit_int128(u128, or, |)
1072zig_bit_int128(i128, or, |)
1073
1074zig_bit_int128(u128, xor, ^)
1075zig_bit_int128(i128, xor, ^)
1076
1077static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs);
1078
1079#if zig_has_int128
1080
1081static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1082 return val ^ zig_maxInt(u128, bits);
7491083}
7501084
751static inline bool zig_subo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {
752 bool overflow;
753#if defined(__GNUC__) && INT128_MAX == INT_MAX
754 overflow = __builtin_ssub_overflow(lhs, rhs, (int*)res);
755#elif defined(__GNUC__) && INT128_MAX == LONG_MAX
756 overflow = __builtin_ssubl_overflow(lhs, rhs, (long*)res);
757#elif defined(__GNUC__) && INT128_MAX == LLONG_MAX
758 overflow = __builtin_ssubll_overflow(lhs, rhs, (long long*)res);
759#else
760 int int_overflow;
761 *res = __suboti4(lhs, rhs, &int_overflow);
762 overflow = int_overflow != 0;
763#endif
764 if (!overflow) {
765 if (*res > max) {
766 // TODO adjust the result to be the truncated bits
767 return true;
768 } else if (*res < min) {
769 // TODO adjust the result to be the truncated bits
770 return true;
771 }
772 }
773 return overflow;
1085static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1086 (void)bits;
1087 return ~val;
7741088}
7751089
776static inline bool zig_subo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {
777#if defined(__GNUC__) && UINT8_MAX == UINT_MAX
778 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
779#elif defined(__GNUC__) && UINT8_MAX == ULONG_MAX
780 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
781#elif defined(__GNUC__) && UINT8_MAX == ULLONG_MAX
782 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
783#endif
784 if (rhs > lhs) {
785 *res = max - (rhs - lhs - 1);
786 return true;
787 }
788 *res = lhs - rhs;
789 return false;
1090static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1091 return lhs >> rhs;
7901092}
7911093
792static inline uint16_t zig_subo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {
793#if defined(__GNUC__) && UINT16_MAX == UINT_MAX
794 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
795#elif defined(__GNUC__) && UINT16_MAX == ULONG_MAX
796 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
797#elif defined(__GNUC__) && UINT16_MAX == ULLONG_MAX
798 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
799#endif
800 if (rhs > lhs) {
801 *res = max - (rhs - lhs - 1);
802 return true;
803 }
804 *res = lhs - rhs;
805 return false;
806}
807
808static inline uint32_t zig_subo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {
809 if (max == UINT32_MAX) {
810#if defined(__GNUC__) && UINT32_MAX == UINT_MAX
811 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
812#elif defined(__GNUC__) && UINT32_MAX == ULONG_MAX
813 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
814#elif defined(__GNUC__) && UINT32_MAX == ULLONG_MAX
815 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
816#endif
817 int int_overflow;
818 *res = __usubosi4(lhs, rhs, &int_overflow);
819 return int_overflow != 0;
820 } else {
821 if (rhs > lhs) {
822 *res = max - (rhs - lhs - 1);
823 return true;
824 }
825 *res = lhs - rhs;
826 return false;
827 }
1094static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1095 return lhs << rhs;
8281096}
8291097
830static inline uint64_t zig_subo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {
831 if (max == UINT64_MAX) {
832#if defined(__GNUC__) && UINT64_MAX == UINT_MAX
833 return __builtin_usub_overflow(lhs, rhs, (unsigned int*)res);
834#elif defined(__GNUC__) && UINT64_MAX == ULONG_MAX
835 return __builtin_usubl_overflow(lhs, rhs, (unsigned long*)res);
836#elif defined(__GNUC__) && UINT64_MAX == ULLONG_MAX
837 return __builtin_usubll_overflow(lhs, rhs, (unsigned long long*)res);
838#else
839 int int_overflow;
840 *res = __usubodi4(lhs, rhs, &int_overflow);
841 return int_overflow != 0;
842#endif
843 } else {
844 if (rhs > lhs) {
845 *res = max - (rhs - lhs - 1);
846 return true;
847 }
848 *res = lhs - rhs;
849 return false;
850 }
1098static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1099 return lhs << rhs;
8511100}
8521101
853static inline uint128_t zig_subo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {
854 if (max == UINT128_MAX) {
855 int int_overflow;
856 *res = __usuboti4(lhs, rhs, &int_overflow);
857 return int_overflow != 0;
858 } else {
859 if (rhs > lhs) {
860 *res = max - (rhs - lhs - 1);
861 return true;
862 }
863 *res = lhs - rhs;
864 return false;
865 }
1102static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
1103 return lhs + rhs;
8661104}
8671105
868static inline bool zig_mulo_i8(int8_t lhs, int8_t rhs, int8_t *res, int8_t min, int8_t max) {
869#if defined(__GNUC__) && INT8_MAX == INT_MAX
870 if (min == INT8_MIN && max == INT8_MAX) {
871 return __builtin_smul_overflow(lhs, rhs, (int*)res);
872 }
873#elif defined(__GNUC__) && INT8_MAX == LONG_MAX
874 if (min == INT8_MIN && max == INT8_MAX) {
875 return __builtin_smull_overflow(lhs, rhs, (long*)res);
876 }
877#elif defined(__GNUC__) && INT8_MAX == LLONG_MAX
878 if (min == INT8_MIN && max == INT8_MAX) {
879 return __builtin_smulll_overflow(lhs, rhs, (long long*)res);
880 }
881#endif
882 int16_t big_result = (int16_t)lhs * (int16_t)rhs;
883 if (big_result > max) {
884 *res = big_result - ((int16_t)max - (int16_t)min);
885 return true;
886 }
887 if (big_result < min) {
888 *res = big_result + ((int16_t)max - (int16_t)min);
889 return true;
890 }
891 *res = big_result;
892 return false;
1106static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
1107 return lhs + rhs;
8931108}
8941109
895static inline bool zig_mulo_i16(int16_t lhs, int16_t rhs, int16_t *res, int16_t min, int16_t max) {
896#if defined(__GNUC__) && INT16_MAX == INT_MAX
897 if (min == INT16_MIN && max == INT16_MAX) {
898 return __builtin_smul_overflow(lhs, rhs, (int*)res);
899 }
900#elif defined(__GNUC__) && INT16_MAX == LONG_MAX
901 if (min == INT16_MIN && max == INT16_MAX) {
902 return __builtin_smull_overflow(lhs, rhs, (long*)res);
903 }
904#elif defined(__GNUC__) && INT16_MAX == LLONG_MAX
905 if (min == INT16_MIN && max == INT16_MAX) {
906 return __builtin_smulll_overflow(lhs, rhs, (long long*)res);
907 }
908#endif
909 int32_t big_result = (int32_t)lhs * (int32_t)rhs;
910 if (big_result > max) {
911 *res = big_result - ((int32_t)max - (int32_t)min);
912 return true;
913 }
914 if (big_result < min) {
915 *res = big_result + ((int32_t)max - (int32_t)min);
916 return true;
917 }
918 *res = big_result;
919 return false;
1110static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
1111 return lhs - rhs;
9201112}
9211113
922static inline bool zig_mulo_i32(int32_t lhs, int32_t rhs, int32_t *res, int32_t min, int32_t max) {
923#if defined(__GNUC__) && INT32_MAX == INT_MAX
924 if (min == INT32_MIN && max == INT32_MAX) {
925 return __builtin_smul_overflow(lhs, rhs, (int*)res);
926 }
927#elif defined(__GNUC__) && INT32_MAX == LONG_MAX
928 if (min == INT32_MIN && max == INT32_MAX) {
929 return __builtin_smull_overflow(lhs, rhs, (long*)res);
930 }
931#elif defined(__GNUC__) && INT32_MAX == LLONG_MAX
932 if (min == INT32_MIN && max == INT32_MAX) {
933 return __builtin_smulll_overflow(lhs, rhs, (long long*)res);
934 }
935#endif
936 int64_t big_result = (int64_t)lhs * (int64_t)rhs;
937 if (big_result > max) {
938 *res = big_result - ((int64_t)max - (int64_t)min);
939 return true;
940 }
941 if (big_result < min) {
942 *res = big_result + ((int64_t)max - (int64_t)min);
943 return true;
944 }
945 *res = big_result;
946 return false;
947}
948
949static inline bool zig_mulo_i64(int64_t lhs, int64_t rhs, int64_t *res, int64_t min, int64_t max) {
950 bool overflow;
951#if defined(__GNUC__) && INT64_MAX == INT_MAX
952 overflow = __builtin_smul_overflow(lhs, rhs, (int*)res);
953#elif defined(__GNUC__) && INT64_MAX == LONG_MAX
954 overflow = __builtin_smull_overflow(lhs, rhs, (long*)res);
955#elif defined(__GNUC__) && INT64_MAX == LLONG_MAX
956 overflow = __builtin_smulll_overflow(lhs, rhs, (long long*)res);
957#else
958 int int_overflow;
959 *res = __mulodi4(lhs, rhs, &int_overflow);
960 overflow = int_overflow != 0;
961#endif
962 if (!overflow) {
963 if (*res > max) {
964 // TODO adjust the result to be the truncated bits
965 return true;
966 } else if (*res < min) {
967 // TODO adjust the result to be the truncated bits
968 return true;
969 }
970 }
971 return overflow;
1114static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1115 return lhs - rhs;
9721116}
9731117
974static inline bool zig_mulo_i128(int128_t lhs, int128_t rhs, int128_t *res, int128_t min, int128_t max) {
975 bool overflow;
976#if defined(__GNUC__) && INT128_MAX == INT_MAX
977 overflow = __builtin_smul_overflow(lhs, rhs, (int*)res);
978#elif defined(__GNUC__) && INT128_MAX == LONG_MAX
979 overflow = __builtin_smull_overflow(lhs, rhs, (long*)res);
980#elif defined(__GNUC__) && INT128_MAX == LLONG_MAX
981 overflow = __builtin_smulll_overflow(lhs, rhs, (long long*)res);
982#else
983 int int_overflow;
984 *res = __muloti4(lhs, rhs, &int_overflow);
985 overflow = int_overflow != 0;
986#endif
987 if (!overflow) {
988 if (*res > max) {
989 // TODO adjust the result to be the truncated bits
990 return true;
991 } else if (*res < min) {
992 // TODO adjust the result to be the truncated bits
993 return true;
994 }
995 }
996 return overflow;
1118static inline zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1119 return lhs * rhs;
9971120}
9981121
999static inline bool zig_mulo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t max) {
1000#if defined(__GNUC__) && UINT8_MAX == UINT_MAX
1001 if (max == UINT8_MAX) {
1002 return __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1003 }
1004#elif defined(__GNUC__) && UINT8_MAX == ULONG_MAX
1005 if (max == UINT8_MAX) {
1006 return __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1007 }
1008#elif defined(__GNUC__) && UINT8_MAX == ULLONG_MAX
1009 if (max == UINT8_MAX) {
1010 return __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1011 }
1012#endif
1013 uint16_t big_result = (uint16_t)lhs * (uint16_t)rhs;
1014 if (big_result > max) {
1015 *res = big_result - max - 1;
1016 return true;
1017 }
1018 *res = big_result;
1019 return false;
1122static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1123 return lhs * rhs;
10201124}
10211125
1022static inline uint16_t zig_mulo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint16_t max) {
1023#if defined(__GNUC__) && UINT16_MAX == UINT_MAX
1024 if (max == UINT16_MAX) {
1025 return __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1026 }
1027#elif defined(__GNUC__) && UINT16_MAX == ULONG_MAX
1028 if (max == UINT16_MAX) {
1029 return __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1030 }
1031#elif defined(__GNUC__) && UINT16_MAX == ULLONG_MAX
1032 if (max == UINT16_MAX) {
1033 return __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1034 }
1035#endif
1036 uint32_t big_result = (uint32_t)lhs * (uint32_t)rhs;
1037 if (big_result > max) {
1038 *res = big_result - max - 1;
1039 return true;
1040 }
1041 *res = big_result;
1042 return false;
1126static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
1127 return lhs / rhs;
10431128}
10441129
1045static inline uint32_t zig_mulo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint32_t max) {
1046#if defined(__GNUC__) && UINT32_MAX == UINT_MAX
1047 if (max == UINT32_MAX) {
1048 return __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1049 }
1050#elif defined(__GNUC__) && UINT32_MAX == ULONG_MAX
1051 if (max == UINT32_MAX) {
1052 return __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1053 }
1054#elif defined(__GNUC__) && UINT32_MAX == ULLONG_MAX
1055 if (max == UINT32_MAX) {
1056 return __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1057 }
1058#endif
1059 uint64_t big_result = (uint64_t)lhs * (uint64_t)rhs;
1060 if (big_result > max) {
1061 *res = big_result - max - 1;
1062 return true;
1063 }
1064 *res = big_result;
1065 return false;
1066}
1067
1068static inline uint64_t zig_mulo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint64_t max) {
1069 bool overflow;
1070#if defined(__GNUC__) && UINT64_MAX == UINT_MAX
1071 overflow = __builtin_umul_overflow(lhs, rhs, (unsigned int*)res);
1072#elif defined(__GNUC__) && UINT64_MAX == ULONG_MAX
1073 overflow = __builtin_umull_overflow(lhs, rhs, (unsigned long*)res);
1074#elif defined(__GNUC__) && UINT64_MAX == ULLONG_MAX
1075 overflow = __builtin_umulll_overflow(lhs, rhs, (unsigned long long*)res);
1076#else
1077 int int_overflow;
1078 *res = __umulodi4(lhs, rhs, &int_overflow);
1079 overflow = int_overflow != 0;
1080#endif
1081 if (*res > max && !overflow) {
1082 *res -= max - 1;
1083 return true;
1084 }
1085 return overflow;
1130static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
1131 return lhs / rhs;
10861132}
10871133
1088static inline uint128_t zig_mulo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint128_t max) {
1089 int overflow;
1090 *res = __umuloti4(lhs, rhs, &overflow);
1091 if (*res > max && overflow == 0) {
1092 *res -= max - 1;
1093 return true;
1094 }
1095 return overflow != 0;
1134static inline zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
1135 return lhs % rhs;
1136}
1137
1138static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
1139 return lhs % rhs;
1140}
1141
1142static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1143 return zig_div_trunc_i128(lhs, rhs) - (((lhs ^ rhs) & zig_rem_i128(lhs, rhs)) < zig_as_i128(0, 0));
1144}
1145
1146static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1147 zig_i128 rem = zig_rem_i128(lhs, rhs);
1148 return rem + (((lhs ^ rhs) & rem) < zig_as_i128(0, 0) ? rhs : zig_as_i128(0, 0));
1149}
1150
1151#else /* zig_has_int128 */
1152
1153static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1154 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
10961155}
10971156
1098static inline float zig_bitcast_f32_u32(uint32_t arg) {
1099 float dest;
1100 memcpy(&dest, &arg, sizeof dest);
1101 return dest;
1102}
1103
1104static inline float zig_bitcast_f64_u64(uint64_t arg) {
1105 double dest;
1106 memcpy(&dest, &arg, sizeof dest);
1107 return dest;
1108}
1109
1110#define zig_add_sat_u(ZT, T) static inline T zig_adds_##ZT(T x, T y, T max) { \
1111 return (x > max - y) ? max : x + y; \
1112}
1113
1114#define zig_add_sat_s(ZT, T, T2) static inline T zig_adds_##ZT(T2 x, T2 y, T2 min, T2 max) { \
1115 T2 res = x + y; \
1116 return (res < min) ? min : (res > max) ? max : res; \
1157static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1158 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
11171159}
11181160
1119zig_add_sat_u( u8, uint8_t)
1120zig_add_sat_s( i8, int8_t, int16_t)
1121zig_add_sat_u(u16, uint16_t)
1122zig_add_sat_s(i16, int16_t, int32_t)
1123zig_add_sat_u(u32, uint32_t)
1124zig_add_sat_s(i32, int32_t, int64_t)
1125zig_add_sat_u(u64, uint64_t)
1126zig_add_sat_s(i64, int64_t, int128_t)
1127zig_add_sat_s(isize, intptr_t, int128_t)
1128zig_add_sat_s(short, short, int)
1129zig_add_sat_s(int, int, long)
1130zig_add_sat_s(long, long, long long)
1131
1132#define zig_sub_sat_u(ZT, T) static inline T zig_subs_##ZT(T x, T y, T max) { \
1133 return (x > max + y) ? max : x - y; \
1161static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1162 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1163 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
11341164}
11351165
1136#define zig_sub_sat_s(ZT, T, T2) static inline T zig_subs_##ZT(T2 x, T2 y, T2 min, T2 max) { \
1137 T2 res = x - y; \
1138 return (res < min) ? min : (res > max) ? max : res; \
1139}
1140
1141zig_sub_sat_u( u8, uint8_t)
1142zig_sub_sat_s( i8, int8_t, int16_t)
1143zig_sub_sat_u(u16, uint16_t)
1144zig_sub_sat_s(i16, int16_t, int32_t)
1145zig_sub_sat_u(u32, uint32_t)
1146zig_sub_sat_s(i32, int32_t, int64_t)
1147zig_sub_sat_u(u64, uint64_t)
1148zig_sub_sat_s(i64, int64_t, int128_t)
1149zig_sub_sat_s(isize, intptr_t, int128_t)
1150zig_sub_sat_s(short, short, int)
1151zig_sub_sat_s(int, int, long)
1152zig_sub_sat_s(long, long, long long)
1166static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1167 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1168 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1169}
11531170
1171static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1172 if (rhs >= zig_as_u8(64)) return (zig_i128){ .hi = lhs.hi << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1173 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1174}
1175
1176static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
1177 zig_u128 res;
1178 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1179 return res;
1180}
11541181
1155#define zig_mul_sat_u(ZT, T, T2) static inline T zig_muls_##ZT(T2 x, T2 y, T2 max) { \
1156 T2 res = x * y; \
1157 return (res > max) ? max : res; \
1182static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
1183 zig_i128 res;
1184 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1185 return res;
11581186}
11591187
1160#define zig_mul_sat_s(ZT, T, T2) static inline T zig_muls_##ZT(T2 x, T2 y, T2 min, T2 max) { \
1161 T2 res = x * y; \
1162 return (res < min) ? min : (res > max) ? max : res; \
1188static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
1189 zig_u128 res;
1190 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1191 return res;
11631192}
11641193
1165zig_mul_sat_u(u8, uint8_t, uint16_t)
1166zig_mul_sat_s(i8, int8_t, int16_t)
1167zig_mul_sat_u(u16, uint16_t, uint32_t)
1168zig_mul_sat_s(i16, int16_t, int32_t)
1169zig_mul_sat_u(u32, uint32_t, uint64_t)
1170zig_mul_sat_s(i32, int32_t, int64_t)
1171zig_mul_sat_u(u64, uint64_t, uint128_t)
1172zig_mul_sat_s(i64, int64_t, int128_t)
1173zig_mul_sat_s(isize, intptr_t, int128_t)
1174zig_mul_sat_s(short, short, int)
1175zig_mul_sat_s(int, int, long)
1176zig_mul_sat_s(long, long, long long)
1194static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1195 zig_i128 res;
1196 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, zig_maxInt_u64);
1197 return res;
1198}
11771199
1178#define zig_shl_sat_u(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T max) { \
1179 if(x == 0) return 0; \
1180 T bits_set = 64 - __builtin_clzll(x); \
1181 return (bits_set + y > bits) ? max : x << y; \
1200static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1201 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));
11821202}
11831203
1184#define zig_shl_sat_s(ZT, T, bits) static inline T zig_shls_##ZT(T x, T y, T min, T max) { \
1185 if(x == 0) return 0; \
1186 T x_twos_comp = x < 0 ? -x : x; \
1187 T bits_set = 64 - __builtin_clzll(x_twos_comp); \
1188 T min_or_max = (x < 0) ? min : max; \
1189 return (y + bits_set > bits ) ? min_or_max : x << y; \
1204static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1205 zig_i128 rem = zig_rem_i128(lhs, rhs);
1206 return rem + (((lhs.hi ^ rhs.hi) & rem.hi) < zig_as_i64(0) ? rhs : zig_as_i128(0, 0));
11901207}
11911208
1192zig_shl_sat_u(u8, uint8_t, 8)
1193zig_shl_sat_s(i8, int8_t, 7)
1194zig_shl_sat_u(u16, uint16_t, 16)
1195zig_shl_sat_s(i16, int16_t, 15)
1196zig_shl_sat_u(u32, uint32_t, 32)
1197zig_shl_sat_s(i32, int32_t, 31)
1198zig_shl_sat_u(u64, uint64_t, 64)
1199zig_shl_sat_s(i64, int64_t, 63)
1200zig_shl_sat_s(isize, intptr_t, ((sizeof(intptr_t)) * CHAR_BIT - 1))
1201zig_shl_sat_s(short, short, ((sizeof(short )) * CHAR_BIT - 1))
1202zig_shl_sat_s(int, int, ((sizeof(int )) * CHAR_BIT - 1))
1203zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1))
1209#endif /* zig_has_int128 */
12041210
1205#define zig_bitsizeof(T) (CHAR_BIT * sizeof(T))
1206#define zig_bit_mask(T, bit_width) \
1207 ((bit_width) == zig_bitsizeof(T) \
1208 ? ((T)-1) \
1209 : (((T)1 << (T)(bit_width)) - 1))
1211#define zig_div_floor_u128 zig_div_trunc_u128
1212#define zig_mod_u128 zig_rem_u128
12101213
1211static inline int zig_clz(unsigned int value, uint8_t zig_type_bit_width) {
1212 if (value == 0) return zig_type_bit_width;
1213 return __builtin_clz(value) - zig_bitsizeof(unsigned int) + zig_type_bit_width;
1214static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
1215 zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i8(0) ? -zig_as_i128(0, 1) : zig_as_i128(0, 0);
1216 return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
12141217}
12151218
1216static inline int zig_clzl(unsigned long value, uint8_t zig_type_bit_width) {
1217 if (value == 0) return zig_type_bit_width;
1218 return __builtin_clzl(value) - zig_bitsizeof(unsigned long) + zig_type_bit_width;
1219static inline zig_u128 zig_wrap_u128(zig_u128 val, zig_u8 bits) {
1220 return zig_and_u128(val, zig_maxInt(u128, bits));
12191221}
12201222
1221static inline int zig_clzll(unsigned long long value, uint8_t zig_type_bit_width) {
1222 if (value == 0) return zig_type_bit_width;
1223 return __builtin_clzll(value) - zig_bitsizeof(unsigned long long) + zig_type_bit_width;
1223static inline zig_i128 zig_wrap_i128(zig_i128 val, zig_u8 bits) {
1224 return zig_as_i128(zig_wrap_i64(zig_hi_i128(val), bits - zig_as_u8(64)), zig_lo_i128(val));
12241225}
12251226
1226#define zig_clz_u8 zig_clz
1227#define zig_clz_i8 zig_clz
1228#define zig_clz_u16 zig_clz
1229#define zig_clz_i16 zig_clz
1230#define zig_clz_u32 zig_clzl
1231#define zig_clz_i32 zig_clzl
1232#define zig_clz_u64 zig_clzll
1233#define zig_clz_i64 zig_clzll
1227static inline zig_u128 zig_shlw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1228 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
1229}
12341230
1235static inline int zig_clz_u128(uint128_t value, uint8_t zig_type_bit_width) {
1236 if (value == 0) return zig_type_bit_width;
1237 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1238 const uint64_t hi = (value & mask) >> 64;
1239 const uint64_t lo = (value & mask);
1240 const int leading_zeroes = (
1241 hi != 0 ? __builtin_clzll(hi) : 64 + (lo != 0 ? __builtin_clzll(lo) : 64));
1242 return leading_zeroes - zig_bitsizeof(uint128_t) + zig_type_bit_width;
1231static inline zig_i128 zig_shlw_i128(zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1232 return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12431233}
12441234
1245#define zig_clz_i128 zig_clz_u128
1235static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1236 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
1237}
12461238
1247static inline int zig_ctz(unsigned int value, uint8_t zig_type_bit_width) {
1248 if (value == 0) return zig_type_bit_width;
1249 return __builtin_ctz(value & zig_bit_mask(unsigned int, zig_type_bit_width));
1239static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1240 return zig_wrap_i128(zig_bitcast_i128(zig_add_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12501241}
12511242
1252static inline int zig_ctzl(unsigned long value, uint8_t zig_type_bit_width) {
1253 if (value == 0) return zig_type_bit_width;
1254 return __builtin_ctzl(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1243static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1244 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
12551245}
12561246
1257static inline int zig_ctzll(unsigned long value, uint8_t zig_type_bit_width) {
1258 if (value == 0) return zig_type_bit_width;
1259 return __builtin_ctzll(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1247static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1248 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12601249}
12611250
1262#define zig_ctz_u8 zig_ctz
1263#define zig_ctz_i8 zig_ctz
1264#define zig_ctz_u16 zig_ctz
1265#define zig_ctz_i16 zig_ctz
1266#define zig_ctz_u32 zig_ctzl
1267#define zig_ctz_i32 zig_ctzl
1268#define zig_ctz_u64 zig_ctzll
1269#define zig_ctz_i64 zig_ctzll
1251static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1252 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
1253}
12701254
1271static inline int zig_ctz_u128(uint128_t value, uint8_t zig_type_bit_width) {
1272 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1273 const uint64_t hi = (value & mask) >> 64;
1274 const uint64_t lo = (value & mask);
1275 return (lo != 0 ? __builtin_ctzll(lo) : 64 + (hi != 0 ? __builtin_ctzll(hi) : 64));
1255static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1256 return zig_wrap_i128(zig_bitcast_i128(zig_mul_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
12761257}
12771258
1278#define zig_ctz_i128 zig_ctz_u128
1259#if zig_has_int128
12791260
1280static inline int zig_popcount(unsigned int value, uint8_t zig_type_bit_width) {
1281 return __builtin_popcount(value & zig_bit_mask(unsigned int, zig_type_bit_width));
1261static inline zig_bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1262 *res = zig_shlw_u128(lhs, rhs, bits);
1263 return zig_and_u128(lhs, zig_shl_u128(zig_maxInt_u128, bits - rhs)) != zig_as_u128(0, 0);
12821264}
12831265
1284static inline int zig_popcountl(unsigned long value, uint8_t zig_type_bit_width) {
1285 return __builtin_popcountl(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1266static inline zig_bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1267 *res = zig_shlw_i128(lhs, rhs, bits);
1268 zig_i128 mask = zig_bitcast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - zig_as_u8(1)));
1269 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_as_i128(0, 0)) != zig_as_i8(0) &&
1270 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != zig_as_i8(0);
12861271}
12871272
1288static inline int zig_popcountll(unsigned long value, uint8_t zig_type_bit_width) {
1289 return __builtin_popcountll(value & zig_bit_mask(unsigned long, zig_type_bit_width));
1273static inline zig_bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1274#if zig_has_builtin(add_overflow)
1275 zig_u128 full_res;
1276 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1277 *res = zig_wrap_u128(full_res, bits);
1278 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1279#else
1280 *res = zig_addw_u128(lhs, rhs, bits);
1281 return *res < lhs;
1282#endif
12901283}
12911284
1292#define zig_popcount_u8 zig_popcount
1293#define zig_popcount_i8 zig_popcount
1294#define zig_popcount_u16 zig_popcount
1295#define zig_popcount_i16 zig_popcount
1296#define zig_popcount_u32 zig_popcountl
1297#define zig_popcount_i32 zig_popcountl
1298#define zig_popcount_u64 zig_popcountll
1299#define zig_popcount_i64 zig_popcountll
1285zig_extern_c zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1286static inline zig_bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1287#if zig_has_builtin(add_overflow)
1288 zig_i128 full_res;
1289 zig_bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1290#else
1291 zig_c_int overflow_int;
1292 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
1293 zig_bool overflow = overflow_int != 0;
1294#endif
1295 *res = zig_wrap_i128(full_res, bits);
1296 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1297}
13001298
1301static inline int zig_popcount_u128(uint128_t value, uint8_t zig_type_bit_width) {
1302 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1303 const uint64_t hi = (value & mask) >> 64;
1304 const uint64_t lo = (value & mask);
1305 return __builtin_popcountll(hi) + __builtin_popcountll(lo);
1299static inline zig_bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1300#if zig_has_builtin(sub_overflow)
1301 zig_u128 full_res;
1302 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1303 *res = zig_wrap_u128(full_res, bits);
1304 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1305#else
1306 *res = zig_subw_u128(lhs, rhs, bits);
1307 return *res > lhs;
1308#endif
13061309}
13071310
1308#define zig_popcount_i128 zig_popcount_u128
1311zig_extern_c zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1312static inline zig_bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1313#if zig_has_builtin(sub_overflow)
1314 zig_i128 full_res;
1315 zig_bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1316#else
1317 zig_c_int overflow_int;
1318 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
1319 zig_bool overflow = overflow_int != 0;
1320#endif
1321 *res = zig_wrap_i128(full_res, bits);
1322 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1323}
13091324
1310static inline bool zig_shlo_i8(int8_t lhs, int8_t rhs, int8_t *res, uint8_t bits) {
1311 *res = lhs << rhs;
1312 if (zig_clz_i8(lhs, bits) >= rhs) return false;
1313 *res &= UINT8_MAX >> (8 - bits);
1314 return true;
1325static inline zig_bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1326#if zig_has_builtin(mul_overflow)
1327 zig_u128 full_res;
1328 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1329 *res = zig_wrap_u128(full_res, bits);
1330 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1331#else
1332 *res = zig_mulw_u128(lhs, rhs, bits);
1333 return rhs != zig_as_u128(0, 0) && lhs > zig_maxInt(u128, bits) / rhs;
1334#endif
13151335}
13161336
1317static inline bool zig_shlo_i16(int16_t lhs, int16_t rhs, int16_t *res, uint8_t bits) {
1318 *res = lhs << rhs;
1319 if (zig_clz_i16(lhs, bits) >= rhs) return false;
1320 *res &= UINT16_MAX >> (16 - bits);
1321 return true;
1337zig_extern_c zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1338static inline zig_bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1339#if zig_has_builtin(mul_overflow)
1340 zig_i128 full_res;
1341 zig_bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1342#else
1343 zig_c_int overflow_int;
1344 zig_i128 full_res = __muloti4(lhs, rhs, &overflow);
1345 zig_bool overflow = overflow_int != 0;
1346#endif
1347 *res = zig_wrap_i128(full_res, bits);
1348 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
13221349}
13231350
1324static inline bool zig_shlo_i32(int32_t lhs, int32_t rhs, int32_t *res, uint8_t bits) {
1325 *res = lhs << rhs;
1326 if (zig_clz_i32(lhs, bits) >= rhs) return false;
1327 *res &= UINT32_MAX >> (32 - bits);
1328 return true;
1351#else /* zig_has_int128 */
1352
1353static inline zig_bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
1354 return zig_addo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
1355 zig_addo_u64(&res->hi, res->hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
13291356}
13301357
1331static inline bool zig_shlo_i64(int64_t lhs, int64_t rhs, int64_t *res, uint8_t bits) {
1332 *res = lhs << rhs;
1333 if (zig_clz_i64(lhs, bits) >= rhs) return false;
1334 *res &= UINT64_MAX >> (64 - bits);
1335 return true;
1358static inline zig_bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs) {
1359 return zig_subo_u64(&res->hi, lhs.hi, rhs.hi, UINT64_MAX) |
1360 zig_subo_u64(&res->hi, res->hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT64_MAX));
13361361}
13371362
1338static inline bool zig_shlo_i128(int128_t lhs, int128_t rhs, int128_t *res, uint8_t bits) {
1339 *res = lhs << rhs;
1340 if (zig_clz_i128(lhs, bits) >= rhs) return false;
1341 *res &= UINT128_MAX >> (128 - bits);
1342 return true;
1363#endif /* zig_has_int128 */
1364
1365static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1366 zig_u128 res;
1367 if (zig_cmp_u128(rhs, zig_as_u128(0, bits)) >= zig_as_i8(0))
1368 return zig_cmp_u128(lhs, zig_as_u128(0, 0)) != zig_as_i8(0) ? zig_maxInt(u128, bits) : lhs;
1369 return zig_shlo_u128(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u128, bits) : res;
13431370}
13441371
1345static inline bool zig_shlo_u8(uint8_t lhs, uint8_t rhs, uint8_t *res, uint8_t bits) {
1346 *res = lhs << rhs;
1347 if (zig_clz_u8(lhs, bits) >= rhs) return false;
1348 *res &= UINT8_MAX >> (8 - bits);
1349 return true;
1372static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1373 zig_i128 res;
1374 if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_as_u128(0, bits)) < zig_as_i8(0) && !zig_shlo_i128(&res, lhs, rhs, bits)) return res;
1375 return zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i8(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
13501376}
13511377
1352static inline uint16_t zig_shlo_u16(uint16_t lhs, uint16_t rhs, uint16_t *res, uint8_t bits) {
1353 *res = lhs << rhs;
1354 if (zig_clz_u16(lhs, bits) >= rhs) return false;
1355 *res &= UINT16_MAX >> (16 - bits);
1356 return true;
1378static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1379 zig_u128 res;
1380 return zig_addo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
13571381}
13581382
1359static inline uint32_t zig_shlo_u32(uint32_t lhs, uint32_t rhs, uint32_t *res, uint8_t bits) {
1360 *res = lhs << rhs;
1361 if (zig_clz_u32(lhs, bits) >= rhs) return false;
1362 *res &= UINT32_MAX >> (32 - bits);
1363 return true;
1383static inline zig_i128 zig_adds_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1384 zig_i128 res;
1385 if (!zig_addo_i128(&res, lhs, rhs, bits)) return res;
1386 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= zig_as_i8(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
13641387}
13651388
1366static inline uint64_t zig_shlo_u64(uint64_t lhs, uint64_t rhs, uint64_t *res, uint8_t bits) {
1367 *res = lhs << rhs;
1368 if (zig_clz_u64(lhs, bits) >= rhs) return false;
1369 *res &= UINT64_MAX >> (64 - bits);
1370 return true;
1389static inline zig_u128 zig_subs_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1390 zig_u128 res;
1391 return zig_subo_u128(&res, lhs, rhs, bits) ? zig_minInt(u128, bits) : res;
13711392}
13721393
1373static inline uint128_t zig_shlo_u128(uint128_t lhs, uint128_t rhs, uint128_t *res, uint8_t bits) {
1374 *res = lhs << rhs;
1375 if (zig_clz_u128(lhs, bits) >= rhs) return false;
1376 *res &= UINT128_MAX >> (128 - bits);
1377 return true;
1394static inline zig_i128 zig_subs_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1395 zig_i128 res;
1396 if (!zig_subo_i128(&res, lhs, rhs, bits)) return res;
1397 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= zig_as_i8(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
13781398}
13791399
1380#define zig_sign_extend(T) \
1381 static inline T zig_sign_extend_##T(T value, uint8_t zig_type_bit_width) { \
1382 const T m = (T)1 << (T)(zig_type_bit_width - 1); \
1383 return (value ^ m) - m; \
1384 }
1400static inline zig_u128 zig_muls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1401 zig_u128 res;
1402 return zig_mulo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1403}
13851404
1386zig_sign_extend(uint8_t)
1387zig_sign_extend(uint16_t)
1388zig_sign_extend(uint32_t)
1389zig_sign_extend(uint64_t)
1390zig_sign_extend(uint128_t)
1405static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1406 zig_i128 res;
1407 if (!zig_mulo_i128(&res, lhs, rhs, bits)) return res;
1408 return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_as_i128(0, 0)) < zig_as_i8(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1409}
13911410
1392#define zig_byte_swap_u(ZigTypeBits, CTypeBits) \
1393 static inline uint##CTypeBits##_t zig_byte_swap_u##ZigTypeBits(uint##CTypeBits##_t value, uint8_t zig_type_bit_width) { \
1394 return __builtin_bswap##CTypeBits(value) >> (CTypeBits - zig_type_bit_width); \
1395 }
1411static inline zig_u8 zig_clz_u128(zig_u128 val, zig_u8 bits) {
1412 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - zig_as_u8(64));
1413 return zig_clz_u64(zig_lo_u128(val), zig_as_u8(64)) + zig_as_u8(64);
1414}
13961415
1397#define zig_byte_swap_s(ZigTypeBits, CTypeBits) \
1398 static inline int##CTypeBits##_t zig_byte_swap_i##ZigTypeBits(int##CTypeBits##_t value, uint8_t zig_type_bit_width) { \
1399 const uint##CTypeBits##_t swapped = zig_byte_swap_u##ZigTypeBits(value, zig_type_bit_width); \
1400 return zig_sign_extend_uint##CTypeBits##_t(swapped, zig_type_bit_width); \
1401 }
1416static inline zig_u8 zig_clz_i128(zig_i128 val, zig_u8 bits) {
1417 return zig_clz_u128(zig_bitcast_u128(val), bits);
1418}
14021419
1403#define zig_byte_swap(ZigTypeBits, CTypeBits) \
1404 zig_byte_swap_u(ZigTypeBits, CTypeBits) \
1405 zig_byte_swap_s(ZigTypeBits, CTypeBits)
1406
1407zig_byte_swap( 8, 16)
1408zig_byte_swap(16, 16)
1409zig_byte_swap(32, 32)
1410zig_byte_swap(64, 64)
1411
1412static inline uint128_t zig_byte_swap_u128(uint128_t value, uint8_t zig_type_bit_width) {
1413 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
1414 const uint128_t hi = __builtin_bswap64((uint64_t)(value >> 64));
1415 const uint128_t lo = __builtin_bswap64((uint64_t)value);
1416 return (((lo << 64 | hi) >> (128 - zig_type_bit_width))) & mask;
1417}
1418
1419zig_byte_swap_s(128, 128)
1420
1421static const uint8_t zig_bit_reverse_lut[256] = {
1422 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
1423 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1424 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
1425 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1426 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
1427 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1428 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
1429 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1430 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
1431 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1432 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
1433 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1434 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
1435 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1436 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
1437 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1438 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
1439 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1440 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
1441 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1442 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
1443 0x3f, 0xbf, 0x7f, 0xff
1444};
1445
1446static inline uint8_t zig_bit_reverse_u8(uint8_t value, uint8_t zig_type_bit_width) {
1447 const uint8_t reversed = zig_bit_reverse_lut[value] >> (8 - zig_type_bit_width);
1448 return zig_sign_extend_uint8_t(reversed, zig_type_bit_width);
1449}
1450
1451#define zig_bit_reverse_i8 zig_bit_reverse_u8
1452
1453static inline uint16_t zig_bit_reverse_u16(uint16_t value, uint8_t zig_type_bit_width) {
1454 const uint16_t swapped = zig_byte_swap_u16(value, zig_type_bit_width);
1455 const uint16_t reversed = (
1456 ((uint16_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1457 ((uint16_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1458 return zig_sign_extend_uint16_t(
1459 reversed & zig_bit_mask(uint16_t, zig_type_bit_width),
1460 zig_type_bit_width);
1461}
1462
1463#define zig_bit_reverse_i16 zig_bit_reverse_u16
1464
1465static inline uint32_t zig_bit_reverse_u32(uint32_t value, uint8_t zig_type_bit_width) {
1466 const uint32_t swapped = zig_byte_swap_u32(value, zig_type_bit_width);
1467 const uint32_t reversed = (
1468 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
1469 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
1470 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1471 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1472 return zig_sign_extend_uint32_t(
1473 reversed & zig_bit_mask(uint32_t, zig_type_bit_width),
1474 zig_type_bit_width);
1475}
1476
1477#define zig_bit_reverse_i32 zig_bit_reverse_u32
1478
1479static inline uint64_t zig_bit_reverse_u64(uint64_t value, uint8_t zig_type_bit_width) {
1480 const uint64_t swapped = zig_byte_swap_u64(value, zig_type_bit_width);
1481 const uint64_t reversed = (
1482 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x38) & 0xff] << 0x38) |
1483 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x30) & 0xff] << 0x30) |
1484 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x28) & 0xff] << 0x28) |
1485 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x20) & 0xff] << 0x20) |
1486 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
1487 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
1488 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1489 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1490 return zig_sign_extend_uint64_t(
1491 reversed & zig_bit_mask(uint64_t, zig_type_bit_width),
1492 zig_type_bit_width);
1493}
1494
1495#define zig_bit_reverse_i64 zig_bit_reverse_u64
1496
1497static inline uint128_t zig_bit_reverse_u128(uint128_t value, uint8_t zig_type_bit_width) {
1498 const uint128_t swapped = zig_byte_swap_u128(value, zig_type_bit_width);
1499 const uint128_t reversed = (
1500 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x78) & 0xff] << 0x78) |
1501 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x70) & 0xff] << 0x70) |
1502 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x68) & 0xff] << 0x68) |
1503 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x60) & 0xff] << 0x60) |
1504 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x58) & 0xff] << 0x58) |
1505 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x50) & 0xff] << 0x50) |
1506 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x48) & 0xff] << 0x48) |
1507 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x40) & 0xff] << 0x40) |
1508 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x38) & 0xff] << 0x38) |
1509 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x30) & 0xff] << 0x30) |
1510 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x28) & 0xff] << 0x28) |
1511 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x20) & 0xff] << 0x20) |
1512 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
1513 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
1514 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
1515 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
1516 return zig_sign_extend_uint128_t(
1517 reversed & zig_bit_mask(uint128_t, zig_type_bit_width),
1518 zig_type_bit_width);
1519}
1520
1521#define zig_bit_reverse_i128 zig_bit_reverse_u128
1522
1523static inline float zig_div_truncf(float numerator, float denominator) {
1524 return __builtin_truncf(numerator / denominator);
1525}
1526
1527static inline double zig_div_trunc(double numerator, double denominator) {
1528 return __builtin_trunc(numerator / denominator);
1529}
1530
1531static inline long double zig_div_truncl(long double numerator, long double denominator) {
1532 return __builtin_truncf(numerator / denominator);
1533}
1534
1535#define zig_div_trunc_f16 zig_div_truncf
1536#define zig_div_trunc_f32 zig_div_truncf
1537#define zig_div_trunc_f64 zig_div_trunc
1538#define zig_div_trunc_f80 zig_div_truncl
1539#define zig_div_trunc_f128 zig_div_truncl
1540
1541#define zig_div_floorf(numerator, denominator) \
1542 __builtin_floorf((float)(numerator) / (float)(denominator))
1543
1544#define zig_div_floor(numerator, denominator) \
1545 __builtin_floor((double)(numerator) / (double)(denominator))
1546
1547#define zig_div_floorl(numerator, denominator) \
1548 __builtin_floorl((long double)(numerator) / (long double)(denominator))
1420static inline zig_u8 zig_ctz_u128(zig_u128 val, zig_u8 bits) {
1421 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), zig_as_u8(64));
1422 return zig_ctz_u64(zig_hi_u128(val), bits - zig_as_u8(64)) + zig_as_u8(64);
1423}
15491424
1550#define zig_div_floor_f16 zig_div_floorf
1551#define zig_div_floor_f32 zig_div_floorf
1552#define zig_div_floor_f64 zig_div_floor
1553#define zig_div_floor_f80 zig_div_floorl
1554#define zig_div_floor_f128 zig_div_floorl
1555
1556#define zig_div_floor_u8 zig_div_floorf
1557#define zig_div_floor_i8 zig_div_floorf
1558#define zig_div_floor_u16 zig_div_floorf
1559#define zig_div_floor_i16 zig_div_floorf
1560#define zig_div_floor_u32 zig_div_floor
1561#define zig_div_floor_i32 zig_div_floor
1562#define zig_div_floor_u64 zig_div_floor
1563#define zig_div_floor_i64 zig_div_floor
1564#define zig_div_floor_u128 zig_div_floorl
1565#define zig_div_floor_i128 zig_div_floorl
1566
1567static inline float zig_modf(float numerator, float denominator) {
1568 return (numerator - (zig_div_floorf(numerator, denominator) * denominator));
1569}
1570
1571static inline double zig_mod(double numerator, double denominator) {
1572 return (numerator - (zig_div_floor(numerator, denominator) * denominator));
1425static inline zig_u8 zig_ctz_i128(zig_i128 val, zig_u8 bits) {
1426 return zig_ctz_u128(zig_bitcast_u128(val), bits);
15731427}
15741428
1575static inline long double zig_modl(long double numerator, long double denominator) {
1576 return (numerator - (zig_div_floorl(numerator, denominator) * denominator));
1577}
1578
1579#define zig_mod_f16 zig_modf
1580#define zig_mod_f32 zig_modf
1581#define zig_mod_f64 zig_mod
1582#define zig_mod_f80 zig_modl
1583#define zig_mod_f128 zig_modl
1584
1585#define zig_mod_int(ZigType, CType) \
1586 static inline CType zig_mod_##ZigType(CType numerator, CType denominator) { \
1587 return (numerator - (zig_div_floor_##ZigType(numerator, denominator) * denominator)); \
1588 }
1429static inline zig_u8 zig_popcount_u128(zig_u128 val, zig_u8 bits) {
1430 return zig_popcount_u64(zig_hi_u128(val), bits - zig_as_u8(64)) +
1431 zig_popcount_u64(zig_lo_u128(val), zig_as_u8(64));
1432}
15891433
1590zig_mod_int( u8, uint8_t)
1591zig_mod_int( i8, int8_t)
1592zig_mod_int( u16, uint16_t)
1593zig_mod_int( i16, int16_t)
1594zig_mod_int( u32, uint32_t)
1595zig_mod_int( i32, int32_t)
1596zig_mod_int( u64, uint64_t)
1597zig_mod_int( i64, int64_t)
1598zig_mod_int(u128, uint128_t)
1599zig_mod_int(i128, int128_t)
1434static inline zig_u8 zig_popcount_i128(zig_i128 val, zig_u8 bits) {
1435 return zig_popcount_u128(zig_bitcast_u128(val), bits);
1436}
1437
1438static inline zig_u128 zig_byte_swap_u128(zig_u128 val, zig_u8 bits) {
1439 zig_u128 full_res;
1440#if zig_has_builtin(bswap128)
1441 full_res = __builtin_bswap128(val);
1442#else
1443 full_res = zig_as_u128(zig_byte_swap_u64(zig_lo_u128(val), zig_as_u8(64)),
1444 zig_byte_swap_u64(zig_hi_u128(val), zig_as_u8(64)));
1445#endif
1446 return zig_shr_u128(full_res, zig_as_u8(128) - bits);
1447}
1448
1449static inline zig_i128 zig_byte_swap_i128(zig_i128 val, zig_u8 bits) {
1450 return zig_byte_swap_u128(zig_bitcast_u128(val), bits);
1451}
1452
1453static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {
1454 return zig_shr_u128(zig_as_u128(zig_bit_reverse_u64(zig_lo_u128(val), zig_as_u8(64)),
1455 zig_bit_reverse_u64(zig_hi_u128(val), zig_as_u8(64))),
1456 zig_as_u8(128) - bits);
1457}
1458
1459static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
1460 return zig_bit_reverse_u128(zig_bitcast_u128(val), bits);
1461}
1462
1463/* ========================== Float Point Routines ========================== */
1464
1465#define zig_float_builtins(Type) \
1466 zig_extern_c zig_##Type zig_builtin_##Type(sqrt)(zig_##Type); \
1467 zig_extern_c zig_##Type zig_builtin_##Type(sin)(zig_##Type); \
1468 zig_extern_c zig_##Type zig_builtin_##Type(cos)(zig_##Type); \
1469 zig_extern_c zig_##Type zig_builtin_##Type(tan)(zig_##Type); \
1470 zig_extern_c zig_##Type zig_builtin_##Type(exp)(zig_##Type); \
1471 zig_extern_c zig_##Type zig_builtin_##Type(exp2)(zig_##Type); \
1472 zig_extern_c zig_##Type zig_builtin_##Type(log)(zig_##Type); \
1473 zig_extern_c zig_##Type zig_builtin_##Type(log2)(zig_##Type); \
1474 zig_extern_c zig_##Type zig_builtin_##Type(log10)(zig_##Type); \
1475 zig_extern_c zig_##Type zig_builtin_##Type(fabs)(zig_##Type); \
1476 zig_extern_c zig_##Type zig_builtin_##Type(floor)(zig_##Type); \
1477 zig_extern_c zig_##Type zig_builtin_##Type(ceil)(zig_##Type); \
1478 zig_extern_c zig_##Type zig_builtin_##Type(round)(zig_##Type); \
1479 zig_extern_c zig_##Type zig_builtin_##Type(trunc)(zig_##Type); \
1480 zig_extern_c zig_##Type zig_builtin_##Type(fmod)(zig_##Type, zig_##Type); \
1481 zig_extern_c zig_##Type zig_builtin_##Type(fma)(zig_##Type, zig_##Type, zig_##Type); \
1482\
1483 static inline zig_##Type zig_div_trunc_##Type(zig_##Type lhs, zig_##Type rhs) { \
1484 return zig_builtin_##Type(trunc)(lhs / rhs); \
1485 } \
1486\
1487 static inline zig_##Type zig_div_floor_##Type(zig_##Type lhs, zig_##Type rhs) { \
1488 return zig_builtin_##Type(floor)(lhs / rhs); \
1489 } \
1490\
1491 static inline zig_##Type zig_mod_##Type(zig_##Type lhs, zig_##Type rhs) { \
1492 return lhs - zig_div_floor_##Type(lhs, rhs) * rhs; \
1493 }
1494zig_float_builtins(f16)
1495zig_float_builtins(f32)
1496zig_float_builtins(f64)
1497zig_float_builtins(f80)
1498zig_float_builtins(f128)
1499zig_float_builtins(c_longdouble)
lib/std/debug.zig+7-1
......@@ -1222,7 +1222,13 @@ pub const DebugInfo = struct {
12221222 }
12231223
12241224 pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1225 if (comptime builtin.target.isDarwin()) {
1225 if (builtin.zig_backend == .stage2_c) {
1226 return @as(error{
1227 InvalidDebugInfo,
1228 MissingDebugInfo,
1229 UnsupportedBackend,
1230 }, error.UnsupportedBackend);
1231 } else if (comptime builtin.target.isDarwin()) {
12261232 return self.lookupModuleDyld(address);
12271233 } else if (native_os == .windows) {
12281234 return self.lookupModuleWin32(address);
lib/std/os/linux/arm64.zig+14-5
......@@ -106,11 +106,20 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *
106106pub const restore = restore_rt;
107107
108108pub fn restore_rt() callconv(.Naked) void {
109 return asm volatile ("svc #0"
110 :
111 : [number] "{x8}" (@enumToInt(SYS.rt_sigreturn)),
112 : "memory", "cc"
113 );
109 switch (@import("builtin").zig_backend) {
110 .stage2_c => return asm volatile (
111 \\ mov x8, %[number]
112 \\ svc #0
113 :
114 : [number] "i" (@enumToInt(SYS.rt_sigreturn)),
115 : "memory", "cc"
116 ),
117 else => return asm volatile ("svc #0"
118 :
119 : [number] "{x8}" (@enumToInt(SYS.rt_sigreturn)),
120 : "memory", "cc"
121 ),
122 }
114123}
115124
116125pub const O = struct {
lib/std/os/linux/i386.zig+28-10
......@@ -124,19 +124,37 @@ const CloneFn = std.meta.FnPtr(fn (arg: usize) callconv(.C) u8);
124124pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
125125
126126pub fn restore() callconv(.Naked) void {
127 return asm volatile ("int $0x80"
128 :
129 : [number] "{eax}" (@enumToInt(SYS.sigreturn)),
130 : "memory"
131 );
127 switch (@import("builtin").zig_backend) {
128 .stage2_c => return asm volatile (
129 \\ movl %[number], %%eax
130 \\ int $0x80
131 :
132 : [number] "i" (@enumToInt(SYS.sigreturn)),
133 : "memory"
134 ),
135 else => return asm volatile ("int $0x80"
136 :
137 : [number] "{eax}" (@enumToInt(SYS.sigreturn)),
138 : "memory"
139 ),
140 }
132141}
133142
134143pub fn restore_rt() callconv(.Naked) void {
135 return asm volatile ("int $0x80"
136 :
137 : [number] "{eax}" (@enumToInt(SYS.rt_sigreturn)),
138 : "memory"
139 );
144 switch (@import("builtin").zig_backend) {
145 .stage2_c => return asm volatile (
146 \\ movl %[number], %%eax
147 \\ int $0x80
148 :
149 : [number] "i" (@enumToInt(SYS.rt_sigreturn)),
150 : "memory"
151 ),
152 else => return asm volatile ("int $0x80"
153 :
154 : [number] "{eax}" (@enumToInt(SYS.rt_sigreturn)),
155 : "memory"
156 ),
157 }
140158}
141159
142160pub const O = struct {
lib/std/os/linux/x86_64.zig+15-5
......@@ -108,11 +108,21 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
108108pub const restore = restore_rt;
109109
110110pub fn restore_rt() callconv(.Naked) void {
111 return asm volatile ("syscall"
112 :
113 : [number] "{rax}" (@enumToInt(SYS.rt_sigreturn)),
114 : "rcx", "r11", "memory"
115 );
111 switch (@import("builtin").zig_backend) {
112 .stage2_c => return asm volatile (
113 \\ movl %[number], %%eax
114 \\ syscall
115 \\ retq
116 :
117 : [number] "i" (@enumToInt(SYS.rt_sigreturn)),
118 : "rcx", "r11", "memory"
119 ),
120 else => return asm volatile ("syscall"
121 :
122 : [number] "{rax}" (@enumToInt(SYS.rt_sigreturn)),
123 : "rcx", "r11", "memory"
124 ),
125 }
116126}
117127
118128pub const mode_t = usize;
lib/std/start.zig+101-73
......@@ -23,7 +23,6 @@ comptime {
2323 // Until then, we have simplified logic here for self-hosted. TODO remove this once
2424 // self-hosted is capable enough to handle all of the real start.zig logic.
2525 if (builtin.zig_backend == .stage2_wasm or
26 builtin.zig_backend == .stage2_c or
2726 builtin.zig_backend == .stage2_x86_64 or
2827 builtin.zig_backend == .stage2_x86 or
2928 builtin.zig_backend == .stage2_aarch64 or
......@@ -265,75 +264,104 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
265264}
266265
267266fn _start() callconv(.Naked) noreturn {
268 switch (native_arch) {
269 .x86_64 => {
270 argc_argv_ptr = asm volatile (
271 \\ xor %%rbp, %%rbp
272 : [argc] "={rsp}" (-> [*]usize),
273 );
274 },
275 .i386 => {
276 argc_argv_ptr = asm volatile (
277 \\ xor %%ebp, %%ebp
278 : [argc] "={esp}" (-> [*]usize),
279 );
280 },
281 .aarch64, .aarch64_be, .arm, .armeb, .thumb => {
282 argc_argv_ptr = asm volatile (
283 \\ mov fp, #0
284 \\ mov lr, #0
285 : [argc] "={sp}" (-> [*]usize),
286 );
287 },
288 .riscv64 => {
289 argc_argv_ptr = asm volatile (
290 \\ li s0, 0
291 \\ li ra, 0
292 : [argc] "={sp}" (-> [*]usize),
293 );
294 },
295 .mips, .mipsel => {
296 // The lr is already zeroed on entry, as specified by the ABI.
297 argc_argv_ptr = asm volatile (
298 \\ move $fp, $0
299 : [argc] "={sp}" (-> [*]usize),
300 );
301 },
302 .powerpc => {
303 // Setup the initial stack frame and clear the back chain pointer.
304 argc_argv_ptr = asm volatile (
305 \\ mr 4, 1
306 \\ li 0, 0
307 \\ stwu 1,-16(1)
308 \\ stw 0, 0(1)
309 \\ mtlr 0
310 : [argc] "={r4}" (-> [*]usize),
311 :
312 : "r0"
313 );
314 },
315 .powerpc64le => {
316 // Setup the initial stack frame and clear the back chain pointer.
317 // TODO: Support powerpc64 (big endian) on ELFv2.
318 argc_argv_ptr = asm volatile (
319 \\ mr 4, 1
320 \\ li 0, 0
321 \\ stdu 0, -32(1)
322 \\ mtlr 0
323 : [argc] "={r4}" (-> [*]usize),
324 :
325 : "r0"
326 );
267 switch (builtin.zig_backend) {
268 .stage2_c => {
269 @export(argc_argv_ptr, .{ .name = "argc_argv_ptr" });
270 @export(posixCallMainAndExit, .{ .name = "_posixCallMainAndExit" });
271 switch (native_arch) {
272 .x86_64 => asm volatile (
273 \\ xorl %%ebp, %%ebp
274 \\ movq %%rsp, argc_argv_ptr
275 \\ andq $-16, %%rsp
276 \\ call _posixCallMainAndExit
277 ),
278 .i386 => asm volatile (
279 \\ xorl %%ebp, %%ebp
280 \\ movl %%esp, argc_argv_ptr
281 \\ andl $-16, %%esp
282 \\ jmp _posixCallMainAndExit
283 ),
284 .aarch64, .aarch64_be, .arm, .armeb, .thumb => asm volatile (
285 \\ mov fp, #0
286 \\ mov lr, #0
287 \\ str sp, argc_argv_ptr
288 \\ and sp, #-16
289 \\ b _posixCallMainAndExit
290 ),
291 else => @compileError("unsupported arch"),
292 }
293 unreachable;
327294 },
328 .sparc64 => {
329 // argc is stored after a register window (16 registers) plus stack bias
330 argc_argv_ptr = asm (
331 \\ mov %%g0, %%i6
332 \\ add %%o6, 2175, %[argc]
333 : [argc] "=r" (-> [*]usize),
334 );
295 else => switch (native_arch) {
296 .x86_64 => {
297 argc_argv_ptr = asm volatile (
298 \\ xor %%ebp, %%ebp
299 : [argc] "={rsp}" (-> [*]usize),
300 );
301 },
302 .i386 => {
303 argc_argv_ptr = asm volatile (
304 \\ xor %%ebp, %%ebp
305 : [argc] "={esp}" (-> [*]usize),
306 );
307 },
308 .aarch64, .aarch64_be, .arm, .armeb, .thumb => {
309 argc_argv_ptr = asm volatile (
310 \\ mov fp, #0
311 \\ mov lr, #0
312 : [argc] "={sp}" (-> [*]usize),
313 );
314 },
315 .riscv64 => {
316 argc_argv_ptr = asm volatile (
317 \\ li s0, 0
318 \\ li ra, 0
319 : [argc] "={sp}" (-> [*]usize),
320 );
321 },
322 .mips, .mipsel => {
323 // The lr is already zeroed on entry, as specified by the ABI.
324 argc_argv_ptr = asm volatile (
325 \\ move $fp, $0
326 : [argc] "={sp}" (-> [*]usize),
327 );
328 },
329 .powerpc => {
330 // Setup the initial stack frame and clear the back chain pointer.
331 argc_argv_ptr = asm volatile (
332 \\ mr 4, 1
333 \\ li 0, 0
334 \\ stwu 1,-16(1)
335 \\ stw 0, 0(1)
336 \\ mtlr 0
337 : [argc] "={r4}" (-> [*]usize),
338 :
339 : "r0"
340 );
341 },
342 .powerpc64le => {
343 // Setup the initial stack frame and clear the back chain pointer.
344 // TODO: Support powerpc64 (big endian) on ELFv2.
345 argc_argv_ptr = asm volatile (
346 \\ mr 4, 1
347 \\ li 0, 0
348 \\ stdu 0, -32(1)
349 \\ mtlr 0
350 : [argc] "={r4}" (-> [*]usize),
351 :
352 : "r0"
353 );
354 },
355 .sparc64 => {
356 // argc is stored after a register window (16 registers) plus stack bias
357 argc_argv_ptr = asm (
358 \\ mov %%g0, %%i6
359 \\ add %%o6, 2175, %[argc]
360 : [argc] "=r" (-> [*]usize),
361 );
362 },
363 else => @compileError("unsupported arch"),
335364 },
336 else => @compileError("unsupported arch"),
337365 }
338366 // If LLVM inlines stack variables into _start, they will overwrite
339367 // the command line argument data.
......@@ -363,7 +391,7 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
363391 std.os.windows.kernel32.ExitProcess(@bitCast(std.os.windows.UINT, result));
364392}
365393
366fn posixCallMainAndExit() noreturn {
394fn posixCallMainAndExit() callconv(.C) noreturn {
367395 @setAlignStack(16);
368396
369397 const argc = argc_argv_ptr[0];
......@@ -462,7 +490,7 @@ fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
462490 return initEventLoopAndCallMain();
463491}
464492
465fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C) i32 {
493fn main(c_argc: c_int, c_argv: [*c][*c]u8, c_envp: [*c][*c]u8) callconv(.C) c_int {
466494 var env_count: usize = 0;
467495 while (c_envp[env_count] != null) : (env_count += 1) {}
468496 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
......@@ -474,11 +502,11 @@ fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) callconv(.C)
474502 expandStackSize(phdrs);
475503 }
476504
477 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp });
505 return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), @ptrCast([*][*:0]u8, c_argv), envp });
478506}
479507
480fn mainWithoutEnv(c_argc: i32, c_argv: [*][*:0]u8) callconv(.C) usize {
481 std.os.argv = c_argv[0..@intCast(usize, c_argc)];
508fn mainWithoutEnv(c_argc: c_int, c_argv: [*c][*c]u8) callconv(.C) c_int {
509 std.os.argv = @ptrCast([*][*:0]u8, c_argv)[0..@intCast(usize, c_argc)];
482510 return @call(.{ .modifier = .always_inline }, callMain, .{});
483511}
484512
lib/test_runner.zig+2-1
......@@ -8,7 +8,8 @@ var log_err_count: usize = 0;
88
99pub fn main() void {
1010 if (builtin.zig_backend != .stage1 and
11 (builtin.zig_backend != .stage2_llvm or builtin.cpu.arch == .wasm32))
11 (builtin.zig_backend != .stage2_llvm or builtin.cpu.arch == .wasm32) and
12 builtin.zig_backend != .stage2_c)
1213 {
1314 return main2() catch @panic("test failure");
1415 }
src/Compilation.zig+8-5
......@@ -3103,13 +3103,16 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31033103 .decl_index = decl_index,
31043104 .decl = decl,
31053105 .fwd_decl = fwd_decl.toManaged(gpa),
3106 .typedefs = c_codegen.TypedefMap.initContext(gpa, .{
3107 .mod = module,
3108 }),
3106 .typedefs = c_codegen.TypedefMap.initContext(gpa, .{ .mod = module }),
31093107 .typedefs_arena = typedefs_arena.allocator(),
31103108 };
3111 defer dg.fwd_decl.deinit();
3112 defer dg.typedefs.deinit();
3109 defer {
3110 for (dg.typedefs.values()) |typedef| {
3111 module.gpa.free(typedef.rendered);
3112 }
3113 dg.typedefs.deinit();
3114 dg.fwd_decl.deinit();
3115 }
31133116
31143117 c_codegen.genHeader(&dg) catch |err| switch (err) {
31153118 error.AnalysisFail => {
src/codegen/c.zig+2694-1470
......@@ -18,8 +18,8 @@ const Air = @import("../Air.zig");
1818const Liveness = @import("../Liveness.zig");
1919const CType = @import("../type.zig").CType;
2020
21const Mutability = enum { Const, Mut };
22const BigIntConst = std.math.big.int.Const;
21const Mutability = enum { Const, ConstArgument, Mut };
22const BigInt = std.math.big.int;
2323
2424pub const CValue = union(enum) {
2525 none: void,
......@@ -34,8 +34,8 @@ pub const CValue = union(enum) {
3434 /// By-value
3535 decl: Decl.Index,
3636 decl_ref: Decl.Index,
37 /// An undefined (void *) pointer (cannot be dereferenced)
38 undefined_ptr: void,
37 /// An undefined value (cannot be dereferenced)
38 undef: Type,
3939 /// Render the slice as an identifier (using fmtIdent)
4040 identifier: []const u8,
4141 /// Render these bytes literally.
......@@ -48,6 +48,11 @@ const BlockData = struct {
4848 result: CValue,
4949};
5050
51const TypedefKind = enum {
52 Forward,
53 Complete,
54};
55
5156pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
5257pub const TypedefMap = std.ArrayHashMap(
5358 Type,
......@@ -63,9 +68,16 @@ const FormatTypeAsCIdentContext = struct {
6368
6469const ValueRenderLocation = enum {
6570 FunctionArgument,
71 Initializer,
6672 Other,
6773};
6874
75const BuiltinInfo = enum {
76 None,
77 Range,
78 Bits,
79};
80
6981/// TODO make this not cut off at 128 bytes
7082fn formatTypeAsCIdentifier(
7183 data: FormatTypeAsCIdentContext,
......@@ -73,11 +85,11 @@ fn formatTypeAsCIdentifier(
7385 options: std.fmt.FormatOptions,
7486 writer: anytype,
7587) !void {
76 _ = fmt;
77 _ = options;
78 var buffer = [1]u8{0} ** 128;
79 var buf = std.fmt.bufPrint(&buffer, "{}", .{data.ty.fmt(data.mod)}) catch &buffer;
80 return formatIdent(buf, "", .{}, writer);
88 var stack = std.heap.stackFallback(128, data.mod.gpa);
89 const allocator = stack.get();
90 const str = std.fmt.allocPrint(allocator, "{}", .{data.ty.fmt(data.mod)}) catch "";
91 defer allocator.free(str);
92 return formatIdent(str, fmt, options, writer);
8193}
8294
8395pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsCIdentifier) {
......@@ -88,23 +100,9 @@ pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsC
88100}
89101
90102const reserved_idents = std.ComptimeStringMap(void, .{
91 .{ "_Alignas", {
103 .{ "alignas", {
92104 @setEvalBranchQuota(4000);
93105 } },
94 .{ "_Alignof", {} },
95 .{ "_Atomic", {} },
96 .{ "_Bool", {} },
97 .{ "_Complex", {} },
98 .{ "_Decimal128", {} },
99 .{ "_Decimal32", {} },
100 .{ "_Decimal64", {} },
101 .{ "_Generic", {} },
102 .{ "_Imaginary", {} },
103 .{ "_Noreturn", {} },
104 .{ "_Pragma", {} },
105 .{ "_Static_assert", {} },
106 .{ "_Thread_local", {} },
107 .{ "alignas", {} },
108106 .{ "alignof", {} },
109107 .{ "asm", {} },
110108 .{ "atomic_bool", {} },
......@@ -199,6 +197,15 @@ const reserved_idents = std.ComptimeStringMap(void, .{
199197 .{ "while ", {} },
200198});
201199
200fn isReservedIdent(ident: []const u8) bool {
201 if (ident.len >= 2 and ident[0] == '_') {
202 switch (ident[1]) {
203 'A'...'Z', '_' => return true,
204 else => return false,
205 }
206 } else return reserved_idents.has(ident);
207}
208
202209fn formatIdent(
203210 ident: []const u8,
204211 comptime fmt: []const u8,
......@@ -207,7 +214,7 @@ fn formatIdent(
207214) !void {
208215 _ = options;
209216 const solo = fmt.len != 0 and fmt[0] == ' '; // space means solo; not part of a bigger ident.
210 if (solo and reserved_idents.has(ident)) {
217 if (solo and isReservedIdent(ident)) {
211218 try writer.writeAll("zig_e_");
212219 }
213220 for (ident) |c, i| {
......@@ -247,30 +254,27 @@ pub const Function = struct {
247254
248255 const val = f.air.value(inst).?;
249256 const ty = f.air.typeOf(inst);
250 switch (ty.zigTypeTag()) {
251 .Array => {
252 const writer = f.object.code_header.writer();
253 const decl_c_value = f.allocLocalValue();
254 gop.value_ptr.* = decl_c_value;
255 try writer.writeAll("static ");
256 try f.object.dg.renderTypeAndName(
257 writer,
258 ty,
259 decl_c_value,
260 .Const,
261 0,
262 );
263 try writer.writeAll(" = ");
264 try f.object.dg.renderValue(writer, ty, val, .Other);
265 try writer.writeAll(";\n ");
266 return decl_c_value;
267 },
268 else => {
269 const result = CValue{ .constant = inst };
270 gop.value_ptr.* = result;
271 return result;
272 },
273 }
257
258 const result = if (lowersToArray(ty, f.object.dg.module.getTarget())) result: {
259 const writer = f.object.code_header.writer();
260 const decl_c_value = f.allocLocalValue();
261 try writer.writeAll("static ");
262 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, 0, .Complete);
263 try writer.writeAll(" = ");
264 try f.object.dg.renderValue(writer, ty, val, .Initializer);
265 try writer.writeAll(";\n ");
266 break :result decl_c_value;
267 } else CValue{ .constant = inst };
268
269 gop.value_ptr.* = result;
270 return result;
271 }
272
273 fn wantSafety(f: *Function) bool {
274 return switch (f.object.dg.module.optimizeMode()) {
275 .Debug, .ReleaseSafe => true,
276 .ReleaseFast, .ReleaseSmall => false,
277 };
274278 }
275279
276280 fn allocLocalValue(f: *Function) CValue {
......@@ -291,17 +295,19 @@ pub const Function = struct {
291295 local_value,
292296 mutability,
293297 alignment,
298 .Complete,
294299 );
295300 return local_value;
296301 }
297302
298 fn writeCValue(f: *Function, w: anytype, c_value: CValue) !void {
303 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
299304 switch (c_value) {
300305 .constant => |inst| {
301306 const ty = f.air.typeOf(inst);
302307 const val = f.air.value(inst).?;
303 return f.object.dg.renderValue(w, ty, val, .Other);
308 return f.object.dg.renderValue(w, ty, val, location);
304309 },
310 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
305311 else => return f.object.dg.writeCValue(w, c_value),
306312 }
307313 }
......@@ -319,17 +325,48 @@ pub const Function = struct {
319325 }
320326 }
321327
328 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
329 switch (c_value) {
330 .constant => |inst| {
331 const ty = f.air.typeOf(inst);
332 const val = f.air.value(inst).?;
333 try f.object.dg.renderValue(w, ty, val, .Other);
334 try w.writeByte('.');
335 return f.writeCValue(w, member, .Other);
336 },
337 else => return f.object.dg.writeCValueMember(w, c_value, member),
338 }
339 }
340
341 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
342 switch (c_value) {
343 .constant => |inst| {
344 const ty = f.air.typeOf(inst);
345 const val = f.air.value(inst).?;
346 try w.writeByte('(');
347 try f.object.dg.renderValue(w, ty, val, .Other);
348 try w.writeAll(")->");
349 return f.writeCValue(w, member, .Other);
350 },
351 else => return f.object.dg.writeCValueDerefMember(w, c_value, member),
352 }
353 }
354
322355 fn fail(f: *Function, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
323356 return f.object.dg.fail(format, args);
324357 }
325358
326359 fn renderType(f: *Function, w: anytype, t: Type) !void {
327 return f.object.dg.renderType(w, t);
360 return f.object.dg.renderType(w, t, .Complete);
328361 }
329362
330363 fn renderTypecast(f: *Function, w: anytype, t: Type) !void {
331364 return f.object.dg.renderTypecast(w, t);
332365 }
366
367 fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) {
368 return f.object.dg.fmtIntLiteral(ty, val);
369 }
333370};
334371
335372/// This data is available when outputting .c code for a `Module`.
......@@ -362,13 +399,13 @@ pub const DeclGen = struct {
362399 @setCold(true);
363400 const src = LazySrcLoc.nodeOffset(0);
364401 const src_loc = src.toSrcLoc(dg.decl);
365 dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, src_loc, format, args);
402 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
366403 return error.AnalysisFail;
367404 }
368405
369406 fn getTypedefName(dg: *DeclGen, t: Type) ?[]const u8 {
370 if (dg.typedefs.get(t)) |some| {
371 return some.name;
407 if (dg.typedefs.get(t)) |typedef| {
408 return typedef.name;
372409 } else {
373410 return null;
374411 }
......@@ -381,86 +418,49 @@ pub const DeclGen = struct {
381418 val: Value,
382419 decl_index: Decl.Index,
383420 ) error{ OutOfMemory, AnalysisFail }!void {
421 const decl = dg.module.declPtr(decl_index);
422 assert(decl.has_tv);
423
424 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
425 if (ty.isPtrAtRuntime() and !decl.ty.isFnOrHasRuntimeBits()) {
426 return dg.writeCValue(writer, CValue{ .undef = ty });
427 }
428
429 // Chase function values in order to be able to reference the original function.
430 inline for (.{ .function, .extern_fn }) |tag|
431 if (decl.val.castTag(tag)) |func|
432 if (func.data.owner_decl != decl_index)
433 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl);
434
384435 if (ty.isSlice()) {
385436 try writer.writeByte('(');
386437 try dg.renderTypecast(writer, ty);
387 try writer.writeAll("){");
438 try writer.writeAll("){ .ptr = ");
439
388440 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
389 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Other);
390 try writer.writeAll(", ");
391 try writer.print("{d}", .{val.sliceLen(dg.module)});
392 try writer.writeAll("}");
393 return;
441 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer);
442
443 var len_pl: Value.Payload.U64 = .{
444 .base = .{ .tag = .int_u64 },
445 .data = val.sliceLen(dg.module),
446 };
447 const len_val = Value.initPayload(&len_pl.base);
448 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)});
394449 }
395450
396 const decl = dg.module.declPtr(decl_index);
397 assert(decl.has_tv);
398451 // We shouldn't cast C function pointers as this is UB (when you call
399452 // them). The analysis until now should ensure that the C function
400453 // pointers are compatible. If they are not, then there is a bug
401454 // somewhere and we should let the C compiler tell us about it.
402 if (ty.castPtrToFn() == null) {
403 // Determine if we must pointer cast.
404 if (ty.eql(decl.ty, dg.module)) {
405 try writer.writeByte('&');
406 try dg.renderDeclName(writer, decl_index);
407 return;
408 }
409
455 const need_typecast = if (ty.castPtrToFn()) |_| false else !ty.eql(decl.ty, dg.module);
456 if (need_typecast) {
410457 try writer.writeAll("((");
411458 try dg.renderTypecast(writer, ty);
412 try writer.writeAll(")&");
413 try dg.renderDeclName(writer, decl_index);
414459 try writer.writeByte(')');
415 return;
416460 }
417
461 try writer.writeByte('&');
418462 try dg.renderDeclName(writer, decl_index);
419 }
420
421 fn renderInt128(
422 writer: anytype,
423 int_val: anytype,
424 ) error{ OutOfMemory, AnalysisFail }!void {
425 const int_info = @typeInfo(@TypeOf(int_val)).Int;
426 const is_signed = int_info.signedness == .signed;
427 const is_neg = int_val < 0;
428 comptime assert(int_info.bits > 64 and int_info.bits <= 128);
429
430 // Clang and GCC don't support 128-bit integer constants but will hopefully unfold them
431 // if we construct one manually.
432 const magnitude = std.math.absCast(int_val);
433
434 const high = @truncate(u64, magnitude >> 64);
435 const low = @truncate(u64, magnitude);
436
437 // (int128_t)/<->( ( (uint128_t)( val_high << 64 )u ) + (uint128_t)val_low/u )
438 if (is_signed) try writer.writeAll("(int128_t)");
439 if (is_neg) try writer.writeByte('-');
440
441 try writer.print("(((uint128_t)0x{x}u<<64)", .{high});
442
443 if (low > 0)
444 try writer.print("+(uint128_t)0x{x}u", .{low});
445
446 return writer.writeByte(')');
447 }
448
449 fn renderBigIntConst(
450 dg: *DeclGen,
451 writer: anytype,
452 val: BigIntConst,
453 signed: bool,
454 ) error{ OutOfMemory, AnalysisFail }!void {
455 if (signed) {
456 try renderInt128(writer, val.to(i128) catch {
457 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
458 });
459 } else {
460 try renderInt128(writer, val.to(u128) catch {
461 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
462 });
463 }
463 if (need_typecast) try writer.writeByte(')');
464464 }
465465
466466 // Renders a "parent" pointer by recursing to the root decl/variable
......@@ -468,9 +468,11 @@ pub const DeclGen = struct {
468468 //
469469 // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
470470 fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type) error{ OutOfMemory, AnalysisFail }!void {
471 try writer.writeByte('(');
472 try dg.renderTypecast(writer, ptr_ty);
473 try writer.writeByte(')');
471 if (!ptr_ty.isSlice()) {
472 try writer.writeByte('(');
473 try dg.renderTypecast(writer, ptr_ty);
474 try writer.writeByte(')');
475 }
474476 switch (ptr_val.tag()) {
475477 .decl_ref_mut, .decl_ref, .variable => {
476478 const decl_index = switch (ptr_val.tag()) {
......@@ -482,43 +484,80 @@ pub const DeclGen = struct {
482484 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index);
483485 },
484486 .field_ptr => {
487 const ptr_info = ptr_ty.ptrInfo();
485488 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
486489 const container_ty = field_ptr.container_ty;
487490 const index = field_ptr.field_index;
491
492 var container_ptr_ty_pl: Type.Payload.ElemType = .{
493 .base = .{ .tag = .c_mut_pointer },
494 .data = field_ptr.container_ty,
495 };
496 const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base);
497
488498 const FieldInfo = struct { name: []const u8, ty: Type };
489499 const field_info: FieldInfo = switch (container_ty.zigTypeTag()) {
490 .Struct => .{
491 .name = container_ty.structFields().keys()[index],
492 .ty = container_ty.structFields().values()[index].ty,
500 .Struct => switch (container_ty.containerLayout()) {
501 .Auto, .Extern => FieldInfo{
502 .name = container_ty.structFields().keys()[index],
503 .ty = container_ty.structFields().values()[index].ty,
504 },
505 .Packed => if (ptr_info.data.host_size == 0) {
506 const target = dg.module.getTarget();
507
508 const byte_offset = container_ty.packedStructFieldByteOffset(index, target);
509 var byte_offset_pl = Value.Payload.U64{
510 .base = .{ .tag = .int_u64 },
511 .data = byte_offset,
512 };
513 const byte_offset_val = Value.initPayload(&byte_offset_pl.base);
514
515 var u8_ptr_pl = ptr_info;
516 u8_ptr_pl.data.pointee_type = Type.u8;
517 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
518
519 try writer.writeAll("&((");
520 try dg.renderTypecast(writer, u8_ptr_ty);
521 try writer.writeByte(')');
522 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
523 return writer.print(")[{}]", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)});
524 } else {
525 var host_pl = Type.Payload.Bits{
526 .base = .{ .tag = .int_unsigned },
527 .data = ptr_info.data.host_size * 8,
528 };
529 const host_ty = Type.initPayload(&host_pl.base);
530
531 try writer.writeByte('(');
532 try dg.renderTypecast(writer, ptr_ty);
533 try writer.writeByte(')');
534 return dg.renderParentPtr(writer, field_ptr.container_ptr, host_ty);
535 },
493536 },
494 .Union => .{
537 .Union => FieldInfo{
495538 .name = container_ty.unionFields().keys()[index],
496539 .ty = container_ty.unionFields().values()[index].ty,
497540 },
498 .Pointer => switch (container_ty.ptrSize()) {
499 .Slice => switch (index) {
541 .Pointer => field_info: {
542 assert(container_ty.isSlice());
543 break :field_info switch (index) {
500544 0 => FieldInfo{ .name = "ptr", .ty = container_ty.childType() },
501545 1 => FieldInfo{ .name = "len", .ty = Type.usize },
502546 else => unreachable,
503 },
504 else => unreachable,
547 };
505548 },
506549 else => unreachable,
507550 };
508 var container_ptr_ty_pl: Type.Payload.ElemType = .{
509 .base = .{ .tag = .c_mut_pointer },
510 .data = field_ptr.container_ty,
511 };
512 const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base);
513551
514552 if (field_info.ty.hasRuntimeBitsIgnoreComptime()) {
515553 try writer.writeAll("&(");
516554 try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
517 if (field_ptr.container_ty.tag() == .union_tagged or field_ptr.container_ty.tag() == .union_safety_tagged) {
518 try writer.print(")->payload.{ }", .{fmtIdent(field_info.name)});
519 } else {
520 try writer.print(")->{ }", .{fmtIdent(field_info.name)});
555 try writer.writeAll(")->");
556 switch (field_ptr.container_ty.tag()) {
557 .union_tagged, .union_safety_tagged => try writer.writeAll("payload."),
558 else => {},
521559 }
560 try writer.print("{ }", .{fmtIdent(field_info.name)});
522561 } else {
523562 try dg.renderParentPtr(writer, field_ptr.container_ptr, field_info.ty);
524563 }
......@@ -565,49 +604,162 @@ pub const DeclGen = struct {
565604 const target = dg.module.getTarget();
566605 if (val.isUndefDeep()) {
567606 switch (ty.zigTypeTag()) {
568 // Using '{}' for integer and floats seemed to error C compilers (both GCC and Clang)
569 // with 'error: expected expression' (including when built with 'zig cc')
570 .Int => {
571 const c_bits = toCIntBits(ty.intInfo(dg.module.getTarget()).bits) orelse
572 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
573 switch (c_bits) {
574 8 => return writer.writeAll("0xaau"),
575 16 => return writer.writeAll("0xaaaau"),
576 32 => return writer.writeAll("0xaaaaaaaau"),
577 64 => return writer.writeAll("0xaaaaaaaaaaaaaaaau"),
578 128 => return renderInt128(writer, @as(u128, 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa)),
607 // bool b = 0xaa; evals to true, but memcpy(&b, 0xaa, 1); evals to false.
608 .Bool => return dg.renderValue(writer, ty, Value.@"false", location),
609 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}),
610 .Float => {
611 try writer.writeByte('(');
612 try dg.renderTypecast(writer, ty);
613 try writer.writeAll(")zig_suffix_");
614 try dg.renderTypeForBuiltinFnName(writer, ty);
615 try writer.writeByte('(');
616 switch (ty.floatBits(target)) {
617 16 => try writer.print("{x}", .{@bitCast(f16, undefPattern(u16))}),
618 32 => try writer.print("{x}", .{@bitCast(f32, undefPattern(u32))}),
619 64 => try writer.print("{x}", .{@bitCast(f64, undefPattern(u64))}),
620 80 => try writer.print("{x}", .{@bitCast(f80, undefPattern(u80))}),
621 128 => try writer.print("{x}", .{@bitCast(f128, undefPattern(u128))}),
579622 else => unreachable,
580623 }
624 return writer.writeByte(')');
581625 },
582 .Float => {
583 switch (ty.floatBits(dg.module.getTarget())) {
584 32 => return writer.writeAll("zig_bitcast_f32_u32(0xaaaaaaaau)"),
585 64 => return writer.writeAll("zig_bitcast_f64_u64(0xaaaaaaaaaaaaaaaau)"),
586 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
626 .Pointer => if (ty.isSlice()) {
627 if (location != .Initializer) {
628 try writer.writeByte('(');
629 try dg.renderTypecast(writer, ty);
630 try writer.writeByte(')');
587631 }
632
633 try writer.writeAll("{(");
634 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
635 const ptr_ty = ty.slicePtrFieldType(&buf);
636 try dg.renderTypecast(writer, ptr_ty);
637 return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)});
638 } else {
639 try writer.writeAll("((");
640 try dg.renderTypecast(writer, ty);
641 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)});
588642 },
589 .Pointer => switch (dg.module.getTarget().cpu.arch.ptrBitWidth()) {
590 32 => return writer.writeAll("(void *)0xaaaaaaaa"),
591 64 => return writer.writeAll("(void *)0xaaaaaaaaaaaaaaaa"),
592 else => unreachable,
643 .Optional => {
644 var opt_buf: Type.Payload.ElemType = undefined;
645 const payload_ty = ty.optionalChild(&opt_buf);
646
647 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
648 return dg.renderValue(writer, Type.bool, val, location);
649 }
650
651 if (ty.optionalReprIsPayload()) {
652 return dg.renderValue(writer, payload_ty, val, location);
653 }
654
655 if (location != .Initializer) {
656 try writer.writeByte('(');
657 try dg.renderTypecast(writer, ty);
658 try writer.writeByte(')');
659 }
660
661 try writer.writeAll("{ .payload = ");
662 try dg.renderValue(writer, payload_ty, val, .Initializer);
663 try writer.writeAll(", .is_null = ");
664 try dg.renderValue(writer, Type.bool, val, .Initializer);
665 return writer.writeAll(" }");
593666 },
594 .Struct, .ErrorUnion => {
595 try writer.writeByte('(');
596 try dg.renderTypecast(writer, ty);
597 return writer.writeAll("){0xaa}");
667 .Struct => switch (ty.containerLayout()) {
668 .Auto, .Extern => {
669 if (location != .Initializer) {
670 try writer.writeByte('(');
671 try dg.renderTypecast(writer, ty);
672 try writer.writeByte(')');
673 }
674
675 try writer.writeByte('{');
676 var empty = true;
677 for (ty.structFields().values()) |field| {
678 if (!field.ty.hasRuntimeBits()) continue;
679
680 if (!empty) try writer.writeByte(',');
681 try dg.renderValue(writer, field.ty, val, .Initializer);
682
683 empty = false;
684 }
685 if (empty) try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
686 return writer.writeByte('}');
687 },
688 .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}),
689 },
690 .Union => {
691 if (location != .Initializer) {
692 try writer.writeByte('(');
693 try dg.renderTypecast(writer, ty);
694 try writer.writeByte(')');
695 }
696
697 try writer.writeByte('{');
698 if (ty.unionTagTypeSafety()) |tag_ty| {
699 try writer.writeAll(" .tag = ");
700 try dg.renderValue(writer, tag_ty, val, .Initializer);
701 try writer.writeAll(", .payload = {");
702 }
703 for (ty.unionFields().values()) |field| {
704 if (!field.ty.hasRuntimeBits()) continue;
705 try dg.renderValue(writer, field.ty, val, .Initializer);
706 break;
707 } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
708 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
709 return writer.writeByte('}');
710 },
711 .ErrorUnion => {
712 if (location != .Initializer) {
713 try writer.writeByte('(');
714 try dg.renderTypecast(writer, ty);
715 try writer.writeByte(')');
716 }
717
718 try writer.writeAll("{ .payload = ");
719 try dg.renderValue(writer, ty.errorUnionPayload(), val, .Initializer);
720 return writer.print(", .error = {x} }}", .{
721 try dg.fmtIntLiteral(ty.errorUnionSet(), val),
722 });
598723 },
599 else => {
600 // This should lower to 0xaa bytes in safe modes, and for unsafe modes should
601 // lower to leaving variables uninitialized (that might need to be implemented
602 // outside of this function).
603 return writer.writeAll("{}");
724 .Array => {
725 if (location != .Initializer) {
726 try writer.writeByte('(');
727 try dg.renderTypecast(writer, ty);
728 try writer.writeByte(')');
729 }
730
731 try writer.writeByte('{');
732 const c_len = ty.arrayLenIncludingSentinel();
733 var index: usize = 0;
734 while (index < c_len) : (index += 1) {
735 if (index > 0) try writer.writeAll(", ");
736 try dg.renderValue(writer, ty.childType(), val, .Initializer);
737 }
738 return writer.writeByte('}');
604739 },
740 .ComptimeInt,
741 .ComptimeFloat,
742 .Type,
743 .EnumLiteral,
744 .Void,
745 .NoReturn,
746 .Undefined,
747 .Null,
748 .BoundFn,
749 .Opaque,
750 => unreachable,
751 .Fn,
752 .Frame,
753 .AnyFrame,
754 .Vector,
755 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
756 @tagName(tag),
757 }),
605758 }
759 unreachable;
606760 }
607761 switch (ty.zigTypeTag()) {
608762 .Int => switch (val.tag()) {
609 .int_big_positive => try dg.renderBigIntConst(writer, val.castTag(.int_big_positive).?.asBigInt(), ty.isSignedInt()),
610 .int_big_negative => try dg.renderBigIntConst(writer, val.castTag(.int_big_negative).?.asBigInt(), true),
611763 .field_ptr,
612764 .elem_ptr,
613765 .opt_payload_ptr,
......@@ -615,48 +767,86 @@ pub const DeclGen = struct {
615767 .decl_ref_mut,
616768 .decl_ref,
617769 => try dg.renderParentPtr(writer, val, ty),
618 else => {
619 if (ty.isSignedInt())
620 return writer.print("{d}", .{val.toSignedInt()});
621 return writer.print("{d}u", .{val.toUnsignedInt(target)});
622 },
770 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}),
623771 },
624772 .Float => {
625 if (ty.floatBits(dg.module.getTarget()) <= 64) {
626 if (std.math.isNan(val.toFloat(f64)) or std.math.isInf(val.toFloat(f64))) {
627 // just generate a bit cast (exactly like we do in airBitcast)
628 switch (ty.tag()) {
629 .f32 => return writer.print("zig_bitcast_f32_u32(0x{x})", .{@bitCast(u32, val.toFloat(f32))}),
630 .f64 => return writer.print("zig_bitcast_f64_u64(0x{x})", .{@bitCast(u64, val.toFloat(f64))}),
631 else => return dg.fail("TODO float types > 64 bits are not support in renderValue() as of now", .{}),
632 }
633 } else {
634 return writer.print("{x}", .{val.toFloat(f64)});
773 try writer.writeByte('(');
774 try dg.renderTypecast(writer, ty);
775 try writer.writeByte(')');
776 const f128_val = val.toFloat(f128);
777 if (std.math.signbit(f128_val)) try writer.writeByte('-');
778 if (std.math.isFinite(f128_val)) {
779 try writer.writeAll("zig_suffix_");
780 try dg.renderTypeForBuiltinFnName(writer, ty);
781 try writer.writeByte('(');
782 switch (ty.floatBits(target)) {
783 16 => try writer.print("{x}", .{@fabs(val.toFloat(f16))}),
784 32 => try writer.print("{x}", .{@fabs(val.toFloat(f32))}),
785 64 => try writer.print("{x}", .{@fabs(val.toFloat(f64))}),
786 80 => try writer.print("{x}", .{@fabs(val.toFloat(f80))}),
787 128 => try writer.print("{x}", .{@fabs(f128_val)}),
788 else => unreachable,
635789 }
790 } else {
791 const operation = if (std.math.isSignalNan(f128_val))
792 "nans"
793 else if (std.math.isNan(f128_val))
794 "nan"
795 else if (std.math.isInf(f128_val))
796 "inf"
797 else
798 unreachable;
799 try writer.writeAll("zig_builtin_constant_");
800 try dg.renderTypeForBuiltinFnName(writer, ty);
801 try writer.writeByte('(');
802 try writer.writeAll(operation);
803 try writer.writeAll(")(");
804 if (std.math.isNan(f128_val)) switch (ty.floatBits(target)) {
805 // We only actually need to pass the significand, but it will get
806 // properly masked anyway, so just pass the whole value.
807 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, @fabs(val.toFloat(f16)))}),
808 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, @fabs(val.toFloat(f32)))}),
809 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, @fabs(val.toFloat(f64)))}),
810 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, @fabs(val.toFloat(f80)))}),
811 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, @fabs(f128_val))}),
812 else => unreachable,
813 };
636814 }
637 return dg.fail("TODO: C backend: implement lowering large float values", .{});
815 return writer.writeByte(')');
638816 },
639817 .Pointer => switch (val.tag()) {
640 .null_value => try writer.writeAll("NULL"),
641 // Technically this should produce NULL but the integer literal 0 will always coerce
642 // to the assigned pointer type. Note this is just a hack to fix warnings from ordered comparisons (<, >, etc)
643 // between pointers and 0, which is an extension to begin with.
644 .zero => try writer.writeByte('0'),
818 .null_value, .zero => if (ty.isSlice()) {
819 var slice_pl = Value.Payload.Slice{
820 .base = .{ .tag = .slice },
821 .data = .{ .ptr = val, .len = Value.undef },
822 };
823 const slice_val = Value.initPayload(&slice_pl.base);
824
825 return dg.renderValue(writer, ty, slice_val, location);
826 } else {
827 try writer.writeAll("((");
828 try dg.renderTypecast(writer, ty);
829 try writer.writeAll(")NULL)");
830 },
645831 .variable => {
646832 const decl = val.castTag(.variable).?.data.owner_decl;
647833 return dg.renderDeclValue(writer, ty, val, decl);
648834 },
649835 .slice => {
836 if (location != .Initializer) {
837 try writer.writeByte('(');
838 try dg.renderTypecast(writer, ty);
839 try writer.writeByte(')');
840 }
841
650842 const slice = val.castTag(.slice).?.data;
651843 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
652844
653 try writer.writeByte('(');
654 try dg.renderTypecast(writer, ty);
655 try writer.writeAll("){");
656 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, location);
845 try writer.writeByte('{');
846 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, .Initializer);
657847 try writer.writeAll(", ");
658 try dg.renderValue(writer, Type.usize, slice.len, location);
659 try writer.writeAll("}");
848 try dg.renderValue(writer, Type.usize, slice.len, .Initializer);
849 try writer.writeByte('}');
660850 },
661851 .function => {
662852 const func = val.castTag(.function).?.data;
......@@ -669,7 +859,7 @@ pub const DeclGen = struct {
669859 .int_u64, .one => {
670860 try writer.writeAll("((");
671861 try dg.renderTypecast(writer, ty);
672 try writer.print(")0x{x}u)", .{val.toUnsignedInt(target)});
862 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)});
673863 },
674864 .field_ptr,
675865 .elem_ptr,
......@@ -681,111 +871,106 @@ pub const DeclGen = struct {
681871 else => unreachable,
682872 },
683873 .Array => {
874 if (location == .FunctionArgument) {
875 try writer.writeByte('(');
876 try dg.renderTypecast(writer, ty);
877 try writer.writeByte(')');
878 }
879
684880 // First try specific tag representations for more efficiency.
685881 switch (val.tag()) {
686882 .undef, .empty_struct_value, .empty_array => {
687883 try writer.writeByte('{');
688884 const ai = ty.arrayInfo();
689885 if (ai.sentinel) |s| {
690 try dg.renderValue(writer, ai.elem_type, s, location);
886 try dg.renderValue(writer, ai.elem_type, s, .Initializer);
887 } else {
888 try writer.writeByte('0');
691889 }
692890 try writer.writeByte('}');
693891 },
694892 else => {
695893 // Fall back to generic implementation.
696 var arena = std.heap.ArenaAllocator.init(dg.module.gpa);
894 var arena = std.heap.ArenaAllocator.init(dg.gpa);
697895 defer arena.deinit();
698896 const arena_allocator = arena.allocator();
699897
700 if (location == .FunctionArgument) {
701 try writer.writeByte('(');
702 try dg.renderTypecast(writer, ty);
703 try writer.writeByte(')');
704 }
705
706898 try writer.writeByte('{');
707899 const ai = ty.arrayInfo();
708900 var index: usize = 0;
709901 while (index < ai.len) : (index += 1) {
710 if (index != 0) try writer.writeAll(",");
902 if (index != 0) try writer.writeByte(',');
711903 const elem_val = try val.elemValue(dg.module, arena_allocator, index);
712 try dg.renderValue(writer, ai.elem_type, elem_val, .Other);
904 try dg.renderValue(writer, ai.elem_type, elem_val, .Initializer);
713905 }
714906 if (ai.sentinel) |s| {
715 if (index != 0) try writer.writeAll(",");
716 try dg.renderValue(writer, ai.elem_type, s, .Other);
907 if (index != 0) try writer.writeByte(',');
908 try dg.renderValue(writer, ai.elem_type, s, .Initializer);
717909 }
718910 try writer.writeByte('}');
719911 },
720912 }
721913 },
722 .Bool => return writer.print("{}", .{val.toBool()}),
914 .Bool => return writer.print("zig_{}", .{val.toBool()}),
723915 .Optional => {
724916 var opt_buf: Type.Payload.ElemType = undefined;
725917 const payload_ty = ty.optionalChild(&opt_buf);
726918
727 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
728 const is_null = val.castTag(.opt_payload) == null;
729 return writer.print("{}", .{is_null});
730 }
919 const is_null_val = Value.makeBool(val.tag() == .null_value);
920 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
921 return dg.renderValue(writer, Type.bool, is_null_val, location);
731922
732923 if (ty.optionalReprIsPayload()) {
733 if (val.castTag(.opt_payload)) |payload| {
734 return dg.renderValue(writer, payload_ty, payload.data, location);
735 } else {
736 return dg.renderValue(writer, payload_ty, val, location);
737 }
924 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val;
925 return dg.renderValue(writer, payload_ty, payload_val, location);
738926 }
739927
740 try writer.writeByte('(');
741 try dg.renderTypecast(writer, ty);
742 try writer.writeAll("){");
743 if (val.castTag(.opt_payload)) |pl| {
744 const payload_val = pl.data;
745 try writer.writeAll(" .is_null = false, .payload = ");
746 try dg.renderValue(writer, payload_ty, payload_val, location);
747 try writer.writeAll(" }");
748 } else {
749 try writer.writeAll(" .is_null = true }");
928 if (location != .Initializer) {
929 try writer.writeByte('(');
930 try dg.renderTypecast(writer, ty);
931 try writer.writeByte(')');
750932 }
933
934 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef;
935
936 try writer.writeAll("{ .payload = ");
937 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);
938 try writer.writeAll(", .is_null = ");
939 try dg.renderValue(writer, Type.bool, is_null_val, .Initializer);
940 try writer.writeAll(" }");
751941 },
752942 .ErrorSet => {
753 switch (val.tag()) {
754 .@"error" => {
755 const payload = val.castTag(.@"error").?;
756 // error values will be #defined at the top of the file
757 return writer.print("zig_error_{s}", .{payload.data.name});
758 },
759 else => {
760 // In this case we are rendering an error union which has a
761 // 0 bits payload.
762 return writer.writeAll("0");
763 },
764 }
943 const error_name = if (val.castTag(.@"error")) |error_pl|
944 error_pl.data.name
945 else
946 dg.module.error_name_list.items[0];
947 // Error values are already defined by genErrDecls.
948 try writer.print("zig_error_{}", .{fmtIdent(error_name)});
765949 },
766950 .ErrorUnion => {
767 const error_type = ty.errorUnionSet();
768 const payload_type = ty.errorUnionPayload();
951 const error_ty = ty.errorUnionSet();
952 const payload_ty = ty.errorUnionPayload();
769953
770 if (!payload_type.hasRuntimeBits()) {
954 if (!payload_ty.hasRuntimeBits()) {
771955 // We use the error type directly as the type.
772956 const err_val = if (val.errorUnionIsPayload()) Value.initTag(.zero) else val;
773 return dg.renderValue(writer, error_type, err_val, location);
957 return dg.renderValue(writer, error_ty, err_val, location);
774958 }
775959
776 try writer.writeByte('(');
777 try dg.renderTypecast(writer, ty);
778 try writer.writeAll("){");
779 if (val.castTag(.eu_payload)) |pl| {
780 const payload_val = pl.data;
781 try writer.writeAll(" .payload = ");
782 try dg.renderValue(writer, payload_type, payload_val, location);
783 try writer.writeAll(", .error = 0 }");
784 } else {
785 try writer.writeAll(" .error = ");
786 try dg.renderValue(writer, error_type, val, location);
787 try writer.writeAll(" }");
960 if (location != .Initializer) {
961 try writer.writeByte('(');
962 try dg.renderTypecast(writer, ty);
963 try writer.writeByte(')');
788964 }
965
966 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
967 const error_val = if (val.errorUnionIsPayload()) Value.zero else val;
968
969 try writer.writeAll("{ .payload = ");
970 try dg.renderValue(writer, payload_ty, payload_val, .Initializer);
971 try writer.writeAll(", .error = ");
972 try dg.renderValue(writer, error_ty, error_val, .Initializer);
973 try writer.writeAll(" }");
789974 },
790975 .Enum => {
791976 switch (val.tag()) {
......@@ -832,37 +1017,79 @@ pub const DeclGen = struct {
8321017 },
8331018 else => unreachable,
8341019 },
835 .Struct => {
836 const field_vals = val.castTag(.aggregate).?.data;
1020 .Struct => switch (ty.containerLayout()) {
1021 .Auto, .Extern => {
1022 const field_vals = val.castTag(.aggregate).?.data;
1023
1024 if (location != .Initializer) {
1025 try writer.writeByte('(');
1026 try dg.renderTypecast(writer, ty);
1027 try writer.writeByte(')');
1028 }
8371029
838 try writer.writeAll("(");
839 try dg.renderTypecast(writer, ty);
840 try writer.writeAll("){");
1030 try writer.writeByte('{');
1031 var empty = true;
1032 for (field_vals) |field_val, field_index| {
1033 const field_ty = ty.structFieldType(field_index);
1034 if (!field_ty.hasRuntimeBits()) continue;
8411035
842 var i: usize = 0;
843 for (field_vals) |field_val, field_index| {
844 const field_ty = ty.structFieldType(field_index);
845 if (!field_ty.hasRuntimeBits()) continue;
1036 if (!empty) try writer.writeByte(',');
1037 try dg.renderValue(writer, field_ty, field_val, .Initializer);
8461038
847 if (i != 0) try writer.writeAll(",");
848 try dg.renderValue(writer, field_ty, field_val, location);
849 i += 1;
850 }
1039 empty = false;
1040 }
1041 if (empty) try writer.print("{}", .{try dg.fmtIntLiteral(Type.u8, Value.zero)});
1042 try writer.writeByte('}');
1043 },
1044 .Packed => {
1045 const field_vals = val.castTag(.aggregate).?.data;
1046 const int_info = ty.intInfo(target);
1047
1048 var bit_offset_ty_pl = Type.Payload.Bits{
1049 .base = .{ .tag = .int_unsigned },
1050 .data = Type.smallestUnsignedBits(int_info.bits - 1),
1051 };
1052 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
8511053
852 try writer.writeAll("}");
1054 var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 };
1055 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
1056
1057 try writer.writeByte('(');
1058 var empty = true;
1059 for (field_vals) |field_val, index| {
1060 const field_ty = ty.structFieldType(index);
1061 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1062
1063 if (!empty) try writer.writeAll(" | ");
1064 try writer.writeByte('(');
1065 try dg.renderTypecast(writer, ty);
1066 try writer.writeByte(')');
1067 try dg.renderValue(writer, field_ty, field_val, .Other);
1068 try writer.writeAll(" << ");
1069 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1070
1071 bit_offset_val_pl.data += field_ty.bitSize(target);
1072 empty = false;
1073 }
1074 if (empty) try dg.renderValue(writer, ty, Value.undef, .Initializer);
1075 try writer.writeByte(')');
1076 },
8531077 },
8541078 .Union => {
8551079 const union_obj = val.castTag(.@"union").?.data;
8561080 const layout = ty.unionGetLayout(target);
8571081
858 try writer.writeAll("(");
859 try dg.renderTypecast(writer, ty);
860 try writer.writeAll("){");
1082 if (location != .Initializer) {
1083 try writer.writeByte('(');
1084 try dg.renderTypecast(writer, ty);
1085 try writer.writeByte(')');
1086 }
8611087
1088 try writer.writeByte('{');
8621089 if (ty.unionTagTypeSafety()) |tag_ty| {
8631090 if (layout.tag_size != 0) {
8641091 try writer.writeAll(".tag = ");
865 try dg.renderValue(writer, tag_ty, union_obj.tag, location);
1092 try dg.renderValue(writer, tag_ty, union_obj.tag, .Initializer);
8661093 try writer.writeAll(", ");
8671094 }
8681095 try writer.writeAll(".payload = {");
......@@ -873,12 +1100,10 @@ pub const DeclGen = struct {
8731100 const field_name = ty.unionFields().keys()[index];
8741101 if (field_ty.hasRuntimeBits()) {
8751102 try writer.print(".{ } = ", .{fmtIdent(field_name)});
876 try dg.renderValue(writer, field_ty, union_obj.val, location);
877 }
878 if (ty.unionTagTypeSafety()) |_| {
879 try writer.writeAll("}");
880 }
881 try writer.writeAll("}");
1103 try dg.renderValue(writer, field_ty, union_obj.val, .Initializer);
1104 } else try writer.writeByte('0');
1105 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
1106 try writer.writeByte('}');
8821107 },
8831108
8841109 .ComptimeInt => unreachable,
......@@ -901,75 +1126,69 @@ pub const DeclGen = struct {
9011126 }
9021127 }
9031128
904 fn renderFunctionSignature(dg: *DeclGen, w: anytype, is_global: bool) !void {
905 if (!is_global) {
906 try w.writeAll("static ");
907 }
908 if (dg.decl.val.castTag(.function)) |func_payload| {
909 const func: *Module.Fn = func_payload.data;
910 if (func.is_cold) {
911 try w.writeAll("ZIG_COLD ");
912 }
913 }
1129 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind) !void {
9141130 const fn_info = dg.decl.ty.fnInfo();
915 if (fn_info.return_type.hasRuntimeBits()) {
916 try dg.renderType(w, fn_info.return_type);
917 } else if (fn_info.return_type.isError()) {
918 try dg.renderType(w, Type.anyerror);
919 } else if (fn_info.return_type.zigTypeTag() == .NoReturn) {
920 try w.writeAll("zig_noreturn void");
921 } else {
922 try w.writeAll("void");
923 }
924 try w.writeAll(" ");
1131 if (fn_info.cc == .Naked) try w.writeAll("zig_naked ");
1132 if (dg.decl.val.castTag(.function)) |func_payload|
1133 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1134
1135 const target = dg.module.getTarget();
1136 var ret_buf: LowerFnRetTyBuffer = undefined;
1137 const ret_ty = lowerFnRetTy(fn_info.return_type, &ret_buf, target);
1138
1139 try dg.renderType(w, ret_ty, kind);
1140 try w.writeByte(' ');
9251141 try dg.renderDeclName(w, dg.decl_index);
926 try w.writeAll("(");
1142 try w.writeByte('(');
9271143
928 var params_written: usize = 0;
929 for (fn_info.param_types) |param_type, index| {
1144 var index: usize = 0;
1145 for (fn_info.param_types) |param_type| {
9301146 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
931 if (params_written > 0) {
932 try w.writeAll(", ");
933 }
1147 if (index > 0) try w.writeAll(", ");
9341148 const name = CValue{ .arg = index };
935 try dg.renderTypeAndName(w, param_type, name, .Mut, 0);
936 params_written += 1;
1149 try dg.renderTypeAndName(w, param_type, name, .ConstArgument, 0, kind);
1150 index += 1;
9371151 }
9381152
9391153 if (fn_info.is_var_args) {
940 if (params_written != 0) try w.writeAll(", ");
1154 if (index > 0) try w.writeAll(", ");
9411155 try w.writeAll("...");
942 } else if (params_written == 0) {
943 try w.writeAll("void");
1156 } else if (index == 0) {
1157 try dg.renderType(w, Type.void, kind);
9441158 }
9451159 try w.writeByte(')');
9461160 }
9471161
948 fn renderPtrToFnTypedef(dg: *DeclGen, t: Type, fn_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1162 fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
9491163 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
9501164 defer buffer.deinit();
9511165 const bw = buffer.writer();
9521166
953 const fn_info = fn_ty.fnInfo();
1167 const fn_info = t.fnInfo();
1168
1169 const target = dg.module.getTarget();
1170 var ret_buf: LowerFnRetTyBuffer = undefined;
1171 const ret_ty = lowerFnRetTy(fn_info.return_type, &ret_buf, target);
9541172
9551173 try bw.writeAll("typedef ");
956 try dg.renderType(bw, fn_info.return_type);
1174 try dg.renderType(bw, ret_ty, .Forward);
9571175 try bw.writeAll(" (*");
958
959 const name_start = buffer.items.len;
960 try bw.print("zig_F_{s})(", .{typeToCIdentifier(t, dg.module)});
961 const name_end = buffer.items.len - 2;
1176 const name_begin = buffer.items.len;
1177 try bw.print("zig_F_{}", .{typeToCIdentifier(t, dg.module)});
1178 const name_end = buffer.items.len;
1179 try bw.writeAll(")(");
9621180
9631181 const param_len = fn_info.param_types.len;
9641182
9651183 var params_written: usize = 0;
9661184 var index: usize = 0;
9671185 while (index < param_len) : (index += 1) {
968 if (!fn_info.param_types[index].hasRuntimeBitsIgnoreComptime()) continue;
1186 const param_ty = fn_info.param_types[index];
1187 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
9691188 if (params_written > 0) {
9701189 try bw.writeAll(", ");
9711190 }
972 try dg.renderTypecast(bw, fn_info.param_types[index]);
1191 try dg.renderTypeAndName(bw, param_ty, .{ .bytes = "" }, .Mut, 0, .Forward);
9731192 params_written += 1;
9741193 }
9751194
......@@ -977,13 +1196,13 @@ pub const DeclGen = struct {
9771196 if (params_written != 0) try bw.writeAll(", ");
9781197 try bw.writeAll("...");
9791198 } else if (params_written == 0) {
980 try bw.writeAll("void");
1199 try dg.renderType(bw, Type.void, .Forward);
9811200 }
9821201 try bw.writeAll(");\n");
9831202
9841203 const rendered = buffer.toOwnedSlice();
9851204 errdefer dg.typedefs.allocator.free(rendered);
986 const name = rendered[name_start..name_end];
1205 const name = rendered[name_begin..name_end];
9871206
9881207 try dg.typedefs.ensureUnusedCapacity(1);
9891208 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -995,36 +1214,35 @@ pub const DeclGen = struct {
9951214 }
9961215
9971216 fn renderSliceTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1217 std.debug.assert(t.sentinel() == null); // expected canonical type
1218
9981219 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
9991220 defer buffer.deinit();
10001221 const bw = buffer.writer();
10011222
1002 try bw.writeAll("typedef struct { ");
1003
1004 var ptr_type_buf: Type.SlicePtrFieldTypeBuffer = undefined;
1005 const ptr_type = t.slicePtrFieldType(&ptr_type_buf);
1006 const ptr_name = CValue{ .bytes = "ptr" };
1007 try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0);
1008
1009 const ptr_sentinel = ptr_type.ptrInfo().data.sentinel;
1010 const child_type = t.childType();
1011
1012 try bw.writeAll("; size_t len; } ");
1013 const name_index = buffer.items.len;
1014 if (t.isConstPtr()) {
1015 try bw.print("zig_L_{s}", .{typeToCIdentifier(child_type, dg.module)});
1016 } else {
1017 try bw.print("zig_M_{s}", .{typeToCIdentifier(child_type, dg.module)});
1018 }
1019 if (ptr_sentinel) |s| {
1020 try bw.writeAll("_s_");
1021 try dg.renderValue(bw, child_type, s, .Other);
1022 }
1223 var ptr_ty_buf: Type.SlicePtrFieldTypeBuffer = undefined;
1224 const ptr_ty = t.slicePtrFieldType(&ptr_ty_buf);
1225 const ptr_name = CValue{ .identifier = "ptr" };
1226 const len_ty = Type.usize;
1227 const len_name = CValue{ .identifier = "len" };
1228
1229 try bw.writeAll("typedef struct {\n ");
1230 try dg.renderTypeAndName(bw, ptr_ty, ptr_name, .Mut, 0, .Complete);
1231 try bw.writeAll(";\n ");
1232 try dg.renderTypeAndName(bw, len_ty, len_name, .Mut, 0, .Complete);
1233
1234 try bw.writeAll(";\n} ");
1235 const name_begin = buffer.items.len;
1236 try bw.print("zig_{c}_{}", .{
1237 @as(u8, if (t.isConstPtr()) 'L' else 'M'),
1238 typeToCIdentifier(t.childType(), dg.module),
1239 });
1240 const name_end = buffer.items.len;
10231241 try bw.writeAll(";\n");
10241242
10251243 const rendered = buffer.toOwnedSlice();
10261244 errdefer dg.typedefs.allocator.free(rendered);
1027 const name = rendered[name_index .. rendered.len - 2];
1245 const name = rendered[name_begin..name_end];
10281246
10291247 try dg.typedefs.ensureUnusedCapacity(1);
10301248 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1035,36 +1253,34 @@ pub const DeclGen = struct {
10351253 return name;
10361254 }
10371255
1038 fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1039 const struct_obj = t.castTag(.@"struct").?.data; // Handle 0 bit types elsewhere.
1040 const fqn = try struct_obj.getFullyQualifiedName(dg.module);
1041 defer dg.typedefs.allocator.free(fqn);
1256 fn renderFwdTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1257 // The forward declaration for T is stored with a key of *const T.
1258 const child_ty = t.childType();
10421259
1043 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1044 defer buffer.deinit();
1260 var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator);
1261 defer fqn_buf.deinit();
10451262
1046 try buffer.appendSlice("typedef struct {\n");
1047 {
1048 var it = struct_obj.fields.iterator();
1049 while (it.next()) |entry| {
1050 const field_ty = entry.value_ptr.ty;
1051 if (!field_ty.hasRuntimeBits()) continue;
1263 const owner_decl = dg.module.declPtr(child_ty.getOwnerDecl());
1264 try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer());
10521265
1053 const alignment = entry.value_ptr.abi_align;
1054 const name: CValue = .{ .identifier = entry.key_ptr.* };
1055 try buffer.append(' ');
1056 try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment);
1057 try buffer.appendSlice(";\n");
1058 }
1059 }
1060 try buffer.appendSlice("} ");
1266 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1267 defer buffer.deinit();
10611268
1062 const name_start = buffer.items.len;
1063 try buffer.writer().print("zig_S_{};\n", .{fmtIdent(fqn)});
1269 const tag = switch (child_ty.zigTypeTag()) {
1270 .Struct => "struct ",
1271 .Union => if (child_ty.unionTagTypeSafety()) |_| "struct " else "union ",
1272 else => unreachable,
1273 };
1274 const name_begin = buffer.items.len + "typedef ".len + tag.len;
1275 try buffer.writer().print("typedef {s}zig_S_{} ", .{ tag, fmtIdent(fqn_buf.items) });
1276 const name_end = buffer.items.len - " ".len;
1277 try buffer.ensureUnusedCapacity((name_end - name_begin) + ";\n".len);
1278 buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]);
1279 buffer.appendSliceAssumeCapacity(";\n");
10641280
10651281 const rendered = buffer.toOwnedSlice();
10661282 errdefer dg.typedefs.allocator.free(rendered);
1067 const name = rendered[name_start .. rendered.len - 2];
1283 const name = rendered[name_begin..name_end];
10681284
10691285 try dg.typedefs.ensureUnusedCapacity(1);
10701286 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1075,36 +1291,84 @@ pub const DeclGen = struct {
10751291 return name;
10761292 }
10771293
1078 fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1079 const tuple = t.tupleFields();
1294 fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1295 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1296 const ptr_ty = Type.initPayload(&ptr_pl.base);
1297 const name = dg.getTypedefName(ptr_ty) orelse
1298 try dg.renderFwdTypedef(ptr_ty);
10801299
10811300 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
10821301 defer buffer.deinit();
1083 const writer = buffer.writer();
10841302
1085 try buffer.appendSlice("typedef struct {\n");
1303 try buffer.appendSlice("struct ");
1304 try buffer.appendSlice(name);
1305 try buffer.appendSlice(" {\n");
10861306 {
1087 for (tuple.types) |field_ty, i| {
1088 const val = tuple.values[i];
1089 if (val.tag() != .unreachable_value) continue;
1090
1091 var name = std.ArrayList(u8).init(dg.gpa);
1092 defer name.deinit();
1093 try name.writer().print("field_{d}", .{i});
1307 var it = t.structFields().iterator();
1308 var empty = true;
1309 while (it.next()) |field| {
1310 const field_ty = field.value_ptr.ty;
1311 if (!field_ty.hasRuntimeBits()) continue;
10941312
1313 const alignment = field.value_ptr.abi_align;
1314 const field_name = CValue{ .identifier = field.key_ptr.* };
10951315 try buffer.append(' ');
1096 try dg.renderTypeAndName(writer, field_ty, .{ .bytes = name.items }, .Mut, 0);
1316 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete);
10971317 try buffer.appendSlice(";\n");
1318
1319 empty = false;
10981320 }
1321 if (empty) try buffer.appendSlice(" char empty_struct;\n");
10991322 }
1100 try buffer.appendSlice("} ");
1323 try buffer.appendSlice("};\n");
1324
1325 const rendered = buffer.toOwnedSlice();
1326 errdefer dg.typedefs.allocator.free(rendered);
1327
1328 try dg.typedefs.ensureUnusedCapacity(1);
1329 dg.typedefs.putAssumeCapacityNoClobber(
1330 try t.copy(dg.typedefs_arena),
1331 .{ .name = name, .rendered = rendered },
1332 );
1333
1334 return name;
1335 }
1336
1337 fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1338 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1339 defer buffer.deinit();
1340
1341 try buffer.appendSlice("typedef struct {\n");
1342 {
1343 const fields = t.tupleFields();
1344 var empty = true;
1345 for (fields.types) |field_ty, i| {
1346 if (!field_ty.hasRuntimeBits()) continue;
1347 const val = fields.values[i];
1348 if (val.tag() != .unreachable_value) continue;
1349
1350 var field_name_buf: []const u8 = &.{};
1351 defer dg.typedefs.allocator.free(field_name_buf);
1352 const field_name = if (t.isTuple()) field_name: {
1353 field_name_buf = try std.fmt.allocPrint(dg.typedefs.allocator, "field_{d}", .{i});
1354 break :field_name field_name_buf;
1355 } else t.structFieldName(i);
11011356
1102 const name_start = buffer.items.len;
1103 try writer.print("zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
1357 try buffer.append(' ');
1358 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .identifier = field_name }, .Mut, 0, .Complete);
1359 try buffer.appendSlice(";\n");
1360
1361 empty = false;
1362 }
1363 if (empty) try buffer.appendSlice(" char empty_tuple;\n");
1364 }
1365 const name_begin = buffer.items.len + "} ".len;
1366 try buffer.writer().print("}} zig_T_{};\n", .{typeToCIdentifier(t, dg.module)});
1367 const name_end = buffer.items.len - ";\n".len;
11041368
11051369 const rendered = buffer.toOwnedSlice();
11061370 errdefer dg.typedefs.allocator.free(rendered);
1107 const name = rendered[name_start .. rendered.len - 2];
1371 const name = rendered[name_begin..name_end];
11081372
11091373 try dg.typedefs.ensureUnusedCapacity(1);
11101374 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1116,51 +1380,56 @@ pub const DeclGen = struct {
11161380 }
11171381
11181382 fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1119 const union_ty = t.cast(Type.Payload.Union).?.data;
1120 const fqn = try union_ty.getFullyQualifiedName(dg.module);
1121 defer dg.typedefs.allocator.free(fqn);
1122
1123 const target = dg.module.getTarget();
1124 const layout = t.unionGetLayout(target);
1383 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1384 const ptr_ty = Type.initPayload(&ptr_pl.base);
1385 const name = dg.getTypedefName(ptr_ty) orelse
1386 try dg.renderFwdTypedef(ptr_ty);
11251387
11261388 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
11271389 defer buffer.deinit();
11281390
1129 try buffer.appendSlice("typedef ");
1130 if (t.unionTagTypeSafety()) |tag_ty| {
1131 const name: CValue = .{ .bytes = "tag" };
1132 try buffer.appendSlice("struct {\n ");
1391 try buffer.appendSlice(if (t.unionTagTypeSafety()) |_| "struct " else "union ");
1392 try buffer.appendSlice(name);
1393 try buffer.appendSlice(" {\n");
1394
1395 const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: {
1396 const target = dg.module.getTarget();
1397 const layout = t.unionGetLayout(target);
11331398 if (layout.tag_size != 0) {
1134 try dg.renderTypeAndName(buffer.writer(), tag_ty, name, .Mut, 0);
1399 try buffer.append(' ');
1400 try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0, .Complete);
11351401 try buffer.appendSlice(";\n");
11361402 }
1137 }
1403 try buffer.appendSlice(" union {\n");
1404 break :indent " ";
1405 } else " ";
11381406
1139 try buffer.appendSlice("union {\n");
11401407 {
11411408 var it = t.unionFields().iterator();
1142 while (it.next()) |entry| {
1143 const field_ty = entry.value_ptr.ty;
1409 var empty = true;
1410 while (it.next()) |field| {
1411 const field_ty = field.value_ptr.ty;
11441412 if (!field_ty.hasRuntimeBits()) continue;
1145 const alignment = entry.value_ptr.abi_align;
1146 const name: CValue = .{ .identifier = entry.key_ptr.* };
1147 try buffer.append(' ');
1148 try dg.renderTypeAndName(buffer.writer(), field_ty, name, .Mut, alignment);
1413
1414 const alignment = field.value_ptr.abi_align;
1415 const field_name = CValue{ .identifier = field.key_ptr.* };
1416 try buffer.appendSlice(indent);
1417 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete);
11491418 try buffer.appendSlice(";\n");
1150 }
1151 }
1152 try buffer.appendSlice("} ");
11531419
1154 if (t.unionTagTypeSafety()) |_| {
1155 try buffer.appendSlice("payload;\n} ");
1420 empty = false;
1421 }
1422 if (empty) {
1423 try buffer.appendSlice(indent);
1424 try buffer.appendSlice("char empty_union;\n");
1425 }
11561426 }
11571427
1158 const name_start = buffer.items.len;
1159 try buffer.writer().print("zig_U_{};\n", .{fmtIdent(fqn)});
1428 if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n");
1429 try buffer.appendSlice("};\n");
11601430
11611431 const rendered = buffer.toOwnedSlice();
11621432 errdefer dg.typedefs.allocator.free(rendered);
1163 const name = rendered[name_start .. rendered.len - 2];
11641433
11651434 try dg.typedefs.ensureUnusedCapacity(1);
11661435 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1172,42 +1441,39 @@ pub const DeclGen = struct {
11721441 }
11731442
11741443 fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1175 const payload_ty = t.errorUnionPayload();
1176 const error_ty = t.errorUnionSet();
1444 assert(t.errorUnionSet().tag() == .anyerror);
11771445
11781446 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
11791447 defer buffer.deinit();
11801448 const bw = buffer.writer();
11811449
1182 const payload_name = CValue{ .bytes = "payload" };
1450 const payload_ty = t.errorUnionPayload();
1451 const payload_name = CValue{ .identifier = "payload" };
1452 const error_ty = t.errorUnionSet();
1453 const error_name = CValue{ .identifier = "error" };
1454
11831455 const target = dg.module.getTarget();
11841456 const payload_align = payload_ty.abiAlignment(target);
1185 const error_align = Type.anyerror.abiAlignment(target);
1457 const error_align = error_ty.abiAlignment(target);
1458 try bw.writeAll("typedef struct {\n ");
11861459 if (error_align > payload_align) {
1187 try bw.writeAll("typedef struct { ");
1188 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0);
1189 try bw.writeAll("; uint16_t error; } ");
1190 } else {
1191 try bw.writeAll("typedef struct { uint16_t error; ");
1192 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0);
1193 try bw.writeAll("; } ");
1194 }
1195
1196 const name_index = buffer.items.len;
1197 if (error_ty.castTag(.error_set_inferred)) |inf_err_set_payload| {
1198 const func = inf_err_set_payload.data.func;
1199 try bw.writeAll("zig_E_");
1200 try dg.renderDeclName(bw, func.owner_decl);
1201 try bw.writeAll(";\n");
1460 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1461 try bw.writeAll(";\n ");
1462 try dg.renderTypeAndName(bw, error_ty, error_name, .Mut, 0, .Complete);
12021463 } else {
1203 try bw.print("zig_E_{s}_{s};\n", .{
1204 typeToCIdentifier(error_ty, dg.module), typeToCIdentifier(payload_ty, dg.module),
1205 });
1464 try dg.renderTypeAndName(bw, error_ty, error_name, .Mut, 0, .Complete);
1465 try bw.writeAll(";\n ");
1466 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
12061467 }
1468 try bw.writeAll(";\n} ");
1469 const name_begin = buffer.items.len;
1470 try bw.print("zig_E_{}", .{typeToCIdentifier(payload_ty, dg.module)});
1471 const name_end = buffer.items.len;
1472 try bw.writeAll(";\n");
12071473
12081474 const rendered = buffer.toOwnedSlice();
12091475 errdefer dg.typedefs.allocator.free(rendered);
1210 const name = rendered[name_index .. rendered.len - 2];
1476 const name = rendered[name_begin..name_end];
12111477
12121478 try dg.typedefs.ensureUnusedCapacity(1);
12131479 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1219,26 +1485,28 @@ pub const DeclGen = struct {
12191485 }
12201486
12211487 fn renderArrayTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1488 const info = t.arrayInfo();
1489 std.debug.assert(info.sentinel == null); // expected canonical type
1490
12221491 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
12231492 defer buffer.deinit();
12241493 const bw = buffer.writer();
12251494
1226 const elem_type = t.elemType();
1227 const sentinel_bit = @boolToInt(t.sentinel() != null);
1228 const c_len = t.arrayLen() + sentinel_bit;
1229
12301495 try bw.writeAll("typedef ");
1231 try dg.renderType(bw, elem_type);
1496 try dg.renderType(bw, info.elem_type, .Complete);
12321497
1233 const name_start = buffer.items.len + 1;
1234 try bw.print(" zig_A_{s}_{d}", .{ typeToCIdentifier(elem_type, dg.module), c_len });
1498 const name_begin = buffer.items.len + " ".len;
1499 try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(info.elem_type, dg.module), info.len });
12351500 const name_end = buffer.items.len;
12361501
1237 try bw.print("[{d}];\n", .{c_len});
1502 const c_len = if (info.len > 0) info.len else 1;
1503 var c_len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = c_len };
1504 const c_len_val = Value.initPayload(&c_len_pl.base);
1505 try bw.print("[{}];\n", .{try dg.fmtIntLiteral(Type.usize, c_len_val)});
12381506
12391507 const rendered = buffer.toOwnedSlice();
12401508 errdefer dg.typedefs.allocator.free(rendered);
1241 const name = rendered[name_start..name_end];
1509 const name = rendered[name_begin..name_end];
12421510
12431511 try dg.typedefs.ensureUnusedCapacity(1);
12441512 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1254,16 +1522,48 @@ pub const DeclGen = struct {
12541522 defer buffer.deinit();
12551523 const bw = buffer.writer();
12561524
1257 try bw.writeAll("typedef struct { ");
1258 const payload_name = CValue{ .bytes = "payload" };
1259 try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
1260 try bw.writeAll("; bool is_null; } ");
1261 const name_index = buffer.items.len;
1262 try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type, dg.module)});
1525 try bw.writeAll("typedef struct {\n ");
1526 try dg.renderTypeAndName(bw, child_type, .{ .identifier = "payload" }, .Mut, 0, .Complete);
1527 try bw.writeAll(";\n ");
1528 try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete);
1529 try bw.writeAll(";\n} ");
1530 const name_begin = buffer.items.len;
1531 try bw.print("zig_Q_{}", .{typeToCIdentifier(child_type, dg.module)});
1532 const name_end = buffer.items.len;
1533 try bw.writeAll(";\n");
1534
1535 const rendered = buffer.toOwnedSlice();
1536 errdefer dg.typedefs.allocator.free(rendered);
1537 const name = rendered[name_begin..name_end];
1538
1539 try dg.typedefs.ensureUnusedCapacity(1);
1540 dg.typedefs.putAssumeCapacityNoClobber(
1541 try t.copy(dg.typedefs_arena),
1542 .{ .name = name, .rendered = rendered },
1543 );
1544
1545 return name;
1546 }
1547
1548 fn renderOpaqueTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1549 const opaque_ty = t.cast(Type.Payload.Opaque).?.data;
1550 const unqualified_name = dg.module.declPtr(opaque_ty.owner_decl).name;
1551 const fqn = try opaque_ty.getFullyQualifiedName(dg.module);
1552 defer dg.typedefs.allocator.free(fqn);
1553
1554 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1555 defer buffer.deinit();
1556
1557 try buffer.writer().print("typedef struct { } ", .{fmtIdent(std.mem.span(unqualified_name))});
1558
1559 const name_begin = buffer.items.len;
1560 try buffer.writer().print("zig_O_{}", .{fmtIdent(fqn)});
1561 const name_end = buffer.items.len;
1562 try buffer.appendSlice(";\n");
12631563
12641564 const rendered = buffer.toOwnedSlice();
12651565 errdefer dg.typedefs.allocator.free(rendered);
1266 const name = rendered[name_index .. rendered.len - 2];
1566 const name = rendered[name_begin..name_end];
12671567
12681568 try dg.typedefs.ensureUnusedCapacity(1);
12691569 dg.typedefs.putAssumeCapacityNoClobber(
......@@ -1286,84 +1586,98 @@ pub const DeclGen = struct {
12861586 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
12871587 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
12881588 ///
1289 fn renderType(dg: *DeclGen, w: anytype, t: Type) error{ OutOfMemory, AnalysisFail }!void {
1589 fn renderType(
1590 dg: *DeclGen,
1591 w: anytype,
1592 t: Type,
1593 kind: TypedefKind,
1594 ) error{ OutOfMemory, AnalysisFail }!void {
12901595 const target = dg.module.getTarget();
12911596
12921597 switch (t.zigTypeTag()) {
1293 .NoReturn, .Void => try w.writeAll("void"),
1294 .Bool => try w.writeAll("bool"),
1295 .Int => {
1296 switch (t.tag()) {
1297 .u1, .u8 => try w.writeAll("uint8_t"),
1298 .i8 => try w.writeAll("int8_t"),
1299 .u16 => try w.writeAll("uint16_t"),
1300 .i16 => try w.writeAll("int16_t"),
1301 .u32 => try w.writeAll("uint32_t"),
1302 .i32 => try w.writeAll("int32_t"),
1303 .u64 => try w.writeAll("uint64_t"),
1304 .i64 => try w.writeAll("int64_t"),
1305 .u128 => try w.writeAll("uint128_t"),
1306 .i128 => try w.writeAll("int128_t"),
1307 .usize => try w.writeAll("uintptr_t"),
1308 .isize => try w.writeAll("intptr_t"),
1309 .c_short => try w.writeAll("short"),
1310 .c_ushort => try w.writeAll("unsigned short"),
1311 .c_int => try w.writeAll("int"),
1312 .c_uint => try w.writeAll("unsigned int"),
1313 .c_long => try w.writeAll("long"),
1314 .c_ulong => try w.writeAll("unsigned long"),
1315 .c_longlong => try w.writeAll("long long"),
1316 .c_ulonglong => try w.writeAll("unsigned long long"),
1317 .int_signed, .int_unsigned => {
1318 const info = t.intInfo(target);
1319 const sign_prefix = switch (info.signedness) {
1320 .signed => "",
1321 .unsigned => "u",
1598 .NoReturn, .Void, .Bool, .Int, .Float, .ErrorSet => |tag| {
1599 const is_named = switch (tag) {
1600 .Int => t.isNamedInt(),
1601 .ErrorSet => false,
1602 else => true,
1603 };
1604 if (is_named) {
1605 try w.writeAll("zig_");
1606 try t.print(w, dg.module);
1607 } else {
1608 const int_info = t.intInfo(target);
1609 if (toCIntBits(int_info.bits)) |c_bits|
1610 return w.print("zig_{c}{d}", .{ signAbbrev(int_info.signedness), c_bits })
1611 else if (loweredArrayInfo(t, target)) |array_info| {
1612 assert(array_info.sentinel == null);
1613 var array_pl = Type.Payload.Array{
1614 .base = .{ .tag = .array },
1615 .data = .{ .len = array_info.len, .elem_type = array_info.elem_type },
13221616 };
1323 const c_bits = toCIntBits(info.bits) orelse
1324 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
1325 try w.print("{s}int{d}_t", .{ sign_prefix, c_bits });
1326 },
1327 else => unreachable,
1328 }
1329 },
1330 .Float => {
1331 switch (t.tag()) {
1332 .f32 => try w.writeAll("float"),
1333 .f64 => try w.writeAll("double"),
1334 .c_longdouble => try w.writeAll("long double"),
1335 .f16 => return dg.fail("TODO: C backend: implement float type f16", .{}),
1336 .f128 => return dg.fail("TODO: C backend: implement float type f128", .{}),
1337 else => unreachable,
1617 const array_ty = Type.initPayload(&array_pl.base);
1618
1619 return dg.renderType(w, array_ty, kind);
1620 } else return dg.fail("C backend: Unable to lower unnamed integer type {}", .{
1621 t.fmt(dg.module),
1622 });
13381623 }
13391624 },
13401625 .Pointer => {
1341 if (t.isSlice()) {
1342 const name = dg.getTypedefName(t) orelse
1343 try dg.renderSliceTypedef(t);
1626 const ptr_info = t.ptrInfo().data;
1627 if (ptr_info.size == .Slice) {
1628 var slice_pl = Type.Payload.ElemType{
1629 .base = .{ .tag = if (t.ptrIsMutable()) .mut_slice else .const_slice },
1630 .data = ptr_info.pointee_type,
1631 };
1632 const slice_ty = Type.initPayload(&slice_pl.base);
1633
1634 const name = dg.getTypedefName(slice_ty) orelse
1635 try dg.renderSliceTypedef(slice_ty);
13441636
13451637 return w.writeAll(name);
13461638 }
13471639
1348 if (t.castPtrToFn()) |fn_ty| {
1349 const name = dg.getTypedefName(t) orelse
1350 try dg.renderPtrToFnTypedef(t, fn_ty);
1640 if (ptr_info.pointee_type.zigTypeTag() == .Fn) {
1641 const name = dg.getTypedefName(ptr_info.pointee_type) orelse
1642 try dg.renderPtrToFnTypedef(ptr_info.pointee_type);
13511643
13521644 return w.writeAll(name);
13531645 }
13541646
1355 try dg.renderType(w, t.elemType());
1356 if (t.isConstPtr()) {
1357 try w.writeAll(" const");
1358 }
1359 if (t.isVolatilePtr()) {
1360 try w.writeAll(" volatile");
1361 }
1647 if (ptr_info.host_size != 0) {
1648 var host_pl = Type.Payload.Bits{
1649 .base = .{ .tag = .int_unsigned },
1650 .data = ptr_info.host_size * 8,
1651 };
1652 const host_ty = Type.initPayload(&host_pl.base);
1653
1654 try dg.renderType(w, host_ty, .Forward);
1655 } else if (t.isCPtr() and ptr_info.pointee_type.eql(Type.u8, dg.module) and
1656 (dg.decl.val.tag() == .extern_fn or
1657 std.mem.eql(u8, std.mem.span(dg.decl.name), "main")))
1658 {
1659 // This is a hack, since the c compiler expects a lot of external
1660 // library functions to have char pointers in their signatures, but
1661 // u8 and i8 produce unsigned char and signed char respectively,
1662 // which in C are (not very usefully) different than char.
1663 try w.writeAll("char");
1664 } else try dg.renderType(w, switch (ptr_info.pointee_type.tag()) {
1665 .anyopaque => Type.void,
1666 else => ptr_info.pointee_type,
1667 }, .Forward);
1668 if (t.isConstPtr()) try w.writeAll(" const");
1669 if (t.isVolatilePtr()) try w.writeAll(" volatile");
13621670 return w.writeAll(" *");
13631671 },
13641672 .Array => {
1365 const name = dg.getTypedefName(t) orelse
1366 try dg.renderArrayTypedef(t);
1673 var array_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{
1674 .len = t.arrayLenIncludingSentinel(),
1675 .elem_type = t.childType(),
1676 } };
1677 const array_ty = Type.initPayload(&array_pl.base);
1678
1679 const name = dg.getTypedefName(array_ty) orelse
1680 try dg.renderArrayTypedef(array_ty);
13671681
13681682 return w.writeAll(name);
13691683 },
......@@ -1371,57 +1685,74 @@ pub const DeclGen = struct {
13711685 var opt_buf: Type.Payload.ElemType = undefined;
13721686 const child_type = t.optionalChild(&opt_buf);
13731687
1374 if (!child_type.hasRuntimeBitsIgnoreComptime()) {
1375 return w.writeAll("bool");
1376 }
1688 if (!child_type.hasRuntimeBitsIgnoreComptime())
1689 return dg.renderType(w, Type.bool, kind);
13771690
1378 if (t.optionalReprIsPayload()) {
1379 return dg.renderType(w, child_type);
1380 }
1691 if (t.optionalReprIsPayload())
1692 return dg.renderType(w, child_type, kind);
13811693
13821694 const name = dg.getTypedefName(t) orelse
13831695 try dg.renderOptionalTypedef(t, child_type);
13841696
13851697 return w.writeAll(name);
13861698 },
1387 .ErrorSet => {
1388 comptime assert(Type.anyerror.abiSize(builtin.target) == 2);
1389 return w.writeAll("uint16_t");
1390 },
13911699 .ErrorUnion => {
13921700 const payload_ty = t.errorUnionPayload();
13931701
1394 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1395 return dg.renderType(w, Type.anyerror);
1396 }
1702 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
1703 return dg.renderType(w, Type.anyerror, kind);
13971704
1398 const name = dg.getTypedefName(t) orelse
1399 try dg.renderErrorUnionTypedef(t);
1705 var error_union_pl = Type.Payload.ErrorUnion{
1706 .data = .{ .error_set = Type.anyerror, .payload = payload_ty },
1707 };
1708 const error_union_ty = Type.initPayload(&error_union_pl.base);
14001709
1401 return w.writeAll(name);
1402 },
1403 .Struct => {
1404 const name = dg.getTypedefName(t) orelse if (t.isTuple() or t.tag() == .anon_struct)
1405 try dg.renderTupleTypedef(t)
1406 else
1407 try dg.renderStructTypedef(t);
1710 const name = dg.getTypedefName(error_union_ty) orelse
1711 try dg.renderErrorUnionTypedef(error_union_ty);
14081712
14091713 return w.writeAll(name);
14101714 },
1411 .Union => {
1412 const name = dg.getTypedefName(t) orelse
1413 try dg.renderUnionTypedef(t);
1715 .Struct, .Union => |tag| if (tag == .Struct and t.containerLayout() == .Packed)
1716 try dg.renderType(w, t.castTag(.@"struct").?.data.backing_int_ty, kind)
1717 else if (kind == .Complete or t.isTupleOrAnonStruct()) {
1718 const name = dg.getTypedefName(t) orelse switch (tag) {
1719 .Struct => if (t.isTupleOrAnonStruct())
1720 try dg.renderTupleTypedef(t)
1721 else
1722 try dg.renderStructTypedef(t),
1723 .Union => try dg.renderUnionTypedef(t),
1724 else => unreachable,
1725 };
14141726
1415 return w.writeAll(name);
1727 try w.writeAll(name);
1728 } else {
1729 var ptr_pl = Type.Payload.ElemType{
1730 .base = .{ .tag = .single_const_pointer },
1731 .data = t,
1732 };
1733 const ptr_ty = Type.initPayload(&ptr_pl.base);
1734
1735 const name = dg.getTypedefName(ptr_ty) orelse
1736 try dg.renderFwdTypedef(ptr_ty);
1737
1738 try w.writeAll(name);
14161739 },
14171740 .Enum => {
14181741 // For enums, we simply use the integer tag type.
1419 var int_tag_ty_buffer: Type.Payload.Bits = undefined;
1420 const int_tag_ty = t.intTagType(&int_tag_ty_buffer);
1742 var int_tag_buf: Type.Payload.Bits = undefined;
1743 const int_tag_ty = t.intTagType(&int_tag_buf);
1744
1745 try dg.renderType(w, int_tag_ty, kind);
1746 },
1747 .Opaque => switch (t.tag()) {
1748 .@"opaque" => {
1749 const name = dg.getTypedefName(t) orelse
1750 try dg.renderOpaqueTypedef(t);
14211751
1422 try dg.renderType(w, int_tag_ty);
1752 try w.writeAll(name);
1753 },
1754 else => unreachable,
14231755 },
1424 .Opaque => return w.writeAll("void"),
14251756
14261757 .Frame,
14271758 .AnyFrame,
......@@ -1456,13 +1787,8 @@ pub const DeclGen = struct {
14561787 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
14571788 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
14581789 ///
1459 fn renderTypecast(
1460 dg: *DeclGen,
1461 w: anytype,
1462 ty: Type,
1463 ) error{ OutOfMemory, AnalysisFail }!void {
1464 const name = CValue{ .bytes = "" };
1465 return renderTypeAndName(dg, w, ty, name, .Mut, 0);
1790 fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void {
1791 return renderTypeAndName(dg, w, ty, .{ .bytes = "" }, .Mut, 0, .Complete);
14661792 }
14671793
14681794 /// Renders a type and name in field declaration/definition format.
......@@ -1481,26 +1807,36 @@ pub const DeclGen = struct {
14811807 name: CValue,
14821808 mutability: Mutability,
14831809 alignment: u32,
1810 kind: TypedefKind,
14841811 ) error{ OutOfMemory, AnalysisFail }!void {
14851812 var suffix = std.ArrayList(u8).init(dg.gpa);
14861813 defer suffix.deinit();
1814 const suffix_writer = suffix.writer();
14871815
14881816 // Any top-level array types are rendered here as a suffix, which
14891817 // avoids creating typedefs for every array type
1818 const target = dg.module.getTarget();
14901819 var render_ty = ty;
1491 while (render_ty.zigTypeTag() == .Array) {
1492 const sentinel_bit = @boolToInt(render_ty.sentinel() != null);
1493 const c_len = render_ty.arrayLen() + sentinel_bit;
1494 try suffix.writer().print("[{d}]", .{c_len});
1495 render_ty = render_ty.elemType();
1820 var depth: u32 = 0;
1821 while (loweredArrayInfo(render_ty, target)) |array_info| {
1822 const c_len = array_info.len + @boolToInt(array_info.sentinel != null);
1823 var c_len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = c_len };
1824 const c_len_val = Value.initPayload(&c_len_pl.base);
1825
1826 try suffix_writer.writeByte('[');
1827 if (mutability == .ConstArgument and depth == 0) try suffix_writer.writeAll("static const ");
1828 try suffix.writer().print("{}]", .{try dg.fmtIntLiteral(Type.usize, c_len_val)});
1829 render_ty = array_info.elem_type;
1830 depth += 1;
14961831 }
14971832
1498 if (alignment != 0)
1499 try w.print("ZIG_ALIGN({}) ", .{alignment});
1500 try dg.renderType(w, render_ty);
1833 if (alignment != 0 and alignment > ty.abiAlignment(target)) {
1834 try w.print("zig_align({}) ", .{alignment});
1835 }
1836 try dg.renderType(w, render_ty, kind);
15011837
15021838 const const_prefix = switch (mutability) {
1503 .Const => "const ",
1839 .Const, .ConstArgument => "const ",
15041840 .Mut => "",
15051841 };
15061842 try w.print(" {s}", .{const_prefix});
......@@ -1508,6 +1844,79 @@ pub const DeclGen = struct {
15081844 try w.writeAll(suffix.items);
15091845 }
15101846
1847 fn renderTagNameFn(dg: *DeclGen, enum_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1848 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1849 defer buffer.deinit();
1850 const bw = buffer.writer();
1851
1852 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
1853
1854 try buffer.appendSlice("static ");
1855 try dg.renderType(bw, name_slice_ty, .Complete);
1856 const name_begin = buffer.items.len + " ".len;
1857 try bw.print(" zig_tagName_{}(", .{typeToCIdentifier(enum_ty, dg.module)});
1858 const name_end = buffer.items.len - "(".len;
1859 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0, .Complete);
1860 try buffer.appendSlice(") {\n switch (tag) {\n");
1861 for (enum_ty.enumFields().keys()) |name, index| {
1862 const name_z = try dg.typedefs.allocator.dupeZ(u8, name);
1863 defer dg.typedefs.allocator.free(name_z);
1864 const name_bytes = name_z[0 .. name_z.len + 1];
1865
1866 var tag_pl: Value.Payload.U32 = .{
1867 .base = .{ .tag = .enum_field_index },
1868 .data = @intCast(u32, index),
1869 };
1870 const tag_val = Value.initPayload(&tag_pl.base);
1871
1872 var int_pl: Value.Payload.U64 = undefined;
1873 const int_val = tag_val.enumToInt(enum_ty, &int_pl);
1874
1875 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
1876 const name_ty = Type.initPayload(&name_ty_pl.base);
1877
1878 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_bytes };
1879 const name_val = Value.initPayload(&name_pl.base);
1880
1881 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
1882 const len_val = Value.initPayload(&len_pl.base);
1883
1884 try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});
1885 try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0, .Complete);
1886 try buffer.appendSlice(" = ");
1887 try dg.renderValue(bw, name_ty, name_val, .Initializer);
1888 try buffer.appendSlice(";\n return (");
1889 try dg.renderTypecast(bw, name_slice_ty);
1890 try bw.print("){{{}, {}}};\n", .{
1891 fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val),
1892 });
1893
1894 try buffer.appendSlice(" }\n");
1895 }
1896 try buffer.appendSlice(" }\n while (");
1897 try dg.renderValue(bw, Type.bool, Value.@"true", .Other);
1898 try buffer.appendSlice(") ");
1899 _ = try airBreakpoint(bw);
1900 try buffer.appendSlice("}\n");
1901
1902 const rendered = buffer.toOwnedSlice();
1903 errdefer dg.typedefs.allocator.free(rendered);
1904 const name = rendered[name_begin..name_end];
1905
1906 try dg.typedefs.ensureUnusedCapacity(1);
1907 dg.typedefs.putAssumeCapacityNoClobber(
1908 try enum_ty.copy(dg.typedefs_arena),
1909 .{ .name = name, .rendered = rendered },
1910 );
1911
1912 return name;
1913 }
1914
1915 fn getTagNameFn(dg: *DeclGen, enum_ty: Type) ![]const u8 {
1916 return dg.getTypedefName(enum_ty) orelse
1917 try dg.renderTagNameFn(enum_ty);
1918 }
1919
15111920 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
15121921 switch (tv.val.tag()) {
15131922 .extern_fn => return true,
......@@ -1523,7 +1932,7 @@ pub const DeclGen = struct {
15231932 }
15241933 }
15251934
1526 fn writeCValue(dg: DeclGen, w: anytype, c_value: CValue) !void {
1935 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
15271936 switch (c_value) {
15281937 .none => unreachable,
15291938 .local => |i| return w.print("t{d}", .{i}),
......@@ -1535,20 +1944,13 @@ pub const DeclGen = struct {
15351944 try w.writeByte('&');
15361945 return dg.renderDeclName(w, decl);
15371946 },
1538 .undefined_ptr => {
1539 const target = dg.module.getTarget();
1540 switch (target.cpu.arch.ptrBitWidth()) {
1541 32 => try w.writeAll("(void *)0xaaaaaaaa"),
1542 64 => try w.writeAll("(void *)0xaaaaaaaaaaaaaaaa"),
1543 else => unreachable,
1544 }
1545 },
1947 .undef => |ty| return dg.renderValue(w, ty, Value.undef, .Other),
15461948 .identifier => |ident| return w.print("{ }", .{fmtIdent(ident)}),
15471949 .bytes => |bytes| return w.writeAll(bytes),
15481950 }
15491951 }
15501952
1551 fn writeCValueDeref(dg: DeclGen, w: anytype, c_value: CValue) !void {
1953 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
15521954 switch (c_value) {
15531955 .none => unreachable,
15541956 .local => |i| return w.print("(*t{d})", .{i}),
......@@ -1561,7 +1963,7 @@ pub const DeclGen = struct {
15611963 return w.writeByte(')');
15621964 },
15631965 .decl_ref => |decl| return dg.renderDeclName(w, decl),
1564 .undefined_ptr => unreachable,
1966 .undef => unreachable,
15651967 .identifier => |ident| return w.print("(*{ })", .{fmtIdent(ident)}),
15661968 .bytes => |bytes| {
15671969 try w.writeAll("(*");
......@@ -1571,23 +1973,175 @@ pub const DeclGen = struct {
15711973 }
15721974 }
15731975
1574 fn renderDeclName(dg: DeclGen, writer: anytype, decl_index: Decl.Index) !void {
1976 fn writeCValueMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
1977 try dg.writeCValue(writer, c_value);
1978 try writer.writeByte('.');
1979 try dg.writeCValue(writer, member);
1980 }
1981
1982 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
1983 switch (c_value) {
1984 .none, .constant, .undef => unreachable,
1985 .local, .arg, .decl, .identifier, .bytes => {
1986 try dg.writeCValue(writer, c_value);
1987 try writer.writeAll("->");
1988 },
1989 .local_ref, .decl_ref => {
1990 try dg.writeCValueDeref(writer, c_value);
1991 try writer.writeByte('.');
1992 },
1993 }
1994 try dg.writeCValue(writer, member);
1995 }
1996
1997 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index) !void {
15751998 const decl = dg.module.declPtr(decl_index);
15761999 dg.module.markDeclAlive(decl);
15772000
15782001 if (dg.module.decl_exports.get(decl_index)) |exports| {
15792002 return writer.writeAll(exports[0].options.name);
1580 } else if (decl.val.tag() == .extern_fn) {
2003 } else if (decl.isExtern()) {
15812004 return writer.writeAll(mem.sliceTo(decl.name, 0));
15822005 } else {
1583 const gpa = dg.module.gpa;
2006 const gpa = dg.gpa;
15842007 const name = try decl.getFullyQualifiedName(dg.module);
15852008 defer gpa.free(name);
15862009 return writer.print("{ }", .{fmtIdent(name)});
15872010 }
15882011 }
2012
2013 fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void {
2014 const target = dg.module.getTarget();
2015 if (ty.isAbiInt()) {
2016 const int_info = ty.intInfo(target);
2017 const c_bits = toCIntBits(int_info.bits) orelse
2018 return dg.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
2019 try writer.print("{c}{d}", .{ signAbbrev(int_info.signedness), c_bits });
2020 } else if (ty.isRuntimeFloat()) {
2021 try ty.print(writer, dg.module);
2022 } else return dg.fail("TODO: CBE: implement renderTypeForBuiltinFnName for type {}", .{
2023 ty.fmt(dg.module),
2024 });
2025 }
2026
2027 fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
2028 const target = dg.module.getTarget();
2029 switch (info) {
2030 .None => {},
2031 .Range => {
2032 var arena = std.heap.ArenaAllocator.init(dg.gpa);
2033 defer arena.deinit();
2034
2035 const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2036 var stack align(@alignOf(ExpectedContents)) =
2037 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
2038
2039 const int_info = ty.intInfo(target);
2040 if (int_info.signedness == .signed) {
2041 const min_val = try ty.minInt(stack.get(), target);
2042 try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val)});
2043 }
2044
2045 const max_val = try ty.maxInt(stack.get(), target);
2046 try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val)});
2047 },
2048 .Bits => {
2049 var bits_pl = Value.Payload.U64{
2050 .base = .{ .tag = .int_u64 },
2051 .data = ty.bitSize(target),
2052 };
2053 const bits_val = Value.initPayload(&bits_pl.base);
2054 try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val)});
2055 },
2056 }
2057 }
2058
2059 fn fmtIntLiteral(
2060 dg: *DeclGen,
2061 ty: Type,
2062 val: Value,
2063 ) !std.fmt.Formatter(formatIntLiteral) {
2064 const int_info = ty.intInfo(dg.module.getTarget());
2065 const c_bits = toCIntBits(int_info.bits);
2066 if (c_bits == null or c_bits.? > 128)
2067 return dg.fail("TODO implement integer constants larger than 128 bits", .{});
2068 return std.fmt.Formatter(formatIntLiteral){ .data = .{
2069 .ty = ty,
2070 .val = val,
2071 .mod = dg.module,
2072 } };
2073 }
15892074};
15902075
2076pub fn genGlobalAsm(mod: *Module, code: *std.ArrayList(u8)) !void {
2077 var it = mod.global_assembly.valueIterator();
2078 while (it.next()) |asm_source| {
2079 try code.writer().print("__asm({s});\n", .{fmtStringLiteral(asm_source.*)});
2080 }
2081}
2082
2083pub fn genErrDecls(o: *Object) !void {
2084 const writer = o.writer();
2085
2086 try writer.writeAll("enum {\n");
2087 o.indent_writer.pushIndent();
2088 var max_name_len: usize = 0;
2089 for (o.dg.module.error_name_list.items) |name, value| {
2090 max_name_len = std.math.max(name.len, max_name_len);
2091 var err_pl = Value.Payload.Error{ .data = .{ .name = name } };
2092 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_pl.base), .Other);
2093 try writer.print(" = {d}u,\n", .{value});
2094 }
2095 o.indent_writer.popIndent();
2096 try writer.writeAll("};\n");
2097
2098 const name_prefix = "zig_errorName";
2099 const name_buf = try o.dg.gpa.alloc(u8, name_prefix.len + "_".len + max_name_len + 1);
2100 defer o.dg.gpa.free(name_buf);
2101
2102 std.mem.copy(u8, name_buf, name_prefix ++ "_");
2103 for (o.dg.module.error_name_list.items) |name| {
2104 std.mem.copy(u8, name_buf[name_prefix.len + "_".len ..], name);
2105 name_buf[name_prefix.len + "_".len + name.len] = 0;
2106
2107 const identifier = name_buf[0 .. name_prefix.len + "_".len + name.len :0];
2108 const name_z = identifier[name_prefix.len + "_".len ..];
2109
2110 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
2111 const name_ty = Type.initPayload(&name_ty_pl.base);
2112
2113 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name_z };
2114 const name_val = Value.initPayload(&name_pl.base);
2115
2116 try writer.writeAll("static ");
2117 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0, .Complete);
2118 try writer.writeAll(" = ");
2119 try o.dg.renderValue(writer, name_ty, name_val, .Initializer);
2120 try writer.writeAll(";\n");
2121 }
2122
2123 var name_array_ty_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{
2124 .len = o.dg.module.error_name_list.items.len,
2125 .elem_type = Type.initTag(.const_slice_u8_sentinel_0),
2126 } };
2127 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
2128
2129 try writer.writeAll("static ");
2130 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .Const, 0, .Complete);
2131 try writer.writeAll(" = {");
2132 for (o.dg.module.error_name_list.items) |name, value| {
2133 if (value != 0) try writer.writeByte(',');
2134
2135 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
2136 const len_val = Value.initPayload(&len_pl.base);
2137
2138 try writer.print("{{" ++ name_prefix ++ "_{}, {}}}", .{
2139 fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val),
2140 });
2141 }
2142 try writer.writeAll("};\n");
2143}
2144
15912145pub fn genFunc(f: *Function) !void {
15922146 const tracy = trace(@src());
15932147 defer tracy.end();
......@@ -1599,14 +2153,13 @@ pub fn genFunc(f: *Function) !void {
15992153
16002154 const is_global = o.dg.module.decl_exports.contains(f.func.owner_decl);
16012155 const fwd_decl_writer = o.dg.fwd_decl.writer();
1602 if (is_global) {
1603 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
1604 }
1605 try o.dg.renderFunctionSignature(fwd_decl_writer, is_global);
2156 try fwd_decl_writer.writeAll(if (is_global) "zig_extern_c " else "static ");
2157 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
16062158 try fwd_decl_writer.writeAll(";\n");
16072159
16082160 try o.indent_writer.insertNewline();
1609 try o.dg.renderFunctionSignature(o.writer(), is_global);
2161 if (!is_global) try o.writer().writeAll("static ");
2162 try o.dg.renderFunctionSignature(o.writer(), .Complete);
16102163 try o.writer().writeByte(' ');
16112164
16122165 // In case we need to use the header, populate it with a copy of the function
......@@ -1638,16 +2191,16 @@ pub fn genDecl(o: *Object) !void {
16382191 .val = o.dg.decl.val,
16392192 };
16402193 if (tv.val.tag() == .extern_fn) {
1641 const writer = o.writer();
1642 try writer.writeAll("ZIG_EXTERN_C ");
1643 try o.dg.renderFunctionSignature(writer, true);
1644 try writer.writeAll(";\n");
2194 const fwd_decl_writer = o.dg.fwd_decl.writer();
2195 try fwd_decl_writer.writeAll("zig_extern_c ");
2196 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
2197 try fwd_decl_writer.writeAll(";\n");
16452198 } else if (tv.val.castTag(.variable)) |var_payload| {
16462199 const variable: *Module.Var = var_payload.data;
16472200 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
16482201 const fwd_decl_writer = o.dg.fwd_decl.writer();
16492202 if (is_global) {
1650 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
2203 try fwd_decl_writer.writeAll("zig_extern_c ");
16512204 }
16522205 if (variable.is_threadlocal) {
16532206 try fwd_decl_writer.writeAll("zig_threadlocal ");
......@@ -1659,34 +2212,36 @@ pub fn genDecl(o: *Object) !void {
16592212 .decl = o.dg.decl_index,
16602213 };
16612214
1662 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");
2215 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
16632216 try fwd_decl_writer.writeAll(";\n");
16642217
1665 if (variable.init.isUndefDeep()) {
2218 if (variable.is_extern or variable.init.isUndefDeep()) {
16662219 return;
16672220 }
16682221
1669 try o.indent_writer.insertNewline();
16702222 const w = o.writer();
1671 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");
2223 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
16722224 try w.writeAll(" = ");
16732225 if (variable.init.tag() != .unreachable_value) {
1674 try o.dg.renderValue(w, tv.ty, variable.init, .Other);
2226 try o.dg.renderValue(w, tv.ty, variable.init, .Initializer);
16752227 }
1676 try w.writeAll(";");
2228 try w.writeByte(';');
16772229 try o.indent_writer.insertNewline();
16782230 } else {
2231 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
2232
2233 const fwd_decl_writer = o.dg.fwd_decl.writer();
2234 try fwd_decl_writer.writeAll("static ");
2235 try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2236 try fwd_decl_writer.writeAll(";\n");
2237
16792238 const writer = o.writer();
16802239 try writer.writeAll("static ");
1681
16822240 // TODO ask the Decl if it is const
16832241 // https://github.com/ziglang/zig/issues/7582
1684
1685 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
1686 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align");
1687
2242 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
16882243 try writer.writeAll(" = ");
1689 try o.dg.renderValue(writer, tv.ty, tv.val, .Other);
2244 try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);
16902245 try writer.writeAll(";\n");
16912246 }
16922247}
......@@ -1705,8 +2260,8 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
17052260 .Fn => {
17062261 const is_global = dg.declIsGlobal(tv);
17072262 if (is_global) {
1708 try writer.writeAll("ZIG_EXTERN_C ");
1709 try dg.renderFunctionSignature(writer, is_global);
2263 try writer.writeAll("zig_extern_c ");
2264 try dg.renderFunctionSignature(writer, .Complete);
17102265 try dg.fwd_decl.appendSlice(";\n");
17112266 }
17122267 },
......@@ -1733,44 +2288,53 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
17332288 .const_ty => unreachable, // excluded from function bodies
17342289 .arg => airArg(f),
17352290
1736 .breakpoint => try airBreakpoint(f),
2291 .breakpoint => try airBreakpoint(f.object.writer()),
17372292 .ret_addr => try airRetAddr(f, inst),
17382293 .frame_addr => try airFrameAddress(f, inst),
17392294 .unreach => try airUnreach(f),
17402295 .fence => try airFence(f, inst),
17412296
1742 .ptr_add => try airPtrAddSub(f, inst, " + "),
1743 .ptr_sub => try airPtrAddSub(f, inst, " - "),
2297 .ptr_add => try airPtrAddSub(f, inst, '+'),
2298 .ptr_sub => try airPtrAddSub(f, inst, '-'),
17442299
17452300 // TODO use a different strategy for add, sub, mul, div
17462301 // that communicates to the optimizer that wrapping is UB.
1747 .add => try airBinOp (f, inst, " + "),
1748 .sub => try airBinOp (f, inst, " - "),
1749 .mul => try airBinOp (f, inst, " * "),
1750 .div_float, .div_exact => try airBinOp( f, inst, " / "),
1751 .rem => try airBinOp( f, inst, " % "),
2302 .add => try airBinOp(f, inst, "+", "add", .None),
2303 .sub => try airBinOp(f, inst, "-", "sub", .None),
2304 .mul => try airBinOp(f, inst, "*", "mul", .None),
2305 .div_float, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .None),
17522306
2307 .rem => blk: {
2308 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2309 const lhs_ty = f.air.typeOf(bin_op.lhs);
2310 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
2311 // so we only check one.
2312 break :blk if (lhs_ty.isInt())
2313 try airBinOp(f, inst, "%", "rem", .None)
2314 else
2315 try airBinFloatOp(f, inst, "fmod");
2316 },
17532317 .div_trunc => blk: {
17542318 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
17552319 const lhs_ty = f.air.typeOf(bin_op.lhs);
17562320 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
17572321 // so we only check one.
17582322 break :blk if (lhs_ty.isInt())
1759 try airBinOp(f, inst, " / ")
2323 try airBinOp(f, inst, "/", "div_trunc", .None)
17602324 else
1761 try airBinOpBuiltinCall(f, inst, "div_trunc");
2325 try airBinBuiltinCall(f, inst, "div_trunc", .None);
17622326 },
1763 .div_floor => try airBinOpBuiltinCall(f, inst, "div_floor"),
1764 .mod => try airBinOpBuiltinCall(f, inst, "mod"),
2327 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .None),
2328 .mod => try airBinBuiltinCall(f, inst, "mod", .None),
17652329
1766 .addwrap => try airWrapOp(f, inst, " + ", "addw_"),
1767 .subwrap => try airWrapOp(f, inst, " - ", "subw_"),
1768 .mulwrap => try airWrapOp(f, inst, " * ", "mulw_"),
2330 .addwrap => try airBinBuiltinCall(f, inst, "addw", .Bits),
2331 .subwrap => try airBinBuiltinCall(f, inst, "subw", .Bits),
2332 .mulwrap => try airBinBuiltinCall(f, inst, "mulw", .Bits),
17692333
1770 .add_sat => try airSatOp(f, inst, "adds_"),
1771 .sub_sat => try airSatOp(f, inst, "subs_"),
1772 .mul_sat => try airSatOp(f, inst, "muls_"),
1773 .shl_sat => try airSatOp(f, inst, "shls_"),
2334 .add_sat => try airBinBuiltinCall(f, inst, "adds", .Bits),
2335 .sub_sat => try airBinBuiltinCall(f, inst, "subs", .Bits),
2336 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .Bits),
2337 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .Bits),
17742338
17752339 .neg => try airNeg(f, inst),
17762340
......@@ -1787,41 +2351,40 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
17872351 .floor,
17882352 .ceil,
17892353 .round,
1790 .trunc_float,
1791 => |tag| return f.fail("TODO: C backend: implement unary op for tag '{s}'", .{@tagName(tag)}),
2354 => |tag| try airUnFloatOp(f, inst, @tagName(tag)),
2355 .trunc_float => try airUnFloatOp(f, inst, "trunc"),
17922356
17932357 .mul_add => try airMulAdd(f, inst),
17942358
1795 .add_with_overflow => try airOverflow(f, inst, "addo_"),
1796 .sub_with_overflow => try airOverflow(f, inst, "subo_"),
1797 .mul_with_overflow => try airOverflow(f, inst, "mulo_"),
1798 .shl_with_overflow => try airOverflow(f, inst, "shlo_"),
2359 .add_with_overflow => try airOverflow(f, inst, "add", .Bits),
2360 .sub_with_overflow => try airOverflow(f, inst, "sub", .Bits),
2361 .mul_with_overflow => try airOverflow(f, inst, "mul", .Bits),
2362 .shl_with_overflow => try airOverflow(f, inst, "shl", .Bits),
17992363
1800 .min => try airMinMax(f, inst, "<"),
1801 .max => try airMinMax(f, inst, ">"),
2364 .min => try airMinMax(f, inst, '<'),
2365 .max => try airMinMax(f, inst, '>'),
18022366
18032367 .slice => try airSlice(f, inst),
18042368
1805 .cmp_gt => try airBinOp(f, inst, " > "),
1806 .cmp_gte => try airBinOp(f, inst, " >= "),
1807 .cmp_lt => try airBinOp(f, inst, " < "),
1808 .cmp_lte => try airBinOp(f, inst, " <= "),
2369 .cmp_gt => try airCmpOp(f, inst, ">"),
2370 .cmp_gte => try airCmpOp(f, inst, ">="),
2371 .cmp_lt => try airCmpOp(f, inst, "<"),
2372 .cmp_lte => try airCmpOp(f, inst, "<="),
18092373
18102374 .cmp_eq => try airEquality(f, inst, "((", "=="),
18112375 .cmp_neq => try airEquality(f, inst, "!((", "!="),
18122376
18132377 .cmp_vector => return f.fail("TODO: C backend: implement cmp_vector", .{}),
1814 .cmp_lt_errors_len => return f.fail("TODO: C backend: implement cmp_lt_errors_len", .{}),
2378 .cmp_lt_errors_len => try airCmpLtErrorsLen(f, inst),
18152379
18162380 // bool_and and bool_or are non-short-circuit operations
1817 .bool_and => try airBinOp(f, inst, " & "),
1818 .bool_or => try airBinOp(f, inst, " | "),
1819 .bit_and => try airBinOp(f, inst, " & "),
1820 .bit_or => try airBinOp(f, inst, " | "),
1821 .xor => try airBinOp(f, inst, " ^ "),
1822 .shr, .shr_exact => try airBinOp(f, inst, " >> "),
1823 .shl, .shl_exact => try airBinOp(f, inst, " << "),
1824 .not => try airNot (f, inst),
2381 .bool_and, .bit_and => try airBinOp(f, inst, "&", "and", .None),
2382 .bool_or, .bit_or => try airBinOp(f, inst, "|", "or", .None),
2383 .xor => try airBinOp(f, inst, "^", "xor", .None),
2384 .shr, .shr_exact => try airBinBuiltinCall(f, inst, "shr", .None),
2385 .shl, => try airBinBuiltinCall(f, inst, "shl", .None),
2386 .shl_exact => try airBinOp(f, inst, "<<", "shl", .None),
2387 .not => try airNot (f, inst),
18252388
18262389 .optional_payload => try airOptionalPayload(f, inst),
18272390 .optional_payload_ptr => try airOptionalPayloadPtr(f, inst),
......@@ -1833,10 +2396,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
18332396 .is_err_ptr => try airIsErr(f, inst, true, "!="),
18342397 .is_non_err_ptr => try airIsErr(f, inst, true, "=="),
18352398
1836 .is_null => try airIsNull(f, inst, "==", ""),
1837 .is_non_null => try airIsNull(f, inst, "!=", ""),
1838 .is_null_ptr => try airIsNull(f, inst, "==", "[0]"),
1839 .is_non_null_ptr => try airIsNull(f, inst, "!=", "[0]"),
2399 .is_null => try airIsNull(f, inst, "==", false),
2400 .is_non_null => try airIsNull(f, inst, "!=", false),
2401 .is_null_ptr => try airIsNull(f, inst, "==", true),
2402 .is_non_null_ptr => try airIsNull(f, inst, "!=", true),
18402403
18412404 .alloc => try airAlloc(f, inst),
18422405 .ret_ptr => try airRetPtr(f, inst),
......@@ -1848,8 +2411,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
18482411 .trunc => try airTrunc(f, inst),
18492412 .bool_to_int => try airBoolToInt(f, inst),
18502413 .load => try airLoad(f, inst),
1851 .ret => try airRet(f, inst),
1852 .ret_load => try airRetLoad(f, inst),
2414 .ret => try airRet(f, inst, false),
2415 .ret_load => try airRet(f, inst, true),
18532416 .store => try airStore(f, inst),
18542417 .loop => try airLoop(f, inst),
18552418 .cond_br => try airCondBr(f, inst),
......@@ -1865,11 +2428,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
18652428 .memcpy => try airMemcpy(f, inst),
18662429 .set_union_tag => try airSetUnionTag(f, inst),
18672430 .get_union_tag => try airGetUnionTag(f, inst),
1868 .clz => try airBuiltinCall(f, inst, "clz"),
1869 .ctz => try airBuiltinCall(f, inst, "ctz"),
1870 .popcount => try airBuiltinCall(f, inst, "popcount"),
1871 .byte_swap => try airBuiltinCall(f, inst, "byte_swap"),
1872 .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"),
2431 .clz => try airUnBuiltinCall(f, inst, "clz", .Bits),
2432 .ctz => try airUnBuiltinCall(f, inst, "ctz", .Bits),
2433 .popcount => try airUnBuiltinCall(f, inst, "popcount", .Bits),
2434 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .Bits),
2435 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .Bits),
18732436 .tag_name => try airTagName(f, inst),
18742437 .error_name => try airErrorName(f, inst),
18752438 .splat => try airSplat(f, inst),
......@@ -1922,11 +2485,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
19222485 .field_parent_ptr => try airFieldParentPtr(f, inst),
19232486
19242487 .struct_field_val => try airStructFieldVal(f, inst),
1925 .slice_ptr => try airSliceField(f, inst, ".ptr;\n"),
1926 .slice_len => try airSliceField(f, inst, ".len;\n"),
2488 .slice_ptr => try airSliceField(f, inst, false, "ptr"),
2489 .slice_len => try airSliceField(f, inst, false, "len"),
19272490
1928 .ptr_slice_len_ptr => try airPtrSliceFieldPtr(f, inst, ".len;\n"),
1929 .ptr_slice_ptr_ptr => try airPtrSliceFieldPtr(f, inst, ".ptr;\n"),
2491 .ptr_slice_len_ptr => try airSliceField(f, inst, true, "len"),
2492 .ptr_slice_ptr_ptr => try airSliceField(f, inst, true, "ptr"),
19302493
19312494 .ptr_elem_val => try airPtrElemVal(f, inst),
19322495 .ptr_elem_ptr => try airPtrElemPtr(f, inst),
......@@ -1934,8 +2497,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
19342497 .slice_elem_ptr => try airSliceElemPtr(f, inst),
19352498 .array_elem_val => try airArrayElemVal(f, inst),
19362499
1937 .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst, ""),
1938 .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst, "&"),
2500 .unwrap_errunion_payload => try airUnwrapErrUnionPay(f, inst, false),
2501 .unwrap_errunion_payload_ptr => try airUnwrapErrUnionPay(f, inst, true),
19392502 .unwrap_errunion_err => try airUnwrapErrUnionErr(f, inst),
19402503 .unwrap_errunion_err_ptr => try airUnwrapErrUnionErr(f, inst),
19412504 .wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
......@@ -1983,10 +2546,10 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
19832546 }
19842547
19852548 f.object.indent_writer.popIndent();
1986 try writer.writeAll("}");
2549 try writer.writeByte('}');
19872550}
19882551
1989fn airSliceField(f: *Function, inst: Air.Inst.Index, suffix: []const u8) !CValue {
2552fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue {
19902553 if (f.liveness.isUnused(inst)) return CValue.none;
19912554
19922555 const inst_ty = f.air.typeOfIndex(inst);
......@@ -1995,26 +2558,14 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, suffix: []const u8) !CValue
19952558 const writer = f.object.writer();
19962559 const local = try f.allocLocal(inst_ty, .Const);
19972560 try writer.writeAll(" = ");
1998 try f.writeCValue(writer, operand);
1999 try writer.writeAll(suffix);
2561 if (is_ptr) {
2562 try writer.writeByte('&');
2563 try f.writeCValueDerefMember(writer, operand, .{ .identifier = field_name });
2564 } else try f.writeCValueMember(writer, operand, .{ .identifier = field_name });
2565 try writer.writeAll(";\n");
20002566 return local;
20012567}
20022568
2003fn airPtrSliceFieldPtr(f: *Function, inst: Air.Inst.Index, suffix: []const u8) !CValue {
2004 if (f.liveness.isUnused(inst))
2005 return CValue.none;
2006
2007 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
2008 const operand = try f.resolveInst(ty_op.operand);
2009 const writer = f.object.writer();
2010
2011 _ = writer;
2012 _ = operand;
2013 _ = suffix;
2014
2015 return f.fail("TODO: C backend: airPtrSliceFieldPtr", .{});
2016}
2017
20182569fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
20192570 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
20202571 const ptr_ty = f.air.typeOf(bin_op.lhs);
......@@ -2025,9 +2576,9 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
20252576 const writer = f.object.writer();
20262577 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
20272578 try writer.writeAll(" = ");
2028 try f.writeCValue(writer, ptr);
2579 try f.writeCValue(writer, ptr, .Other);
20292580 try writer.writeByte('[');
2030 try f.writeCValue(writer, index);
2581 try f.writeCValue(writer, index, .Other);
20312582 try writer.writeAll("];\n");
20322583 return local;
20332584}
......@@ -2049,10 +2600,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
20492600 // It's a pointer to an array, so we need to de-reference.
20502601 try f.writeCValueDeref(writer, ptr);
20512602 } else {
2052 try f.writeCValue(writer, ptr);
2603 try f.writeCValue(writer, ptr, .Other);
20532604 }
20542605 try writer.writeAll(")[");
2055 try f.writeCValue(writer, index);
2606 try f.writeCValue(writer, index, .Other);
20562607 try writer.writeAll("];\n");
20572608 return local;
20582609}
......@@ -2067,9 +2618,9 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
20672618 const writer = f.object.writer();
20682619 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
20692620 try writer.writeAll(" = ");
2070 try f.writeCValue(writer, slice);
2621 try f.writeCValue(writer, slice, .Other);
20712622 try writer.writeAll(".ptr[");
2072 try f.writeCValue(writer, index);
2623 try f.writeCValue(writer, index, .Other);
20732624 try writer.writeAll("];\n");
20742625 return local;
20752626}
......@@ -2085,9 +2636,9 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
20852636 const writer = f.object.writer();
20862637 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
20872638 try writer.writeAll(" = &");
2088 try f.writeCValue(writer, slice);
2639 try f.writeCValue(writer, slice, .Other);
20892640 try writer.writeAll(".ptr[");
2090 try f.writeCValue(writer, index);
2641 try f.writeCValue(writer, index, .Other);
20912642 try writer.writeAll("];\n");
20922643 return local;
20932644}
......@@ -2101,9 +2652,9 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
21012652 const writer = f.object.writer();
21022653 const local = try f.allocLocal(f.air.typeOfIndex(inst), .Const);
21032654 try writer.writeAll(" = ");
2104 try f.writeCValue(writer, array);
2105 try writer.writeAll("[");
2106 try f.writeCValue(writer, index);
2655 try f.writeCValue(writer, array, .Other);
2656 try writer.writeByte('[');
2657 try f.writeCValue(writer, index, .Other);
21072658 try writer.writeAll("];\n");
21082659 return local;
21092660}
......@@ -2115,7 +2666,7 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
21152666 const elem_type = inst_ty.elemType();
21162667 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;
21172668 if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) {
2118 return CValue.undefined_ptr;
2669 return CValue{ .undef = inst_ty };
21192670 }
21202671
21212672 const target = f.object.dg.module.getTarget();
......@@ -2130,9 +2681,13 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
21302681 const writer = f.object.writer();
21312682 const inst_ty = f.air.typeOfIndex(inst);
21322683
2684 const elem_ty = inst_ty.elemType();
2685 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) {
2686 return CValue{ .undef = inst_ty };
2687 }
2688
21332689 // First line: the variable used as data storage.
2134 const elem_type = inst_ty.elemType();
2135 const local = try f.allocLocal(elem_type, .Mut);
2690 const local = try f.allocLocal(elem_ty, .Mut);
21362691 try writer.writeAll(";\n");
21372692
21382693 return CValue{ .local_ref = local.local };
......@@ -2146,13 +2701,15 @@ fn airArg(f: *Function) CValue {
21462701
21472702fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
21482703 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
2149 const is_volatile = f.air.typeOf(ty_op.operand).isVolatilePtr();
2704 const ptr_info = f.air.typeOf(ty_op.operand).ptrInfo().data;
21502705
2151 if (!is_volatile and f.liveness.isUnused(inst))
2706 const inst_ty = f.air.typeOfIndex(inst);
2707 if (!inst_ty.hasRuntimeBitsIgnoreComptime() or
2708 !ptr_info.@"volatile" and f.liveness.isUnused(inst))
21522709 return CValue.none;
21532710
2154 const inst_ty = f.air.typeOfIndex(inst);
2155 const is_array = inst_ty.zigTypeTag() == .Array;
2711 const target = f.object.dg.module.getTarget();
2712 const is_array = lowersToArray(inst_ty, target);
21562713 const operand = try f.resolveInst(ty_op.operand);
21572714 const writer = f.object.writer();
21582715
......@@ -2162,53 +2719,97 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
21622719 if (is_array) {
21632720 // Insert a memcpy to initialize this array. The source operand is always a pointer
21642721 // and thus we only need to know size/type information from the local type/dest.
2165 try writer.writeAll(";");
2166 try f.object.indent_writer.insertNewline();
2722 try writer.writeAll(";\n");
21672723 try writer.writeAll("memcpy(");
2168 try f.writeCValue(writer, local);
2724 try f.writeCValue(writer, local, .FunctionArgument);
21692725 try writer.writeAll(", ");
2170 try f.writeCValue(writer, operand);
2726 try f.writeCValue(writer, operand, .FunctionArgument);
21712727 try writer.writeAll(", sizeof(");
2172 try f.writeCValue(writer, local);
2173 try writer.writeAll("));\n");
2174 } else {
2175 try writer.writeAll(" = ");
2176 try f.writeCValueDeref(writer, operand);
2177 try writer.writeAll(";\n");
2178 }
2179 return local;
2180}
2728 try f.renderTypecast(writer, inst_ty);
2729 try writer.writeAll("))");
2730 } else if (ptr_info.host_size != 0) {
2731 var host_pl = Type.Payload.Bits{
2732 .base = .{ .tag = .int_unsigned },
2733 .data = ptr_info.host_size * 8,
2734 };
2735 const host_ty = Type.initPayload(&host_pl.base);
21812736
2182fn airRet(f: *Function, inst: Air.Inst.Index) !CValue {
2183 const un_op = f.air.instructions.items(.data)[inst].un_op;
2184 const writer = f.object.writer();
2185 const ret_ty = f.air.typeOf(un_op);
2186 if (ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
2187 const operand = try f.resolveInst(un_op);
2188 try writer.writeAll("return ");
2189 try f.writeCValue(writer, operand);
2190 try writer.writeAll(";\n");
2191 } else if (ret_ty.isError()) {
2192 try writer.writeAll("return 0;");
2737 var bit_offset_ty_pl = Type.Payload.Bits{
2738 .base = .{ .tag = .int_unsigned },
2739 .data = Type.smallestUnsignedBits(host_pl.data - 1),
2740 };
2741 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
2742
2743 var bit_offset_val_pl: Value.Payload.U64 = .{
2744 .base = .{ .tag = .int_u64 },
2745 .data = ptr_info.bit_offset,
2746 };
2747 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
2748
2749 var field_pl = Type.Payload.Bits{
2750 .base = .{ .tag = .int_unsigned },
2751 .data = @intCast(u16, inst_ty.bitSize(target)),
2752 };
2753 const field_ty = Type.initPayload(&field_pl.base);
2754
2755 try writer.writeAll(" = (");
2756 try f.renderTypecast(writer, inst_ty);
2757 try writer.writeAll(")zig_wrap_");
2758 try f.object.dg.renderTypeForBuiltinFnName(writer, field_ty);
2759 try writer.writeAll("((");
2760 try f.renderTypecast(writer, field_ty);
2761 try writer.writeAll(")zig_shr_");
2762 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
2763 try writer.writeByte('(');
2764 try f.writeCValueDeref(writer, operand);
2765 try writer.print(", {})", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
2766 try f.object.dg.renderBuiltinInfo(writer, field_ty, .Bits);
2767 try writer.writeByte(')');
21932768 } else {
2194 try writer.writeAll("return;\n");
2769 try writer.writeAll(" = ");
2770 try f.writeCValueDeref(writer, operand);
21952771 }
2196 return CValue.none;
2772 try writer.writeAll(";\n");
2773 return local;
21972774}
21982775
2199fn airRetLoad(f: *Function, inst: Air.Inst.Index) !CValue {
2776fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
22002777 const un_op = f.air.instructions.items(.data)[inst].un_op;
22012778 const writer = f.object.writer();
2202 const ptr_ty = f.air.typeOf(un_op);
2203 const ret_ty = ptr_ty.childType();
2204 if (ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
2205 const ptr = try f.resolveInst(un_op);
2206 try writer.writeAll("return *");
2207 try f.writeCValue(writer, ptr);
2779 const target = f.object.dg.module.getTarget();
2780 const op_ty = f.air.typeOf(un_op);
2781 const ret_ty = if (is_ptr) op_ty.childType() else op_ty;
2782 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
2783 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
2784
2785 if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) {
2786 var deref = is_ptr;
2787 const operand = try f.resolveInst(un_op);
2788 const ret_val = if (lowersToArray(ret_ty, target)) ret_val: {
2789 const array_local = try f.allocLocal(lowered_ret_ty, .Mut);
2790 try writer.writeAll(";\n");
2791 try writer.writeAll("memcpy(");
2792 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
2793 try writer.writeAll(", ");
2794 if (deref)
2795 try f.writeCValueDeref(writer, operand)
2796 else
2797 try f.writeCValue(writer, operand, .FunctionArgument);
2798 deref = false;
2799 try writer.writeAll(", sizeof(");
2800 try f.renderTypecast(writer, ret_ty);
2801 try writer.writeAll("));\n");
2802 break :ret_val array_local;
2803 } else operand;
2804
2805 try writer.writeAll("return ");
2806 if (deref)
2807 try f.writeCValueDeref(writer, ret_val)
2808 else
2809 try f.writeCValue(writer, ret_val, .Other);
22082810 try writer.writeAll(";\n");
2209 } else if (ret_ty.isError()) {
2210 try writer.writeAll("return 0;\n");
2211 } else {
2811 } else if (f.object.dg.decl.ty.fnCallingConvention() != .Naked) {
2812 // Not even allowed to return void in a naked function.
22122813 try writer.writeAll("return;\n");
22132814 }
22142815 return CValue.none;
......@@ -2226,8 +2827,8 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
22262827 const local = try f.allocLocal(inst_ty, .Const);
22272828 try writer.writeAll(" = (");
22282829 try f.renderTypecast(writer, inst_ty);
2229 try writer.writeAll(")");
2230 try f.writeCValue(writer, operand);
2830 try writer.writeByte(')');
2831 try f.writeCValue(writer, operand, .Other);
22312832 try writer.writeAll(";\n");
22322833 return local;
22332834}
......@@ -2244,32 +2845,44 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
22442845 const dest_int_info = inst_ty.intInfo(target);
22452846 const dest_bits = dest_int_info.bits;
22462847
2247 try writer.writeAll(" = ");
2848 try writer.writeAll(" = (");
2849 try f.renderTypecast(writer, inst_ty);
2850 try writer.writeByte(')');
22482851
22492852 if (dest_bits >= 8 and std.math.isPowerOfTwo(dest_bits)) {
2250 try f.writeCValue(writer, operand);
2853 try f.writeCValue(writer, operand, .Other);
22512854 try writer.writeAll(";\n");
2252 return local;
2253 }
2254
2255 switch (dest_int_info.signedness) {
2855 } else switch (dest_int_info.signedness) {
22562856 .unsigned => {
2257 try f.writeCValue(writer, operand);
2258 const mask = (@as(u65, 1) << @intCast(u7, dest_bits)) - 1;
2259 try writer.print(" & {d}ULL;\n", .{mask});
2260 return local;
2857 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
2858 defer arena.deinit();
2859
2860 const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
2861 var stack align(@alignOf(ExpectedContents)) =
2862 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
2863
2864 const mask_val = try inst_ty.maxInt(stack.get(), target);
2865
2866 try writer.writeByte('(');
2867 try f.writeCValue(writer, operand, .Other);
2868 try writer.print(" & {x});\n", .{try f.fmtIntLiteral(inst_ty, mask_val)});
22612869 },
22622870 .signed => {
22632871 const operand_ty = f.air.typeOf(ty_op.operand);
22642872 const c_bits = toCIntBits(operand_ty.intInfo(target).bits) orelse
22652873 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
2266 const shift_rhs = c_bits - dest_bits;
2267 try writer.print("(int{d}_t)((uint{d}_t)", .{ c_bits, c_bits });
2268 try f.writeCValue(writer, operand);
2269 try writer.print(" << {d}) >> {d};\n", .{ shift_rhs, shift_rhs });
2270 return local;
2874 var shift_pl = Value.Payload.U64{
2875 .base = .{ .tag = .int_u64 },
2876 .data = c_bits - dest_bits,
2877 };
2878 const shift_val = Value.initPayload(&shift_pl.base);
2879
2880 try writer.print("((int{d}_t)((uint{0d}_t)", .{c_bits});
2881 try f.writeCValue(writer, operand, .Other);
2882 try writer.print(" << {}) >> {0});\n", .{try f.fmtIntLiteral(Type.u8, shift_val)});
22712883 },
22722884 }
2885 return local;
22732886}
22742887
22752888fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -2281,256 +2894,127 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
22812894 const operand = try f.resolveInst(un_op);
22822895 const local = try f.allocLocal(inst_ty, .Const);
22832896 try writer.writeAll(" = ");
2284 try f.writeCValue(writer, operand);
2897 try f.writeCValue(writer, operand, .Other);
22852898 try writer.writeAll(";\n");
22862899 return local;
22872900}
22882901
2289fn airStoreUndefined(f: *Function, dest_ptr: CValue) !CValue {
2290 const is_debug_build = f.object.dg.module.optimizeMode() == .Debug;
2291 if (!is_debug_build)
2292 return CValue.none;
2293
2294 const writer = f.object.writer();
2295 try writer.writeAll("memset(");
2296 try f.writeCValue(writer, dest_ptr);
2297 try writer.writeAll(", 0xaa, sizeof(");
2298 try f.writeCValueDeref(writer, dest_ptr);
2299 try writer.writeAll("));\n");
2902fn airStoreUndefined(f: *Function, lhs_child_ty: Type, dest_ptr: CValue) !CValue {
2903 if (f.wantSafety()) {
2904 const writer = f.object.writer();
2905 try writer.writeAll("memset(");
2906 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
2907 try writer.print(", {x}, sizeof(", .{try f.fmtIntLiteral(Type.u8, Value.undef)});
2908 try f.renderTypecast(writer, lhs_child_ty);
2909 try writer.writeAll("));\n");
2910 }
23002911 return CValue.none;
23012912}
23022913
23032914fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
23042915 // *a = b;
23052916 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2306 const dest_ptr = try f.resolveInst(bin_op.lhs);
2917 const ptr_info = f.air.typeOf(bin_op.lhs).ptrInfo().data;
2918 if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) return CValue.none;
2919
2920 const ptr_val = try f.resolveInst(bin_op.lhs);
2921 const src_ty = f.air.typeOf(bin_op.rhs);
23072922 const src_val = try f.resolveInst(bin_op.rhs);
2308 const lhs_child_type = f.air.typeOf(bin_op.lhs).childType();
23092923
23102924 // TODO Sema should emit a different instruction when the store should
23112925 // possibly do the safety 0xaa bytes for undefined.
23122926 const src_val_is_undefined =
23132927 if (f.air.value(bin_op.rhs)) |v| v.isUndefDeep() else false;
23142928 if (src_val_is_undefined)
2315 return try airStoreUndefined(f, dest_ptr);
2929 return try airStoreUndefined(f, ptr_info.pointee_type, ptr_val);
23162930
2931 const target = f.object.dg.module.getTarget();
23172932 const writer = f.object.writer();
2318 if (lhs_child_type.zigTypeTag() == .Array) {
2933 if (lowersToArray(ptr_info.pointee_type, target)) {
23192934 // For this memcpy to safely work we need the rhs to have the same
23202935 // underlying type as the lhs (i.e. they must both be arrays of the same underlying type).
2321 const rhs_type = f.air.typeOf(bin_op.rhs);
2322 assert(rhs_type.eql(lhs_child_type, f.object.dg.module));
2936 assert(src_ty.eql(ptr_info.pointee_type, f.object.dg.module));
23232937
23242938 // If the source is a constant, writeCValue will emit a brace initialization
23252939 // so work around this by initializing into new local.
23262940 // TODO this should be done by manually initializing elements of the dest array
23272941 const array_src = if (src_val == .constant) blk: {
2328 const new_local = try f.allocLocal(rhs_type, .Const);
2942 const new_local = try f.allocLocal(src_ty, .Const);
23292943 try writer.writeAll(" = ");
2330 try f.writeCValue(writer, src_val);
2331 try writer.writeAll(";");
2332 try f.object.indent_writer.insertNewline();
2944 try f.writeCValue(writer, src_val, .Initializer);
2945 try writer.writeAll(";\n");
23332946
23342947 break :blk new_local;
23352948 } else src_val;
23362949
23372950 try writer.writeAll("memcpy(");
2338 try f.writeCValue(writer, dest_ptr);
2951 try f.writeCValue(writer, ptr_val, .FunctionArgument);
23392952 try writer.writeAll(", ");
2340 try f.writeCValue(writer, array_src);
2953 try f.writeCValue(writer, array_src, .FunctionArgument);
23412954 try writer.writeAll(", sizeof(");
2342 try f.writeCValue(writer, array_src);
2343 try writer.writeAll("));\n");
2344 } else {
2345 try f.writeCValueDeref(writer, dest_ptr);
2346 try writer.writeAll(" = ");
2347 try f.writeCValue(writer, src_val);
2348 try writer.writeAll(";\n");
2349 }
2350 return CValue.none;
2351}
2352
2353fn airWrapOp(
2354 f: *Function,
2355 inst: Air.Inst.Index,
2356 str_op: [*:0]const u8,
2357 fn_op: [*:0]const u8,
2358) !CValue {
2359 if (f.liveness.isUnused(inst))
2360 return CValue.none;
2361
2362 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2363 const inst_ty = f.air.typeOfIndex(inst);
2364 const target = f.object.dg.module.getTarget();
2365 const int_info = inst_ty.intInfo(target);
2366 const bits = int_info.bits;
2367
2368 // if it's an unsigned int with non-arbitrary bit size then we can just add
2369 if (int_info.signedness == .unsigned) {
2370 const ok_bits = switch (bits) {
2371 8, 16, 32, 64, 128 => true,
2372 else => false,
2955 try f.renderTypecast(writer, src_ty);
2956 try writer.writeAll("))");
2957 } else if (ptr_info.host_size != 0) {
2958 const host_bits = ptr_info.host_size * 8;
2959 var host_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = host_bits };
2960 const host_ty = Type.initPayload(&host_pl.base);
2961
2962 var bit_offset_ty_pl = Type.Payload.Bits{
2963 .base = .{ .tag = .int_unsigned },
2964 .data = Type.smallestUnsignedBits(host_bits - 1),
23732965 };
2374 if (ok_bits or inst_ty.tag() != .int_unsigned) {
2375 return try airBinOp(f, inst, str_op);
2376 }
2377 }
2378
2379 if (bits > 64) {
2380 return f.fail("TODO: C backend: airWrapOp for large integers", .{});
2381 }
2382
2383 var max_buf: [80]u8 = undefined;
2384 const max = intMax(inst_ty, target, &max_buf);
2385
2386 const lhs = try f.resolveInst(bin_op.lhs);
2387 const rhs = try f.resolveInst(bin_op.rhs);
2388 const w = f.object.writer();
2389
2390 const ret = try f.allocLocal(inst_ty, .Mut);
2391 try w.print(" = zig_{s}", .{fn_op});
2392
2393 switch (inst_ty.tag()) {
2394 .isize => try w.writeAll("isize"),
2395 .c_short => try w.writeAll("short"),
2396 .c_int => try w.writeAll("int"),
2397 .c_long => try w.writeAll("long"),
2398 .c_longlong => try w.writeAll("longlong"),
2399 else => {
2400 const prefix_byte: u8 = signAbbrev(int_info.signedness);
2401 for ([_]u8{ 8, 16, 32, 64 }) |nbits| {
2402 if (bits <= nbits) {
2403 try w.print("{c}{d}", .{ prefix_byte, nbits });
2404 break;
2405 }
2406 } else {
2407 unreachable;
2408 }
2409 },
2410 }
2411
2412 try w.writeByte('(');
2413 try f.writeCValue(w, lhs);
2414 try w.writeAll(", ");
2415 try f.writeCValue(w, rhs);
2416
2417 if (int_info.signedness == .signed) {
2418 var min_buf: [80]u8 = undefined;
2419 const min = intMin(inst_ty, target, &min_buf);
2420
2421 try w.print(", {s}", .{min});
2422 }
2423
2424 try w.print(", {s});", .{max});
2425 try f.object.indent_writer.insertNewline();
2426
2427 return ret;
2428}
2429
2430fn airSatOp(f: *Function, inst: Air.Inst.Index, fn_op: [*:0]const u8) !CValue {
2431 if (f.liveness.isUnused(inst))
2432 return CValue.none;
2433
2434 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2435 const inst_ty = f.air.typeOfIndex(inst);
2436 const int_info = inst_ty.intInfo(f.object.dg.module.getTarget());
2437 const bits = int_info.bits;
2438
2439 switch (bits) {
2440 8, 16, 32, 64, 128 => {},
2441 else => return f.object.dg.fail("TODO: C backend: airSatOp for non power of 2 integers", .{}),
2442 }
2443
2444 // if it's an unsigned int with non-arbitrary bit size then we can just add
2445 if (bits > 64) {
2446 return f.object.dg.fail("TODO: C backend: airSatOp for large integers", .{});
2447 }
2966 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
24482967
2449 var min_buf: [80]u8 = undefined;
2450 const min = switch (int_info.signedness) {
2451 .unsigned => "0",
2452 else => switch (inst_ty.tag()) {
2453 .c_short => "SHRT_MIN",
2454 .c_int => "INT_MIN",
2455 .c_long => "LONG_MIN",
2456 .c_longlong => "LLONG_MIN",
2457 .isize => "INTPTR_MIN",
2458 else => blk: {
2459 // compute the type minimum based on the bitcount (bits)
2460 const val = -1 * std.math.pow(i65, 2, @intCast(i65, bits - 1));
2461 break :blk std.fmt.bufPrint(&min_buf, "{d}", .{val}) catch |err| switch (err) {
2462 error.NoSpaceLeft => unreachable,
2463 };
2464 },
2465 },
2466 };
2968 var bit_offset_val_pl: Value.Payload.U64 = .{
2969 .base = .{ .tag = .int_u64 },
2970 .data = ptr_info.bit_offset,
2971 };
2972 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
24672973
2468 var max_buf: [80]u8 = undefined;
2469 const max = switch (inst_ty.tag()) {
2470 .c_short => "SHRT_MAX",
2471 .c_ushort => "USHRT_MAX",
2472 .c_int => "INT_MAX",
2473 .c_uint => "UINT_MAX",
2474 .c_long => "LONG_MAX",
2475 .c_ulong => "ULONG_MAX",
2476 .c_longlong => "LLONG_MAX",
2477 .c_ulonglong => "ULLONG_MAX",
2478 .isize => "INTPTR_MAX",
2479 .usize => "UINTPTR_MAX",
2480 else => blk: {
2481 const pow_bits = switch (int_info.signedness) {
2482 .signed => bits - 1,
2483 .unsigned => bits,
2484 };
2485 const val = std.math.pow(u65, 2, pow_bits) - 1;
2486 break :blk std.fmt.bufPrint(&max_buf, "{}", .{val}) catch |err| switch (err) {
2487 error.NoSpaceLeft => unreachable,
2488 };
2489 },
2490 };
2974 const src_bits = src_ty.bitSize(target);
24912975
2492 const lhs = try f.resolveInst(bin_op.lhs);
2493 const rhs = try f.resolveInst(bin_op.rhs);
2494 const w = f.object.writer();
2976 const Limb = std.math.big.Limb;
2977 const ExpectedContents = [BigInt.Managed.default_capacity]Limb;
2978 var stack align(@alignOf(ExpectedContents)) =
2979 std.heap.stackFallback(@sizeOf(ExpectedContents), f.object.dg.gpa);
24952980
2496 const ret = try f.allocLocal(inst_ty, .Mut);
2497 try w.print(" = zig_{s}", .{fn_op});
2981 var mask = try BigInt.Managed.initCapacity(stack.get(), BigInt.calcTwosCompLimbCount(host_bits));
2982 defer mask.deinit();
24982983
2499 switch (inst_ty.tag()) {
2500 .isize => try w.writeAll("isize"),
2501 .c_short => try w.writeAll("short"),
2502 .c_int => try w.writeAll("int"),
2503 .c_long => try w.writeAll("long"),
2504 .c_longlong => try w.writeAll("longlong"),
2505 else => {
2506 const prefix_byte: u8 = signAbbrev(int_info.signedness);
2507 for ([_]u8{ 8, 16, 32, 64 }) |nbits| {
2508 if (bits <= nbits) {
2509 try w.print("{c}{d}", .{ prefix_byte, nbits });
2510 break;
2511 }
2512 } else {
2513 unreachable;
2514 }
2515 },
2516 }
2984 try mask.setTwosCompIntLimit(.max, .unsigned, @intCast(usize, src_bits));
2985 try mask.shiftLeft(&mask, ptr_info.bit_offset);
2986 try mask.bitNotWrap(&mask, .unsigned, host_bits);
25172987
2518 try w.writeByte('(');
2519 try f.writeCValue(w, lhs);
2520 try w.writeAll(", ");
2521 try f.writeCValue(w, rhs);
2988 var mask_pl = Value.Payload.BigInt{
2989 .base = .{ .tag = .int_big_positive },
2990 .data = mask.limbs[0..mask.len()],
2991 };
2992 const mask_val = Value.initPayload(&mask_pl.base);
25222993
2523 if (int_info.signedness == .signed) {
2524 try w.print(", {s}", .{min});
2994 try f.writeCValueDeref(writer, ptr_val);
2995 try writer.writeAll(" = zig_or_");
2996 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
2997 try writer.writeAll("(zig_and_");
2998 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
2999 try writer.writeByte('(');
3000 try f.writeCValueDeref(writer, ptr_val);
3001 try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});
3002 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
3003 try writer.writeAll("((");
3004 try f.renderTypecast(writer, host_ty);
3005 try writer.writeByte(')');
3006 try f.writeCValue(writer, src_val, .Other);
3007 try writer.print(", {}))", .{try f.fmtIntLiteral(bit_offset_ty, bit_offset_val)});
3008 } else {
3009 try f.writeCValueDeref(writer, ptr_val);
3010 try writer.writeAll(" = ");
3011 try f.writeCValue(writer, src_val, .Other);
25253012 }
2526
2527 try w.print(", {s});", .{max});
2528 try f.object.indent_writer.insertNewline();
2529
2530 return ret;
3013 try writer.writeAll(";\n");
3014 return CValue.none;
25313015}
25323016
2533fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8) !CValue {
3017fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
25343018 if (f.liveness.isUnused(inst))
25353019 return CValue.none;
25363020
......@@ -2542,56 +3026,29 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, op_abbrev: [*:0]const u8) !CV
25423026
25433027 const inst_ty = f.air.typeOfIndex(inst);
25443028 const scalar_ty = f.air.typeOf(bin_op.lhs).scalarType();
2545 const target = f.object.dg.module.getTarget();
2546 const int_info = scalar_ty.intInfo(target);
25473029 const w = f.object.writer();
2548 const c_bits = toCIntBits(int_info.bits) orelse
2549 return f.fail("TODO: C backend: implement integer arithmetic larger than 128 bits", .{});
2550
2551 var max_buf: [80]u8 = undefined;
2552 const max = intMax(scalar_ty, target, &max_buf);
2553
2554 const ret = try f.allocLocal(inst_ty, .Mut);
2555 try w.writeAll(";");
2556 try f.object.indent_writer.insertNewline();
2557 try f.writeCValue(w, ret);
2558
2559 switch (int_info.signedness) {
2560 .unsigned => {
2561 try w.print(".field_1 = zig_{s}u{d}(", .{
2562 op_abbrev, c_bits,
2563 });
2564 try f.writeCValue(w, lhs);
2565 try w.writeAll(", ");
2566 try f.writeCValue(w, rhs);
2567 try w.writeAll(", &");
2568 try f.writeCValue(w, ret);
2569 try w.print(".field_0, {s}", .{max});
2570 },
2571 .signed => {
2572 var min_buf: [80]u8 = undefined;
2573 const min = intMin(scalar_ty, target, &min_buf);
2574
2575 try w.print(".field_1 = zig_{s}i{d}(", .{
2576 op_abbrev, c_bits,
2577 });
2578 try f.writeCValue(w, lhs);
2579 try w.writeAll(", ");
2580 try f.writeCValue(w, rhs);
2581 try w.writeAll(", &");
2582 try f.writeCValue(w, ret);
2583 try w.print(".field_0, {s}, {s}", .{ min, max });
2584 },
2585 }
25863030
2587 try w.writeAll(");");
2588 try f.object.indent_writer.insertNewline();
2589 return ret;
3031 const local = try f.allocLocal(inst_ty, .Mut);
3032 try w.writeAll(";\n");
3033
3034 try f.writeCValue(w, local, .Other);
3035 try w.writeAll(".field_1 = zig_");
3036 try w.writeAll(operation);
3037 try w.writeAll("o_");
3038 try f.object.dg.renderTypeForBuiltinFnName(w, scalar_ty);
3039 try w.writeAll("(&");
3040 try f.writeCValueMember(w, local, .{ .identifier = "field_0" });
3041 try w.writeAll(", ");
3042 try f.writeCValue(w, lhs, .FunctionArgument);
3043 try w.writeAll(", ");
3044 try f.writeCValue(w, rhs, .FunctionArgument);
3045 try f.object.dg.renderBuiltinInfo(w, scalar_ty, info);
3046 try w.writeAll(");\n");
3047 return local;
25903048}
25913049
25923050fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
2593 if (f.liveness.isUnused(inst))
2594 return CValue.none;
3051 if (f.liveness.isUnused(inst)) return CValue.none;
25953052
25963053 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
25973054 const op = try f.resolveInst(ty_op.operand);
......@@ -2600,33 +3057,74 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
26003057 const inst_ty = f.air.typeOfIndex(inst);
26013058 const local = try f.allocLocal(inst_ty, .Const);
26023059
3060 const target = f.object.dg.module.getTarget();
3061 if (inst_ty.bitSize(target) > 64) {}
3062
26033063 try writer.writeAll(" = ");
2604 if (inst_ty.zigTypeTag() == .Bool)
2605 try writer.writeAll("!")
2606 else
2607 try writer.writeAll("~");
2608 try f.writeCValue(writer, op);
3064 try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');
3065 try f.writeCValue(writer, op, .Other);
26093066 try writer.writeAll(";\n");
26103067
26113068 return local;
26123069}
26133070
2614fn airBinOp(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue {
2615 if (f.liveness.isUnused(inst))
2616 return CValue.none;
3071fn airBinOp(
3072 f: *Function,
3073 inst: Air.Inst.Index,
3074 operator: []const u8,
3075 operation: []const u8,
3076 info: BuiltinInfo,
3077) !CValue {
3078 if (f.liveness.isUnused(inst)) return CValue.none;
26173079
26183080 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3081
3082 const operand_ty = f.air.typeOf(bin_op.lhs);
3083 const target = f.object.dg.module.getTarget();
3084 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3085 return try airBinBuiltinCall(f, inst, operation, info);
3086
3087 const inst_ty = f.air.typeOfIndex(inst);
26193088 const lhs = try f.resolveInst(bin_op.lhs);
26203089 const rhs = try f.resolveInst(bin_op.rhs);
26213090
26223091 const writer = f.object.writer();
3092 const local = try f.allocLocal(inst_ty, .Const);
3093
3094 try writer.writeAll(" = ");
3095 try f.writeCValue(writer, lhs, .Other);
3096 try writer.writeByte(' ');
3097 try writer.writeAll(operator);
3098 try writer.writeByte(' ');
3099 try f.writeCValue(writer, rhs, .Other);
3100 try writer.writeAll(";\n");
3101
3102 return local;
3103}
3104
3105fn airCmpOp(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
3106 if (f.liveness.isUnused(inst)) return CValue.none;
3107
3108 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3109
3110 const operand_ty = f.air.typeOf(bin_op.lhs);
3111 const target = f.object.dg.module.getTarget();
3112 if (operand_ty.isInt() and operand_ty.bitSize(target) > 64)
3113 return try airCmpBuiltinCall(f, inst, operator);
3114
26233115 const inst_ty = f.air.typeOfIndex(inst);
3116 const lhs = try f.resolveInst(bin_op.lhs);
3117 const rhs = try f.resolveInst(bin_op.rhs);
3118
3119 const writer = f.object.writer();
26243120 const local = try f.allocLocal(inst_ty, .Const);
26253121
26263122 try writer.writeAll(" = ");
2627 try f.writeCValue(writer, lhs);
2628 try writer.print("{s}", .{operator});
2629 try f.writeCValue(writer, rhs);
3123 try f.writeCValue(writer, lhs, .Other);
3124 try writer.writeByte(' ');
3125 try writer.writeAll(operator);
3126 try writer.writeByte(' ');
3127 try f.writeCValue(writer, rhs, .Other);
26303128 try writer.writeAll(";\n");
26313129
26323130 return local;
......@@ -2656,31 +3154,48 @@ fn airEquality(
26563154 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
26573155
26583156 try writer.writeAll(negate_prefix);
2659 try f.writeCValue(writer, lhs);
3157 try f.writeCValue(writer, lhs, .Other);
26603158 try writer.writeAll(".is_null && ");
2661 try f.writeCValue(writer, rhs);
3159 try f.writeCValue(writer, rhs, .Other);
26623160 try writer.writeAll(".is_null) || (");
2663 try f.writeCValue(writer, lhs);
3161 try f.writeCValue(writer, lhs, .Other);
26643162 try writer.writeAll(".payload == ");
2665 try f.writeCValue(writer, rhs);
3163 try f.writeCValue(writer, rhs, .Other);
26663164 try writer.writeAll(".payload && ");
2667 try f.writeCValue(writer, lhs);
3165 try f.writeCValue(writer, lhs, .Other);
26683166 try writer.writeAll(".is_null == ");
2669 try f.writeCValue(writer, rhs);
3167 try f.writeCValue(writer, rhs, .Other);
26703168 try writer.writeAll(".is_null));\n");
26713169
26723170 return local;
26733171 }
26743172
2675 try f.writeCValue(writer, lhs);
3173 try f.writeCValue(writer, lhs, .Other);
3174 try writer.writeByte(' ');
26763175 try writer.writeAll(eq_op_str);
2677 try f.writeCValue(writer, rhs);
3176 try writer.writeByte(' ');
3177 try f.writeCValue(writer, rhs, .Other);
26783178 try writer.writeAll(";\n");
26793179
26803180 return local;
26813181}
26823182
2683fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue {
3183fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
3184 if (f.liveness.isUnused(inst)) return CValue.none;
3185
3186 const un_op = f.air.instructions.items(.data)[inst].un_op;
3187 const inst_ty = f.air.typeOfIndex(inst);
3188 const operand = try f.resolveInst(un_op);
3189
3190 const writer = f.object.writer();
3191 const local = try f.allocLocal(inst_ty, .Const);
3192 try writer.writeAll(" = ");
3193 try f.writeCValue(writer, operand, .Other);
3194 try writer.print(" < sizeof({ }) / sizeof(*{0 });\n", .{fmtIdent("zig_errorName")});
3195 return local;
3196}
3197
3198fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
26843199 if (f.liveness.isUnused(inst)) return CValue.none;
26853200
26863201 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
......@@ -2704,17 +3219,19 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CV
27043219 try writer.writeAll(" = (");
27053220 try f.renderTypecast(writer, inst_ty);
27063221 try writer.writeAll(")(((uintptr_t)");
2707 try f.writeCValue(writer, lhs);
2708 try writer.print("){s}(", .{operator});
2709 try f.writeCValue(writer, rhs);
3222 try f.writeCValue(writer, lhs, .Other);
3223 try writer.writeAll(") ");
3224 try writer.writeByte(operator);
3225 try writer.writeAll(" (");
3226 try f.writeCValue(writer, rhs, .Other);
27103227 try writer.writeAll("*sizeof(");
27113228 try f.renderTypecast(writer, elem_ty);
2712 try writer.print(")));\n", .{});
3229 try writer.writeAll(")));\n");
27133230
27143231 return local;
27153232}
27163233
2717fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValue {
3234fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
27183235 if (f.liveness.isUnused(inst)) return CValue.none;
27193236
27203237 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
......@@ -2727,13 +3244,15 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: [*:0]const u8) !CValu
27273244
27283245 // (lhs <> rhs) ? lhs : rhs
27293246 try writer.writeAll(" = (");
2730 try f.writeCValue(writer, lhs);
2731 try writer.print("{s}", .{operator});
2732 try f.writeCValue(writer, rhs);
3247 try f.writeCValue(writer, lhs, .Other);
3248 try writer.writeByte(' ');
3249 try writer.writeByte(operator);
3250 try writer.writeByte(' ');
3251 try f.writeCValue(writer, rhs, .Other);
27333252 try writer.writeAll(") ? ");
2734 try f.writeCValue(writer, lhs);
3253 try f.writeCValue(writer, lhs, .Other);
27353254 try writer.writeAll(" : ");
2736 try f.writeCValue(writer, rhs);
3255 try f.writeCValue(writer, rhs, .Other);
27373256 try writer.writeAll(";\n");
27383257
27393258 return local;
......@@ -2751,10 +3270,13 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
27513270 const inst_ty = f.air.typeOfIndex(inst);
27523271 const local = try f.allocLocal(inst_ty, .Const);
27533272
2754 try writer.writeAll(" = {");
2755 try f.writeCValue(writer, ptr);
3273 try writer.writeAll(" = {(");
3274 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3275 try f.renderTypecast(writer, inst_ty.slicePtrFieldType(&buf));
3276 try writer.writeByte(')');
3277 try f.writeCValue(writer, ptr, .Other);
27563278 try writer.writeAll(", ");
2757 try f.writeCValue(writer, len);
3279 try f.writeCValue(writer, len, .Initializer);
27583280 try writer.writeAll("};\n");
27593281
27603282 return local;
......@@ -2765,6 +3287,9 @@ fn airCall(
27653287 inst: Air.Inst.Index,
27663288 modifier: std.builtin.CallOptions.Modifier,
27673289) !CValue {
3290 // Not even allowed to call panic in a naked function.
3291 if (f.object.dg.decl.ty.fnCallingConvention() == .Naked) return .none;
3292
27683293 switch (modifier) {
27693294 .auto => {},
27703295 .always_tail => return f.fail("TODO: C backend: call with always_tail attribute", .{}),
......@@ -2783,39 +3308,50 @@ fn airCall(
27833308 };
27843309 const writer = f.object.writer();
27853310
2786 const result_local: CValue = r: {
2787 if (f.liveness.isUnused(inst)) {
2788 if (loweredFnRetTyHasBits(fn_ty)) {
2789 try writer.print("(void)", .{});
2790 }
2791 break :r .none;
2792 } else {
2793 const local = try f.allocLocal(fn_ty.fnReturnType(), .Const);
2794 try writer.writeAll(" = ");
2795 break :r local;
2796 }
3311 const target = f.object.dg.module.getTarget();
3312 const ret_ty = fn_ty.fnReturnType();
3313 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
3314 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
3315
3316 const result_local: CValue = if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime())
3317 .none
3318 else if (f.liveness.isUnused(inst)) r: {
3319 try writer.writeByte('(');
3320 try f.renderTypecast(writer, Type.void);
3321 try writer.writeByte(')');
3322 break :r .none;
3323 } else r: {
3324 const local = try f.allocLocal(lowered_ret_ty, .Const);
3325 try writer.writeAll(" = ");
3326 break :r local;
27973327 };
27983328
3329 var is_extern = false;
3330 var name: [*:0]const u8 = "";
27993331 callee: {
28003332 known: {
28013333 const fn_decl = fn_decl: {
28023334 const callee_val = f.air.value(pl_op.operand) orelse break :known;
28033335 break :fn_decl switch (callee_val.tag()) {
2804 .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,
3336 .extern_fn => blk: {
3337 is_extern = true;
3338 break :blk callee_val.castTag(.extern_fn).?.data.owner_decl;
3339 },
28053340 .function => callee_val.castTag(.function).?.data.owner_decl,
28063341 .decl_ref => callee_val.castTag(.decl_ref).?.data,
28073342 else => break :known,
28083343 };
28093344 };
3345 name = f.object.dg.module.declPtr(fn_decl).name;
28103346 try f.object.dg.renderDeclName(writer, fn_decl);
28113347 break :callee;
28123348 }
28133349 // Fall back to function pointer call.
28143350 const callee = try f.resolveInst(pl_op.operand);
2815 try f.writeCValue(writer, callee);
3351 try f.writeCValue(writer, callee, .Other);
28163352 }
28173353
2818 try writer.writeAll("(");
3354 try writer.writeByte('(');
28193355 var args_written: usize = 0;
28203356 for (args) |arg| {
28213357 const ty = f.air.typeOf(arg);
......@@ -2823,16 +3359,32 @@ fn airCall(
28233359 if (args_written != 0) {
28243360 try writer.writeAll(", ");
28253361 }
2826 if (f.air.value(arg)) |val| {
2827 try f.object.dg.renderValue(writer, f.air.typeOf(arg), val, .FunctionArgument);
2828 } else {
2829 const val = try f.resolveInst(arg);
2830 try f.writeCValue(writer, val);
3362 if ((is_extern or std.mem.eql(u8, std.mem.span(name), "main")) and
3363 ty.isCPtr() and ty.childType().tag() == .u8)
3364 {
3365 // Corresponds with hack in renderType .Pointer case.
3366 try writer.writeAll("(char");
3367 if (ty.isConstPtr()) try writer.writeAll(" const");
3368 if (ty.isVolatilePtr()) try writer.writeAll(" volatile");
3369 try writer.writeAll(" *)");
28313370 }
3371 try f.writeCValue(writer, try f.resolveInst(arg), .FunctionArgument);
28323372 args_written += 1;
28333373 }
28343374 try writer.writeAll(");\n");
2835 return result_local;
3375
3376 if (result_local == .none or !lowersToArray(ret_ty, target)) return result_local;
3377
3378 const array_local = try f.allocLocal(ret_ty, .Mut);
3379 try writer.writeAll(";\n");
3380 try writer.writeAll("memcpy(");
3381 try f.writeCValue(writer, array_local, .FunctionArgument);
3382 try writer.writeAll(", ");
3383 try f.writeCValueMember(writer, result_local, .{ .identifier = "array" });
3384 try writer.writeAll(", sizeof(");
3385 try f.renderTypecast(writer, ret_ty);
3386 try writer.writeAll("));\n");
3387 return array_local;
28363388}
28373389
28383390fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -2931,27 +3483,19 @@ fn lowerTry(
29313483 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
29323484
29333485 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
2934 err: {
2935 if (!payload_has_bits) {
2936 if (operand_is_ptr) {
2937 try writer.writeAll("if(*");
2938 } else {
2939 try writer.writeAll("if(");
2940 }
2941 try f.writeCValue(writer, err_union);
2942 try writer.writeAll(")");
2943 break :err;
2944 }
2945 if (operand_is_ptr or isByRef(err_union_ty)) {
2946 try writer.writeAll("if(");
2947 try f.writeCValue(writer, err_union);
2948 try writer.writeAll("->error)");
2949 break :err;
2950 }
2951 try writer.writeAll("if(");
2952 try f.writeCValue(writer, err_union);
2953 try writer.writeAll(".error)");
3486 try writer.writeAll("if (");
3487 if (!payload_has_bits) {
3488 if (operand_is_ptr)
3489 try f.writeCValueDeref(writer, err_union)
3490 else
3491 try f.writeCValue(writer, err_union, .Other);
3492 } else {
3493 if (operand_is_ptr or isByRef(err_union_ty))
3494 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "error" })
3495 else
3496 try f.writeCValueMember(writer, err_union, .{ .identifier = "error" });
29543497 }
3498 try writer.writeByte(')');
29553499
29563500 try genBody(f, body);
29573501 try f.object.indent_writer.insertNewline();
......@@ -2965,15 +3509,25 @@ fn lowerTry(
29653509 }
29663510 }
29673511
2968 const local = try f.allocLocal(result_ty, .Const);
2969 if (operand_is_ptr or isByRef(payload_ty)) {
2970 try writer.writeAll(" = &");
2971 try f.writeCValue(writer, err_union);
2972 try writer.writeAll("->payload;\n");
3512 const target = f.object.dg.module.getTarget();
3513 const is_array = lowersToArray(payload_ty, target);
3514 const local = try f.allocLocal(result_ty, if (is_array) .Mut else .Const);
3515 if (is_array) {
3516 try writer.writeAll(";\n");
3517 try writer.writeAll("memcpy(");
3518 try f.writeCValue(writer, local, .FunctionArgument);
3519 try writer.writeAll(", ");
3520 try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
3521 try writer.writeAll(", sizeof(");
3522 try f.renderTypecast(writer, payload_ty);
3523 try writer.writeAll("));\n");
29733524 } else {
29743525 try writer.writeAll(" = ");
2975 try f.writeCValue(writer, err_union);
2976 try writer.writeAll(".payload;\n");
3526 if (operand_is_ptr or isByRef(payload_ty)) {
3527 try writer.writeByte('&');
3528 try f.writeCValueDerefMember(writer, err_union, .{ .identifier = "payload" });
3529 } else try f.writeCValueMember(writer, err_union, .{ .identifier = "payload" });
3530 try writer.writeAll(";\n");
29773531 }
29783532 return local;
29793533}
......@@ -2987,9 +3541,9 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
29873541 // If result is .none then the value of the block is unused.
29883542 if (result != .none) {
29893543 const operand = try f.resolveInst(branch.operand);
2990 try f.writeCValue(writer, result);
3544 try f.writeCValue(writer, result, .Other);
29913545 try writer.writeAll(" = ");
2992 try f.writeCValue(writer, operand);
3546 try f.writeCValue(writer, operand, .Other);
29933547 try writer.writeAll(";\n");
29943548 }
29953549
......@@ -3013,8 +3567,8 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
30133567 try writer.writeAll(" = (");
30143568 try f.renderTypecast(writer, inst_ty);
30153569
3016 try writer.writeAll(")");
3017 try f.writeCValue(writer, operand);
3570 try writer.writeByte(')');
3571 try f.writeCValue(writer, operand, .Other);
30183572 try writer.writeAll(";\n");
30193573 return local;
30203574 }
......@@ -3023,32 +3577,38 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
30233577 try writer.writeAll(";\n");
30243578
30253579 try writer.writeAll("memcpy(&");
3026 try f.writeCValue(writer, local);
3580 try f.writeCValue(writer, local, .Other);
30273581 try writer.writeAll(", &");
3028 try f.writeCValue(writer, operand);
3582 try f.writeCValue(writer, operand, .Other);
30293583 try writer.writeAll(", sizeof(");
3030 try f.writeCValue(writer, local);
3584 try f.renderTypecast(writer, inst_ty);
30313585 try writer.writeAll("));\n");
30323586
30333587 return local;
30343588}
30353589
3036fn airBreakpoint(f: *Function) !CValue {
3037 try f.object.writer().writeAll("zig_breakpoint();\n");
3590fn airBreakpoint(writer: anytype) !CValue {
3591 try writer.writeAll("zig_breakpoint();\n");
30383592 return CValue.none;
30393593}
30403594
30413595fn airRetAddr(f: *Function, inst: Air.Inst.Index) !CValue {
30423596 if (f.liveness.isUnused(inst)) return CValue.none;
3597 const writer = f.object.writer();
30433598 const local = try f.allocLocal(Type.usize, .Const);
3044 try f.object.writer().writeAll(" = zig_return_address();\n");
3599 try writer.writeAll(" = (");
3600 try f.renderTypecast(writer, Type.usize);
3601 try writer.writeAll(")zig_return_address();\n");
30453602 return local;
30463603}
30473604
30483605fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
30493606 if (f.liveness.isUnused(inst)) return CValue.none;
3607 const writer = f.object.writer();
30503608 const local = try f.allocLocal(Type.usize, .Const);
3051 try f.object.writer().writeAll(" = zig_frame_address();\n");
3609 try writer.writeAll(" = (");
3610 try f.renderTypecast(writer, Type.usize);
3611 try writer.writeAll(")zig_frame_address();\n");
30523612 return local;
30533613}
30543614
......@@ -3064,6 +3624,9 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
30643624}
30653625
30663626fn airUnreach(f: *Function) !CValue {
3627 // Not even allowed to call unreachable in a naked function.
3628 if (f.object.dg.decl.ty.fnCallingConvention() == .Naked) return .none;
3629
30673630 try f.object.writer().writeAll("zig_unreachable();\n");
30683631 return CValue.none;
30693632}
......@@ -3072,9 +3635,12 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {
30723635 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
30733636 const loop = f.air.extraData(Air.Block, ty_pl.payload);
30743637 const body = f.air.extra[loop.end..][0..loop.data.body_len];
3075 try f.object.writer().writeAll("while (true) ");
3638 const writer = f.object.writer();
3639 try writer.writeAll("while (");
3640 try f.object.dg.renderValue(writer, Type.bool, Value.@"true", .Other);
3641 try writer.writeAll(") ");
30763642 try genBody(f, body);
3077 try f.object.indent_writer.insertNewline();
3643 try writer.writeByte('\n');
30783644 return CValue.none;
30793645}
30803646
......@@ -3087,7 +3653,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
30873653 const writer = f.object.writer();
30883654
30893655 try writer.writeAll("if (");
3090 try f.writeCValue(writer, cond);
3656 try f.writeCValue(writer, cond, .Other);
30913657 try writer.writeAll(") ");
30923658 try genBody(f, then_body);
30933659 try writer.writeAll(" else ");
......@@ -3105,7 +3671,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
31053671 const writer = f.object.writer();
31063672
31073673 try writer.writeAll("switch (");
3108 try f.writeCValue(writer, condition);
3674 if (condition_ty.tag() == .bool) {
3675 try writer.writeByte('(');
3676 try f.renderTypecast(writer, Type.u1);
3677 try writer.writeByte(')');
3678 }
3679 try f.writeCValue(writer, condition, .Other);
31093680 try writer.writeAll(") {");
31103681 f.object.indent_writer.pushIndent();
31113682
......@@ -3138,6 +3709,14 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
31383709 return CValue.none;
31393710}
31403711
3712fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool {
3713 return switch (constraint[0]) {
3714 '{' => true,
3715 'i', 'r' => false,
3716 else => value == .constant,
3717 };
3718}
3719
31413720fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
31423721 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
31433722 const extra = f.air.extraData(Air.Asm, ty_pl.payload);
......@@ -3151,54 +3730,79 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
31513730
31523731 if (!is_volatile and f.liveness.isUnused(inst)) return CValue.none;
31533732
3154 if (outputs.len > 1) {
3155 return f.fail("TODO implement codegen for asm with more than 1 output", .{});
3156 }
3157
3158 const output_constraint: ?[]const u8 = for (outputs) |output| {
3159 if (output != .none) {
3160 return f.fail("TODO implement codegen for non-expr asm", .{});
3733 const writer = f.object.writer();
3734 const inst_ty = f.air.typeOfIndex(inst);
3735 const local = if (inst_ty.hasRuntimeBitsIgnoreComptime()) local: {
3736 const local = try f.allocLocal(inst_ty, .Mut);
3737 if (f.wantSafety()) {
3738 try writer.writeAll(" = ");
3739 try f.writeCValue(writer, .{ .undef = inst_ty }, .Initializer);
31613740 }
3741 try writer.writeAll(";\n");
3742 break :local local;
3743 } else .none;
3744
3745 const locals_begin = f.next_local_index;
3746 const constraints_extra_begin = extra_i;
3747 for (outputs) |output| {
31623748 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3163 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
3749 const constraint = std.mem.sliceTo(extra_bytes, 0);
31643750 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
31653751 // This equation accounts for the fact that even if we have exactly 4 bytes
31663752 // for the string, we still use the next u32 for the null terminator.
31673753 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
31683754
3169 break constraint;
3170 } else null;
3171
3172 const writer = f.object.writer();
3173 try writer.writeAll("{\n");
3755 if (constraint.len < 2 or constraint[0] != '=' or
3756 (constraint[1] == '{' and constraint[constraint.len - 1] != '}'))
3757 {
3758 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
3759 }
31743760
3175 const inputs_extra_begin = extra_i;
3176 for (inputs) |input, i| {
3177 const input_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3178 const constraint = std.mem.sliceTo(input_bytes, 0);
3179 const name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
3761 const is_reg = constraint[1] == '{';
3762 if (is_reg) {
3763 const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType();
3764 try writer.writeAll("register ");
3765 _ = try f.allocLocal(output_ty, .Mut);
3766 try writer.writeAll(" __asm(\"");
3767 try writer.writeAll(constraint["={".len .. constraint.len - "}".len]);
3768 try writer.writeAll("\")");
3769 if (f.wantSafety()) {
3770 try writer.writeAll(" = ");
3771 try f.writeCValue(writer, .{ .undef = output_ty }, .Initializer);
3772 }
3773 try writer.writeAll(";\n");
3774 }
3775 }
3776 for (inputs) |input| {
3777 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3778 const constraint = std.mem.sliceTo(extra_bytes, 0);
3779 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
31803780 // This equation accounts for the fact that even if we have exactly 4 bytes
31813781 // for the string, we still use the next u32 for the null terminator.
31823782 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
31833783
3184 if (constraint[0] == '{' and constraint[constraint.len - 1] == '}') {
3185 const reg = constraint[1 .. constraint.len - 1];
3186 const arg_c_value = try f.resolveInst(input);
3187 try writer.writeAll("register ");
3188 try f.renderType(writer, f.air.typeOf(input));
3784 if (constraint.len < 1 or std.mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or
3785 (constraint[0] == '{' and constraint[constraint.len - 1] != '}'))
3786 {
3787 return f.fail("CBE: constraint not supported: '{s}'", .{constraint});
3788 }
31893789
3190 try writer.print(" {s}_constant __asm__(\"{s}\") = ", .{ reg, reg });
3191 try f.writeCValue(writer, arg_c_value);
3192 try writer.writeAll(";\n");
3193 } else {
3194 try writer.writeAll("register ");
3195 try f.renderType(writer, f.air.typeOf(input));
3196 try writer.print(" input_{d} = ", .{i});
3197 try f.writeCValue(writer, try f.resolveInst(input));
3790 const is_reg = constraint[0] == '{';
3791 const input_val = try f.resolveInst(input);
3792 if (asmInputNeedsLocal(constraint, input_val)) {
3793 const input_ty = f.air.typeOf(input);
3794 if (is_reg) try writer.writeAll("register ");
3795 _ = try f.allocLocal(input_ty, .Const);
3796 if (is_reg) {
3797 try writer.writeAll(" __asm(\"");
3798 try writer.writeAll(constraint["{".len .. constraint.len - "}".len]);
3799 try writer.writeAll("\")");
3800 }
3801 try writer.writeAll(" = ");
3802 try f.writeCValue(writer, input_val, .Initializer);
31983803 try writer.writeAll(";\n");
31993804 }
32003805 }
3201
32023806 {
32033807 var clobber_i: u32 = 0;
32043808 while (clobber_i < clobbers_len) : (clobber_i += 1) {
......@@ -3206,58 +3810,109 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
32063810 // This equation accounts for the fact that even if we have exactly 4 bytes
32073811 // for the string, we still use the next u32 for the null terminator.
32083812 extra_i += clobber.len / 4 + 1;
3209
3210 // TODO honor these
32113813 }
32123814 }
3213
32143815 const asm_source = std.mem.sliceAsBytes(f.air.extra[extra_i..])[0..extra.data.source_len];
32153816
3216 const volatile_string: []const u8 = if (is_volatile) "volatile " else "";
3217 try writer.print("__asm {s}(\"{s}\"", .{ volatile_string, asm_source });
3218 if (output_constraint) |_| {
3219 return f.fail("TODO: CBE inline asm output", .{});
3220 }
3221 if (inputs.len > 0) {
3222 if (output_constraint == null) {
3223 try writer.writeAll(" :");
3817 try writer.writeAll("__asm");
3818 if (is_volatile) try writer.writeAll(" volatile");
3819 try writer.print("({s}", .{fmtStringLiteral(asm_source)});
3820
3821 extra_i = constraints_extra_begin;
3822 var locals_index = locals_begin;
3823 try writer.writeByte(':');
3824 for (outputs) |output, index| {
3825 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3826 const constraint = std.mem.sliceTo(extra_bytes, 0);
3827 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
3828 // This equation accounts for the fact that even if we have exactly 4 bytes
3829 // for the string, we still use the next u32 for the null terminator.
3830 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
3831
3832 if (index > 0) try writer.writeByte(',');
3833 try writer.writeByte(' ');
3834 if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
3835 const is_reg = constraint[1] == '{';
3836 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "=r" else constraint)});
3837 if (is_reg) {
3838 try f.writeCValue(writer, .{ .local = locals_index }, .Other);
3839 locals_index += 1;
3840 } else {
3841 try f.writeCValueDeref(writer, try f.resolveInst(output));
32243842 }
3225 try writer.writeAll(": ");
3226 extra_i = inputs_extra_begin;
3227 for (inputs) |_, index| {
3228 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
3843 try writer.writeByte(')');
3844 }
3845 try writer.writeByte(':');
3846 for (inputs) |input, index| {
3847 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3848 const constraint = std.mem.sliceTo(extra_bytes, 0);
3849 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
3850 // This equation accounts for the fact that even if we have exactly 4 bytes
3851 // for the string, we still use the next u32 for the null terminator.
3852 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
3853
3854 if (index > 0) try writer.writeByte(',');
3855 try writer.writeByte(' ');
3856 if (!std.mem.eql(u8, name, "_")) try writer.print("[{s}]", .{name});
3857
3858 const is_reg = constraint[0] == '{';
3859 const input_val = try f.resolveInst(input);
3860 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint)});
3861 try f.writeCValue(writer, if (asmInputNeedsLocal(constraint, input_val)) local: {
3862 const input_local = CValue{ .local = locals_index };
3863 locals_index += 1;
3864 break :local input_local;
3865 } else input_val, .Other);
3866 try writer.writeByte(')');
3867 }
3868 try writer.writeByte(':');
3869 {
3870 var clobber_i: u32 = 0;
3871 while (clobber_i < clobbers_len) : (clobber_i += 1) {
3872 const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(f.air.extra[extra_i..]), 0);
32293873 // This equation accounts for the fact that even if we have exactly 4 bytes
32303874 // for the string, we still use the next u32 for the null terminator.
3231 extra_i += constraint.len / 4 + 1;
3875 extra_i += clobber.len / 4 + 1;
32323876
3233 if (constraint[0] == '{' and constraint[constraint.len - 1] == '}') {
3234 const reg = constraint[1 .. constraint.len - 1];
3235 if (index > 0) {
3236 try writer.writeAll(", ");
3237 }
3238 try writer.print("\"r\"({s}_constant)", .{reg});
3239 } else {
3240 if (index > 0) {
3241 try writer.writeAll(", ");
3242 }
3243 try writer.print("\"r\"(input_{d})", .{index});
3244 }
3877 if (clobber.len == 0) continue;
3878
3879 if (clobber_i > 0) try writer.writeByte(',');
3880 try writer.print(" {s}", .{fmtStringLiteral(clobber)});
32453881 }
32463882 }
32473883 try writer.writeAll(");\n");
3248 try writer.writeAll("}\n");
32493884
3250 if (f.liveness.isUnused(inst))
3251 return CValue.none;
3885 extra_i = constraints_extra_begin;
3886 locals_index = locals_begin;
3887 for (outputs) |output| {
3888 const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]);
3889 const constraint = std.mem.sliceTo(extra_bytes, 0);
3890 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
3891 // This equation accounts for the fact that even if we have exactly 4 bytes
3892 // for the string, we still use the next u32 for the null terminator.
3893 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
32523894
3253 return f.fail("TODO: C backend: inline asm expression result used", .{});
3895 const is_reg = constraint[1] == '{';
3896 if (is_reg) {
3897 try f.writeCValueDeref(writer, if (output == .none)
3898 CValue{ .local_ref = local.local }
3899 else
3900 try f.resolveInst(output));
3901 try writer.writeAll(" = ");
3902 try f.writeCValue(writer, .{ .local = locals_index }, .Other);
3903 locals_index += 1;
3904 try writer.writeAll(";\n");
3905 }
3906 }
3907
3908 return local;
32543909}
32553910
32563911fn airIsNull(
32573912 f: *Function,
32583913 inst: Air.Inst.Index,
3259 operator: [*:0]const u8,
3260 deref_suffix: [*:0]const u8,
3914 operator: []const u8,
3915 is_ptr: bool,
32613916) !CValue {
32623917 if (f.liveness.isUnused(inst))
32633918 return CValue.none;
......@@ -3267,26 +3922,35 @@ fn airIsNull(
32673922 const operand = try f.resolveInst(un_op);
32683923
32693924 const local = try f.allocLocal(Type.initTag(.bool), .Const);
3270 try writer.writeAll(" = (");
3271 try f.writeCValue(writer, operand);
3272
3273 const ty = f.air.typeOf(un_op);
3274 const opt_ty = if (deref_suffix[0] != 0) ty.childType() else ty;
3275 var opt_buf: Type.Payload.ElemType = undefined;
3276 const payload_ty = opt_ty.optionalChild(&opt_buf);
3925 try writer.writeAll(" = ");
3926 try if (is_ptr) f.writeCValueDeref(writer, operand) else f.writeCValue(writer, operand, .Other);
32773927
3278 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3279 try writer.print("){s} {s} true;\n", .{ deref_suffix, operator });
3280 } else if (ty.isPtrLikeOptional()) {
3928 const operand_ty = f.air.typeOf(un_op);
3929 const optional_ty = if (is_ptr) operand_ty.childType() else operand_ty;
3930 var payload_buf: Type.Payload.ElemType = undefined;
3931 const payload_ty = optional_ty.optionalChild(&payload_buf);
3932 var slice_ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
3933
3934 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime())
3935 TypedValue{ .ty = Type.bool, .val = Value.@"true" }
3936 else if (operand_ty.isPtrLikeOptional())
32813937 // operand is a regular pointer, test `operand !=/== NULL`
3282 try writer.print("){s} {s} NULL;\n", .{ deref_suffix, operator });
3283 } else if (payload_ty.zigTypeTag() == .ErrorSet) {
3284 try writer.print("){s} {s} 0;\n", .{ deref_suffix, operator });
3285 } else if (payload_ty.isSlice() and opt_ty.optionalReprIsPayload()) {
3286 try writer.print("){s}.ptr {s} NULL;\n", .{ deref_suffix, operator });
3287 } else {
3288 try writer.print("){s}.is_null {s} true;\n", .{ deref_suffix, operator });
3289 }
3938 TypedValue{ .ty = operand_ty, .val = Value.@"null" }
3939 else if (payload_ty.zigTypeTag() == .ErrorSet)
3940 TypedValue{ .ty = payload_ty, .val = Value.zero }
3941 else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload()) rhs: {
3942 try writer.writeAll(".ptr");
3943 const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf);
3944 break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.@"null" };
3945 } else rhs: {
3946 try writer.writeAll(".is_null");
3947 break :rhs TypedValue{ .ty = Type.bool, .val = Value.@"true" };
3948 };
3949 try writer.writeByte(' ');
3950 try writer.writeAll(operator);
3951 try writer.writeByte(' ');
3952 try f.object.dg.renderValue(writer, rhs.ty, rhs.val, .Other);
3953 try writer.writeAll(";\n");
32903954 return local;
32913955}
32923956
......@@ -3312,7 +3976,7 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
33123976 const inst_ty = f.air.typeOfIndex(inst);
33133977 const local = try f.allocLocal(inst_ty, .Const);
33143978 try writer.writeAll(" = (");
3315 try f.writeCValue(writer, operand);
3979 try f.writeCValue(writer, operand, .Other);
33163980 try writer.writeAll(").payload;\n");
33173981 return local;
33183982}
......@@ -3325,11 +3989,10 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
33253989 const operand = try f.resolveInst(ty_op.operand);
33263990 const ptr_ty = f.air.typeOf(ty_op.operand);
33273991 const opt_ty = ptr_ty.childType();
3328 var buf: Type.Payload.ElemType = undefined;
3329 const payload_ty = opt_ty.optionalChild(&buf);
3992 const inst_ty = f.air.typeOfIndex(inst);
33303993
3331 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3332 return operand;
3994 if (!inst_ty.childType().hasRuntimeBitsIgnoreComptime()) {
3995 return CValue{ .undef = inst_ty };
33333996 }
33343997
33353998 if (opt_ty.optionalReprIsPayload()) {
......@@ -3338,11 +4001,10 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
33384001 return operand;
33394002 }
33404003
3341 const inst_ty = f.air.typeOfIndex(inst);
33424004 const local = try f.allocLocal(inst_ty, .Const);
3343 try writer.writeAll(" = &(");
3344 try f.writeCValue(writer, operand);
3345 try writer.writeAll(")->payload;\n");
4005 try writer.writeAll(" = &");
4006 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" });
4007 try writer.writeAll(";\n");
33464008 return local;
33474009}
33484010
......@@ -3361,7 +4023,9 @@ fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
33614023 }
33624024
33634025 try f.writeCValueDeref(writer, operand);
3364 try writer.writeAll(".is_null = false;\n");
4026 try writer.writeAll(".is_null = ");
4027 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
4028 try writer.writeAll(";\n");
33654029
33664030 const inst_ty = f.air.typeOfIndex(inst);
33674031 const local = try f.allocLocal(inst_ty, .Const);
......@@ -3396,55 +4060,111 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue
33964060}
33974061
33984062fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3399 _ = inst;
3400 return f.fail("TODO: C backend: implement airFieldParentPtr", .{});
4063 if (f.liveness.isUnused(inst)) return CValue.none;
4064
4065 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4066 const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
4067
4068 const struct_ptr_ty = f.air.typeOfIndex(inst);
4069 const field_ptr_ty = f.air.typeOf(extra.field_ptr);
4070 const field_ptr_val = try f.resolveInst(extra.field_ptr);
4071
4072 const target = f.object.dg.module.getTarget();
4073 const struct_ty = struct_ptr_ty.childType();
4074 const field_offset = struct_ty.structFieldOffset(extra.field_index, target);
4075
4076 var field_offset_pl = Value.Payload.I64{
4077 .base = .{ .tag = .int_i64 },
4078 .data = -@intCast(i64, field_offset),
4079 };
4080 const field_offset_val = Value.initPayload(&field_offset_pl.base);
4081
4082 var u8_ptr_pl = field_ptr_ty.ptrInfo();
4083 u8_ptr_pl.data.pointee_type = Type.u8;
4084 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
4085
4086 const writer = f.object.writer();
4087 const local = try f.allocLocal(struct_ptr_ty, .Const);
4088 try writer.writeAll(" = (");
4089 try f.renderTypecast(writer, struct_ptr_ty);
4090 try writer.writeAll(")&((");
4091 try f.renderTypecast(writer, u8_ptr_ty);
4092 try writer.writeByte(')');
4093 try f.writeCValue(writer, field_ptr_val, .Other);
4094 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.isize, field_offset_val)});
4095 return local;
34014096}
34024097
34034098fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struct_ptr: CValue, index: u32) !CValue {
34044099 const writer = f.object.writer();
4100 const field_ptr_ty = f.air.typeOfIndex(inst);
4101 const field_ptr_info = field_ptr_ty.ptrInfo();
34054102 const struct_ty = struct_ptr_ty.elemType();
3406 var field_name: []const u8 = undefined;
3407 var field_val_ty: Type = undefined;
3408
3409 var buf = std.ArrayList(u8).init(f.object.dg.gpa);
3410 defer buf.deinit();
3411 switch (struct_ty.tag()) {
3412 .@"struct" => {
3413 const fields = struct_ty.structFields();
3414 field_name = fields.keys()[index];
3415 field_val_ty = fields.values()[index].ty;
3416 },
3417 .@"union", .union_safety_tagged, .union_tagged => {
3418 const fields = struct_ty.unionFields();
3419 field_name = fields.keys()[index];
3420 field_val_ty = fields.values()[index].ty;
4103 const field_ty = struct_ty.structFieldType(index);
4104
4105 // Ensure complete type definition is visible before accessing fields.
4106 try f.renderType(std.io.null_writer, struct_ty);
4107
4108 const local = try f.allocLocal(field_ptr_ty, .Const);
4109 try writer.writeAll(" = (");
4110 try f.renderTypecast(writer, field_ptr_ty);
4111 try writer.writeByte(')');
4112
4113 const extra_name: ?[]const u8 = switch (struct_ty.tag()) {
4114 .union_tagged, .union_safety_tagged => "payload",
4115 else => null,
4116 };
4117
4118 var field_name_buf: []const u8 = &.{};
4119 defer f.object.dg.gpa.free(field_name_buf);
4120 const field_name: ?[]const u8 = switch (struct_ty.tag()) {
4121 .@"struct" => switch (struct_ty.containerLayout()) {
4122 .Auto, .Extern => struct_ty.structFieldName(index),
4123 .Packed => if (field_ptr_info.data.host_size == 0) {
4124 const target = f.object.dg.module.getTarget();
4125
4126 const byte_offset = struct_ty.packedStructFieldByteOffset(index, target);
4127 var byte_offset_pl = Value.Payload.U64{
4128 .base = .{ .tag = .int_u64 },
4129 .data = byte_offset,
4130 };
4131 const byte_offset_val = Value.initPayload(&byte_offset_pl.base);
4132
4133 var u8_ptr_pl = field_ptr_info;
4134 u8_ptr_pl.data.pointee_type = Type.u8;
4135 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
4136
4137 try writer.writeAll("&((");
4138 try f.renderTypecast(writer, u8_ptr_ty);
4139 try writer.writeByte(')');
4140 try f.writeCValue(writer, struct_ptr, .Other);
4141 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
4142 return local;
4143 } else null,
34214144 },
3422 .tuple, .anon_struct => {
4145 .@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[index],
4146 .tuple, .anon_struct => |tag| field_name: {
34234147 const tuple = struct_ty.tupleFields();
34244148 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
34254149
3426 try buf.writer().print("field_{d}", .{index});
3427 field_name = buf.items;
3428 field_val_ty = tuple.types[index];
4150 if (tag == .anon_struct) break :field_name struct_ty.structFieldName(index);
4151
4152 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index});
4153 break :field_name field_name_buf;
34294154 },
34304155 else => unreachable,
3431 }
3432 const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else "";
3433
3434 const inst_ty = f.air.typeOfIndex(inst);
3435 const local = try f.allocLocal(inst_ty, .Const);
4156 };
34364157
3437 if (field_val_ty.hasRuntimeBitsIgnoreComptime()) {
3438 try writer.writeAll(" = &");
3439 try f.writeCValueDeref(writer, struct_ptr);
3440 try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
3441 } else {
3442 try writer.writeAll(" = (");
3443 try f.renderTypecast(writer, inst_ty);
3444 try writer.writeByte(')');
3445 try f.writeCValue(writer, struct_ptr);
3446 try writer.writeAll(";\n");
3447 }
4158 if (field_ty.hasRuntimeBitsIgnoreComptime()) {
4159 try writer.writeByte('&');
4160 if (extra_name orelse field_name) |name|
4161 try f.writeCValueDerefMember(writer, struct_ptr, .{ .identifier = name })
4162 else
4163 try f.writeCValueDeref(writer, struct_ptr);
4164 if (extra_name) |_| if (field_name) |name|
4165 try writer.print(".{ }", .{fmtIdent(name)});
4166 } else try f.writeCValue(writer, struct_ptr, .Other);
4167 try writer.writeAll(";\n");
34484168 return local;
34494169}
34504170
......@@ -3454,100 +4174,162 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
34544174
34554175 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
34564176 const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;
3457 const writer = f.object.writer();
4177 const inst_ty = f.air.typeOfIndex(inst);
4178 const target = f.object.dg.module.getTarget();
34584179 const struct_byval = try f.resolveInst(extra.struct_operand);
34594180 const struct_ty = f.air.typeOf(extra.struct_operand);
3460 var buf = std.ArrayList(u8).init(f.object.dg.gpa);
3461 defer buf.deinit();
4181 const writer = f.object.writer();
4182
4183 // Ensure complete type definition is visible before accessing fields.
4184 try f.renderType(std.io.null_writer, struct_ty);
4185
4186 var field_name_buf: []const u8 = "";
4187 defer f.object.dg.gpa.free(field_name_buf);
34624188 const field_name = switch (struct_ty.tag()) {
3463 .@"struct" => struct_ty.structFields().keys()[extra.field_index],
4189 .@"struct" => switch (struct_ty.containerLayout()) {
4190 .Auto, .Extern => struct_ty.structFieldName(extra.field_index),
4191 .Packed => {
4192 const struct_obj = struct_ty.castTag(.@"struct").?.data;
4193 const int_info = struct_ty.intInfo(target);
4194
4195 var bit_offset_ty_pl = Type.Payload.Bits{
4196 .base = .{ .tag = .int_unsigned },
4197 .data = Type.smallestUnsignedBits(int_info.bits - 1),
4198 };
4199 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
4200
4201 var bit_offset_val_pl: Value.Payload.U64 = .{
4202 .base = .{ .tag = .int_u64 },
4203 .data = struct_obj.packedFieldBitOffset(target, extra.field_index),
4204 };
4205 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
4206
4207 const field_int_signedness = if (inst_ty.isAbiInt())
4208 inst_ty.intInfo(target).signedness
4209 else
4210 .unsigned;
4211 var field_int_pl = Type.Payload.Bits{
4212 .base = .{ .tag = switch (field_int_signedness) {
4213 .unsigned => .int_unsigned,
4214 .signed => .int_signed,
4215 } },
4216 .data = @intCast(u16, inst_ty.bitSize(target)),
4217 };
4218 const field_int_ty = Type.initPayload(&field_int_pl.base);
4219
4220 const temp_local = try f.allocLocal(field_int_ty, .Const);
4221 try writer.writeAll(" = zig_wrap_");
4222 try f.object.dg.renderTypeForBuiltinFnName(writer, field_int_ty);
4223 try writer.writeAll("((");
4224 try f.renderTypecast(writer, field_int_ty);
4225 try writer.writeAll(")zig_shr_");
4226 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
4227 try writer.writeByte('(');
4228 try f.writeCValue(writer, struct_byval, .Other);
4229 try writer.writeAll(", ");
4230 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
4231 try writer.writeByte(')');
4232 try f.object.dg.renderBuiltinInfo(writer, field_int_ty, .Bits);
4233 try writer.writeAll(");\n");
4234 if (inst_ty.eql(field_int_ty, f.object.dg.module)) return temp_local;
4235
4236 const local = try f.allocLocal(inst_ty, .Mut);
4237 try writer.writeAll(";\n");
4238 try writer.writeAll("memcpy(");
4239 try f.writeCValue(writer, .{ .local_ref = local.local }, .FunctionArgument);
4240 try writer.writeAll(", ");
4241 try f.writeCValue(writer, .{ .local_ref = temp_local.local }, .FunctionArgument);
4242 try writer.writeAll(", sizeof(");
4243 try f.renderTypecast(writer, inst_ty);
4244 try writer.writeAll("));\n");
4245 return local;
4246 },
4247 },
34644248 .@"union", .union_safety_tagged, .union_tagged => struct_ty.unionFields().keys()[extra.field_index],
3465 .tuple, .anon_struct => blk: {
4249 .tuple, .anon_struct => |tag| blk: {
34664250 const tuple = struct_ty.tupleFields();
34674251 if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;
34684252
3469 try buf.writer().print("field_{d}", .{extra.field_index});
3470 break :blk buf.items;
4253 if (tag == .anon_struct) break :blk struct_ty.structFieldName(extra.field_index);
4254
4255 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{extra.field_index});
4256 break :blk field_name_buf;
34714257 },
34724258 else => unreachable,
34734259 };
34744260 const payload = if (struct_ty.tag() == .union_tagged or struct_ty.tag() == .union_safety_tagged) "payload." else "";
34754261
3476 const inst_ty = f.air.typeOfIndex(inst);
3477 const local = try f.allocLocal(inst_ty, .Const);
3478 try writer.writeAll(" = ");
3479 try f.writeCValue(writer, struct_byval);
3480 try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
4262 const is_array = lowersToArray(inst_ty, target);
4263 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4264 if (is_array) {
4265 try writer.writeAll(";\n");
4266 try writer.writeAll("memcpy(");
4267 try f.writeCValue(writer, local, .FunctionArgument);
4268 try writer.writeAll(", ");
4269 try f.writeCValue(writer, struct_byval, .Other);
4270 try writer.print(".{s}{ }, sizeof(", .{ payload, fmtIdent(field_name) });
4271 try f.renderTypecast(writer, inst_ty);
4272 try writer.writeAll("));\n");
4273 } else {
4274 try writer.writeAll(" = ");
4275 try f.writeCValue(writer, struct_byval, .Other);
4276 try writer.print(".{s}{ };\n", .{ payload, fmtIdent(field_name) });
4277 }
34814278 return local;
34824279}
34834280
34844281/// *(E!T) -> E
34854282/// Note that the result is never a pointer.
34864283fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
3487 if (f.liveness.isUnused(inst))
3488 return CValue.none;
4284 if (f.liveness.isUnused(inst)) return CValue.none;
34894285
34904286 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
34914287 const inst_ty = f.air.typeOfIndex(inst);
3492 const writer = f.object.writer();
34934288 const operand = try f.resolveInst(ty_op.operand);
34944289 const operand_ty = f.air.typeOf(ty_op.operand);
34954290
3496 if (operand_ty.zigTypeTag() == .Pointer) {
3497 const err_union_ty = operand_ty.childType();
3498 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
3499 return CValue{ .bytes = "0" };
3500 }
3501 if (!err_union_ty.errorUnionPayload().hasRuntimeBits()) {
3502 return operand;
3503 }
3504 const local = try f.allocLocal(inst_ty, .Const);
3505 try writer.writeAll(" = *");
3506 try f.writeCValue(writer, operand);
3507 try writer.writeAll(";\n");
3508 return local;
3509 }
3510 if (operand_ty.errorUnionSet().errorSetIsEmpty()) {
3511 return CValue{ .bytes = "0" };
3512 }
3513 if (!operand_ty.errorUnionPayload().hasRuntimeBits()) {
3514 return operand;
3515 }
4291 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
4292 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
4293 const error_ty = error_union_ty.errorUnionSet();
4294 const payload_ty = error_union_ty.errorUnionPayload();
4295 if (!payload_ty.hasRuntimeBits()) return operand;
35164296
4297 const writer = f.object.writer();
35174298 const local = try f.allocLocal(inst_ty, .Const);
35184299 try writer.writeAll(" = ");
3519 if (operand_ty.zigTypeTag() == .Pointer) {
3520 try f.writeCValueDeref(writer, operand);
3521 } else {
3522 try f.writeCValue(writer, operand);
3523 }
3524 try writer.writeAll(".error;\n");
4300 if (!error_ty.errorSetIsEmpty())
4301 if (operand_is_ptr)
4302 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
4303 else
4304 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
4305 else
4306 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
4307 try writer.writeAll(";\n");
35254308 return local;
35264309}
35274310
3528fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, maybe_addrof: [*:0]const u8) !CValue {
4311fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
35294312 if (f.liveness.isUnused(inst))
35304313 return CValue.none;
35314314
35324315 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3533 const writer = f.object.writer();
4316 const inst_ty = f.air.typeOfIndex(inst);
35344317 const operand = try f.resolveInst(ty_op.operand);
35354318 const operand_ty = f.air.typeOf(ty_op.operand);
35364319 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
35374320 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
35384321
3539 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {
3540 return CValue.none;
3541 }
3542
3543 const inst_ty = f.air.typeOfIndex(inst);
3544 const maybe_deref = if (operand_is_ptr) "->" else ".";
4322 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) return CValue.none;
35454323
4324 const writer = f.object.writer();
35464325 const local = try f.allocLocal(inst_ty, .Const);
3547 try writer.print(" = {s}(", .{maybe_addrof});
3548 try f.writeCValue(writer, operand);
3549
3550 try writer.print("){s}payload;\n", .{maybe_deref});
4326 try writer.writeAll(" = ");
4327 if (is_ptr) try writer.writeByte('&');
4328 if (operand_is_ptr)
4329 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "payload" })
4330 else
4331 try f.writeCValueMember(writer, operand, .{ .identifier = "payload" });
4332 try writer.writeAll(";\n");
35514333 return local;
35524334}
35534335
......@@ -3566,9 +4348,11 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
35664348
35674349 // .wrap_optional is used to convert non-optionals into optionals so it can never be null.
35684350 const local = try f.allocLocal(inst_ty, .Const);
3569 try writer.writeAll(" = { .is_null = false, .payload =");
3570 try f.writeCValue(writer, operand);
3571 try writer.writeAll("};\n");
4351 try writer.writeAll(" = { .payload = ");
4352 try f.writeCValue(writer, operand, .Initializer);
4353 try writer.writeAll(", .is_null = ");
4354 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
4355 try writer.writeAll(" };\n");
35724356 return local;
35734357}
35744358
......@@ -3578,15 +4362,15 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
35784362 const writer = f.object.writer();
35794363 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
35804364 const operand = try f.resolveInst(ty_op.operand);
3581 const err_un_ty = f.air.typeOfIndex(inst);
3582 const payload_ty = err_un_ty.errorUnionPayload();
3583 if (!payload_ty.hasRuntimeBits()) {
3584 return operand;
3585 }
4365 const error_union_ty = f.air.typeOfIndex(inst);
4366 const payload_ty = error_union_ty.errorUnionPayload();
4367 if (!payload_ty.hasRuntimeBits()) return operand;
35864368
3587 const local = try f.allocLocal(err_un_ty, .Const);
3588 try writer.writeAll(" = { .error = ");
3589 try f.writeCValue(writer, operand);
4369 const local = try f.allocLocal(error_union_ty, .Const);
4370 try writer.writeAll(" = { .payload = ");
4371 try f.writeCValue(writer, .{ .undef = payload_ty }, .Initializer);
4372 try writer.writeAll(", .error = ");
4373 try f.writeCValue(writer, operand, .Initializer);
35904374 try writer.writeAll(" };\n");
35914375 return local;
35924376}
......@@ -3648,19 +4432,31 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
36484432 const operand = try f.resolveInst(ty_op.operand);
36494433
36504434 const inst_ty = f.air.typeOfIndex(inst);
3651 const local = try f.allocLocal(inst_ty, .Const);
3652 try writer.writeAll(" = { .error = 0, .payload = ");
3653 try f.writeCValue(writer, operand);
4435 const payload_ty = inst_ty.errorUnionPayload();
4436 const error_ty = inst_ty.errorUnionSet();
4437 const target = f.object.dg.module.getTarget();
4438 const is_array = lowersToArray(payload_ty, target);
4439 const local = try f.allocLocal(inst_ty, if (is_array) .Mut else .Const);
4440 try writer.writeAll(" = { .payload = ");
4441 try f.writeCValue(writer, if (is_array) CValue{ .undef = payload_ty } else operand, .Initializer);
4442 try writer.writeAll(", .error = ");
4443 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
36544444 try writer.writeAll(" };\n");
4445
4446 if (is_array) {
4447 try writer.writeAll("memcpy(");
4448 try f.writeCValue(writer, local, .Other);
4449 try writer.writeAll(".payload, ");
4450 try f.writeCValue(writer, operand, .FunctionArgument);
4451 try writer.writeAll(", sizeof(");
4452 try f.renderTypecast(writer, payload_ty);
4453 try writer.writeAll("));\n");
4454 }
4455
36554456 return local;
36564457}
36574458
3658fn airIsErr(
3659 f: *Function,
3660 inst: Air.Inst.Index,
3661 is_ptr: bool,
3662 op_str: [*:0]const u8,
3663) !CValue {
4459fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {
36644460 if (f.liveness.isUnused(inst))
36654461 return CValue.none;
36664462
......@@ -3675,19 +4471,21 @@ fn airIsErr(
36754471
36764472 try writer.writeAll(" = ");
36774473
3678 if (error_ty.errorSetIsEmpty()) {
3679 try writer.print("0 {s} 0;\n", .{op_str});
3680 } else {
3681 if (is_ptr) {
3682 try f.writeCValueDeref(writer, operand);
3683 } else {
3684 try f.writeCValue(writer, operand);
3685 }
3686 if (payload_ty.hasRuntimeBits()) {
3687 try writer.writeAll(".error");
3688 }
3689 try writer.print(" {s} 0;\n", .{op_str});
3690 }
4474 if (!error_ty.errorSetIsEmpty())
4475 if (payload_ty.hasRuntimeBits())
4476 if (is_ptr)
4477 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
4478 else
4479 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
4480 else
4481 try f.writeCValue(writer, operand, .Other)
4482 else
4483 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
4484 try writer.writeByte(' ');
4485 try writer.writeAll(operator);
4486 try writer.writeByte(' ');
4487 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
4488 try writer.writeAll(";\n");
36914489 return local;
36924490}
36934491
......@@ -3703,16 +4501,20 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
37034501 const array_len = f.air.typeOf(ty_op.operand).elemType().arrayLen();
37044502
37054503 try writer.writeAll(" = { .ptr = ");
3706 if (operand == .undefined_ptr) {
4504 if (operand == .undef) {
37074505 // Unfortunately, C does not support any equivalent to
37084506 // &(*(void *)p)[0], although LLVM does via GetElementPtr
3709 try f.writeCValue(writer, CValue.undefined_ptr);
4507 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4508 try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer);
37104509 } else {
37114510 try writer.writeAll("&(");
37124511 try f.writeCValueDeref(writer, operand);
3713 try writer.writeAll(")[0]");
4512 try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
37144513 }
3715 try writer.print(", .len = {d} }};\n", .{array_len});
4514
4515 var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len };
4516 const len_val = Value.initPayload(&len_pl.base);
4517 try writer.print(", .len = {} }};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
37164518 return local;
37174519}
37184520
......@@ -3728,7 +4530,7 @@ fn airSimpleCast(f: *Function, inst: Air.Inst.Index) !CValue {
37284530 const operand = try f.resolveInst(ty_op.operand);
37294531
37304532 try writer.writeAll(" = ");
3731 try f.writeCValue(writer, operand);
4533 try f.writeCValue(writer, operand, .Other);
37324534 try writer.writeAll(";\n");
37334535 return local;
37344536}
......@@ -3744,61 +4546,80 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
37444546
37454547 try writer.writeAll(" = (");
37464548 try f.renderTypecast(writer, inst_ty);
3747 try writer.writeAll(")");
3748 try f.writeCValue(writer, operand);
4549 try writer.writeByte(')');
4550 try f.writeCValue(writer, operand, .Other);
37494551 try writer.writeAll(";\n");
37504552 return local;
37514553}
37524554
3753fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
4555fn airUnBuiltinCall(
4556 f: *Function,
4557 inst: Air.Inst.Index,
4558 operation: []const u8,
4559 info: BuiltinInfo,
4560) !CValue {
37544561 if (f.liveness.isUnused(inst)) return CValue.none;
37554562
37564563 const inst_ty = f.air.typeOfIndex(inst);
3757 const local = try f.allocLocal(inst_ty, .Const);
37584564 const operand = f.air.instructions.items(.data)[inst].ty_op.operand;
37594565 const operand_ty = f.air.typeOf(operand);
3760 const target = f.object.dg.module.getTarget();
3761 const writer = f.object.writer();
3762
3763 const int_info = operand_ty.intInfo(target);
3764 const c_bits = toCIntBits(int_info.bits) orelse
3765 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
37664566
3767 try writer.print(" = zig_{s}_", .{fn_name});
3768 try writer.print("{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
3769 try f.writeCValue(writer, try f.resolveInst(operand));
3770 try writer.print(", {d});\n", .{int_info.bits});
4567 const local = try f.allocLocal(inst_ty, .Const);
4568 const writer = f.object.writer();
4569 try writer.writeAll(" = zig_");
4570 try writer.writeAll(operation);
4571 try writer.writeByte('_');
4572 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
4573 try writer.writeByte('(');
4574 try f.writeCValue(writer, try f.resolveInst(operand), .FunctionArgument);
4575 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
4576 try writer.writeAll(");\n");
37714577 return local;
37724578}
37734579
3774fn airBinOpBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
4580fn airBinBuiltinCall(
4581 f: *Function,
4582 inst: Air.Inst.Index,
4583 operation: []const u8,
4584 info: BuiltinInfo,
4585) !CValue {
37754586 if (f.liveness.isUnused(inst)) return CValue.none;
37764587
37774588 const inst_ty = f.air.typeOfIndex(inst);
3778 const local = try f.allocLocal(inst_ty, .Const);
37794589 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3780 const lhs_ty = f.air.typeOf(bin_op.lhs);
3781 const target = f.object.dg.module.getTarget();
4590 const operand_ty = f.air.typeOf(bin_op.lhs);
4591
4592 const local = try f.allocLocal(inst_ty, .Const);
37824593 const writer = f.object.writer();
4594 try writer.writeAll(" = zig_");
4595 try writer.writeAll(operation);
4596 try writer.writeByte('_');
4597 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
4598 try writer.writeByte('(');
4599 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
4600 try writer.writeAll(", ");
4601 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
4602 try f.object.dg.renderBuiltinInfo(writer, operand_ty, info);
4603 try writer.writeAll(");\n");
4604 return local;
4605}
37834606
3784 // For binary operations @TypeOf(lhs)==@TypeOf(rhs), so we only check one.
3785 if (lhs_ty.isInt()) {
3786 const int_info = lhs_ty.intInfo(target);
3787 const c_bits = toCIntBits(int_info.bits) orelse
3788 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3789 try writer.print(" = zig_{s}_{c}{d}", .{ fn_name, signAbbrev(int_info.signedness), c_bits });
3790 } else if (lhs_ty.isRuntimeFloat()) {
3791 const c_bits = lhs_ty.floatBits(target);
3792 try writer.print(" = zig_{s}_f{d}", .{ fn_name, c_bits });
3793 } else {
3794 return f.fail("TODO: C backend: implement airBinOpBuiltinCall for type {s}", .{@tagName(lhs_ty.tag())});
3795 }
4607fn airCmpBuiltinCall(f: *Function, inst: Air.Inst.Index, operator: []const u8) !CValue {
4608 if (f.liveness.isUnused(inst)) return CValue.none;
37964609
4610 const inst_ty = f.air.typeOfIndex(inst);
4611 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4612 const operand_ty = f.air.typeOf(bin_op.lhs);
4613
4614 const local = try f.allocLocal(inst_ty, .Const);
4615 const writer = f.object.writer();
4616 try writer.writeAll(" = zig_cmp_");
4617 try f.object.dg.renderTypeForBuiltinFnName(writer, operand_ty);
37974618 try writer.writeByte('(');
3798 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs));
4619 try f.writeCValue(writer, try f.resolveInst(bin_op.lhs), .FunctionArgument);
37994620 try writer.writeAll(", ");
3800 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs));
3801 try writer.writeAll(");\n");
4621 try f.writeCValue(writer, try f.resolveInst(bin_op.rhs), .FunctionArgument);
4622 try writer.print(") {s} {};\n", .{ operator, try f.fmtIntLiteral(Type.initTag(.i8), Value.zero) });
38024623 return local;
38034624}
38044625
......@@ -3806,23 +4627,58 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
38064627 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
38074628 const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
38084629 const inst_ty = f.air.typeOfIndex(inst);
4630 const is_struct = !inst_ty.isPtrLikeOptional();
4631 const ptr_ty = f.air.typeOf(extra.ptr);
38094632 const ptr = try f.resolveInst(extra.ptr);
38104633 const expected_value = try f.resolveInst(extra.expected_value);
38114634 const new_value = try f.resolveInst(extra.new_value);
3812 const local = try f.allocLocal(inst_ty, .Const);
38134635 const writer = f.object.writer();
38144636
3815 try writer.print(" = zig_cmpxchg_{s}(", .{flavor});
3816 try f.writeCValue(writer, ptr);
4637 const local = try f.allocLocal(inst_ty, .Mut);
4638 try writer.writeAll(" = ");
4639 if (is_struct) try writer.writeAll("{ .payload = ");
4640 try f.writeCValue(writer, expected_value, .Initializer);
4641 if (is_struct) {
4642 try writer.writeAll(", .is_null = ");
4643 try f.object.dg.renderValue(writer, Type.bool, Value.@"false", .Initializer);
4644 try writer.writeAll(" }");
4645 }
4646 try writer.writeAll(";\n");
4647
4648 if (is_struct) {
4649 try f.writeCValue(writer, local, .Other);
4650 try writer.writeAll(".is_null = ");
4651 } else {
4652 try writer.writeAll("if (");
4653 }
4654 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
4655 try f.renderTypecast(writer, ptr_ty.elemType());
4656 try writer.writeByte(')');
4657 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
4658 try writer.writeAll(" *)");
4659 try f.writeCValue(writer, ptr, .Other);
38174660 try writer.writeAll(", ");
3818 try f.writeCValue(writer, expected_value);
4661 if (is_struct)
4662 try f.writeCValueMember(writer, local, .{ .identifier = "payload" })
4663 else
4664 try f.writeCValue(writer, local, .FunctionArgument);
38194665 try writer.writeAll(", ");
3820 try f.writeCValue(writer, new_value);
4666 try f.writeCValue(writer, new_value, .FunctionArgument);
38214667 try writer.writeAll(", ");
38224668 try writeMemoryOrder(writer, extra.successOrder());
38234669 try writer.writeAll(", ");
38244670 try writeMemoryOrder(writer, extra.failureOrder());
3825 try writer.writeAll(");\n");
4671 try writer.writeByte(')');
4672 if (is_struct) {
4673 try writer.writeAll(";\n");
4674 } else {
4675 try writer.writeAll(") {\n");
4676 f.object.indent_writer.pushIndent();
4677 try f.writeCValue(writer, local, .Other);
4678 try writer.writeAll(" = NULL;\n");
4679 f.object.indent_writer.popIndent();
4680 try writer.writeAll("}\n");
4681 }
38264682
38274683 return local;
38284684}
......@@ -3831,15 +4687,29 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
38314687 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
38324688 const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data;
38334689 const inst_ty = f.air.typeOfIndex(inst);
4690 const ptr_ty = f.air.typeOf(pl_op.operand);
38344691 const ptr = try f.resolveInst(pl_op.operand);
38354692 const operand = try f.resolveInst(extra.operand);
38364693 const local = try f.allocLocal(inst_ty, .Const);
38374694 const writer = f.object.writer();
38384695
3839 try writer.print(" = zig_atomicrmw_{s}(", .{toAtomicRmwSuffix(extra.op())});
3840 try f.writeCValue(writer, ptr);
4696 try writer.print(" = zig_atomicrmw_{s}((", .{toAtomicRmwSuffix(extra.op())});
4697 switch (extra.op()) {
4698 else => {
4699 try writer.writeAll("zig_atomic(");
4700 try f.renderTypecast(writer, ptr_ty.elemType());
4701 try writer.writeByte(')');
4702 },
4703 .Nand, .Min, .Max => {
4704 // These are missing from stdatomic.h, so no atomic types for now.
4705 try f.renderTypecast(writer, ptr_ty.elemType());
4706 },
4707 }
4708 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
4709 try writer.writeAll(" *)");
4710 try f.writeCValue(writer, ptr, .Other);
38414711 try writer.writeAll(", ");
3842 try f.writeCValue(writer, operand);
4712 try f.writeCValue(writer, operand, .FunctionArgument);
38434713 try writer.writeAll(", ");
38444714 try writeMemoryOrder(writer, extra.ordering());
38454715 try writer.writeAll(");\n");
......@@ -3858,8 +4728,12 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
38584728 const local = try f.allocLocal(inst_ty, .Const);
38594729 const writer = f.object.writer();
38604730
3861 try writer.writeAll(" = zig_atomic_load(");
3862 try f.writeCValue(writer, ptr);
4731 try writer.writeAll(" = zig_atomic_load((zig_atomic(");
4732 try f.renderTypecast(writer, ptr_ty.elemType());
4733 try writer.writeByte(')');
4734 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
4735 try writer.writeAll(" *)");
4736 try f.writeCValue(writer, ptr, .Other);
38634737 try writer.writeAll(", ");
38644738 try writeMemoryOrder(writer, atomic_load.order);
38654739 try writer.writeAll(");\n");
......@@ -3869,19 +4743,22 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
38694743
38704744fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue {
38714745 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
4746 const ptr_ty = f.air.typeOf(bin_op.lhs);
38724747 const ptr = try f.resolveInst(bin_op.lhs);
38734748 const element = try f.resolveInst(bin_op.rhs);
3874 const inst_ty = f.air.typeOfIndex(inst);
3875 const local = try f.allocLocal(inst_ty, .Const);
38764749 const writer = f.object.writer();
38774750
3878 try writer.writeAll(" = zig_atomic_store(");
3879 try f.writeCValue(writer, ptr);
4751 try writer.writeAll("zig_atomic_store((zig_atomic(");
4752 try f.renderTypecast(writer, ptr_ty.elemType());
4753 try writer.writeByte(')');
4754 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
4755 try writer.writeAll(" *)");
4756 try f.writeCValue(writer, ptr, .Other);
38804757 try writer.writeAll(", ");
3881 try f.writeCValue(writer, element);
4758 try f.writeCValue(writer, element, .FunctionArgument);
38824759 try writer.print(", {s});\n", .{order});
38834760
3884 return local;
4761 return CValue.none;
38854762}
38864763
38874764fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -3893,11 +4770,11 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {
38934770 const writer = f.object.writer();
38944771
38954772 try writer.writeAll("memset(");
3896 try f.writeCValue(writer, dest_ptr);
4773 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
38974774 try writer.writeAll(", ");
3898 try f.writeCValue(writer, value);
4775 try f.writeCValue(writer, value, .FunctionArgument);
38994776 try writer.writeAll(", ");
3900 try f.writeCValue(writer, len);
4777 try f.writeCValue(writer, len, .FunctionArgument);
39014778 try writer.writeAll(");\n");
39024779
39034780 return CValue.none;
......@@ -3912,11 +4789,11 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
39124789 const writer = f.object.writer();
39134790
39144791 try writer.writeAll("memcpy(");
3915 try f.writeCValue(writer, dest_ptr);
4792 try f.writeCValue(writer, dest_ptr, .FunctionArgument);
39164793 try writer.writeAll(", ");
3917 try f.writeCValue(writer, src_ptr);
4794 try f.writeCValue(writer, src_ptr, .FunctionArgument);
39184795 try writer.writeAll(", ");
3919 try f.writeCValue(writer, len);
4796 try f.writeCValue(writer, len, .FunctionArgument);
39204797 try writer.writeAll(");\n");
39214798
39224799 return CValue.none;
......@@ -3933,9 +4810,10 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
39334810 const layout = union_ty.unionGetLayout(target);
39344811 if (layout.tag_size == 0) return CValue.none;
39354812
3936 try f.writeCValue(writer, union_ptr);
3937 try writer.writeAll("->tag = ");
3938 try f.writeCValue(writer, new_tag);
4813 try writer.writeByte('(');
4814 try f.writeCValue(writer, union_ptr, .Other);
4815 try writer.writeAll(")->tag = ");
4816 try f.writeCValue(writer, new_tag, .Other);
39394817 try writer.writeAll(";\n");
39404818
39414819 return CValue.none;
......@@ -3957,7 +4835,7 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
39574835 if (layout.tag_size == 0) return CValue.none;
39584836
39594837 try writer.writeAll(" = ");
3960 try f.writeCValue(writer, operand);
4838 try f.writeCValue(writer, operand, .Other);
39614839 try writer.writeAll(".tag;\n");
39624840 return local;
39634841}
......@@ -3966,18 +4844,17 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
39664844 if (f.liveness.isUnused(inst)) return CValue.none;
39674845
39684846 const un_op = f.air.instructions.items(.data)[inst].un_op;
3969 const writer = f.object.writer();
39704847 const inst_ty = f.air.typeOfIndex(inst);
4848 const enum_ty = f.air.typeOf(un_op);
39714849 const operand = try f.resolveInst(un_op);
3972 const local = try f.allocLocal(inst_ty, .Const);
39734850
3974 try writer.writeAll(" = ");
4851 const writer = f.object.writer();
4852 const local = try f.allocLocal(inst_ty, .Const);
4853 try writer.print(" = {s}(", .{try f.object.dg.getTagNameFn(enum_ty)});
4854 try f.writeCValue(writer, operand, .Other);
4855 try writer.writeAll(");\n");
39754856
3976 _ = operand;
3977 _ = local;
3978 return f.fail("TODO: C backend: implement airTagName", .{});
3979 //try writer.writeAll(";\n");
3980 //return local;
4857 return local;
39814858}
39824859
39834860fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -3989,11 +4866,10 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
39894866 const operand = try f.resolveInst(un_op);
39904867 const local = try f.allocLocal(inst_ty, .Const);
39914868
3992 try writer.writeAll(" = ");
3993
3994 _ = operand;
3995 _ = local;
3996 return f.fail("TODO: C backend: implement airErrorName", .{});
4869 try writer.writeAll(" = zig_errorName[");
4870 try f.writeCValue(writer, operand, .Other);
4871 try writer.writeAll("];\n");
4872 return local;
39974873}
39984874
39994875fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -4061,29 +4937,131 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
40614937
40624938 const inst_ty = f.air.typeOfIndex(inst);
40634939 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4064 const vector_ty = f.air.getRefType(ty_pl.ty);
4065 const len = vector_ty.vectorLen();
4940 const len = @intCast(usize, inst_ty.arrayLen());
40664941 const elements = @ptrCast([]const Air.Inst.Ref, f.air.extra[ty_pl.payload..][0..len]);
4942 const target = f.object.dg.module.getTarget();
4943 const mutability: Mutability = for (elements) |element| {
4944 if (lowersToArray(f.air.typeOf(element), target)) break .Mut;
4945 } else .Const;
40674946
40684947 const writer = f.object.writer();
4069 const local = try f.allocLocal(inst_ty, .Const);
4070 try writer.writeAll(" = {");
4071 switch (vector_ty.zigTypeTag()) {
4072 .Struct => {
4073 const tuple = vector_ty.tupleFields();
4074 var i: usize = 0;
4075 for (elements) |elem, elem_index| {
4076 if (tuple.values[elem_index].tag() != .unreachable_value) continue;
4077
4078 const value = try f.resolveInst(elem);
4079 if (i != 0) try writer.writeAll(", ");
4080 try f.writeCValue(writer, value);
4081 i += 1;
4948 const local = try f.allocLocal(inst_ty, mutability);
4949 try writer.writeAll(" = ");
4950 switch (inst_ty.zigTypeTag()) {
4951 .Array => {
4952 const elem_ty = inst_ty.childType();
4953 try writer.writeByte('{');
4954 var empty = true;
4955 for (elements) |element| {
4956 if (!empty) try writer.writeAll(", ");
4957 try f.writeCValue(writer, try f.resolveInst(element), .Initializer);
4958 empty = false;
4959 }
4960 if (inst_ty.sentinel()) |sentinel| {
4961 if (!empty) try writer.writeAll(", ");
4962 try f.object.dg.renderValue(writer, elem_ty, sentinel, .Initializer);
4963 empty = false;
40824964 }
4965 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});
4966 try writer.writeAll("};\n");
4967 },
4968 .Struct => switch (inst_ty.containerLayout()) {
4969 .Auto, .Extern => {
4970 try writer.writeByte('{');
4971 var empty = true;
4972 for (elements) |element, index| {
4973 if (inst_ty.structFieldValueComptime(index)) |_| continue;
4974
4975 if (!empty) try writer.writeAll(", ");
4976 if (!inst_ty.isTupleOrAnonStruct()) {
4977 try writer.print(".{ } = ", .{fmtIdent(inst_ty.structFieldName(index))});
4978 }
4979
4980 const element_ty = f.air.typeOf(element);
4981 try f.writeCValue(writer, switch (element_ty.zigTypeTag()) {
4982 .Array => CValue{ .undef = element_ty },
4983 else => try f.resolveInst(element),
4984 }, .Initializer);
4985 empty = false;
4986 }
4987 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});
4988 try writer.writeAll("};\n");
4989
4990 for (elements) |element, index| {
4991 if (inst_ty.structFieldValueComptime(index)) |_| continue;
4992
4993 const element_ty = f.air.typeOf(element);
4994 if (element_ty.zigTypeTag() != .Array) continue;
4995
4996 var field_name_buf: []u8 = &.{};
4997 defer f.object.dg.gpa.free(field_name_buf);
4998 const field_name = if (inst_ty.isTuple()) field_name: {
4999 field_name_buf = try std.fmt.allocPrint(f.object.dg.gpa, "field_{d}", .{index});
5000 break :field_name field_name_buf;
5001 } else inst_ty.structFieldName(index);
5002
5003 try writer.writeAll(";\n");
5004 try writer.writeAll("memcpy(");
5005 try f.writeCValue(writer, local, .Other);
5006 try writer.print(".{ }, ", .{fmtIdent(field_name)});
5007 try f.writeCValue(writer, try f.resolveInst(element), .FunctionArgument);
5008 try writer.writeAll(", sizeof(");
5009 try f.renderTypecast(writer, element_ty);
5010 try writer.writeAll("));\n");
5011 }
5012 },
5013 .Packed => {
5014 const int_info = inst_ty.intInfo(target);
5015
5016 var bit_offset_ty_pl = Type.Payload.Bits{
5017 .base = .{ .tag = .int_unsigned },
5018 .data = Type.smallestUnsignedBits(int_info.bits - 1),
5019 };
5020 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
5021
5022 var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 };
5023 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
5024
5025 var empty = true;
5026 for (elements) |_, index| {
5027 const field_ty = inst_ty.structFieldType(index);
5028 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
5029
5030 if (!empty) {
5031 try writer.writeAll("zig_or_");
5032 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5033 try writer.writeByte('(');
5034 }
5035 empty = false;
5036 }
5037 empty = true;
5038 for (elements) |element, index| {
5039 const field_ty = inst_ty.structFieldType(index);
5040 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
5041
5042 if (!empty) try writer.writeAll(", ");
5043 try writer.writeAll("zig_shlw_");
5044 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5045 try writer.writeAll("((");
5046 try f.renderTypecast(writer, inst_ty);
5047 try writer.writeByte(')');
5048 try f.writeCValue(writer, try f.resolveInst(element), .Other);
5049 try writer.writeAll(", ");
5050 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
5051 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .Bits);
5052 try writer.writeByte(')');
5053 if (!empty) try writer.writeByte(')');
5054
5055 bit_offset_val_pl.data += field_ty.bitSize(target);
5056 empty = false;
5057 }
5058 if (empty) try f.writeCValue(writer, .{ .undef = inst_ty }, .Initializer);
5059 try writer.writeAll(";\n");
5060 },
40835061 },
4084 else => |tag| return f.fail("TODO: C backend: implement airAggregateInit for type {s}", .{@tagName(tag)}),
5062 .Vector => return f.fail("TODO: C backend: implement airAggregateInit for vectors", .{}),
5063 else => unreachable,
40855064 }
4086 try writer.writeAll("};\n");
40875065
40885066 return local;
40895067}
......@@ -4091,16 +5069,43 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
40915069fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
40925070 if (f.liveness.isUnused(inst)) return CValue.none;
40935071
4094 const inst_ty = f.air.typeOfIndex(inst);
40955072 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
5073 const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data;
5074 const union_ty = f.air.typeOfIndex(inst);
5075 const target = f.object.dg.module.getTarget();
5076 const layout = union_ty.unionGetLayout(target);
5077 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
5078 const field_name = union_obj.fields.keys()[extra.field_index];
5079 const payload = try f.resolveInst(extra.init);
40965080
40975081 const writer = f.object.writer();
4098 const local = try f.allocLocal(inst_ty, .Const);
4099 try writer.writeAll(" = ");
5082 const local = try f.allocLocal(union_ty, .Const);
5083 try writer.writeAll(" = {");
5084 if (union_ty.unionTagTypeSafety()) |tag_ty| {
5085 if (layout.tag_size != 0) {
5086 const field_index = tag_ty.enumFieldIndex(field_name).?;
41005087
4101 _ = local;
4102 _ = ty_pl;
4103 return f.fail("TODO: C backend: implement airUnionInit", .{});
5088 var tag_pl: Value.Payload.U32 = .{
5089 .base = .{ .tag = .enum_field_index },
5090 .data = @intCast(u32, field_index),
5091 };
5092 const tag_val = Value.initPayload(&tag_pl.base);
5093
5094 var int_pl: Value.Payload.U64 = undefined;
5095 const int_val = tag_val.enumToInt(tag_ty, &int_pl);
5096
5097 try writer.print(".tag = {}, ", .{try f.fmtIntLiteral(tag_ty, int_val)});
5098 }
5099 try writer.writeAll(".payload = {");
5100 }
5101
5102 try writer.print(".{ } = ", .{fmtIdent(field_name)});
5103 try f.writeCValue(writer, payload, .Initializer);
5104
5105 if (union_ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
5106 try writer.writeAll("};\n");
5107
5108 return local;
41045109}
41055110
41065111fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -4115,7 +5120,7 @@ fn airPrefetch(f: *Function, inst: Air.Inst.Index) !CValue {
41155120 const ptr = try f.resolveInst(prefetch.ptr);
41165121 const writer = f.object.writer();
41175122 try writer.writeAll("zig_prefetch(");
4118 try f.writeCValue(writer, ptr);
5123 try f.writeCValue(writer, ptr, .FunctionArgument);
41195124 try writer.print(", {d}, {d});\n", .{
41205125 @enumToInt(prefetch.rw), prefetch.locality,
41215126 });
......@@ -4147,7 +5152,7 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
41475152
41485153 try writer.writeAll(" = ");
41495154 try writer.print("zig_wasm_memory_grow({d}, ", .{pl_op.payload});
4150 try f.writeCValue(writer, operand);
5155 try f.writeCValue(writer, operand, .FunctionArgument);
41515156 try writer.writeAll(");\n");
41525157 return local;
41535158}
......@@ -4160,12 +5165,49 @@ fn airNeg(f: *Function, inst: Air.Inst.Index) !CValue {
41605165 const inst_ty = f.air.typeOfIndex(inst);
41615166 const operand = try f.resolveInst(un_op);
41625167 const local = try f.allocLocal(inst_ty, .Const);
4163 try writer.writeAll("-");
4164 try f.writeCValue(writer, operand);
5168 try writer.writeAll(" = -");
5169 try f.writeCValue(writer, operand, .Other);
41655170 try writer.writeAll(";\n");
41665171 return local;
41675172}
41685173
5174fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
5175 if (f.liveness.isUnused(inst)) return CValue.none;
5176 const un_op = f.air.instructions.items(.data)[inst].un_op;
5177 const writer = f.object.writer();
5178 const inst_ty = f.air.typeOfIndex(inst);
5179 const operand = try f.resolveInst(un_op);
5180 const local = try f.allocLocal(inst_ty, .Const);
5181 try writer.writeAll(" = zig_builtin_");
5182 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5183 try writer.writeByte('(');
5184 try writer.writeAll(operation);
5185 try writer.writeAll(")(");
5186 try f.writeCValue(writer, operand, .FunctionArgument);
5187 try writer.writeAll(");\n");
5188 return local;
5189}
5190
5191fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
5192 if (f.liveness.isUnused(inst)) return CValue.none;
5193 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
5194 const writer = f.object.writer();
5195 const inst_ty = f.air.typeOfIndex(inst);
5196 const lhs = try f.resolveInst(bin_op.lhs);
5197 const rhs = try f.resolveInst(bin_op.rhs);
5198 const local = try f.allocLocal(inst_ty, .Const);
5199 try writer.writeAll(" = zig_builtin_");
5200 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5201 try writer.writeByte('(');
5202 try writer.writeAll(operation);
5203 try writer.writeAll(")(");
5204 try f.writeCValue(writer, lhs, .FunctionArgument);
5205 try writer.writeAll(", ");
5206 try f.writeCValue(writer, rhs, .FunctionArgument);
5207 try writer.writeAll(");\n");
5208 return local;
5209}
5210
41695211fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
41705212 if (f.liveness.isUnused(inst)) return CValue.none;
41715213 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
......@@ -4175,30 +5217,23 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
41755217 const mulend2 = try f.resolveInst(extra.rhs);
41765218 const addend = try f.resolveInst(pl_op.operand);
41775219 const writer = f.object.writer();
4178 const target = f.object.dg.module.getTarget();
4179 const fn_name = switch (inst_ty.floatBits(target)) {
4180 16, 32 => "fmaf",
4181 64 => "fma",
4182 80 => if (CType.longdouble.sizeInBits(target) == 80) "fmal" else "__fmax",
4183 128 => if (CType.longdouble.sizeInBits(target) == 128) "fmal" else "fmaq",
4184 else => unreachable,
4185 };
41865220 const local = try f.allocLocal(inst_ty, .Const);
4187 try writer.writeAll(" = ");
4188 try writer.print("{s}(", .{fn_name});
4189 try f.writeCValue(writer, mulend1);
5221 try writer.writeAll(" = zig_builtin_");
5222 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
5223 try writer.writeAll("(fma)(");
5224 try f.writeCValue(writer, mulend1, .FunctionArgument);
41905225 try writer.writeAll(", ");
4191 try f.writeCValue(writer, mulend2);
5226 try f.writeCValue(writer, mulend2, .FunctionArgument);
41925227 try writer.writeAll(", ");
4193 try f.writeCValue(writer, addend);
5228 try f.writeCValue(writer, addend, .FunctionArgument);
41945229 try writer.writeAll(");\n");
41955230 return local;
41965231}
41975232
41985233fn toMemoryOrder(order: std.builtin.AtomicOrder) [:0]const u8 {
41995234 return switch (order) {
4200 .Unordered => "memory_order_relaxed",
4201 .Monotonic => "memory_order_consume",
5235 // Note: unordered is actually even less atomic than relaxed
5236 .Unordered, .Monotonic => "memory_order_relaxed",
42025237 .Acquire => "memory_order_acquire",
42035238 .Release => "memory_order_release",
42045239 .AcqRel => "memory_order_acq_rel",
......@@ -4293,61 +5328,250 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {
42935328 };
42945329}
42955330
4296fn intMax(ty: Type, target: std.Target, buf: []u8) []const u8 {
4297 switch (ty.tag()) {
4298 .c_short => return "SHRT_MAX",
4299 .c_ushort => return "USHRT_MAX",
4300 .c_int => return "INT_MAX",
4301 .c_uint => return "UINT_MAX",
4302 .c_long => return "LONG_MAX",
4303 .c_ulong => return "ULONG_MAX",
4304 .c_longlong => return "LLONG_MAX",
4305 .c_ulonglong => return "ULLONG_MAX",
4306 else => {
4307 const int_info = ty.intInfo(target);
4308 const rhs = @intCast(u7, int_info.bits - @boolToInt(int_info.signedness == .signed));
4309 const val = (@as(u128, 1) << rhs) - 1;
4310 // TODO make this integer literal have a suffix if necessary (such as "ull")
4311 return std.fmt.bufPrint(buf, "{}", .{val}) catch |err| switch (err) {
4312 error.NoSpaceLeft => unreachable,
4313 };
5331fn formatStringLiteral(
5332 str: []const u8,
5333 comptime fmt: []const u8,
5334 _: std.fmt.FormatOptions,
5335 writer: anytype,
5336) @TypeOf(writer).Error!void {
5337 if (fmt.len != 1 or fmt[0] != 's') @compileError("Invalid fmt: " ++ fmt);
5338 try writer.writeByte('\"');
5339 for (str) |c| switch (c) {
5340 7 => try writer.writeAll("\\a"),
5341 8 => try writer.writeAll("\\b"),
5342 '\t' => try writer.writeAll("\\t"),
5343 '\n' => try writer.writeAll("\\n"),
5344 11 => try writer.writeAll("\\v"),
5345 12 => try writer.writeAll("\\f"),
5346 '\r' => try writer.writeAll("\\r"),
5347 '"', '\'', '?', '\\' => try writer.print("\\{c}", .{c}),
5348 else => switch (c) {
5349 ' '...'~' => try writer.writeByte(c),
5350 else => try writer.print("\\{o:0>3}", .{c}),
43145351 },
4315 }
5352 };
5353 try writer.writeByte('\"');
5354}
5355fn fmtStringLiteral(str: []const u8) std.fmt.Formatter(formatStringLiteral) {
5356 return .{ .data = str };
43165357}
43175358
4318fn intMin(ty: Type, target: std.Target, buf: []u8) []const u8 {
4319 switch (ty.tag()) {
4320 .c_short => return "SHRT_MIN",
4321 .c_int => return "INT_MIN",
4322 .c_long => return "LONG_MIN",
4323 .c_longlong => return "LLONG_MIN",
4324 else => {
4325 const int_info = ty.intInfo(target);
4326 assert(int_info.signedness == .signed);
4327 const val = v: {
4328 if (int_info.bits == 0) break :v 0;
4329 const rhs = @intCast(u7, (int_info.bits - 1));
4330 break :v -(@as(i128, 1) << rhs);
4331 };
4332 return std.fmt.bufPrint(buf, "{d}", .{val}) catch |err| switch (err) {
4333 error.NoSpaceLeft => unreachable,
4334 };
4335 },
4336 }
5359fn undefPattern(comptime T: type) T {
5360 return (1 << (@bitSizeOf(T) | 1)) / 3;
43375361}
43385362
4339fn loweredFnRetTyHasBits(fn_ty: Type) bool {
4340 const ret_ty = fn_ty.fnReturnType();
4341 if (ret_ty.hasRuntimeBitsIgnoreComptime()) {
4342 return true;
5363const FormatIntLiteralContext = struct {
5364 ty: Type,
5365 val: Value,
5366 mod: *Module,
5367};
5368fn formatIntLiteral(
5369 data: FormatIntLiteralContext,
5370 comptime fmt: []const u8,
5371 options: std.fmt.FormatOptions,
5372 writer: anytype,
5373) @TypeOf(writer).Error!void {
5374 const target = data.mod.getTarget();
5375 const int_info = data.ty.intInfo(target);
5376
5377 const Limb = std.math.big.Limb;
5378 const ExpectedContents = struct {
5379 const base = 10;
5380 const limbs_count_128 = BigInt.calcTwosCompLimbCount(128);
5381 const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base);
5382 const worst_case_int = BigInt.Const{
5383 .limbs = &([1]Limb{std.math.maxInt(Limb)} ** expected_needed_limbs_count),
5384 .positive = false,
5385 };
5386
5387 undef_limbs: [limbs_count_128]Limb,
5388 wrap_limbs: [limbs_count_128]Limb,
5389 };
5390 var stack align(@alignOf(ExpectedContents)) =
5391 std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa);
5392 const allocator = stack.get();
5393
5394 var undef_limbs: []Limb = &.{};
5395 defer allocator.free(undef_limbs);
5396
5397 var int_buf: Value.BigIntSpace = undefined;
5398 const int = if (data.val.isUndefDeep()) blk: {
5399 undef_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(int_info.bits));
5400 std.mem.set(Limb, undef_limbs, undefPattern(Limb));
5401
5402 var undef_int = BigInt.Mutable{
5403 .limbs = undef_limbs,
5404 .len = undef_limbs.len,
5405 .positive = true,
5406 };
5407 undef_int.truncate(undef_int.toConst(), int_info.signedness, int_info.bits);
5408 break :blk undef_int.toConst();
5409 } else data.val.toBigInt(&int_buf, target);
5410 assert(int.fitsInTwosComp(int_info.signedness, int_info.bits));
5411
5412 const c_bits = toCIntBits(int_info.bits) orelse unreachable;
5413 var one_limbs: [BigInt.calcLimbLen(1)]Limb = undefined;
5414 const one = BigInt.Mutable.init(&one_limbs, 1).toConst();
5415
5416 const wrap_limbs = try allocator.alloc(Limb, BigInt.calcTwosCompLimbCount(c_bits));
5417 defer allocator.free(wrap_limbs);
5418 var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined };
5419 if (wrap.addWrap(int, one, int_info.signedness, c_bits) or
5420 int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits))
5421 {
5422 const abbrev = switch (data.ty.tag()) {
5423 .c_short, .c_ushort => "SHRT",
5424 .c_int, .c_uint => "INT",
5425 .c_long, .c_ulong => "LONG",
5426 .c_longlong, .c_ulonglong => "LLONG",
5427 .isize, .usize => "INTPTR",
5428 else => return writer.print("zig_{s}Int_{c}{d}", .{
5429 if (int.positive) "max" else "min", signAbbrev(int_info.signedness), c_bits,
5430 }),
5431 };
5432 if (int_info.signedness == .unsigned) try writer.writeByte('U');
5433 return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" });
43435434 }
4344 if (ret_ty.isError()) {
4345 return true;
5435
5436 if (!int.positive) try writer.writeByte('-');
5437 switch (data.ty.tag()) {
5438 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
5439 else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }),
5440 }
5441
5442 const limbs_count_64 = @divExact(64, @bitSizeOf(Limb));
5443 if (c_bits <= 64) {
5444 var base: u8 = undefined;
5445 var case: std.fmt.Case = undefined;
5446 switch (fmt.len) {
5447 0 => base = 10,
5448 1 => switch (fmt[0]) {
5449 'b' => {
5450 base = 2;
5451 try writer.writeAll("0b");
5452 },
5453 'o' => {
5454 base = 8;
5455 try writer.writeByte('0');
5456 },
5457 'd' => base = 10,
5458 'x' => {
5459 base = 16;
5460 case = .lower;
5461 try writer.writeAll("0x");
5462 },
5463 'X' => {
5464 base = 16;
5465 case = .upper;
5466 try writer.writeAll("0x");
5467 },
5468 else => @compileError("Invalid fmt: " ++ fmt),
5469 },
5470 else => @compileError("Invalid fmt: " ++ fmt),
5471 }
5472
5473 var str: [64]u8 = undefined;
5474 var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]Limb = undefined;
5475 try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]);
5476 } else {
5477 assert(c_bits == 128);
5478 const split = std.math.min(int.limbs.len, limbs_count_64);
5479
5480 var upper_pl = Value.Payload.BigInt{
5481 .base = .{ .tag = .int_big_positive },
5482 .data = int.limbs[split..],
5483 };
5484 const upper_val = Value.initPayload(&upper_pl.base);
5485 try formatIntLiteral(.{
5486 .ty = switch (int_info.signedness) {
5487 .unsigned => Type.u64,
5488 .signed => Type.i64,
5489 },
5490 .val = upper_val,
5491 .mod = data.mod,
5492 }, fmt, options, writer);
5493
5494 try writer.writeAll(", ");
5495
5496 var lower_pl = Value.Payload.BigInt{
5497 .base = .{ .tag = .int_big_positive },
5498 .data = int.limbs[0..split],
5499 };
5500 const lower_val = Value.initPayload(&lower_pl.base);
5501 try formatIntLiteral(.{
5502 .ty = Type.u64,
5503 .val = lower_val,
5504 .mod = data.mod,
5505 }, fmt, options, writer);
5506
5507 return writer.writeByte(')');
5508 }
5509
5510 switch (data.ty.tag()) {
5511 .c_short, .c_ushort, .c_int => {},
5512 .c_uint => try writer.writeAll("u"),
5513 .c_long => try writer.writeAll("l"),
5514 .c_ulong => try writer.writeAll("ul"),
5515 .c_longlong => try writer.writeAll("ll"),
5516 .c_ulonglong => try writer.writeAll("ull"),
5517 else => try writer.writeByte(')'),
43465518 }
4347 return false;
43485519}
43495520
43505521fn isByRef(ty: Type) bool {
43515522 _ = ty;
43525523 return false;
43535524}
5525
5526const LowerFnRetTyBuffer = struct {
5527 const names = [1][]const u8{"array"};
5528 types: [1]Type,
5529 values: [1]Value,
5530 payload: Type.Payload.AnonStruct,
5531};
5532fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {
5533 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);
5534
5535 if (lowersToArray(ret_ty, target)) {
5536 buffer.types = [1]Type{ret_ty};
5537 buffer.values = [1]Value{Value.initTag(.unreachable_value)};
5538 buffer.payload = .{ .data = .{
5539 .names = &LowerFnRetTyBuffer.names,
5540 .types = &buffer.types,
5541 .values = &buffer.values,
5542 } };
5543 return Type.initPayload(&buffer.payload.base);
5544 }
5545
5546 return if (ret_ty.hasRuntimeBitsIgnoreComptime()) ret_ty else Type.void;
5547}
5548
5549fn lowersToArray(ty: Type, target: std.Target) bool {
5550 return switch (ty.zigTypeTag()) {
5551 .Array => return true,
5552 else => return ty.isAbiInt() and toCIntBits(@intCast(u32, ty.bitSize(target))) == null,
5553 };
5554}
5555
5556fn loweredArrayInfo(ty: Type, target: std.Target) ?Type.ArrayInfo {
5557 if (!lowersToArray(ty, target)) return null;
5558
5559 switch (ty.zigTypeTag()) {
5560 .Array => return ty.arrayInfo(),
5561 else => {
5562 const abi_size = ty.abiSize(target);
5563 const abi_align = ty.abiAlignment(target);
5564 return Type.ArrayInfo{
5565 .elem_type = switch (abi_align) {
5566 1 => Type.u8,
5567 2 => Type.u16,
5568 4 => Type.u32,
5569 8 => Type.u64,
5570 16 => Type.initTag(.u128),
5571 else => unreachable,
5572 },
5573 .len = @divExact(abi_size, abi_align),
5574 };
5575 },
5576 }
5577}
src/link/C.zig+114-101
......@@ -108,10 +108,8 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
108108 const typedefs = &gop.value_ptr.typedefs;
109109 const code = &gop.value_ptr.code;
110110 fwd_decl.shrinkRetainingCapacity(0);
111 {
112 for (typedefs.values()) |value| {
113 module.gpa.free(value.rendered);
114 }
111 for (typedefs.values()) |typedef| {
112 module.gpa.free(typedef.rendered);
115113 }
116114 typedefs.clearRetainingCapacity();
117115 code.shrinkRetainingCapacity(0);
......@@ -139,14 +137,14 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
139137
140138 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
141139 defer {
142 function.value_map.deinit();
143140 function.blocks.deinit(module.gpa);
141 function.value_map.deinit();
144142 function.object.code.deinit();
145 function.object.dg.fwd_decl.deinit();
146 for (function.object.dg.typedefs.values()) |value| {
147 module.gpa.free(value.rendered);
143 for (function.object.dg.typedefs.values()) |typedef| {
144 module.gpa.free(typedef.rendered);
148145 }
149146 function.object.dg.typedefs.deinit();
147 function.object.dg.fwd_decl.deinit();
150148 }
151149
152150 codegen.genFunc(&function) catch |err| switch (err) {
......@@ -179,10 +177,8 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
179177 const typedefs = &gop.value_ptr.typedefs;
180178 const code = &gop.value_ptr.code;
181179 fwd_decl.shrinkRetainingCapacity(0);
182 {
183 for (typedefs.values()) |value| {
184 module.gpa.free(value.rendered);
185 }
180 for (typedefs.values()) |value| {
181 module.gpa.free(value.rendered);
186182 }
187183 typedefs.clearRetainingCapacity();
188184 code.shrinkRetainingCapacity(0);
......@@ -206,11 +202,11 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
206202 object.indent_writer = .{ .underlying_writer = object.code.writer() };
207203 defer {
208204 object.code.deinit();
209 object.dg.fwd_decl.deinit();
210 for (object.dg.typedefs.values()) |value| {
211 module.gpa.free(value.rendered);
205 for (object.dg.typedefs.values()) |typedef| {
206 module.gpa.free(typedef.rendered);
212207 }
213208 object.dg.typedefs.deinit();
209 object.dg.fwd_decl.deinit();
214210 }
215211
216212 codegen.genDecl(&object) catch |err| switch (err) {
......@@ -260,30 +256,26 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
260256 var f: Flush = .{};
261257 defer f.deinit(gpa);
262258
263 // Covers zig.h and err_typedef_item.
259 // Covers zig.h, typedef, and asm.
264260 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
265261
266 if (zig_h.len != 0) {
267 f.all_buffers.appendAssumeCapacity(.{
268 .iov_base = zig_h,
269 .iov_len = zig_h.len,
270 });
271 f.file_size += zig_h.len;
272 }
262 f.appendBufAssumeCapacity(zig_h);
273263
274 const err_typedef_writer = f.err_typedef_buf.writer(gpa);
275 const err_typedef_index = f.all_buffers.items.len;
264 const typedef_index = f.all_buffers.items.len;
276265 f.all_buffers.items.len += 1;
277266
278 render_errors: {
279 if (module.global_error_set.size == 0) break :render_errors;
280 var it = module.global_error_set.iterator();
281 while (it.next()) |entry| {
282 try err_typedef_writer.print("#define zig_error_{s} {d}\n", .{ entry.key_ptr.*, entry.value_ptr.* });
283 }
284 try err_typedef_writer.writeByte('\n');
267 {
268 var asm_buf = f.asm_buf.toManaged(module.gpa);
269 defer asm_buf.deinit();
270
271 try codegen.genGlobalAsm(module, &asm_buf);
272
273 f.asm_buf = asm_buf.moveToUnmanaged();
274 f.appendBufAssumeCapacity(f.asm_buf.items);
285275 }
286276
277 try self.flushErrDecls(&f);
278
287279 // Typedefs, forward decls, and non-functions first.
288280 // Unlike other backends, the .c code we are emitting is order-dependent. Therefore
289281 // we must traverse the set of Decls that we are emitting according to their dependencies.
......@@ -300,38 +292,19 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
300292
301293 while (f.remaining_decls.popOrNull()) |kv| {
302294 const decl_index = kv.key;
303 try flushDecl(self, &f, decl_index);
295 try self.flushDecl(&f, decl_index);
304296 }
305297
306 if (f.err_typedef_buf.items.len == 0) {
307 f.all_buffers.items[err_typedef_index] = .{
308 .iov_base = "",
309 .iov_len = 0,
310 };
311 } else {
312 f.all_buffers.items[err_typedef_index] = .{
313 .iov_base = f.err_typedef_buf.items.ptr,
314 .iov_len = f.err_typedef_buf.items.len,
315 };
316 f.file_size += f.err_typedef_buf.items.len;
317 }
298 f.all_buffers.items[typedef_index] = .{
299 .iov_base = if (f.typedef_buf.items.len > 0) f.typedef_buf.items.ptr else "",
300 .iov_len = f.typedef_buf.items.len,
301 };
302 f.file_size += f.typedef_buf.items.len;
318303
319 // Now the function bodies.
320 try f.all_buffers.ensureUnusedCapacity(gpa, f.fn_count);
321 for (decl_keys) |decl_index, i| {
322 const decl = module.declPtr(decl_index);
323 if (decl.getFunction() != null) {
324 const decl_block = &decl_values[i];
325 const buf = decl_block.code.items;
326 if (buf.len != 0) {
327 f.all_buffers.appendAssumeCapacity(.{
328 .iov_base = buf.ptr,
329 .iov_len = buf.len,
330 });
331 f.file_size += buf.len;
332 }
333 }
334 }
304 // Now the code.
305 try f.all_buffers.ensureUnusedCapacity(gpa, decl_values.len);
306 for (decl_values) |decl|
307 f.appendBufAssumeCapacity(decl.code.items);
335308
336309 const file = self.base.file.?;
337310 try file.setEndPos(f.file_size);
......@@ -339,14 +312,15 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
339312}
340313
341314const Flush = struct {
315 err_decls: DeclBlock = .{},
342316 remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{},
343317 typedefs: Typedefs = .{},
344 err_typedef_buf: std.ArrayListUnmanaged(u8) = .{},
318 typedef_buf: std.ArrayListUnmanaged(u8) = .{},
319 asm_buf: std.ArrayListUnmanaged(u8) = .{},
345320 /// We collect a list of buffers to write, and write them all at once with pwritev 😎
346321 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
347322 /// Keeps track of the total bytes of `all_buffers`.
348323 file_size: u64 = 0,
349 fn_count: usize = 0,
350324
351325 const Typedefs = std.HashMapUnmanaged(
352326 Type,
......@@ -355,11 +329,18 @@ const Flush = struct {
355329 std.hash_map.default_max_load_percentage,
356330 );
357331
332 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {
333 if (buf.len == 0) return;
334 f.all_buffers.appendAssumeCapacity(.{ .iov_base = buf.ptr, .iov_len = buf.len });
335 f.file_size += buf.len;
336 }
337
358338 fn deinit(f: *Flush, gpa: Allocator) void {
359339 f.all_buffers.deinit(gpa);
360 f.err_typedef_buf.deinit(gpa);
340 f.typedef_buf.deinit(gpa);
361341 f.typedefs.deinit(gpa);
362342 f.remaining_decls.deinit(gpa);
343 f.err_decls.deinit(gpa);
363344 }
364345};
365346
......@@ -367,6 +348,72 @@ const FlushDeclError = error{
367348 OutOfMemory,
368349};
369350
351fn flushTypedefs(self: *C, f: *Flush, typedefs: codegen.TypedefMap.Unmanaged) FlushDeclError!void {
352 if (typedefs.count() == 0) return;
353 const gpa = self.base.allocator;
354 const module = self.base.options.module.?;
355
356 try f.typedefs.ensureUnusedCapacityContext(gpa, @intCast(u32, typedefs.count()), .{
357 .mod = module,
358 });
359 var it = typedefs.iterator();
360 while (it.next()) |new| {
361 const gop = f.typedefs.getOrPutAssumeCapacityContext(new.key_ptr.*, .{
362 .mod = module,
363 });
364 if (!gop.found_existing) {
365 try f.typedef_buf.appendSlice(gpa, new.value_ptr.rendered);
366 }
367 }
368}
369
370fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
371 const module = self.base.options.module.?;
372
373 const fwd_decl = &f.err_decls.fwd_decl;
374 const typedefs = &f.err_decls.typedefs;
375 const code = &f.err_decls.code;
376
377 var object = codegen.Object{
378 .dg = .{
379 .gpa = module.gpa,
380 .module = module,
381 .error_msg = null,
382 .decl_index = undefined,
383 .decl = undefined,
384 .fwd_decl = fwd_decl.toManaged(module.gpa),
385 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),
386 .typedefs_arena = self.arena.allocator(),
387 },
388 .code = code.toManaged(module.gpa),
389 .indent_writer = undefined, // set later so we can get a pointer to object.code
390 };
391 object.indent_writer = .{ .underlying_writer = object.code.writer() };
392 defer {
393 object.code.deinit();
394 for (object.dg.typedefs.values()) |typedef| {
395 module.gpa.free(typedef.rendered);
396 }
397 object.dg.typedefs.deinit();
398 object.dg.fwd_decl.deinit();
399 }
400
401 codegen.genErrDecls(&object) catch |err| switch (err) {
402 error.AnalysisFail => unreachable,
403 else => |e| return e,
404 };
405
406 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
407 typedefs.* = object.dg.typedefs.unmanaged;
408 object.dg.typedefs.unmanaged = .{};
409 code.* = object.code.moveToUnmanaged();
410
411 try self.flushTypedefs(f, typedefs.*);
412 try f.all_buffers.ensureUnusedCapacity(self.base.allocator, 1);
413 f.appendBufAssumeCapacity(fwd_decl.items);
414 f.appendBufAssumeCapacity(code.items);
415}
416
370417/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
371418fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!void {
372419 const module = self.base.options.module.?;
......@@ -383,43 +430,9 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
383430 const decl_block = self.decl_table.getPtr(decl_index).?;
384431 const gpa = self.base.allocator;
385432
386 if (decl_block.typedefs.count() != 0) {
387 try f.typedefs.ensureUnusedCapacityContext(gpa, @intCast(u32, decl_block.typedefs.count()), .{
388 .mod = module,
389 });
390 var it = decl_block.typedefs.iterator();
391 while (it.next()) |new| {
392 const gop = f.typedefs.getOrPutAssumeCapacityContext(new.key_ptr.*, .{
393 .mod = module,
394 });
395 if (!gop.found_existing) {
396 try f.err_typedef_buf.appendSlice(gpa, new.value_ptr.rendered);
397 }
398 }
399 }
400
401 if (decl_block.fwd_decl.items.len != 0) {
402 const buf = decl_block.fwd_decl.items;
403 if (buf.len != 0) {
404 try f.all_buffers.append(gpa, .{
405 .iov_base = buf.ptr,
406 .iov_len = buf.len,
407 });
408 f.file_size += buf.len;
409 }
410 }
411 if (decl.getFunction() != null) {
412 f.fn_count += 1;
413 } else if (decl_block.code.items.len != 0) {
414 const buf = decl_block.code.items;
415 if (buf.len != 0) {
416 try f.all_buffers.append(gpa, .{
417 .iov_base = buf.ptr,
418 .iov_len = buf.len,
419 });
420 f.file_size += buf.len;
421 }
422 }
433 try self.flushTypedefs(f, decl_block.typedefs);
434 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
435 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
423436}
424437
425438pub fn flushEmitH(module: *Module) !void {
src/main.zig+4-1
......@@ -3018,7 +3018,10 @@ fn buildOutputType(
30183018 const c_code_path = try fs.path.join(arena, &[_][]const u8{
30193019 c_code_directory.path orelse ".", c_code_loc.basename,
30203020 });
3021 try test_exec_args.appendSlice(&.{ self_exe_path, "run", "-lc", c_code_path });
3021 try test_exec_args.append(self_exe_path);
3022 try test_exec_args.append("run");
3023 if (link_libc) try test_exec_args.append("-lc");
3024 try test_exec_args.append(c_code_path);
30223025 }
30233026
30243027 const run_or_test = switch (arg_mode) {
src/test.zig+1
......@@ -791,6 +791,7 @@ pub const TestContext = struct {
791791 .updates = std.ArrayList(Update).init(ctx.cases.allocator),
792792 .output_mode = .Exe,
793793 .files = std.ArrayList(File).init(ctx.arena),
794 .link_libc = true,
794795 }) catch @panic("out of memory");
795796 return &ctx.cases.items[ctx.cases.items.len - 1];
796797 }
src/type.zig+20-6
......@@ -5282,7 +5282,7 @@ pub const Type = extern union {
52825282 // Works for vectors and vectors of integers.
52835283 pub fn minInt(ty: Type, arena: Allocator, target: Target) !Value {
52845284 const scalar = try minIntScalar(ty.scalarType(), arena, target);
5285 if (ty.zigTypeTag() == .Vector) {
5285 if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) {
52865286 return Value.Tag.repeated.create(arena, scalar);
52875287 } else {
52885288 return scalar;
......@@ -5294,12 +5294,16 @@ pub const Type = extern union {
52945294 assert(ty.zigTypeTag() == .Int);
52955295 const info = ty.intInfo(target);
52965296
5297 if (info.bits == 0) {
5298 return Value.initTag(.the_only_possible_value);
5299 }
5300
52975301 if (info.signedness == .unsigned) {
52985302 return Value.zero;
52995303 }
53005304
5301 if (info.bits <= 6) {
5302 const n: i64 = -(@as(i64, 1) << @truncate(u6, info.bits - 1));
5305 if (std.math.cast(u6, info.bits - 1)) |shift| {
5306 const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
53035307 return Value.Tag.int_i64.create(arena, n);
53045308 }
53055309
......@@ -5319,13 +5323,23 @@ pub const Type = extern union {
53195323 assert(self.zigTypeTag() == .Int);
53205324 const info = self.intInfo(target);
53215325
5322 if (info.bits <= 6) switch (info.signedness) {
5326 if (info.bits == 0) {
5327 return Value.initTag(.the_only_possible_value);
5328 }
5329
5330 switch (info.bits - @boolToInt(info.signedness == .signed)) {
5331 0 => return Value.zero,
5332 1 => return Value.one,
5333 else => {},
5334 }
5335
5336 if (std.math.cast(u6, info.bits - 1)) |shift| switch (info.signedness) {
53235337 .signed => {
5324 const n: i64 = (@as(i64, 1) << @truncate(u6, info.bits - 1)) - 1;
5338 const n = @as(i64, std.math.maxInt(i64)) >> (63 - shift);
53255339 return Value.Tag.int_i64.create(arena, n);
53265340 },
53275341 .unsigned => {
5328 const n: u64 = (@as(u64, 1) << @truncate(u6, info.bits)) - 1;
5342 const n = @as(u64, std.math.maxInt(u64)) >> (63 - shift);
53295343 return Value.Tag.int_u64.create(arena, n);
53305344 },
53315345 };
test/behavior.zig+1-7
......@@ -213,13 +213,7 @@ test {
213213 _ = @import("behavior/export.zig");
214214 }
215215
216 if (builtin.zig_backend != .stage2_arm and
217 builtin.zig_backend != .stage2_x86_64 and
218 builtin.zig_backend != .stage2_aarch64 and
219 builtin.zig_backend != .stage2_wasm and
220 builtin.zig_backend != .stage2_c and
221 builtin.zig_backend != .stage1)
222 {
216 if (builtin.zig_backend != .stage2_wasm) {
223217 _ = @import("behavior/export_self_referential_type_info.zig");
224218 }
225219}
test/behavior/align.zig-12
......@@ -7,8 +7,6 @@ const assert = std.debug.assert;
77var foo: u8 align(4) = 100;
88
99test "global variable alignment" {
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11
1210 comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
1311 comptime try expect(@TypeOf(&foo) == *align(4) u8);
1412 {
......@@ -223,7 +221,6 @@ fn fnWithAlignedStack() i32 {
223221}
224222
225223test "implicitly decreasing slice alignment" {
226 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
227224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
228225
229226 const a: u32 align(4) = 3;
......@@ -235,7 +232,6 @@ fn addUnalignedSlice(a: []align(1) const u32, b: []align(1) const u32) u32 {
235232}
236233
237234test "specifying alignment allows pointer cast" {
238 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
239235 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
240236
241237 try testBytesAlign(0x33);
......@@ -247,7 +243,6 @@ fn testBytesAlign(b: u8) !void {
247243}
248244
249245test "@alignCast slices" {
250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
251246 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
252247 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
253248
......@@ -301,7 +296,6 @@ fn noop4() align(4) void {}
301296
302297test "function alignment" {
303298 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
304 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
305299 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
306300
307301 // function alignment is a compile error on wasm32/wasm64
......@@ -316,7 +310,6 @@ test "function alignment" {
316310
317311test "implicitly decreasing fn alignment" {
318312 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
319 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
320313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
321314 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
322315
......@@ -341,7 +334,6 @@ fn alignedBig() align(16) i32 {
341334test "@alignCast functions" {
342335 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
343336 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
344 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
345337 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
346338
347339 // function alignment is a compile error on wasm32/wasm64
......@@ -401,8 +393,6 @@ test "function callconv expression depends on generic parameter" {
401393}
402394
403395test "runtime-known array index has best alignment possible" {
404 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
405
406396 // take full advantage of over-alignment
407397 var array align(4) = [_]u8{ 1, 2, 3, 4 };
408398 comptime assert(@TypeOf(&array[0]) == *align(4) u8);
......@@ -482,7 +472,6 @@ test "read 128-bit field from default aligned struct in global memory" {
482472}
483473
484474test "struct field explicit alignment" {
485 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
486475 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
487476 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
488477 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -546,7 +535,6 @@ test "comptime alloc alignment" {
546535 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
547536 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
548537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
549 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
550538 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
551539
552540 comptime var bytes1 = [_]u8{0};
test/behavior/alignof.zig-2
......@@ -12,7 +12,6 @@ const Foo = struct {
1212
1313test "@alignOf(T) before referencing T" {
1414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1615 comptime try expect(@alignOf(Foo) != maxInt(usize));
1716 if (native_arch == .x86_64) {
1817 comptime try expect(@alignOf(Foo) == 4);
......@@ -20,7 +19,6 @@ test "@alignOf(T) before referencing T" {
2019}
2120
2221test "comparison of @alignOf(T) against zero" {
23 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2422 {
2523 const T = struct { x: u32 };
2624 try expect(!(@alignOf(T) == 0));
test/behavior/array.zig-6
......@@ -6,8 +6,6 @@ const expect = testing.expect;
66const expectEqual = testing.expectEqual;
77
88test "array to slice" {
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
10
119 const a: u32 align(4) = 3;
1210 const b: u32 align(8) = 4;
1311 const a_slice: []align(1) const u32 = @as(*const [1]u32, &a)[0..];
......@@ -160,7 +158,6 @@ test "nested arrays of strings" {
160158
161159test "nested arrays of integers" {
162160 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
163 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
164161
165162 const array_of_numbers = [_][2]u8{
166163 [2]u8{ 1, 2 },
......@@ -479,7 +476,6 @@ test "sentinel element count towards the ABI size calculation" {
479476
480477test "zero-sized array with recursive type definition" {
481478 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
482 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
483479
484480 const U = struct {
485481 fn foo(comptime T: type, comptime n: usize) type {
......@@ -501,7 +497,6 @@ test "zero-sized array with recursive type definition" {
501497test "type coercion of anon struct literal to array" {
502498 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
503499 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
504 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
505500 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
506501
507502 const S = struct {
......@@ -532,7 +527,6 @@ test "type coercion of anon struct literal to array" {
532527}
533528
534529test "type coercion of pointer to anon struct literal to pointer to array" {
535 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
536530 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
537531 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
538532 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/asm.zig-4
......@@ -18,7 +18,6 @@ comptime {
1818}
1919
2020test "module level assembly" {
21 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2221 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2322 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2423 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -30,7 +29,6 @@ test "module level assembly" {
3029}
3130
3231test "output constraint modifiers" {
33 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3432 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
3533 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3634 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -51,7 +49,6 @@ test "output constraint modifiers" {
5149}
5250
5351test "alternative constraints" {
54 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5552 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
5653 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5754 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -115,7 +112,6 @@ test "sized integer/float in asm input" {
115112}
116113
117114test "struct/array/union types as input values" {
118 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
119115 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
120116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
121117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/atomics.zig-14
......@@ -4,7 +4,6 @@ const expect = std.testing.expect;
44const expectEqual = std.testing.expectEqual;
55
66test "cmpxchg" {
7 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -33,7 +32,6 @@ fn testCmpxchg() !void {
3332}
3433
3534test "fence" {
36 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3735 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
3836 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3937 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -45,7 +43,6 @@ test "fence" {
4543}
4644
4745test "atomicrmw and atomicload" {
48 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4946 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
5047 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -75,7 +72,6 @@ fn testAtomicLoad(ptr: *u8) !void {
7572}
7673
7774test "cmpxchg with ptr" {
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7975 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
8076 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
8177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -102,7 +98,6 @@ test "cmpxchg with ptr" {
10298}
10399
104100test "cmpxchg with ignored result" {
105 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
106101 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
107102 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
108103 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -117,7 +112,6 @@ test "cmpxchg with ignored result" {
117112}
118113
119114test "128-bit cmpxchg" {
120 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
121115 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
122116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
123117 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -151,7 +145,6 @@ fn test_u128_cmpxchg() !void {
151145var a_global_variable = @as(u32, 1234);
152146
153147test "cmpxchg on a global variable" {
154 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
155148 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
156149 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
157150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -170,7 +163,6 @@ test "cmpxchg on a global variable" {
170163}
171164
172165test "atomic load and rmw with enum" {
173 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
174166 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
175167 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
176168 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -189,7 +181,6 @@ test "atomic load and rmw with enum" {
189181}
190182
191183test "atomic store" {
192 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
193184 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
194185 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
195186 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -204,7 +195,6 @@ test "atomic store" {
204195}
205196
206197test "atomic store comptime" {
207 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
208198 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
209199 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
210200 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -224,7 +214,6 @@ fn testAtomicStore() !void {
224214}
225215
226216test "atomicrmw with floats" {
227 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
228217 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
229218 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
230219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -253,7 +242,6 @@ fn testAtomicRmwFloat() !void {
253242}
254243
255244test "atomicrmw with ints" {
256 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
257245 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
258246 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
259247 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -288,7 +276,6 @@ fn testAtomicRmwInt() !void {
288276}
289277
290278test "atomics with different types" {
291 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
292279 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
293280 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
294281 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -319,7 +306,6 @@ fn testAtomicsWithType(comptime T: type, a: T, b: T) !void {
319306}
320307
321308test "return @atomicStore, using it as a void value" {
322 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
323309 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
324310 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
325311 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/basic.zig-7
......@@ -333,7 +333,6 @@ test "call result of if else expression" {
333333 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
334334 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
335335 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
336 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
337336
338337 try expect(mem.eql(u8, f2(true), "a"));
339338 try expect(mem.eql(u8, f2(false), "b"));
......@@ -364,8 +363,6 @@ fn testMemcpyMemset() !void {
364363}
365364
366365test "variable is allowed to be a pointer to an opaque type" {
367 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
368
369366 var x: i32 = 1234;
370367 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
371368}
......@@ -386,8 +383,6 @@ fn testTakeAddressOfParameter(f: f32) !void {
386383}
387384
388385test "pointer to void return type" {
389 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
390
391386 try testPointerToVoidReturnType();
392387}
393388fn testPointerToVoidReturnType() anyerror!void {
......@@ -593,7 +588,6 @@ test "equality compare fn ptrs" {
593588
594589test "self reference through fn ptr field" {
595590 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
596 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
597591
598592 const S = struct {
599593 const A = struct {
......@@ -881,7 +875,6 @@ test "labeled block implicitly ends in a break" {
881875}
882876
883877test "catch in block has correct result location" {
884 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
885878 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
886879
887880 const S = struct {
test/behavior/bitcast.zig-8
......@@ -161,7 +161,6 @@ test "@bitCast packed structs at runtime and comptime" {
161161 return error.SkipZigTest;
162162 }
163163 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
164 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
165164 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
166165 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
167166 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -189,7 +188,6 @@ test "@bitCast packed structs at runtime and comptime" {
189188
190189test "@bitCast extern structs at runtime and comptime" {
191190 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
192 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
193191 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
194192
195193 const Full = extern struct {
......@@ -221,7 +219,6 @@ test "@bitCast extern structs at runtime and comptime" {
221219
222220test "bitcast packed struct to integer and back" {
223221 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
224 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
225222 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
226223 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
227224 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -261,7 +258,6 @@ test "implicit cast to error union by returning" {
261258
262259test "bitcast packed struct literal to byte" {
263260 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
264 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
265261
266262 const Foo = packed struct {
267263 value: u8,
......@@ -271,8 +267,6 @@ test "bitcast packed struct literal to byte" {
271267}
272268
273269test "comptime bitcast used in expression has the correct type" {
274 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
275
276270 const Foo = packed struct {
277271 value: u8,
278272 };
......@@ -290,8 +284,6 @@ test "bitcast passed as tuple element" {
290284}
291285
292286test "triple level result location with bitcast sandwich passed as tuple element" {
293 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
294
295287 const S = struct {
296288 fn foo(args: anytype) !void {
297289 comptime try expect(@TypeOf(args[0]) == f64);
test/behavior/bugs/10970.zig-1
......@@ -7,7 +7,6 @@ test "breaking from a loop in an if statement" {
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1110
1211 var cond = true;
1312 const opt = while (cond) {
test/behavior/bugs/11159.zig-1
......@@ -9,7 +9,6 @@ test {
99
1010test {
1111 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
12 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1312
1413 const S = struct {
1514 comptime x: i32 = 0,
test/behavior/bugs/11181.zig-4
......@@ -1,8 +1,6 @@
11const builtin = @import("builtin");
22
33test "const inferred array of slices" {
4 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5
64 const T = struct { v: bool };
75
86 const decls = [_][]const T{
......@@ -14,8 +12,6 @@ test "const inferred array of slices" {
1412}
1513
1614test "var inferred array of slices" {
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
18
1915 const T = struct { v: bool };
2016
2117 var decls = [_][]const T{
test/behavior/bugs/11213.zig-2
......@@ -3,8 +3,6 @@ const builtin = @import("builtin");
33const testing = std.testing;
44
55test {
6 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7
86 const g: error{Test}!void = error.Test;
97
108 var v: u32 = 0;
test/behavior/bugs/12776.zig-1
......@@ -31,7 +31,6 @@ const CPU = packed struct {
3131test {
3232 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
3333 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
34 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
3534 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
3635 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
3736
test/behavior/bugs/12891.zig-1
......@@ -8,7 +8,6 @@ test "issue12891" {
88}
99test "nan" {
1010 if (builtin.zig_backend == .stage1) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1211
1312 const f = comptime std.math.nan(f64);
1413 var i: usize = 0;
test/behavior/bugs/12972.zig-1
......@@ -5,7 +5,6 @@ pub fn f(_: [:null]const ?u8) void {}
55test {
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
98
109 const c: u8 = 42;
1110 f(&[_:null]?u8{c});
test/behavior/bugs/12984.zig-1
......@@ -14,7 +14,6 @@ pub const CustomDraw = DeleagateWithContext(fn (?OnConfirm) void);
1414test "simple test" {
1515 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1616 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1918
2019 var c: CustomDraw = undefined;
test/behavior/bugs/13068.zig-1
......@@ -7,7 +7,6 @@ var list = std.ArrayList(u32).init(allocator);
77test {
88 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1312
test/behavior/bugs/1310.zig-1
......@@ -24,6 +24,5 @@ fn agent_callback(_vm: [*]VM, options: [*]u8) callconv(.C) i32 {
2424
2525test "fixed" {
2626 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
27 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2827 try expect(agent_callback(undefined, undefined) == 11);
2928}
test/behavior/bugs/13128.zig-1
......@@ -12,7 +12,6 @@ fn foo(val: U) !void {
1212}
1313
1414test "runtime union init, most-aligned field != largest" {
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1716 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/bugs/1421.zig-1
......@@ -10,7 +10,6 @@ const S = struct {
1010
1111test "functions with return type required to be comptime are generic" {
1212 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1413 const ti = S.method();
1514 try expect(@as(std.builtin.TypeId, ti) == std.builtin.TypeId.Struct);
1615}
test/behavior/bugs/1442.zig-1
......@@ -10,7 +10,6 @@ test "const error union field alignment" {
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1111 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1212 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
13 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1413 var union_or_err: anyerror!Union = Union{ .Color = 1234 };
1514 try std.testing.expect((union_or_err catch unreachable).Color == 1234);
1615}
test/behavior/bugs/1500.zig-1
......@@ -6,7 +6,6 @@ const A = struct {
66const B = *const fn (A) void;
77
88test "allow these dependencies" {
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
109 var a: A = undefined;
1110 var b: B = undefined;
1211 if (false) {
test/behavior/bugs/1607.zig-1
......@@ -14,7 +14,6 @@ test "slices pointing at the same address as global array." {
1414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1515 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1616 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
17 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1817 try checkAddress(&a);
1918 comptime try checkAddress(&a);
2019}
test/behavior/bugs/1735.zig-1
......@@ -43,7 +43,6 @@ const a = struct {
4343
4444test "initialization" {
4545 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
46 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
4746 var t = a.init();
4847 try std.testing.expect(t.foo.len == 0);
4948}
test/behavior/bugs/1914.zig-2
......@@ -12,7 +12,6 @@ const b_list: []B = &[_]B{};
1212const a = A{ .b_list_pointer = &b_list };
1313
1414test "segfault bug" {
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1615 const assert = std.debug.assert;
1716 const obj = B{ .a_pointer = &a };
1817 assert(obj.a_pointer == &a); // this makes zig crash
......@@ -29,6 +28,5 @@ pub const B2 = struct {
2928var b_value = B2{ .pointer_array = &[_]*A2{} };
3029
3130test "basic stuff" {
32 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3331 std.debug.assert(&b_value == &b_value);
3432}
test/behavior/bugs/2006.zig-1
......@@ -6,7 +6,6 @@ const S = struct {
66 p: *S,
77};
88test "bug 2006" {
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
109 var a: S = undefined;
1110 a = S{ .p = undefined };
1211 try expect(@sizeOf(S) != 0);
test/behavior/bugs/2114.zig-1
......@@ -12,7 +12,6 @@ test "fixed" {
1212 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1313 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1414 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1615
1716 try testCtz();
1817 comptime try testCtz();
test/behavior/bugs/2578.zig-1
......@@ -15,7 +15,6 @@ test "fixed" {
1515 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1616 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1717 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1918
2019 bar(t);
2120}
test/behavior/bugs/2692.zig-1
......@@ -5,7 +5,6 @@ fn foo(a: []u8) void {
55}
66
77test "address of 0 length array" {
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
98 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
109
1110 var pt: [0]u8 = undefined;
test/behavior/bugs/3007.zig-1
......@@ -22,7 +22,6 @@ test "fixed" {
2222 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2323 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2424 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2625
2726 default_foo = get_foo() catch null; // This Line
2827 try std.testing.expect(!default_foo.?.free);
test/behavior/bugs/3046.zig-1
......@@ -15,7 +15,6 @@ var some_struct: SomeStruct = undefined;
1515test "fixed" {
1616 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1717 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1918
2019 some_struct = SomeStruct{
2120 .field = couldFail() catch @as(i32, 0),
test/behavior/bugs/3367.zig-1
......@@ -10,7 +10,6 @@ const Mixin = struct {
1010};
1111
1212test "container member access usingnamespace decls" {
13 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1413 var foo = Foo{};
1514 foo.two();
1615}
test/behavior/bugs/3742.zig-1
......@@ -38,6 +38,5 @@ test "fixed" {
3838 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
3939 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
4040 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
41 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
4241 ArgSerializer.serializeCommand(GET.init("banana"));
4342}
test/behavior/bugs/4328.zig+8-8
......@@ -5,10 +5,10 @@ const FILE = extern struct {
55 dummy_field: u8,
66};
77
8extern fn printf([*c]const u8, ...) c_int;
9extern fn fputs([*c]const u8, noalias [*c]FILE) c_int;
10extern fn ftell([*c]FILE) c_long;
11extern fn fopen([*c]const u8, [*c]const u8) [*c]FILE;
8extern fn c_printf([*c]const u8, ...) c_int;
9extern fn c_fputs([*c]const u8, noalias [*c]FILE) c_int;
10extern fn c_ftell([*c]FILE) c_long;
11extern fn c_fopen([*c]const u8, [*c]const u8) [*c]FILE;
1212
1313const S = extern struct {
1414 state: c_short,
......@@ -18,7 +18,7 @@ const S = extern struct {
1818
1919test "Extern function calls in @TypeOf" {
2020 const Test = struct {
21 fn test_fn_1(a: anytype, b: anytype) @TypeOf(printf("%d %s\n", a, b)) {
21 fn test_fn_1(a: anytype, b: anytype) @TypeOf(c_printf("%d %s\n", a, b)) {
2222 return 0;
2323 }
2424
......@@ -38,7 +38,7 @@ test "Extern function calls in @TypeOf" {
3838
3939test "Peer resolution of extern function calls in @TypeOf" {
4040 const Test = struct {
41 fn test_fn() @TypeOf(ftell(null), fputs(null, null)) {
41 fn test_fn() @TypeOf(c_ftell(null), c_fputs(null, null)) {
4242 return 0;
4343 }
4444
......@@ -55,12 +55,12 @@ test "Extern function calls, dereferences and field access in @TypeOf" {
5555 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
5656
5757 const Test = struct {
58 fn test_fn_1(a: c_long) @TypeOf(fopen("test", "r").*) {
58 fn test_fn_1(a: c_long) @TypeOf(c_fopen("test", "r").*) {
5959 _ = a;
6060 return .{ .dummy_field = 0 };
6161 }
6262
63 fn test_fn_2(a: anytype) @TypeOf(fopen("test", "r").*.dummy_field) {
63 fn test_fn_2(a: anytype) @TypeOf(c_fopen("test", "r").*.dummy_field) {
6464 _ = a;
6565 return 255;
6666 }
test/behavior/bugs/4954.zig-1
......@@ -5,7 +5,6 @@ fn f(buf: []u8) void {
55}
66
77test "crash" {
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
98 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1110
test/behavior/bugs/5398.zig-1
......@@ -22,7 +22,6 @@ test "assignment of field with padding" {
2222 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2424 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
25 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2625
2726 renderable = Renderable{
2827 .mesh = Mesh{ .id = 0 },
test/behavior/bugs/5487.zig-1
......@@ -13,6 +13,5 @@ test "crash" {
1313 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1515 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
16 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1716 _ = io.multiWriter(.{writer()});
1817}
test/behavior/bugs/726.zig-2
......@@ -5,7 +5,6 @@ test "@ptrCast from const to nullable" {
55 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
98
109 const c: u8 = 4;
1110 var x: ?*const u8 = @ptrCast(?*const u8, &c);
......@@ -16,7 +15,6 @@ test "@ptrCast from var in empty struct to nullable" {
1615 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1716 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1817 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
19 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2018
2119 const container = struct {
2220 var c: u8 = 4;
test/behavior/bugs/920.zig-1
......@@ -67,7 +67,6 @@ const NormalDist = blk: {
6767
6868test "bug 920 fixed" {
6969 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
70 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7170 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7271 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7372 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/bugs/9584.zig-1
......@@ -49,7 +49,6 @@ test {
4949 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5050 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5352
5453 var flags = A{
5554 .a = false,
test/behavior/call.zig-2
......@@ -58,7 +58,6 @@ test "basic invocations" {
5858test "tuple parameters" {
5959 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
6060 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
6261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6362
6463 const add = struct {
......@@ -87,7 +86,6 @@ test "tuple parameters" {
8786}
8887
8988test "result location of function call argument through runtime condition and struct init" {
90 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
9189 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9290 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
9391
test/behavior/cast.zig-39
......@@ -119,7 +119,6 @@ test "@intToFloat(f80)" {
119119 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
120120 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
121121 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
122 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
123122
124123 const S = struct {
125124 fn doTheTest(comptime Int: type) !void {
......@@ -395,7 +394,6 @@ test "expected [*c]const u8, found [*:0]const u8" {
395394test "explicit cast from integer to error type" {
396395 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
397396 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
398 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
399397 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
400398 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
401399
......@@ -410,7 +408,6 @@ fn testCastIntToErr(err: anyerror) !void {
410408
411409test "peer resolve array and const slice" {
412410 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
413 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
414411 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
415412 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
416413
......@@ -451,7 +448,6 @@ fn castToOptionalTypeError(z: i32) !void {
451448
452449test "implicitly cast from [0]T to anyerror![]T" {
453450 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
454 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
455451
456452 try testCastZeroArrayToErrSliceMut();
457453 comptime try testCastZeroArrayToErrSliceMut();
......@@ -467,7 +463,6 @@ fn gimmeErrOrSlice() anyerror![]u8 {
467463
468464test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
469465 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
470 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
471466 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
472467
473468 const S = struct {
......@@ -546,7 +541,6 @@ fn testPeerErrorAndArray2(x: u8) anyerror![]const u8 {
546541
547542test "single-item pointer of array to slice to unknown length pointer" {
548543 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
549 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
550544
551545 try testCastPtrOfArrayToSliceAndPtr();
552546 comptime try testCastPtrOfArrayToSliceAndPtr();
......@@ -575,7 +569,6 @@ fn testCastPtrOfArrayToSliceAndPtr() !void {
575569
576570test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
577571 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
578 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
579572 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
580573
581574 const window_name = [1][*]const u8{"window name"};
......@@ -813,7 +806,6 @@ test "peer type resolution: error union after non-error" {
813806test "peer cast *[0]T to E![]const T" {
814807 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
815808 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
816 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
817809 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
818810
819811 var buffer: [5]u8 = "abcde".*;
......@@ -828,7 +820,6 @@ test "peer cast *[0]T to E![]const T" {
828820test "peer cast *[0]T to []const T" {
829821 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
830822 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
831 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
832823 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
833824
834825 var buffer: [5]u8 = "abcde".*;
......@@ -839,8 +830,6 @@ test "peer cast *[0]T to []const T" {
839830}
840831
841832test "peer cast *[N]T to [*]T" {
842 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
843
844833 var array = [4:99]i32{ 1, 2, 3, 4 };
845834 var dest: [*]i32 = undefined;
846835 try expect(@TypeOf(&array, dest) == [*]i32);
......@@ -849,7 +838,6 @@ test "peer cast *[N]T to [*]T" {
849838
850839test "peer resolution of string literals" {
851840 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
852 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
853841 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
854842 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
855843
......@@ -872,7 +860,6 @@ test "peer resolution of string literals" {
872860
873861test "peer cast [:x]T to []T" {
874862 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
875 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
876863
877864 const S = struct {
878865 fn doTheTest() !void {
......@@ -888,7 +875,6 @@ test "peer cast [:x]T to []T" {
888875
889876test "peer cast [N:x]T to [N]T" {
890877 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
891 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
892878
893879 const S = struct {
894880 fn doTheTest() !void {
......@@ -903,7 +889,6 @@ test "peer cast [N:x]T to [N]T" {
903889
904890test "peer cast *[N:x]T to *[N]T" {
905891 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
906 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
907892
908893 const S = struct {
909894 fn doTheTest() !void {
......@@ -937,7 +922,6 @@ test "peer cast [*:x]T to [*]T" {
937922
938923test "peer cast [:x]T to [*:x]T" {
939924 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
940 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
941925 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
942926 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
943927
......@@ -1018,7 +1002,6 @@ test "cast between C pointer with different but compatible types" {
10181002
10191003test "peer type resolve string lit with sentinel-terminated mutable slice" {
10201004 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1021 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10221005
10231006 var array: [4:0]u8 = undefined;
10241007 array[4] = 0; // TODO remove this when #4372 is solved
......@@ -1035,8 +1018,6 @@ test "peer type resolve array pointers, one of them const" {
10351018}
10361019
10371020test "peer type resolve array pointer and unknown pointer" {
1038 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1039
10401021 const const_array: [4]u8 = undefined;
10411022 var array: [4]u8 = undefined;
10421023 var const_ptr: [*]const u8 = undefined;
......@@ -1069,7 +1050,6 @@ test "comptime float casts" {
10691050
10701051test "pointer reinterpret const float to int" {
10711052 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1072 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10731053
10741054 // The hex representation is 0x3fe3333333333303.
10751055 const float: f64 = 5.99999999999994648725e-01;
......@@ -1084,7 +1064,6 @@ test "pointer reinterpret const float to int" {
10841064
10851065test "implicit cast from [*]T to ?*anyopaque" {
10861066 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1087 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10881067 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10891068
10901069 var a = [_]u8{ 3, 2, 1 };
......@@ -1102,8 +1081,6 @@ fn incrementVoidPtrArray(array: ?*anyopaque, len: usize) void {
11021081
11031082test "compile time int to ptr of function" {
11041083 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1105
1106 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11071084 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11081085
11091086 try foobar(FUNCTION_CONSTANT);
......@@ -1120,7 +1097,6 @@ fn foobar(func: PFN_void) !void {
11201097
11211098test "implicit ptr to *anyopaque" {
11221099 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1123 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11241100 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11251101
11261102 var a: u32 = 1;
......@@ -1149,7 +1125,6 @@ fn returnNullLitFromOptionalTypeErrorRef() anyerror!?*A {
11491125
11501126test "peer type resolution: [0]u8 and []const u8" {
11511127 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1152 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11531128
11541129 try expect(peerTypeEmptyArrayAndSlice(true, "hi").len == 0);
11551130 try expect(peerTypeEmptyArrayAndSlice(false, "hi").len == 1);
......@@ -1168,7 +1143,6 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
11681143
11691144test "implicitly cast from [N]T to ?[]const T" {
11701145 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1171 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11721146 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11731147 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
11741148
......@@ -1182,7 +1156,6 @@ fn castToOptionalSlice() ?[]const u8 {
11821156
11831157test "cast u128 to f128 and back" {
11841158 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1185 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11861159 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11871160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11881161 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -1221,7 +1194,6 @@ test "implicit cast from *[N]T to ?[*]T" {
12211194
12221195test "implicit cast from *T to ?*anyopaque" {
12231196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1224 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12251197 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12261198
12271199 var a: u8 = 1;
......@@ -1235,7 +1207,6 @@ fn incrementVoidPtrValue(value: ?*anyopaque) void {
12351207
12361208test "implicit cast *[0]T to E![]const u8" {
12371209 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1238 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12391210
12401211 var x = @as(anyerror![]const u8, &[0]u8{});
12411212 try expect((x catch unreachable).len == 0);
......@@ -1247,15 +1218,12 @@ test "cast from array reference to fn: comptime fn ptr" {
12471218 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
12481219}
12491220test "cast from array reference to fn: runtime fn ptr" {
1250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1251
12521221 var f = @ptrCast(*align(1) const fn () callconv(.C) void, &global_array);
12531222 try expect(@ptrToInt(f) == @ptrToInt(&global_array));
12541223}
12551224
12561225test "*const [N]null u8 to ?[]const u8" {
12571226 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1258 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12591227 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12601228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
12611229
......@@ -1291,7 +1259,6 @@ test "cast between [*c]T and ?[*:0]T on fn parameter" {
12911259var global_struct: struct { f0: usize } = undefined;
12921260test "assignment to optional pointer result loc" {
12931261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1294 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12951262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12961263
12971264 var foo: struct { ptr: ?*anyopaque } = .{ .ptr = &global_struct };
......@@ -1318,7 +1285,6 @@ fn boolToStr(b: bool) []const u8 {
13181285
13191286test "cast f16 to wider types" {
13201287 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1321 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13221288 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13231289 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13241290 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -1337,7 +1303,6 @@ test "cast f16 to wider types" {
13371303
13381304test "cast f128 to narrower types" {
13391305 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1340 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13411306 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13421307 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13431308 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -1356,7 +1321,6 @@ test "cast f128 to narrower types" {
13561321
13571322test "peer type resolution: unreachable, null, slice" {
13581323 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1359 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13601324 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13611325 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13621326
......@@ -1396,7 +1360,6 @@ test "cast i8 fn call peers to i32 result" {
13961360test "cast compatible optional types" {
13971361 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13981362 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1399 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14001363 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
14011364
14021365 var a: ?[:0]const u8 = null;
......@@ -1414,13 +1377,11 @@ test "coerce undefined single-item pointer of array to error union of slice" {
14141377}
14151378
14161379test "pointer to empty struct literal to mutable slice" {
1417 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14181380 var x: []i32 = &.{};
14191381 try expect(x.len == 0);
14201382}
14211383
14221384test "coerce between pointers of compatible differently-named floats" {
1423 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14241385 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14251386 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14261387 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/cast_int.zig-1
......@@ -8,7 +8,6 @@ test "@intCast i32 to u7" {
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1211
1312 var x: u128 = maxInt(u128);
1413 var y: i32 = 120;
test/behavior/defer.zig-1
......@@ -108,7 +108,6 @@ test "mixing normal and error defers" {
108108}
109109
110110test "errdefer with payload" {
111 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
112111 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
113112 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
114113 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/empty_union.zig-4
......@@ -3,7 +3,6 @@ const std = @import("std");
33const expect = std.testing.expect;
44
55test "switch on empty enum" {
6 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
87
98 const E = enum {};
......@@ -12,7 +11,6 @@ test "switch on empty enum" {
1211}
1312
1413test "switch on empty enum with a specified tag type" {
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1614 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1715
1816 const E = enum(u8) {};
......@@ -21,7 +19,6 @@ test "switch on empty enum with a specified tag type" {
2119}
2220
2321test "switch on empty auto numbered tagged union" {
24 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2522 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2623 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2724
......@@ -31,7 +28,6 @@ test "switch on empty auto numbered tagged union" {
3128}
3229
3330test "switch on empty tagged union" {
34 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3531 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3632 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
3733
test/behavior/enum.zig-4
......@@ -972,7 +972,6 @@ fn test3_2(f: Test3Foo) !void {
972972}
973973
974974test "@tagName" {
975 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
976975 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
977976 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
978977 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -989,7 +988,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 {
989988const BareNumber = enum { One, Two, Three };
990989
991990test "@tagName non-exhaustive enum" {
992 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
993991 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
994992 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
995993 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -1001,7 +999,6 @@ test "@tagName non-exhaustive enum" {
1001999const NonExhaustive = enum(u8) { A, B, _ };
10021000
10031001test "@tagName is null-terminated" {
1004 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10051002 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10061003 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10071004 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -1017,7 +1014,6 @@ test "@tagName is null-terminated" {
10171014}
10181015
10191016test "tag name with assigned enum values" {
1020 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10211017 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10221018 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10231019 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
test/behavior/error.zig+16-4
......@@ -258,7 +258,6 @@ fn testComptimeTestErrorEmptySet(x: EmptyErrorSet!i32) !void {
258258}
259259
260260test "comptime err to int of error set with only 1 possible value" {
261 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
262261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
263262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
264263
......@@ -471,7 +470,6 @@ test "function pointer with return type that is error union with payload which i
471470 return error.SkipZigTest;
472471 }
473472
474 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
475473 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
476474 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
477475
......@@ -556,7 +554,6 @@ test "error union comptime caching" {
556554}
557555
558556test "@errorName" {
559 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
560557 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
561558 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
562559 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -570,7 +567,6 @@ fn gimmeItBroke() anyerror {
570567}
571568
572569test "@errorName sentinel length matches slice length" {
573 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
574570 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
575571 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
576572 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -843,3 +839,19 @@ fn non_errorable() void {
843839test "catch within a function that calls no errorable functions" {
844840 non_errorable();
845841}
842
843test "error from comptime string" {
844 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
845 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
846 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
847
848 const name = "Weird error name!";
849 const S = struct {
850 fn foo() !void {
851 return @field(anyerror, name);
852 }
853 };
854 if (S.foo()) unreachable else |err| {
855 try expect(mem.eql(u8, name, @errorName(err)));
856 }
857}
test/behavior/eval.zig-9
......@@ -531,7 +531,6 @@ test "@tagName of @typeInfo" {
531531}
532532
533533test "static eval list init" {
534 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
535534 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
536535 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
537536 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -719,7 +718,6 @@ test "*align(1) u16 is the same as *align(1:0:2) u16" {
719718}
720719
721720test "array concatenation of function calls" {
722 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
723721 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
724722 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
725723
......@@ -728,7 +726,6 @@ test "array concatenation of function calls" {
728726}
729727
730728test "array multiplication of function calls" {
731 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
732729 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
733730 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
734731
......@@ -746,7 +743,6 @@ fn scalar(x: u32) u32 {
746743
747744test "array concatenation peer resolves element types - value" {
748745 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
749 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
750746 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
751747 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
752748
......@@ -763,7 +759,6 @@ test "array concatenation peer resolves element types - value" {
763759
764760test "array concatenation peer resolves element types - pointer" {
765761 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
766 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
767762 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
768763 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
769764
......@@ -782,7 +777,6 @@ test "array concatenation sets the sentinel - value" {
782777 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
783778 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
784779 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
785 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
786780 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
787781 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
788782
......@@ -801,7 +795,6 @@ test "array concatenation sets the sentinel - value" {
801795
802796test "array concatenation sets the sentinel - pointer" {
803797 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
804 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
805798 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
806799
807800 var a = [2]u3{ 1, 7 };
......@@ -821,7 +814,6 @@ test "array multiplication sets the sentinel - value" {
821814 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
822815 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
823816 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
824 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
825817 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
826818 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
827819
......@@ -838,7 +830,6 @@ test "array multiplication sets the sentinel - value" {
838830
839831test "array multiplication sets the sentinel - pointer" {
840832 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
841 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
842833 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
843834 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
844835
test/behavior/export_self_referential_type_info.zig+1-1
......@@ -1 +1 @@
1export const foo: c_int = @boolToInt(@typeInfo(@This()).Struct.is_tuple);
1export const self_referential_type_info: c_int = @boolToInt(@typeInfo(@This()).Struct.is_tuple);
test/behavior/field_parent_ptr.zig-2
......@@ -4,7 +4,6 @@ const builtin = @import("builtin");
44test "@fieldParentPtr non-first field" {
55 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
66 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
7 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
87 try testParentFieldPtr(&foo.c);
98 comptime try testParentFieldPtr(&foo.c);
109}
......@@ -12,7 +11,6 @@ test "@fieldParentPtr non-first field" {
1211test "@fieldParentPtr first field" {
1312 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1413 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1614 try testParentFieldPtrFirst(&foo.a);
1715 comptime try testParentFieldPtrFirst(&foo.a);
1816}
test/behavior/floatop.zig-15
......@@ -21,7 +21,6 @@ fn epsForType(comptime T: type) T {
2121
2222test "floating point comparisons" {
2323 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2524 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2625
2726 try testFloatComparisons();
......@@ -55,7 +54,6 @@ fn testFloatComparisons() !void {
5554
5655test "different sized float comparisons" {
5756 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5957 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6058 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6159 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -91,7 +89,6 @@ fn testDifferentSizedFloatComparisons() !void {
9189
9290test "negative f128 floatToInt at compile-time" {
9391 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
94 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
9592 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9693 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9794
......@@ -150,7 +147,6 @@ fn testSqrt() !void {
150147
151148test "more @sqrt f16 tests" {
152149 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
153 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
154150 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
155151 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
156152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -305,7 +301,6 @@ test "@log" {
305301 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
306302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
307303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
308 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
309304
310305 comptime try testLog();
311306 try testLog();
......@@ -545,7 +540,6 @@ fn testTrunc() !void {
545540
546541test "negation f16" {
547542 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
548 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
549543 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
550544 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
551545 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -573,7 +567,6 @@ test "negation f32" {
573567 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
574568 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
575569 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
576 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
577570 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
578571
579572 const S = struct {
......@@ -595,7 +588,6 @@ test "negation f64" {
595588 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
596589 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
597590 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
598 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
599591
600592 const S = struct {
601593 fn doTheTest() !void {
......@@ -615,7 +607,6 @@ test "negation f80" {
615607 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
616608 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
617609 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
618 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
619610 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
620611
621612 const S = struct {
......@@ -636,7 +627,6 @@ test "negation f128" {
636627 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
637628 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
638629 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
639 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
640630 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
641631
642632 const S = struct {
......@@ -680,7 +670,6 @@ test "comptime fixed-width float zero divided by zero produces NaN" {
680670 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
681671 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
682672 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
683 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
684673
685674 inline for (.{ f16, f32, f64, f80, f128 }) |F| {
686675 try expect(math.isNan(@as(F, 0) / @as(F, 0)));
......@@ -716,7 +705,6 @@ test "nan negation f16" {
716705 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
717706 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
718707 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
719 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
720708
721709 const nan_comptime = comptime math.nan(f16);
722710 const neg_nan_comptime = -nan_comptime;
......@@ -736,7 +724,6 @@ test "nan negation f32" {
736724 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
737725 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
738726 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
739 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
740727
741728 const nan_comptime = comptime math.nan(f32);
742729 const neg_nan_comptime = -nan_comptime;
......@@ -756,7 +743,6 @@ test "nan negation f64" {
756743 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
757744 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
758745 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
759 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
760746
761747 const nan_comptime = comptime math.nan(f64);
762748 const neg_nan_comptime = -nan_comptime;
......@@ -776,7 +762,6 @@ test "nan negation f128" {
776762 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
777763 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
778764 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
779 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
780765
781766 const nan_comptime = comptime math.nan(f128);
782767 const neg_nan_comptime = -nan_comptime;
test/behavior/fn.zig-8
......@@ -97,7 +97,6 @@ test "discard the result of a function that returns a struct" {
9797}
9898
9999test "inline function call that calls optional function pointer, return pointer at callsite interacts correctly with callsite return type" {
100 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
101100 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
102101 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
103102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -146,7 +145,6 @@ fn fnWithUnreachable() noreturn {
146145}
147146
148147test "extern struct with stdcallcc fn pointer" {
149 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
150148 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
151149 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
152150 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -274,7 +272,6 @@ test "void parameters" {
274272 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
275273 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
276274
277 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
278275 try voidFun(1, void{}, 2, {});
279276}
280277fn voidFun(a: i32, b: void, c: i32, d: void) !void {
......@@ -286,7 +283,6 @@ fn voidFun(a: i32, b: void, c: i32, d: void) !void {
286283}
287284
288285test "call function with empty string" {
289 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
290286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
291287
292288 acceptsString("");
......@@ -305,7 +301,6 @@ test "function pointers" {
305301 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
306302 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
307303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
308 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
309304
310305 const fns = [_]*const @TypeOf(fn1){
311306 &fn1,
......@@ -399,8 +394,6 @@ test "ability to give comptime types and non comptime types to same parameter" {
399394}
400395
401396test "function with inferred error set but returning no error" {
402 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
403
404397 const S = struct {
405398 fn foo() !void {}
406399 };
......@@ -410,7 +403,6 @@ test "function with inferred error set but returning no error" {
410403}
411404
412405test "import passed byref to function in return type" {
413 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
414406 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
415407
416408 const S = struct {
test/behavior/for.zig-1
......@@ -195,7 +195,6 @@ test "for on slice with allowzero ptr" {
195195 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
196196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
197197 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
198 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
199198
200199 const S = struct {
201200 fn doTheTest(slice: []const u8) !void {
test/behavior/generics.zig+5-5
......@@ -204,7 +204,6 @@ fn foo2(arg: anytype) bool {
204204}
205205
206206test "generic struct" {
207 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
208207 var a1 = GenNode(i32){
209208 .value = 13,
210209 .next = null,
......@@ -361,13 +360,14 @@ test "nested generic function" {
361360
362361test "extern function used as generic parameter" {
363362 const S = struct {
364 extern fn foo() void;
365 extern fn bar() void;
366 inline fn baz(comptime _: anytype) type {
363 extern fn usedAsGenericParameterFoo() void;
364 extern fn usedAsGenericParameterBar() void;
365 inline fn usedAsGenericParameterBaz(comptime _: anytype) type {
367366 return struct {};
368367 }
369368 };
370 try expect(S.baz(S.foo) != S.baz(S.bar));
369 try expect(S.usedAsGenericParameterBaz(S.usedAsGenericParameterFoo) !=
370 S.usedAsGenericParameterBaz(S.usedAsGenericParameterBar));
371371}
372372
373373test "generic struct as parameter type" {
test/behavior/int128.zig-1
......@@ -43,7 +43,6 @@ test "int128" {
4343 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
4444 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
4545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
46 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4746
4847 var buff: i128 = -1;
4948 try expect(buff < 0 and (buff + 1) == 0);
test/behavior/math.zig-41
......@@ -376,7 +376,6 @@ fn testBinaryNot(x: u16) !void {
376376}
377377
378378test "division" {
379 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
380379 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
381380 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
382381 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -453,7 +452,6 @@ fn testDivision() !void {
453452}
454453
455454test "division half-precision floats" {
456 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
457455 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
458456 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
459457 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -603,7 +601,6 @@ fn should_not_be_zero(x: f128) !void {
603601}
604602
605603test "128-bit multiplication" {
606 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
607604 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
608605 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
609606 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -616,8 +613,6 @@ test "128-bit multiplication" {
616613}
617614
618615test "@addWithOverflow" {
619 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
620
621616 {
622617 var result: u8 = undefined;
623618 try expect(@addWithOverflow(u8, 250, 100, &result));
......@@ -652,8 +647,6 @@ test "@addWithOverflow" {
652647}
653648
654649test "small int addition" {
655 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
656
657650 var x: u2 = 0;
658651 try expect(x == 0);
659652
......@@ -673,8 +666,6 @@ test "small int addition" {
673666}
674667
675668test "basic @mulWithOverflow" {
676 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
677
678669 var result: u8 = undefined;
679670 try expect(@mulWithOverflow(u8, 86, 3, &result));
680671 try expect(result == 2);
......@@ -693,7 +684,6 @@ test "basic @mulWithOverflow" {
693684
694685// TODO migrate to this for all backends once they handle more cases
695686test "extensive @mulWithOverflow" {
696 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
697687 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
698688
699689 {
......@@ -843,7 +833,6 @@ test "extensive @mulWithOverflow" {
843833}
844834
845835test "@mulWithOverflow bitsize > 32" {
846 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
847836 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
848837 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
849838
......@@ -897,8 +886,6 @@ test "@mulWithOverflow bitsize > 32" {
897886}
898887
899888test "@subWithOverflow" {
900 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
901
902889 {
903890 var result: u8 = undefined;
904891 try expect(@subWithOverflow(u8, 1, 2, &result));
......@@ -933,8 +920,6 @@ test "@subWithOverflow" {
933920}
934921
935922test "@shlWithOverflow" {
936 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
937
938923 {
939924 var result: u4 = undefined;
940925 var a: u4 = 2;
......@@ -977,8 +962,6 @@ test "@shlWithOverflow" {
977962}
978963
979964test "overflow arithmetic with u0 values" {
980 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
981
982965 var result: u0 = undefined;
983966 try expect(!@addWithOverflow(u0, 0, 0, &result));
984967 try expect(result == 0);
......@@ -1007,7 +990,6 @@ test "allow signed integer division/remainder when values are comptime-known and
1007990}
1008991
1009992test "quad hex float literal parsing accurate" {
1010 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1011993 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1012994 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1013995 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1163,7 +1145,6 @@ test "comptime float rem int" {
11631145
11641146test "remainder division" {
11651147 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1166 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11671148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11681149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11691150 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1196,7 +1177,6 @@ fn remdivOne(comptime T: type, a: T, b: T, c: T) !void {
11961177
11971178test "float remainder division using @rem" {
11981179 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1199 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12001180 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12011181 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12021182 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1240,7 +1220,6 @@ fn fremOne(comptime T: type, a: T, b: T, c: T, epsilon: T) !void {
12401220
12411221test "float modulo division using @mod" {
12421222 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1243 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12441223 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12451224 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12461225 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
......@@ -1286,7 +1265,6 @@ test "@sqrt" {
12861265 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
12871266 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12881267 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1289 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12901268
12911269 try testSqrt(f64, 12.0);
12921270 comptime try testSqrt(f64, 12.0);
......@@ -1312,7 +1290,6 @@ test "@fabs" {
13121290 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13131291 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13141292 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1315 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13161293
13171294 try testFabs(f128, 12.0);
13181295 comptime try testFabs(f128, 12.0);
......@@ -1334,7 +1311,6 @@ test "@fabs f80" {
13341311 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13351312 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13361313 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1337 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13381314
13391315 try testFabs(f80, 12.0);
13401316 comptime try testFabs(f80, 12.0);
......@@ -1351,7 +1327,6 @@ test "@floor" {
13511327 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13521328 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13531329 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1354 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13551330
13561331 try testFloor(f64, 12.0);
13571332 comptime try testFloor(f64, 12.0);
......@@ -1371,7 +1346,6 @@ test "@floor f80" {
13711346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13721347 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13731348 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1374 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13751349 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/12602
13761350
13771351 try testFloor(f80, 12.0);
......@@ -1383,7 +1357,6 @@ test "@floor f128" {
13831357 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13841358 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13851359 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1386 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13871360
13881361 try testFloor(f128, 12.0);
13891362 comptime try testFloor(f128, 12.0);
......@@ -1400,7 +1373,6 @@ test "@ceil" {
14001373 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14011374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14021375 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1403 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14041376
14051377 try testCeil(f64, 12.0);
14061378 comptime try testCeil(f64, 12.0);
......@@ -1420,7 +1392,6 @@ test "@ceil f80" {
14201392 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14211393 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14221394 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1423 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14241395 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/12602
14251396
14261397 try testCeil(f80, 12.0);
......@@ -1432,7 +1403,6 @@ test "@ceil f128" {
14321403 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14331404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14341405 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1435 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14361406
14371407 try testCeil(f128, 12.0);
14381408 comptime try testCeil(f128, 12.0);
......@@ -1449,7 +1419,6 @@ test "@trunc" {
14491419 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14501420 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14511421 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1452 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14531422
14541423 try testTrunc(f64, 12.0);
14551424 comptime try testTrunc(f64, 12.0);
......@@ -1469,7 +1438,6 @@ test "@trunc f80" {
14691438 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14701439 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14711440 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1472 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14731441 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/12602
14741442
14751443 try testTrunc(f80, 12.0);
......@@ -1487,7 +1455,6 @@ test "@trunc f128" {
14871455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14881456 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14891457 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1490 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14911458
14921459 try testTrunc(f128, 12.0);
14931460 comptime try testTrunc(f128, 12.0);
......@@ -1512,7 +1479,6 @@ test "@round" {
15121479 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15131480 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15141481 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1515 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15161482
15171483 try testRound(f64, 12.0);
15181484 comptime try testRound(f64, 12.0);
......@@ -1532,7 +1498,6 @@ test "@round f80" {
15321498 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15331499 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15341500 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1535 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15361501 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/12602
15371502
15381503 try testRound(f80, 12.0);
......@@ -1544,7 +1509,6 @@ test "@round f128" {
15441509 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15451510 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
15461511 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1547 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15481512
15491513 try testRound(f128, 12.0);
15501514 comptime try testRound(f128, 12.0);
......@@ -1578,7 +1542,6 @@ test "vector integer addition" {
15781542}
15791543
15801544test "NaN comparison" {
1581 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15821545 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
15831546 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
15841547 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1595,7 +1558,6 @@ test "NaN comparison" {
15951558}
15961559
15971560test "NaN comparison f80" {
1598 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
15991561 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16001562 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16011563 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1647,7 +1609,6 @@ test "compare undefined literal with comptime_int" {
16471609}
16481610
16491611test "signed zeros are represented properly" {
1650 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16511612 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16521613 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16531614 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1688,7 +1649,6 @@ test "fabs" {
16881649 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
16891650 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
16901651 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1691 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
16921652
16931653 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
16941654 // normals
......@@ -1717,7 +1677,6 @@ test "absFloat" {
17171677 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
17181678 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
17191679 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1720 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
17211680
17221681 try testAbsFloat();
17231682 comptime try testAbsFloat();
test/behavior/maximum_minimum.zig-2
......@@ -6,7 +6,6 @@ const expectEqual = std.testing.expectEqual;
66
77test "@max" {
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1211
......@@ -55,7 +54,6 @@ test "@min" {
5554 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5957
6058 const S = struct {
6159 fn doTheTest() !void {
test/behavior/muladd.zig-4
......@@ -2,7 +2,6 @@ const builtin = @import("builtin");
22const expect = @import("std").testing.expect;
33
44test "@mulAdd" {
5 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
65 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
87 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -28,7 +27,6 @@ fn testMulAdd() !void {
2827
2928test "@mulAdd f16" {
3029 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
31 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3230 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3331 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3432 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -46,7 +44,6 @@ fn testMulAdd16() !void {
4644
4745test "@mulAdd f80" {
4846 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
49 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5047 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5148 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5249 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -65,7 +62,6 @@ fn testMulAdd80() !void {
6562}
6663
6764test "@mulAdd f128" {
68 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
6965 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
7066 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/optional.zig-3
......@@ -66,7 +66,6 @@ test "optional with void type" {
6666}
6767
6868test "address of unwrap optional" {
69 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7069 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
7170 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
......@@ -270,7 +269,6 @@ test "0-bit child type coerced to optional return ptr result location" {
270269}
271270
272271test "0-bit child type coerced to optional" {
273 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
274272 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
275273 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
276274
......@@ -333,7 +331,6 @@ test "array of optional unaligned types" {
333331}
334332
335333test "optional pointer to zero bit optional payload" {
336 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
337334 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
338335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
339336 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/packed-struct.zig-6
......@@ -150,7 +150,6 @@ test "consistent size of packed structs" {
150150
151151test "correct sizeOf and offsets in packed structs" {
152152 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
153 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
154153 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
155154 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
156155 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -221,7 +220,6 @@ test "correct sizeOf and offsets in packed structs" {
221220
222221test "nested packed structs" {
223222 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
224 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
225223 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
226224 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
227225 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -270,7 +268,6 @@ test "nested packed structs" {
270268
271269test "regular in irregular packed struct" {
272270 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
273 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
274271 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
275272 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
276273 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -293,7 +290,6 @@ test "regular in irregular packed struct" {
293290test "byte-aligned field pointer offsets" {
294291 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
295292 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
296 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
297293 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
298294 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
299295 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -396,7 +392,6 @@ test "byte-aligned field pointer offsets" {
396392
397393test "load pointer from packed struct" {
398394 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
399 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
400395 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
401396 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
402397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -418,7 +413,6 @@ test "load pointer from packed struct" {
418413}
419414
420415test "@ptrToInt on a packed struct field" {
421 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
422416 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
423417 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
424418 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
test/behavior/packed_struct_explicit_backing_int.zig-1
......@@ -6,7 +6,6 @@ const native_endian = builtin.cpu.arch.endian();
66
77test "packed struct explicit backing integer" {
88 assert(builtin.zig_backend != .stage1);
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1110 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1211 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
test/behavior/pointers.zig-4
......@@ -157,7 +157,6 @@ test "implicit casting between C pointer and optional non-C pointer" {
157157}
158158
159159test "implicit cast error unions with non-optional to optional pointer" {
160 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
161160 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
162161 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
163162 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -205,7 +204,6 @@ test "allowzero pointer and slice" {
205204}
206205
207206test "assign null directly to C pointer and test null equality" {
208 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
209207 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
210208 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
211209 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -337,7 +335,6 @@ test "pointer sentinel with optional element" {
337335
338336test "pointer sentinel with +inf" {
339337 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
340 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
341338 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
342339 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
343340 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
......@@ -404,7 +401,6 @@ test "@ptrToInt on null optional at comptime" {
404401}
405402
406403test "indexing array with sentinel returns correct type" {
407 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
408404 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
409405 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
410406 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/ptrcast.zig-1
......@@ -133,7 +133,6 @@ test "lower reinterpreted comptime field ptr (with under-aligned fields)" {
133133 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
134134 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
135135 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
136 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO: CBE does not yet support under-aligned fields
137136
138137 // Test lowering a field ptr
139138 comptime var bytes align(2) = [_]u8{ 1, 2, 3, 4, 5, 6 };
test/behavior/saturating_arithmetic.zig-7
......@@ -8,7 +8,6 @@ test "saturating add" {
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1211
1312 const S = struct {
1413 fn doTheTest() !void {
......@@ -55,7 +54,6 @@ test "saturating add 128bit" {
5554 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
5655 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5756 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5957 const S = struct {
6058 fn doTheTest() !void {
6159 try testSatAdd(i128, maxInt(i128), -maxInt(i128), 0);
......@@ -79,7 +77,6 @@ test "saturating subtraction" {
7977 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
8078 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8179 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
82 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
8380
8481 const S = struct {
8582 fn doTheTest() !void {
......@@ -125,7 +122,6 @@ test "saturating subtraction 128bit" {
125122 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
126123 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
127124 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
128 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
129125
130126 const S = struct {
131127 fn doTheTest() !void {
......@@ -152,7 +148,6 @@ test "saturating multiplication" {
152148 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
153149 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
154150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
155 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
156151
157152 if (builtin.zig_backend == .stage1 and builtin.cpu.arch == .wasm32) {
158153 // https://github.com/ziglang/zig/issues/9660
......@@ -200,7 +195,6 @@ test "saturating shift-left" {
200195 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
201196 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
202197 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
204198
205199 const S = struct {
206200 fn doTheTest() !void {
......@@ -239,7 +233,6 @@ test "saturating shl uses the LHS type" {
239233 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
240234 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
241235 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
242 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
243236
244237 const lhs_const: u8 = 1;
245238 var lhs_var: u8 = 1;
test/behavior/sizeof_and_typeof.zig-1
......@@ -19,7 +19,6 @@ test "@sizeOf on compile-time types" {
1919
2020test "@TypeOf() with multiple arguments" {
2121 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
22 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2322 {
2423 var var_1: u32 = undefined;
2524 var var_2: u8 = undefined;
test/behavior/slice.zig-11
......@@ -169,7 +169,6 @@ test "comptime pointer cast array and then slice" {
169169
170170test "slicing zero length array" {
171171 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
172 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
173172 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
174173
175174 const s1 = ""[0..];
......@@ -206,8 +205,6 @@ test "slice string literal has correct type" {
206205}
207206
208207test "result location zero sized array inside struct field implicit cast to slice" {
209 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
210
211208 const E = struct {
212209 entries: []u32,
213210 };
......@@ -229,7 +226,6 @@ fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
229226
230227test "C pointer" {
231228 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
232 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
233229
234230 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
235231 var len: u32 = 10;
......@@ -323,7 +319,6 @@ test "empty array to slice" {
323319
324320test "@ptrCast slice to pointer" {
325321 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
326 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
327322
328323 const S = struct {
329324 fn doTheTest() !void {
......@@ -339,7 +334,6 @@ test "@ptrCast slice to pointer" {
339334}
340335
341336test "slice syntax resulting in pointer-to-array" {
342 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
343337 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
344338 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
345339 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -477,7 +471,6 @@ test "slice syntax resulting in pointer-to-array" {
477471}
478472
479473test "slice pointer-to-array null terminated" {
480 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
481474 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
482475 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
483476
......@@ -503,7 +496,6 @@ test "slice pointer-to-array null terminated" {
503496}
504497
505498test "slice pointer-to-array zero length" {
506 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
507499 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
508500
509501 comptime {
......@@ -541,7 +533,6 @@ test "slice pointer-to-array zero length" {
541533}
542534
543535test "type coercion of pointer to anon struct literal to pointer to slice" {
544 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
545536 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
546537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
547538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -637,7 +628,6 @@ test "slice sentinel access at comptime" {
637628test "slicing array with sentinel as end index" {
638629 // Doesn't work in stage1
639630 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
640 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
641631 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
642632
643633 const S = struct {
......@@ -657,7 +647,6 @@ test "slicing array with sentinel as end index" {
657647test "slicing slice with sentinel as end index" {
658648 // Doesn't work in stage1
659649 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
660 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
661650 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
662651
663652 const S = struct {
test/behavior/struct.zig-33
......@@ -284,7 +284,6 @@ const Val = struct {
284284
285285test "struct point to self" {
286286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
287 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
288287 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
289288
290289 var root: Node = undefined;
......@@ -319,7 +318,6 @@ const VoidStructFieldsFoo = struct {
319318
320319test "return empty struct from fn" {
321320 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
322 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
323321 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
324322
325323 _ = testReturnEmptyStructFromFn();
......@@ -331,7 +329,6 @@ fn testReturnEmptyStructFromFn() EmptyStruct2 {
331329
332330test "pass slice of empty struct to fn" {
333331 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
334 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
335332 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
336333
337334 try expect(testPassSliceOfEmptyStructToFn(&[_]EmptyStruct2{EmptyStruct2{}}) == 1);
......@@ -342,7 +339,6 @@ fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) usize {
342339
343340test "self-referencing struct via array member" {
344341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
345 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
346342 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
347343 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
348344 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -356,8 +352,6 @@ test "self-referencing struct via array member" {
356352}
357353
358354test "empty struct method call" {
359 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
360
361355 const es = EmptyStruct{};
362356 try expect(es.method() == 1234);
363357}
......@@ -370,7 +364,6 @@ const EmptyStruct = struct {
370364
371365test "align 1 field before self referential align 8 field as slice return type" {
372366 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
373 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
374367 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
375368
376369 const result = alloc(Expr);
......@@ -394,7 +387,6 @@ const APackedStruct = packed struct {
394387test "packed struct" {
395388 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
396389 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
397 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
398390 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
399391 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
400392 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -421,7 +413,6 @@ const Foo96Bits = packed struct {
421413test "packed struct 24bits" {
422414 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
423415 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
424 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
425416 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
426417 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
427418 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO
......@@ -470,7 +461,6 @@ test "packed struct 24bits" {
470461test "runtime struct initialization of bitfield" {
471462 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
472463 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
473 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
474464 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
475465 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
476466 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -515,7 +505,6 @@ test "packed struct fields are ordered from LSB to MSB" {
515505 }
516506 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
517507 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
518 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
519508 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
520509 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
521510 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -537,7 +526,6 @@ test "packed struct fields are ordered from LSB to MSB" {
537526test "implicit cast packed struct field to const ptr" {
538527 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
539528 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
540 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
541529 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
542530 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
543531 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -559,7 +547,6 @@ test "implicit cast packed struct field to const ptr" {
559547
560548test "zero-bit field in packed struct" {
561549 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
562 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
563550 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
564551 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
565552
......@@ -605,7 +592,6 @@ const bit_field_1 = BitField1{
605592test "bit field access" {
606593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
607594 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
608 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
609595 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
610596 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
611597 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -638,7 +624,6 @@ fn getC(data: *const BitField1) u2 {
638624
639625test "default struct initialization fields" {
640626 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
641 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
642627 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
643628
644629 const S = struct {
......@@ -771,7 +756,6 @@ test "pointer to packed struct member in a stack variable" {
771756test "packed struct with u0 field access" {
772757 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
773758 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
774 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
775759 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
776760
777761 const S = packed struct {
......@@ -783,7 +767,6 @@ test "packed struct with u0 field access" {
783767
784768test "access to global struct fields" {
785769 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
786 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
787770 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
788771
789772 g_foo.bar.value = 42;
......@@ -810,7 +793,6 @@ test "packed struct with fp fields" {
810793 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
811794 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
812795 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
813 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
814796
815797 const S = packed struct {
816798 data0: f32,
......@@ -886,7 +868,6 @@ test "packed struct field passed to generic function" {
886868 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
887869 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
888870 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
889 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
890871 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
891872
892873 const S = struct {
......@@ -910,7 +891,6 @@ test "packed struct field passed to generic function" {
910891
911892test "anonymous struct literal syntax" {
912893 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
913 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
914894
915895 const S = struct {
916896 const Point = struct {
......@@ -932,8 +912,6 @@ test "anonymous struct literal syntax" {
932912}
933913
934914test "fully anonymous struct" {
935 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
936
937915 const S = struct {
938916 fn doTheTest() !void {
939917 try dump(.{
......@@ -956,8 +934,6 @@ test "fully anonymous struct" {
956934}
957935
958936test "fully anonymous list literal" {
959 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
960
961937 const S = struct {
962938 fn doTheTest() !void {
963939 try dump(.{ @as(u32, 1234), @as(f64, 12.34), true, "hi" });
......@@ -1000,7 +976,6 @@ test "comptime struct field" {
1000976}
1001977
1002978test "tuple element initialized with fn call" {
1003 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1004979 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1005980 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1006981 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1039,7 +1014,6 @@ test "struct with union field" {
10391014}
10401015
10411016test "type coercion of anon struct literal to struct" {
1042 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10431017 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10441018 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10451019 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1078,7 +1052,6 @@ test "type coercion of anon struct literal to struct" {
10781052
10791053test "type coercion of pointer to anon struct literal to pointer to struct" {
10801054 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1081 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10821055 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10831056 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10841057 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1118,7 +1091,6 @@ test "type coercion of pointer to anon struct literal to pointer to struct" {
11181091test "packed struct with undefined initializers" {
11191092 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11201093 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1121 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11221094 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11231095 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11241096 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1190,7 +1162,6 @@ test "for loop over pointers to struct, getting field from struct pointer" {
11901162
11911163test "anon init through error unions and optionals" {
11921164 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1193 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11941165 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11951166 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11961167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1219,7 +1190,6 @@ test "anon init through error unions and optionals" {
12191190
12201191test "anon init through optional" {
12211192 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1222 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12231193 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12241194 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12251195 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1241,7 +1211,6 @@ test "anon init through optional" {
12411211
12421212test "anon init through error union" {
12431213 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1244 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12451214 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12461215 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12471216 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1263,7 +1232,6 @@ test "anon init through error union" {
12631232
12641233test "typed init through error unions and optionals" {
12651234 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
1266 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12671235 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
12681236 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12691237 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1332,7 +1300,6 @@ test "packed struct aggregate init" {
13321300 }
13331301 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
13341302 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1335 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13361303 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13371304 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13381305 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/struct_contains_null_ptr_itself.zig-1
......@@ -5,7 +5,6 @@ const builtin = @import("builtin");
55test "struct contains null pointer which contains original struct" {
66 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
77 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
98 var x: ?*NodeLineComment = null;
109 try expect(x == null);
1110}
test/behavior/struct_contains_slice_of_itself.zig-2
......@@ -12,7 +12,6 @@ const NodeAligned = struct {
1212};
1313
1414test "struct contains slice of itself" {
15 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1615 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1716
1817 var other_nodes = [_]Node{
......@@ -52,7 +51,6 @@ test "struct contains slice of itself" {
5251}
5352
5453test "struct contains aligned slice of itself" {
55 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5654 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5755
5856 var other_nodes = [_]NodeAligned{
test/behavior/switch.zig-3
......@@ -420,7 +420,6 @@ test "else prong of switch on error set excludes other cases" {
420420 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
421421 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
422422 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
423 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
424423
425424 const S = struct {
426425 fn doTheTest() !void {
......@@ -455,7 +454,6 @@ test "switch prongs with error set cases make a new error set type for capture v
455454 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
456455 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
457456 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
458 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
459457
460458 const S = struct {
461459 fn doTheTest() !void {
......@@ -621,7 +619,6 @@ test "switch capture copies its payload" {
621619 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
622620 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
623621 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
624 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
625622
626623 const S = struct {
627624 fn doTheTest() !void {
test/behavior/switch_prong_err_enum.zig-1
......@@ -24,7 +24,6 @@ test "switch prong returns error enum" {
2424 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2525 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2626 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
27 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2827 switch (doThing(17) catch unreachable) {
2928 FormValue.Address => |payload| {
3029 try expect(payload == 1);
test/behavior/switch_prong_implicit_cast.zig-1
......@@ -18,7 +18,6 @@ test "switch prong implicit cast" {
1818 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1919 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2020 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
21 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2221 const result = switch (foo(2) catch unreachable) {
2322 FormValue.One => false,
2423 FormValue.Two => |x| x,
test/behavior/translate_c_macros.zig-8
......@@ -21,7 +21,6 @@ test "casting to void with a macro" {
2121}
2222
2323test "initializer list expression" {
24 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2524 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
2625 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2726 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -48,7 +47,6 @@ test "reference to a struct type" {
4847test "cast negative integer to pointer" {
4948 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
5049 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
51 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
5250 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5351 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5452
......@@ -58,7 +56,6 @@ test "cast negative integer to pointer" {
5856test "casting to union with a macro" {
5957 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
6058 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
6259 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
6360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
6461
......@@ -75,7 +72,6 @@ test "casting to union with a macro" {
7572test "casting or calling a value with a paren-surrounded macro" {
7673 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
7774 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7975 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
8076 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8177
......@@ -95,7 +91,6 @@ test "casting or calling a value with a paren-surrounded macro" {
9591test "nested comma operator" {
9692 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
9793 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
98 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
9994 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10095 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10196
......@@ -106,7 +101,6 @@ test "nested comma operator" {
106101test "cast functions" {
107102 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
108103 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
109 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
110104 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
111105 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
112106
......@@ -120,7 +114,6 @@ test "cast functions" {
120114test "large integer macro" {
121115 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
122116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
123 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
124117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
125118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
126119
......@@ -151,7 +144,6 @@ test "string and char literals that are not UTF-8 encoded. Issue #12784" {
151144test "Macro that uses division operator. Issue #13162" {
152145 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
153146 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
154 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
155147 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
156148 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
157149
test/behavior/tuple.zig-5
......@@ -205,7 +205,6 @@ test "initializing anon struct with explicit type" {
205205}
206206
207207test "fieldParentPtr of tuple" {
208 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
209208 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
210209 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
211210 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -216,7 +215,6 @@ test "fieldParentPtr of tuple" {
216215}
217216
218217test "fieldParentPtr of anon struct" {
219 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
220218 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
221219 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
222220 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
......@@ -257,7 +255,6 @@ test "initializing anon struct with mixed comptime-runtime fields" {
257255}
258256
259257test "tuple in tuple passed to generic function" {
260 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
261258 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
262259 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
263260 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
......@@ -277,7 +274,6 @@ test "tuple in tuple passed to generic function" {
277274}
278275
279276test "coerce tuple to tuple" {
280 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
281277 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
282278 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
283279 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
......@@ -292,7 +288,6 @@ test "coerce tuple to tuple" {
292288}
293289
294290test "tuple type with void field" {
295 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
296291 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
297292 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
298293 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/type.zig-7
......@@ -200,7 +200,6 @@ test "Type.ErrorUnion" {
200200
201201test "Type.Opaque" {
202202 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
204203 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
205204 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
206205 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -248,7 +247,6 @@ fn add(a: i32, b: i32) i32 {
248247
249248test "Type.ErrorSet" {
250249 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
251 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
252250
253251 try testing.expect(@Type(.{ .ErrorSet = null }) == anyerror);
254252
......@@ -351,7 +349,6 @@ test "Type.Struct" {
351349}
352350
353351test "Type.Enum" {
354 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
355352 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
356353 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
357354 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -396,7 +393,6 @@ test "Type.Enum" {
396393
397394test "Type.Union" {
398395 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
399 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
400396 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
401397 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
402398 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -462,7 +458,6 @@ test "Type.Union" {
462458}
463459
464460test "Type.Union from Type.Enum" {
465 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
466461 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
467462
468463 const Tag = @Type(.{
......@@ -490,7 +485,6 @@ test "Type.Union from Type.Enum" {
490485}
491486
492487test "Type.Union from regular enum" {
493 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
494488 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
495489
496490 const E = enum { working_as_expected };
......@@ -509,7 +503,6 @@ test "Type.Union from regular enum" {
509503
510504test "Type.Fn" {
511505 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
512 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
513506
514507 if (true) {
515508 // https://github.com/ziglang/zig/issues/12360
test/behavior/type_info.zig+4-13
......@@ -355,19 +355,12 @@ fn testOpaque() !void {
355355}
356356
357357test "type info: function type info" {
358 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
359 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
360 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
361
362 // wasm doesn't support align attributes on functions
363 if (builtin.target.cpu.arch == .wasm32 or builtin.target.cpu.arch == .wasm64) return error.SkipZigTest;
364
365358 try testFunction();
366359 comptime try testFunction();
367360}
368361
369362fn testFunction() !void {
370 const fn_info = @typeInfo(@TypeOf(foo));
363 const fn_info = @typeInfo(@TypeOf(typeInfoFoo));
371364 try expect(fn_info == .Fn);
372365 try expect(fn_info.Fn.alignment > 0);
373366 try expect(fn_info.Fn.calling_convention == .C);
......@@ -375,16 +368,14 @@ fn testFunction() !void {
375368 try expect(fn_info.Fn.args.len == 2);
376369 try expect(fn_info.Fn.is_var_args);
377370 try expect(fn_info.Fn.return_type.? == usize);
378 const fn_aligned_info = @typeInfo(@TypeOf(fooAligned));
371 const fn_aligned_info = @typeInfo(@TypeOf(typeInfoFooAligned));
379372 try expect(fn_aligned_info.Fn.alignment == 4);
380373}
381374
382extern fn foo(a: usize, b: bool, ...) callconv(.C) usize;
383extern fn fooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
375extern fn typeInfoFoo(a: usize, b: bool, ...) callconv(.C) usize;
376extern fn typeInfoFooAligned(a: usize, b: bool, ...) align(4) callconv(.C) usize;
384377
385378test "type info: generic function types" {
386 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
387
388379 if (builtin.zig_backend != .stage1) {
389380 // stage1 marks all args/return types as null if the function
390381 // is generic at all. stage2 is more specific.
test/behavior/undefined.zig-1
......@@ -15,7 +15,6 @@ const static_array = initStaticArray();
1515test "init static array to undefined" {
1616 // This test causes `initStaticArray()` to be codegen'd, and the
1717 // C backend does not yet support returning arrays, so it fails
18 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
1918 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
2019 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
2120
test/behavior/union.zig-13
......@@ -431,7 +431,6 @@ const Foo1 = union(enum) {
431431var glbl: Foo1 = undefined;
432432
433433test "global union with single field is correctly initialized" {
434 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
435434 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
436435 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
437436 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -476,7 +475,6 @@ test "update the tag value for zero-sized unions" {
476475}
477476
478477test "union initializer generates padding only if needed" {
479 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
480478 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
481479 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
482480 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -753,7 +751,6 @@ fn Setter(comptime attr: Attribute) type {
753751}
754752
755753test "return union init with void payload" {
756 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
757754 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
758755 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
759756 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
......@@ -779,7 +776,6 @@ test "return union init with void payload" {
779776}
780777
781778test "@unionInit stored to a const" {
782 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
783779 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
784780 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
785781 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -942,7 +938,6 @@ test "function call result coerces from tagged union to the tag" {
942938}
943939
944940test "cast from anonymous struct to union" {
945 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
946941 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
947942 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
948943 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -975,7 +970,6 @@ test "cast from anonymous struct to union" {
975970}
976971
977972test "cast from pointer to anonymous struct to pointer to union" {
978 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
979973 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
980974 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
981975 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1062,7 +1056,6 @@ test "containers with single-field enums" {
10621056}
10631057
10641058test "@unionInit on union with tag but no fields" {
1065 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10661059 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10671060 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
10681061 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
......@@ -1138,7 +1131,6 @@ test "global variable struct contains union initialized to non-most-aligned fiel
11381131}
11391132
11401133test "union with no result loc initiated with a runtime value" {
1141 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11421134 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11431135 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11441136 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
......@@ -1155,7 +1147,6 @@ test "union with no result loc initiated with a runtime value" {
11551147}
11561148
11571149test "union with a large struct field" {
1158 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11591150 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11601151 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11611152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
......@@ -1189,7 +1180,6 @@ test "comptime equality of extern unions with same tag" {
11891180}
11901181
11911182test "union tag is set when initiated as a temporary value at runtime" {
1192 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11931183 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11941184 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11951185
......@@ -1325,7 +1315,6 @@ test "union and enum field order doesn't match" {
13251315}
13261316
13271317test "@unionInit uses tag value instead of field index" {
1328 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13291318 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13301319 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13311320 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1353,7 +1342,6 @@ test "@unionInit uses tag value instead of field index" {
13531342}
13541343
13551344test "union field ptr - zero sized payload" {
1356 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13571345 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13581346 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13591347
......@@ -1367,7 +1355,6 @@ test "union field ptr - zero sized payload" {
13671355}
13681356
13691357test "union field ptr - zero sized field" {
1370 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13711358 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13721359 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
13731360
test/behavior/union_with_members.zig-1
......@@ -19,7 +19,6 @@ const ET = union(enum) {
1919test "enum with members" {
2020 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
2121 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
2322 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2423 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2524
test/behavior/vector.zig-2
......@@ -811,7 +811,6 @@ test "vector reduce operation" {
811811test "vector @reduce comptime" {
812812 if (builtin.zig_backend == .stage1) return error.SkipZigTest;
813813 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
814 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
815814 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
816815 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
817816 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1138,7 +1137,6 @@ test "array of vectors is copied" {
11381137
11391138test "byte vector initialized in inline function" {
11401139 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1141 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
11421140 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
11431141 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
11441142 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/widening.zig-4
......@@ -8,7 +8,6 @@ test "integer widening" {
88 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1010 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
11 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1211
1312 var a: u8 = 250;
1413 var b: u16 = a;
......@@ -30,7 +29,6 @@ test "integer widening u0 to u8" {
3029test "implicit unsigned integer to signed integer" {
3130 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
3231 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
33 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
3432
3533 var a: u8 = 250;
3634 var b: i16 = a;
......@@ -42,7 +40,6 @@ test "float widening" {
4240 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
4341 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
4442 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
45 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
4643
4744 var a: f16 = 12.34;
4845 var b: f32 = a;
......@@ -62,7 +59,6 @@ test "float widening f16 to f128" {
6259 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
6360 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
6461 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
65 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
6662
6763 // TODO https://github.com/ziglang/zig/issues/3282
6864 if (builtin.cpu.arch == .aarch64) return error.SkipZigTest;
test/cases/aarch64-macos/hello_world_with_updates.0.zig+1-1
......@@ -2,4 +2,4 @@
22// output_mode=Exe
33// target=aarch64-macos
44//
5// :109:9: error: root struct of file 'tmp' has no member named 'main'
5// :108:9: error: root struct of file 'tmp' has no member named 'main'
test/cases/x86_64-linux/hello_world_with_updates.0.zig+1-1
......@@ -2,4 +2,4 @@
22// output_mode=Exe
33// target=x86_64-linux
44//
5// :109:9: error: root struct of file 'tmp' has no member named 'main'
5// :108:9: error: root struct of file 'tmp' has no member named 'main'
test/cases/x86_64-macos/hello_world_with_updates.0.zig+1-1
......@@ -2,4 +2,4 @@
22// output_mode=Exe
33// target=x86_64-macos
44//
5// :109:9: error: root struct of file 'tmp' has no member named 'main'
5// :108:9: error: root struct of file 'tmp' has no member named 'main'
test/cases/x86_64-windows/hello_world_with_updates.0.zig+1-1
......@@ -2,4 +2,4 @@
22// output_mode=Exe
33// target=x86_64-windows
44//
5// :130:9: error: root struct of file 'tmp' has no member named 'main'
5// :129:9: error: root struct of file 'tmp' has no member named 'main'
test/stage2/cbe.zig+11-11
......@@ -951,7 +951,7 @@ pub fn addCases(ctx: *TestContext) !void {
951951 ctx.h("simple header", linux_x64,
952952 \\export fn start() void{}
953953 ,
954 \\ZIG_EXTERN_C void start(void);
954 \\zig_extern_c zig_void start(zig_void);
955955 \\
956956 );
957957 ctx.h("header with single param function", linux_x64,
......@@ -959,7 +959,7 @@ pub fn addCases(ctx: *TestContext) !void {
959959 \\ _ = a;
960960 \\}
961961 ,
962 \\ZIG_EXTERN_C void start(uint8_t a0);
962 \\zig_extern_c zig_void start(zig_u8 const a0);
963963 \\
964964 );
965965 ctx.h("header with multiple param function", linux_x64,
......@@ -967,25 +967,25 @@ pub fn addCases(ctx: *TestContext) !void {
967967 \\ _ = a; _ = b; _ = c;
968968 \\}
969969 ,
970 \\ZIG_EXTERN_C void start(uint8_t a0, uint8_t a1, uint8_t a2);
970 \\zig_extern_c zig_void start(zig_u8 const a0, zig_u8 const a1, zig_u8 const a2);
971971 \\
972972 );
973973 ctx.h("header with u32 param function", linux_x64,
974974 \\export fn start(a: u32) void{ _ = a; }
975975 ,
976 \\ZIG_EXTERN_C void start(uint32_t a0);
976 \\zig_extern_c zig_void start(zig_u32 const a0);
977977 \\
978978 );
979979 ctx.h("header with usize param function", linux_x64,
980980 \\export fn start(a: usize) void{ _ = a; }
981981 ,
982 \\ZIG_EXTERN_C void start(uintptr_t a0);
982 \\zig_extern_c zig_void start(zig_usize const a0);
983983 \\
984984 );
985985 ctx.h("header with bool param function", linux_x64,
986986 \\export fn start(a: bool) void{_ = a;}
987987 ,
988 \\ZIG_EXTERN_C void start(bool a0);
988 \\zig_extern_c zig_void start(zig_bool const a0);
989989 \\
990990 );
991991 ctx.h("header with noreturn function", linux_x64,
......@@ -993,7 +993,7 @@ pub fn addCases(ctx: *TestContext) !void {
993993 \\ unreachable;
994994 \\}
995995 ,
996 \\ZIG_EXTERN_C zig_noreturn void start(void);
996 \\zig_extern_c zig_noreturn start(zig_void);
997997 \\
998998 );
999999 ctx.h("header with multiple functions", linux_x64,
......@@ -1001,15 +1001,15 @@ pub fn addCases(ctx: *TestContext) !void {
10011001 \\export fn b() void{}
10021002 \\export fn c() void{}
10031003 ,
1004 \\ZIG_EXTERN_C void a(void);
1005 \\ZIG_EXTERN_C void b(void);
1006 \\ZIG_EXTERN_C void c(void);
1004 \\zig_extern_c zig_void a(zig_void);
1005 \\zig_extern_c zig_void b(zig_void);
1006 \\zig_extern_c zig_void c(zig_void);
10071007 \\
10081008 );
10091009 ctx.h("header with multiple includes", linux_x64,
10101010 \\export fn start(a: u32, b: usize) void{ _ = a; _ = b; }
10111011 ,
1012 \\ZIG_EXTERN_C void start(uint32_t a0, uintptr_t a1);
1012 \\zig_extern_c zig_void start(zig_u32 const a0, zig_usize const a1);
10131013 \\
10141014 );
10151015}