authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-22 11:06:13-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-02-22 11:06:13-05:00
logc9e02d3e69f909a6eb215286c6109f2b3f1e68a2
tree2cd77390db945adb9b54ca9cdb5356bc66bb381d
parent436e99d13ba188412b8a431b69cc9ff29c6bec4a
parent248fb40dcc5eb50cf19e711197c5d1b210abf1b3
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14691 from jacobly0/ctype


18 files changed, 6472 insertions(+), 2040 deletions(-)

CMakeLists.txt+2-1
......@@ -569,6 +569,7 @@ set(ZIG_STAGE2_SOURCES
569569 "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig"
570570 "${CMAKE_SOURCE_DIR}/src/codegen.zig"
571571 "${CMAKE_SOURCE_DIR}/src/codegen/c.zig"
572 "${CMAKE_SOURCE_DIR}/src/codegen/c/type.zig"
572573 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"
573574 "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig"
574575 "${CMAKE_SOURCE_DIR}/src/glibc.zig"
......@@ -784,7 +785,7 @@ set_target_properties(zig2 PROPERTIES
784785 COMPILE_FLAGS ${ZIG2_COMPILE_FLAGS}
785786 LINK_FLAGS ${ZIG2_LINK_FLAGS}
786787)
787target_include_directories(zig2 PUBLIC "${CMAKE_SOURCE_DIR}/lib")
788target_include_directories(zig2 PUBLIC "${CMAKE_SOURCE_DIR}/stage1")
788789target_link_libraries(zig2 LINK_PUBLIC zigcpp)
789790
790791if(MSVC)
build.zig+31
......@@ -509,8 +509,39 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
509509 run_opt.addArg("-o");
510510 run_opt.addFileSourceArg(.{ .path = "stage1/zig1.wasm" });
511511
512 const CopyFileStep = struct {
513 const Step = std.Build.Step;
514 const FileSource = std.Build.FileSource;
515 const CopyFileStep = @This();
516
517 step: Step,
518 builder: *std.Build,
519 source: FileSource,
520 dest_rel_path: []const u8,
521
522 pub fn init(builder: *std.Build, source: FileSource, dest_rel_path: []const u8) CopyFileStep {
523 return CopyFileStep{
524 .builder = builder,
525 .step = Step.init(.custom, builder.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }), builder.allocator, make),
526 .source = source.dupe(builder),
527 .dest_rel_path = builder.dupePath(dest_rel_path),
528 };
529 }
530
531 fn make(step: *Step) !void {
532 const self = @fieldParentPtr(CopyFileStep, "step", step);
533 const full_src_path = self.source.getPath(self.builder);
534 const full_dest_path = self.builder.pathFromRoot(self.dest_rel_path);
535 try self.builder.updateFile(full_src_path, full_dest_path);
536 }
537 };
538
539 const copy_zig_h = try b.allocator.create(CopyFileStep);
540 copy_zig_h.* = CopyFileStep.init(b, .{ .path = "lib/zig.h" }, "stage1/zig.h");
541
512542 const update_zig1_step = b.step("update-zig1", "Update stage1/zig1.wasm");
513543 update_zig1_step.dependOn(&run_opt.step);
544 update_zig1_step.dependOn(&copy_zig_h.step);
514545}
515546
516547fn addCompilerStep(
lib/std/hash_map.zig+2-2
......@@ -508,7 +508,7 @@ pub fn HashMap(
508508 /// If a new entry needs to be stored, this function asserts there
509509 /// is enough capacity to store it.
510510 pub fn getOrPutAssumeCapacityAdapted(self: *Self, key: anytype, ctx: anytype) GetOrPutResult {
511 return self.unmanaged.getOrPutAssumeCapacityAdapted(self.allocator, key, ctx);
511 return self.unmanaged.getOrPutAssumeCapacityAdapted(key, ctx);
512512 }
513513
514514 pub fn getOrPutValue(self: *Self, key: K, value: V) Allocator.Error!Entry {
......@@ -2130,7 +2130,7 @@ test "std.hash_map getOrPutAdapted" {
21302130 try testing.expectEqual(map.count(), keys.len);
21312131
21322132 inline for (keys, 0..) |key_str, i| {
2133 const result = try map.getOrPutAdapted(key_str, AdaptedContext{});
2133 const result = map.getOrPutAssumeCapacityAdapted(key_str, AdaptedContext{});
21342134 try testing.expect(result.found_existing);
21352135 try testing.expectEqual(real_keys[i], result.key_ptr.*);
21362136 try testing.expectEqual(@as(u64, i) * 2, result.value_ptr.*);
lib/std/multi_array_list.zig+3-9
......@@ -433,15 +433,9 @@ pub fn MultiArrayList(comptime S: type) type {
433433 }
434434
435435 fn capacityInBytes(capacity: usize) usize {
436 if (builtin.zig_backend == .stage2_c) {
437 var bytes: usize = 0;
438 for (sizes.bytes) |size| bytes += size * capacity;
439 return bytes;
440 } else {
441 const sizes_vector: @Vector(sizes.bytes.len, usize) = sizes.bytes;
442 const capacity_vector = @splat(sizes.bytes.len, capacity);
443 return @reduce(.Add, capacity_vector * sizes_vector);
444 }
436 comptime var elem_bytes: usize = 0;
437 inline for (sizes.bytes) |size| elem_bytes += size;
438 return elem_bytes * capacity;
445439 }
446440
447441 fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {
lib/zig.h+860-767
......@@ -1,6 +1,8 @@
11#undef linux
22
3#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
34#define __STDC_WANT_IEC_60559_TYPES_EXT__
5#endif
46#include <float.h>
57#include <limits.h>
68#include <stddef.h>
......@@ -286,701 +288,802 @@ typedef char bool;
286288#endif
287289
288290#if __STDC_VERSION__ >= 201112L
289#define zig_noreturn _Noreturn void
291#define zig_noreturn _Noreturn
290292#elif zig_has_attribute(noreturn) || defined(zig_gnuc)
291#define zig_noreturn __attribute__((noreturn)) void
293#define zig_noreturn __attribute__((noreturn))
292294#elif _MSC_VER
293#define zig_noreturn __declspec(noreturn) void
295#define zig_noreturn __declspec(noreturn)
294296#else
295#define zig_noreturn void
297#define zig_noreturn
296298#endif
297299
298300#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
299301
300typedef uintptr_t zig_usize;
301typedef intptr_t zig_isize;
302typedef signed short int zig_c_short;
303typedef unsigned short int zig_c_ushort;
304typedef signed int zig_c_int;
305typedef unsigned int zig_c_uint;
306typedef signed long int zig_c_long;
307typedef unsigned long int zig_c_ulong;
308typedef signed long long int zig_c_longlong;
309typedef unsigned long long int zig_c_ulonglong;
310
311typedef uint8_t zig_u8;
312typedef int8_t zig_i8;
313typedef uint16_t zig_u16;
314typedef int16_t zig_i16;
315typedef uint32_t zig_u32;
316typedef int32_t zig_i32;
317typedef uint64_t zig_u64;
318typedef int64_t zig_i64;
319
320#define zig_as_u8(val) UINT8_C(val)
321#define zig_as_i8(val) INT8_C(val)
322#define zig_as_u16(val) UINT16_C(val)
323#define zig_as_i16(val) INT16_C(val)
324#define zig_as_u32(val) UINT32_C(val)
325#define zig_as_i32(val) INT32_C(val)
326#define zig_as_u64(val) UINT64_C(val)
327#define zig_as_i64(val) INT64_C(val)
328
329#define zig_minInt_u8 zig_as_u8(0)
330#define zig_maxInt_u8 UINT8_MAX
302#define zig_compiler_rt_abbrev_uint32_t si
303#define zig_compiler_rt_abbrev_int32_t si
304#define zig_compiler_rt_abbrev_uint64_t di
305#define zig_compiler_rt_abbrev_int64_t di
306#define zig_compiler_rt_abbrev_zig_u128 ti
307#define zig_compiler_rt_abbrev_zig_i128 ti
308#define zig_compiler_rt_abbrev_zig_f16 hf
309#define zig_compiler_rt_abbrev_zig_f32 sf
310#define zig_compiler_rt_abbrev_zig_f64 df
311#define zig_compiler_rt_abbrev_zig_f80 xf
312#define zig_compiler_rt_abbrev_zig_f128 tf
313
314zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
315zig_extern void *memset (void *, int, size_t);
316
317/* ===================== 8/16/32/64-bit Integer Support ===================== */
318
319#if __STDC_VERSION__ >= 199901L || _MSC_VER
320#include <stdint.h>
321#else
322
323#if SCHAR_MIN == ~0x7F && SCHAR_MAX == 0x7F && UCHAR_MAX == 0xFF
324typedef unsigned char uint8_t;
325typedef signed char int8_t;
326#define INT8_C(c) c
327#define UINT8_C(c) c##U
328#elif SHRT_MIN == ~0x7F && SHRT_MAX == 0x7F && USHRT_MAX == 0xFF
329typedef unsigned short uint8_t;
330typedef signed short int8_t;
331#define INT8_C(c) c
332#define UINT8_C(c) c##U
333#elif INT_MIN == ~0x7F && INT_MAX == 0x7F && UINT_MAX == 0xFF
334typedef unsigned int uint8_t;
335typedef signed int int8_t;
336#define INT8_C(c) c
337#define UINT8_C(c) c##U
338#elif LONG_MIN == ~0x7F && LONG_MAX == 0x7F && ULONG_MAX == 0xFF
339typedef unsigned long uint8_t;
340typedef signed long int8_t;
341#define INT8_C(c) c##L
342#define UINT8_C(c) c##LU
343#elif LLONG_MIN == ~0x7F && LLONG_MAX == 0x7F && ULLONG_MAX == 0xFF
344typedef unsigned long long uint8_t;
345typedef signed long long int8_t;
346#define INT8_C(c) c##LL
347#define UINT8_C(c) c##LLU
348#endif
349#define INT8_MIN (~INT8_C(0x7F))
350#define INT8_MAX ( INT8_C(0x7F))
351#define UINT8_MAX ( INT8_C(0xFF))
352
353#if SCHAR_MIN == ~0x7FFF && SCHAR_MAX == 0x7FFF && UCHAR_MAX == 0xFFFF
354typedef unsigned char uint16_t;
355typedef signed char int16_t;
356#define INT16_C(c) c
357#define UINT16_C(c) c##U
358#elif SHRT_MIN == ~0x7FFF && SHRT_MAX == 0x7FFF && USHRT_MAX == 0xFFFF
359typedef unsigned short uint16_t;
360typedef signed short int16_t;
361#define INT16_C(c) c
362#define UINT16_C(c) c##U
363#elif INT_MIN == ~0x7FFF && INT_MAX == 0x7FFF && UINT_MAX == 0xFFFF
364typedef unsigned int uint16_t;
365typedef signed int int16_t;
366#define INT16_C(c) c
367#define UINT16_C(c) c##U
368#elif LONG_MIN == ~0x7FFF && LONG_MAX == 0x7FFF && ULONG_MAX == 0xFFFF
369typedef unsigned long uint16_t;
370typedef signed long int16_t;
371#define INT16_C(c) c##L
372#define UINT16_C(c) c##LU
373#elif LLONG_MIN == ~0x7FFF && LLONG_MAX == 0x7FFF && ULLONG_MAX == 0xFFFF
374typedef unsigned long long uint16_t;
375typedef signed long long int16_t;
376#define INT16_C(c) c##LL
377#define UINT16_C(c) c##LLU
378#endif
379#define INT16_MIN (~INT16_C(0x7FFF))
380#define INT16_MAX ( INT16_C(0x7FFF))
381#define UINT16_MAX ( INT16_C(0xFFFF))
382
383#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
384typedef unsigned char uint32_t;
385typedef signed char int32_t;
386#define INT32_C(c) c
387#define UINT32_C(c) c##U
388#elif SHRT_MIN == ~0x7FFFFFFF && SHRT_MAX == 0x7FFFFFFF && USHRT_MAX == 0xFFFFFFFF
389typedef unsigned short uint32_t;
390typedef signed short int32_t;
391#define INT32_C(c) c
392#define UINT32_C(c) c##U
393#elif INT_MIN == ~0x7FFFFFFF && INT_MAX == 0x7FFFFFFF && UINT_MAX == 0xFFFFFFFF
394typedef unsigned int uint32_t;
395typedef signed int int32_t;
396#define INT32_C(c) c
397#define UINT32_C(c) c##U
398#elif LONG_MIN == ~0x7FFFFFFF && LONG_MAX == 0x7FFFFFFF && ULONG_MAX == 0xFFFFFFFF
399typedef unsigned long uint32_t;
400typedef signed long int32_t;
401#define INT32_C(c) c##L
402#define UINT32_C(c) c##LU
403#elif LLONG_MIN == ~0x7FFFFFFF && LLONG_MAX == 0x7FFFFFFF && ULLONG_MAX == 0xFFFFFFFF
404typedef unsigned long long uint32_t;
405typedef signed long long int32_t;
406#define INT32_C(c) c##LL
407#define UINT32_C(c) c##LLU
408#endif
409#define INT32_MIN (~INT32_C(0x7FFFFFFF))
410#define INT32_MAX ( INT32_C(0x7FFFFFFF))
411#define UINT32_MAX ( INT32_C(0xFFFFFFFF))
412
413#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
414typedef unsigned char uint64_t;
415typedef signed char int64_t;
416#define INT64_C(c) c
417#define UINT64_C(c) c##U
418#elif SHRT_MIN == ~0x7FFFFFFFFFFFFFFF && SHRT_MAX == 0x7FFFFFFFFFFFFFFF && USHRT_MAX == 0xFFFFFFFFFFFFFFFF
419typedef unsigned short uint64_t;
420typedef signed short int64_t;
421#define INT64_C(c) c
422#define UINT64_C(c) c##U
423#elif INT_MIN == ~0x7FFFFFFFFFFFFFFF && INT_MAX == 0x7FFFFFFFFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF
424typedef unsigned int uint64_t;
425typedef signed int int64_t;
426#define INT64_C(c) c
427#define UINT64_C(c) c##U
428#elif LONG_MIN == ~0x7FFFFFFFFFFFFFFF && LONG_MAX == 0x7FFFFFFFFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF
429typedef unsigned long uint64_t;
430typedef signed long int64_t;
431#define INT64_C(c) c##L
432#define UINT64_C(c) c##LU
433#elif LLONG_MIN == ~0x7FFFFFFFFFFFFFFF && LLONG_MAX == 0x7FFFFFFFFFFFFFFF && ULLONG_MAX == 0xFFFFFFFFFFFFFFFF
434typedef unsigned long long uint64_t;
435typedef signed long long int64_t;
436#define INT64_C(c) c##LL
437#define UINT64_C(c) c##LLU
438#endif
439#define INT64_MIN (~INT64_C(0x7FFFFFFFFFFFFFFF))
440#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
441#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))
442
443typedef size_t uintptr_t;
444typedef ptrdiff_t intptr_t;
445
446#endif
447
331448#define zig_minInt_i8 INT8_MIN
332449#define zig_maxInt_i8 INT8_MAX
333#define zig_minInt_u16 zig_as_u16(0)
334#define zig_maxInt_u16 UINT16_MAX
450#define zig_minInt_u8 UINT8_C(0)
451#define zig_maxInt_u8 UINT8_MAX
335452#define zig_minInt_i16 INT16_MIN
336453#define zig_maxInt_i16 INT16_MAX
337#define zig_minInt_u32 zig_as_u32(0)
338#define zig_maxInt_u32 UINT32_MAX
454#define zig_minInt_u16 UINT16_C(0)
455#define zig_maxInt_u16 UINT16_MAX
339456#define zig_minInt_i32 INT32_MIN
340457#define zig_maxInt_i32 INT32_MAX
341#define zig_minInt_u64 zig_as_u64(0)
342#define zig_maxInt_u64 UINT64_MAX
458#define zig_minInt_u32 UINT32_C(0)
459#define zig_maxInt_u32 UINT32_MAX
343460#define zig_minInt_i64 INT64_MIN
344461#define zig_maxInt_i64 INT64_MAX
462#define zig_minInt_u64 UINT64_C(0)
463#define zig_maxInt_u64 UINT64_MAX
345464
346#define zig_compiler_rt_abbrev_u32 si
347#define zig_compiler_rt_abbrev_i32 si
348#define zig_compiler_rt_abbrev_u64 di
349#define zig_compiler_rt_abbrev_i64 di
350#define zig_compiler_rt_abbrev_u128 ti
351#define zig_compiler_rt_abbrev_i128 ti
352#define zig_compiler_rt_abbrev_f16 hf
353#define zig_compiler_rt_abbrev_f32 sf
354#define zig_compiler_rt_abbrev_f64 df
355#define zig_compiler_rt_abbrev_f80 xf
356#define zig_compiler_rt_abbrev_f128 tf
357
358zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, zig_usize);
359zig_extern 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_expand_maxInt(Type, bits) zig_maxInt(Type, bits)
365#define zig_minInt(Type, bits) zig_not_##Type(zig_maxInt(Type, bits), bits)
366#define zig_expand_minInt(Type, bits) zig_minInt(Type, bits)
465#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
466#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
467#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
468#define zig_minInt_u(w, bits) zig_intLimit(u, w, min, bits)
469#define zig_maxInt_u(w, bits) zig_intLimit(u, w, max, bits)
367470
368471#define zig_int_operator(Type, RhsType, operation, operator) \
369 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##RhsType rhs) { \
472 static inline Type zig_##operation(Type lhs, RhsType rhs) { \
370473 return lhs operator rhs; \
371474 }
372475#define zig_int_basic_operator(Type, operation, operator) \
373 zig_int_operator(Type, Type, operation, operator)
476 zig_int_operator(Type, Type, operation, operator)
374477#define zig_int_shift_operator(Type, operation, operator) \
375 zig_int_operator(Type, u8, operation, operator)
478 zig_int_operator(Type, uint8_t, operation, operator)
376479#define zig_int_helpers(w) \
377 zig_int_basic_operator(u##w, and, &) \
378 zig_int_basic_operator(i##w, and, &) \
379 zig_int_basic_operator(u##w, or, |) \
380 zig_int_basic_operator(i##w, or, |) \
381 zig_int_basic_operator(u##w, xor, ^) \
382 zig_int_basic_operator(i##w, xor, ^) \
383 zig_int_shift_operator(u##w, shl, <<) \
384 zig_int_shift_operator(i##w, shl, <<) \
385 zig_int_shift_operator(u##w, shr, >>) \
480 zig_int_basic_operator(uint##w##_t, and_u##w, &) \
481 zig_int_basic_operator( int##w##_t, and_i##w, &) \
482 zig_int_basic_operator(uint##w##_t, or_u##w, |) \
483 zig_int_basic_operator( int##w##_t, or_i##w, |) \
484 zig_int_basic_operator(uint##w##_t, xor_u##w, ^) \
485 zig_int_basic_operator( int##w##_t, xor_i##w, ^) \
486 zig_int_shift_operator(uint##w##_t, shl_u##w, <<) \
487 zig_int_shift_operator( int##w##_t, shl_i##w, <<) \
488 zig_int_shift_operator(uint##w##_t, shr_u##w, >>) \
386489\
387 static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \
388 zig_i##w sign_mask = lhs < zig_as_i##w(0) ? -zig_as_i##w(1) : zig_as_i##w(0); \
490 static inline int##w##_t zig_shr_i##w(int##w##_t lhs, uint8_t rhs) { \
491 int##w##_t sign_mask = lhs < INT##w##_C(0) ? -INT##w##_C(1) : INT##w##_C(0); \
389492 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
390493 } \
391494\
392 static inline zig_u##w zig_not_u##w(zig_u##w val, zig_u8 bits) { \
393 return val ^ zig_maxInt(u##w, bits); \
495 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \
496 return val ^ zig_maxInt_u(w, bits); \
394497 } \
395498\
396 static inline zig_i##w zig_not_i##w(zig_i##w val, zig_u8 bits) { \
499 static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \
397500 (void)bits; \
398501 return ~val; \
399502 } \
400503\
401 static inline zig_u##w zig_wrap_u##w(zig_u##w val, zig_u8 bits) { \
402 return val & zig_maxInt(u##w, bits); \
504 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \
505 return val & zig_maxInt_u(w, bits); \
403506 } \
404507\
405 static inline zig_i##w zig_wrap_i##w(zig_i##w val, zig_u8 bits) { \
406 return (val & zig_as_u##w(1) << (bits - zig_as_u8(1))) != 0 \
407 ? val | zig_minInt(i##w, bits) : val & zig_maxInt(i##w, bits); \
508 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \
509 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
510 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
408511 } \
409512\
410 zig_int_basic_operator(u##w, div_floor, /) \
513 zig_int_basic_operator(uint##w##_t, div_floor_u##w, /) \
411514\
412 static inline zig_i##w zig_div_floor_i##w(zig_i##w lhs, zig_i##w rhs) { \
413 return lhs / rhs - (((lhs ^ rhs) & (lhs % rhs)) < zig_as_i##w(0)); \
515 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \
516 return lhs / rhs - (((lhs ^ rhs) & (lhs % rhs)) < INT##w##_C(0)); \
414517 } \
415518\
416 zig_int_basic_operator(u##w, mod, %) \
519 zig_int_basic_operator(uint##w##_t, mod_u##w, %) \
417520\
418 static inline zig_i##w zig_mod_i##w(zig_i##w lhs, zig_i##w rhs) { \
419 zig_i##w rem = lhs % rhs; \
420 return rem + (((lhs ^ rhs) & rem) < zig_as_i##w(0) ? rhs : zig_as_i##w(0)); \
521 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
522 int##w##_t rem = lhs % rhs; \
523 return rem + (((lhs ^ rhs) & rem) < INT##w##_C(0) ? rhs : INT##w##_C(0)); \
421524 } \
422525\
423 static inline zig_u##w zig_shlw_u##w(zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
526 static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
424527 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
425528 } \
426529\
427 static inline zig_i##w zig_shlw_i##w(zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
428 return zig_wrap_i##w((zig_i##w)zig_shl_u##w((zig_u##w)lhs, (zig_u##w)rhs), bits); \
530 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
531 return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, (uint##w##_t)rhs), bits); \
429532 } \
430533\
431 static inline zig_u##w zig_addw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
534 static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
432535 return zig_wrap_u##w(lhs + rhs, bits); \
433536 } \
434537\
435 static inline zig_i##w zig_addw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
436 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs + (zig_u##w)rhs), bits); \
538 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
539 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \
437540 } \
438541\
439 static inline zig_u##w zig_subw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
542 static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
440543 return zig_wrap_u##w(lhs - rhs, bits); \
441544 } \
442545\
443 static inline zig_i##w zig_subw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
444 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs - (zig_u##w)rhs), bits); \
546 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
547 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \
445548 } \
446549\
447 static inline zig_u##w zig_mulw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
550 static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
448551 return zig_wrap_u##w(lhs * rhs, bits); \
449552 } \
450553\
451 static inline zig_i##w zig_mulw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
452 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs * (zig_u##w)rhs), bits); \
554 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
555 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \
453556 }
454557zig_int_helpers(8)
455558zig_int_helpers(16)
456559zig_int_helpers(32)
457560zig_int_helpers(64)
458561
459static inline bool zig_addo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
562static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
460563#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
461 zig_u32 full_res;
564 uint32_t full_res;
462565 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
463566 *res = zig_wrap_u32(full_res, bits);
464 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
567 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
465568#else
466569 *res = zig_addw_u32(lhs, rhs, bits);
467570 return *res < lhs;
468571#endif
469572}
470573
471static inline void zig_vaddo_u32(zig_u8 *ov, zig_u32 *res, int n,
472 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
574static inline void zig_vaddo_u32(uint8_t *ov, uint32_t *res, int n,
575 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
473576{
474577 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits);
475578}
476579
477zig_extern zig_i32 __addosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
478static inline bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
580zig_extern int32_t __addosi4(int32_t lhs, int32_t rhs, int *overflow);
581static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
479582#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
480 zig_i32 full_res;
583 int32_t full_res;
481584 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
482585#else
483 zig_c_int overflow_int;
484 zig_i32 full_res = __addosi4(lhs, rhs, &overflow_int);
586 int overflow_int;
587 int32_t full_res = __addosi4(lhs, rhs, &overflow_int);
485588 bool overflow = overflow_int != 0;
486589#endif
487590 *res = zig_wrap_i32(full_res, bits);
488 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
591 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
489592}
490593
491static inline void zig_vaddo_i32(zig_u8 *ov, zig_i32 *res, int n,
492 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
594static inline void zig_vaddo_i32(uint8_t *ov, int32_t *res, int n,
595 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
493596{
494597 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits);
495598}
496599
497static inline bool zig_addo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
600static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
498601#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
499 zig_u64 full_res;
602 uint64_t full_res;
500603 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
501604 *res = zig_wrap_u64(full_res, bits);
502 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
605 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
503606#else
504607 *res = zig_addw_u64(lhs, rhs, bits);
505608 return *res < lhs;
506609#endif
507610}
508611
509static inline void zig_vaddo_u64(zig_u8 *ov, zig_u64 *res, int n,
510 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
612static inline void zig_vaddo_u64(uint8_t *ov, uint64_t *res, int n,
613 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
511614{
512615 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits);
513616}
514617
515zig_extern zig_i64 __addodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
516static inline bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
618zig_extern int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
619static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
517620#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
518 zig_i64 full_res;
621 int64_t full_res;
519622 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
520623#else
521 zig_c_int overflow_int;
522 zig_i64 full_res = __addodi4(lhs, rhs, &overflow_int);
624 int overflow_int;
625 int64_t full_res = __addodi4(lhs, rhs, &overflow_int);
523626 bool overflow = overflow_int != 0;
524627#endif
525628 *res = zig_wrap_i64(full_res, bits);
526 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
629 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
527630}
528631
529static inline void zig_vaddo_i64(zig_u8 *ov, zig_i64 *res, int n,
530 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
632static inline void zig_vaddo_i64(uint8_t *ov, int64_t *res, int n,
633 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
531634{
532635 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits);
533636}
534637
535static inline bool zig_addo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
638static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
536639#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
537 zig_u8 full_res;
640 uint8_t full_res;
538641 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
539642 *res = zig_wrap_u8(full_res, bits);
540 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
643 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
541644#else
542 zig_u32 full_res;
645 uint32_t full_res;
543646 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
544 *res = (zig_u8)full_res;
647 *res = (uint8_t)full_res;
545648 return overflow;
546649#endif
547650}
548651
549static inline void zig_vaddo_u8(zig_u8 *ov, zig_u8 *res, int n,
550 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
652static inline void zig_vaddo_u8(uint8_t *ov, uint8_t *res, int n,
653 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
551654{
552655 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits);
553656}
554657
555static inline bool zig_addo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
658static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
556659#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
557 zig_i8 full_res;
660 int8_t full_res;
558661 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
559662 *res = zig_wrap_i8(full_res, bits);
560 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
663 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
561664#else
562 zig_i32 full_res;
665 int32_t full_res;
563666 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
564 *res = (zig_i8)full_res;
667 *res = (int8_t)full_res;
565668 return overflow;
566669#endif
567670}
568671
569static inline void zig_vaddo_i8(zig_u8 *ov, zig_i8 *res, int n,
570 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
672static inline void zig_vaddo_i8(uint8_t *ov, int8_t *res, int n,
673 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
571674{
572675 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits);
573676}
574677
575static inline bool zig_addo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
678static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
576679#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
577 zig_u16 full_res;
680 uint16_t full_res;
578681 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
579682 *res = zig_wrap_u16(full_res, bits);
580 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
683 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
581684#else
582 zig_u32 full_res;
685 uint32_t full_res;
583686 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
584 *res = (zig_u16)full_res;
687 *res = (uint16_t)full_res;
585688 return overflow;
586689#endif
587690}
588691
589static inline void zig_vaddo_u16(zig_u8 *ov, zig_u16 *res, int n,
590 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
692static inline void zig_vaddo_u16(uint8_t *ov, uint16_t *res, int n,
693 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
591694{
592695 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits);
593696}
594697
595static inline bool zig_addo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
698static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
596699#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
597 zig_i16 full_res;
700 int16_t full_res;
598701 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
599702 *res = zig_wrap_i16(full_res, bits);
600 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
703 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
601704#else
602 zig_i32 full_res;
705 int32_t full_res;
603706 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
604 *res = (zig_i16)full_res;
707 *res = (int16_t)full_res;
605708 return overflow;
606709#endif
607710}
608711
609static inline void zig_vaddo_i16(zig_u8 *ov, zig_i16 *res, int n,
610 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
712static inline void zig_vaddo_i16(uint8_t *ov, int16_t *res, int n,
713 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
611714{
612715 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits);
613716}
614717
615static inline bool zig_subo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
718static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
616719#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
617 zig_u32 full_res;
720 uint32_t full_res;
618721 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
619722 *res = zig_wrap_u32(full_res, bits);
620 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
723 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
621724#else
622725 *res = zig_subw_u32(lhs, rhs, bits);
623726 return *res > lhs;
624727#endif
625728}
626729
627static inline void zig_vsubo_u32(zig_u8 *ov, zig_u32 *res, int n,
628 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
730static inline void zig_vsubo_u32(uint8_t *ov, uint32_t *res, int n,
731 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
629732{
630733 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits);
631734}
632735
633zig_extern zig_i32 __subosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
634static inline bool zig_subo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
736zig_extern int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);
737static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
635738#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
636 zig_i32 full_res;
739 int32_t full_res;
637740 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
638741#else
639 zig_c_int overflow_int;
640 zig_i32 full_res = __subosi4(lhs, rhs, &overflow_int);
742 int overflow_int;
743 int32_t full_res = __subosi4(lhs, rhs, &overflow_int);
641744 bool overflow = overflow_int != 0;
642745#endif
643746 *res = zig_wrap_i32(full_res, bits);
644 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
747 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
645748}
646749
647static inline void zig_vsubo_i32(zig_u8 *ov, zig_i32 *res, int n,
648 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
750static inline void zig_vsubo_i32(uint8_t *ov, int32_t *res, int n,
751 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
649752{
650753 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits);
651754}
652755
653static inline bool zig_subo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
756static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
654757#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
655 zig_u64 full_res;
758 uint64_t full_res;
656759 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
657760 *res = zig_wrap_u64(full_res, bits);
658 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
761 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
659762#else
660763 *res = zig_subw_u64(lhs, rhs, bits);
661764 return *res > lhs;
662765#endif
663766}
664767
665static inline void zig_vsubo_u64(zig_u8 *ov, zig_u64 *res, int n,
666 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
768static inline void zig_vsubo_u64(uint8_t *ov, uint64_t *res, int n,
769 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
667770{
668771 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits);
669772}
670773
671zig_extern zig_i64 __subodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
672static inline bool zig_subo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
774zig_extern int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);
775static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
673776#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
674 zig_i64 full_res;
777 int64_t full_res;
675778 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
676779#else
677 zig_c_int overflow_int;
678 zig_i64 full_res = __subodi4(lhs, rhs, &overflow_int);
780 int overflow_int;
781 int64_t full_res = __subodi4(lhs, rhs, &overflow_int);
679782 bool overflow = overflow_int != 0;
680783#endif
681784 *res = zig_wrap_i64(full_res, bits);
682 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
785 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
683786}
684787
685static inline void zig_vsubo_i64(zig_u8 *ov, zig_i64 *res, int n,
686 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
788static inline void zig_vsubo_i64(uint8_t *ov, int64_t *res, int n,
789 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
687790{
688791 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits);
689792}
690793
691static inline bool zig_subo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
794static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
692795#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
693 zig_u8 full_res;
796 uint8_t full_res;
694797 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
695798 *res = zig_wrap_u8(full_res, bits);
696 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
799 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
697800#else
698 zig_u32 full_res;
801 uint32_t full_res;
699802 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
700 *res = (zig_u8)full_res;
803 *res = (uint8_t)full_res;
701804 return overflow;
702805#endif
703806}
704807
705static inline void zig_vsubo_u8(zig_u8 *ov, zig_u8 *res, int n,
706 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
808static inline void zig_vsubo_u8(uint8_t *ov, uint8_t *res, int n,
809 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
707810{
708811 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits);
709812}
710813
711static inline bool zig_subo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
814static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
712815#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
713 zig_i8 full_res;
816 int8_t full_res;
714817 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
715818 *res = zig_wrap_i8(full_res, bits);
716 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
819 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
717820#else
718 zig_i32 full_res;
821 int32_t full_res;
719822 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
720 *res = (zig_i8)full_res;
823 *res = (int8_t)full_res;
721824 return overflow;
722825#endif
723826}
724827
725static inline void zig_vsubo_i8(zig_u8 *ov, zig_i8 *res, int n,
726 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
828static inline void zig_vsubo_i8(uint8_t *ov, int8_t *res, int n,
829 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
727830{
728831 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits);
729832}
730833
731834
732static inline bool zig_subo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
835static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
733836#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
734 zig_u16 full_res;
837 uint16_t full_res;
735838 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
736839 *res = zig_wrap_u16(full_res, bits);
737 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
840 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
738841#else
739 zig_u32 full_res;
842 uint32_t full_res;
740843 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
741 *res = (zig_u16)full_res;
844 *res = (uint16_t)full_res;
742845 return overflow;
743846#endif
744847}
745848
746static inline void zig_vsubo_u16(zig_u8 *ov, zig_u16 *res, int n,
747 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
849static inline void zig_vsubo_u16(uint8_t *ov, uint16_t *res, int n,
850 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
748851{
749852 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits);
750853}
751854
752855
753static inline bool zig_subo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
856static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
754857#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
755 zig_i16 full_res;
858 int16_t full_res;
756859 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
757860 *res = zig_wrap_i16(full_res, bits);
758 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
861 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
759862#else
760 zig_i32 full_res;
863 int32_t full_res;
761864 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
762 *res = (zig_i16)full_res;
865 *res = (int16_t)full_res;
763866 return overflow;
764867#endif
765868}
766869
767static inline void zig_vsubo_i16(zig_u8 *ov, zig_i16 *res, int n,
768 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
870static inline void zig_vsubo_i16(uint8_t *ov, int16_t *res, int n,
871 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
769872{
770873 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits);
771874}
772875
773static inline bool zig_mulo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
876static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
774877#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
775 zig_u32 full_res;
878 uint32_t full_res;
776879 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
777880 *res = zig_wrap_u32(full_res, bits);
778 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
881 return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
779882#else
780883 *res = zig_mulw_u32(lhs, rhs, bits);
781 return rhs != zig_as_u32(0) && lhs > zig_maxInt(u32, bits) / rhs;
884 return rhs != UINT32_C(0) && lhs > zig_maxInt_u(32, bits) / rhs;
782885#endif
783886}
784887
785static inline void zig_vmulo_u32(zig_u8 *ov, zig_u32 *res, int n,
786 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
888static inline void zig_vmulo_u32(uint8_t *ov, uint32_t *res, int n,
889 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
787890{
788891 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits);
789892}
790893
791zig_extern zig_i32 __mulosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
792static inline bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
894zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
895static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
793896#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
794 zig_i32 full_res;
897 int32_t full_res;
795898 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
796899#else
797 zig_c_int overflow_int;
798 zig_i32 full_res = __mulosi4(lhs, rhs, &overflow_int);
900 int overflow_int;
901 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
799902 bool overflow = overflow_int != 0;
800903#endif
801904 *res = zig_wrap_i32(full_res, bits);
802 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
905 return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
803906}
804907
805static inline void zig_vmulo_i32(zig_u8 *ov, zig_i32 *res, int n,
806 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
908static inline void zig_vmulo_i32(uint8_t *ov, int32_t *res, int n,
909 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
807910{
808911 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits);
809912}
810913
811static inline bool zig_mulo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
914static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
812915#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
813 zig_u64 full_res;
916 uint64_t full_res;
814917 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
815918 *res = zig_wrap_u64(full_res, bits);
816 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
919 return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
817920#else
818921 *res = zig_mulw_u64(lhs, rhs, bits);
819 return rhs != zig_as_u64(0) && lhs > zig_maxInt(u64, bits) / rhs;
922 return rhs != UINT64_C(0) && lhs > zig_maxInt_u(64, bits) / rhs;
820923#endif
821924}
822925
823static inline void zig_vmulo_u64(zig_u8 *ov, zig_u64 *res, int n,
824 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
926static inline void zig_vmulo_u64(uint8_t *ov, uint64_t *res, int n,
927 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
825928{
826929 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits);
827930}
828931
829zig_extern zig_i64 __mulodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
830static inline bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
932zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
933static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
831934#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
832 zig_i64 full_res;
935 int64_t full_res;
833936 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
834937#else
835 zig_c_int overflow_int;
836 zig_i64 full_res = __mulodi4(lhs, rhs, &overflow_int);
938 int overflow_int;
939 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
837940 bool overflow = overflow_int != 0;
838941#endif
839942 *res = zig_wrap_i64(full_res, bits);
840 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
943 return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
841944}
842945
843static inline void zig_vmulo_i64(zig_u8 *ov, zig_i64 *res, int n,
844 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
946static inline void zig_vmulo_i64(uint8_t *ov, int64_t *res, int n,
947 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
845948{
846949 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits);
847950}
848951
849static inline bool zig_mulo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
952static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
850953#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
851 zig_u8 full_res;
954 uint8_t full_res;
852955 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
853956 *res = zig_wrap_u8(full_res, bits);
854 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
957 return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
855958#else
856 zig_u32 full_res;
959 uint32_t full_res;
857960 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
858 *res = (zig_u8)full_res;
961 *res = (uint8_t)full_res;
859962 return overflow;
860963#endif
861964}
862965
863static inline void zig_vmulo_u8(zig_u8 *ov, zig_u8 *res, int n,
864 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
966static inline void zig_vmulo_u8(uint8_t *ov, uint8_t *res, int n,
967 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
865968{
866969 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits);
867970}
868971
869static inline bool zig_mulo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
972static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
870973#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
871 zig_i8 full_res;
974 int8_t full_res;
872975 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
873976 *res = zig_wrap_i8(full_res, bits);
874 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
977 return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
875978#else
876 zig_i32 full_res;
979 int32_t full_res;
877980 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
878 *res = (zig_i8)full_res;
981 *res = (int8_t)full_res;
879982 return overflow;
880983#endif
881984}
882985
883static inline void zig_vmulo_i8(zig_u8 *ov, zig_i8 *res, int n,
884 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
986static inline void zig_vmulo_i8(uint8_t *ov, int8_t *res, int n,
987 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
885988{
886989 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits);
887990}
888991
889static inline bool zig_mulo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
992static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
890993#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
891 zig_u16 full_res;
994 uint16_t full_res;
892995 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
893996 *res = zig_wrap_u16(full_res, bits);
894 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
997 return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
895998#else
896 zig_u32 full_res;
999 uint32_t full_res;
8971000 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
898 *res = (zig_u16)full_res;
1001 *res = (uint16_t)full_res;
8991002 return overflow;
9001003#endif
9011004}
9021005
903static inline void zig_vmulo_u16(zig_u8 *ov, zig_u16 *res, int n,
904 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
1006static inline void zig_vmulo_u16(uint8_t *ov, uint16_t *res, int n,
1007 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
9051008{
9061009 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits);
9071010}
9081011
909static inline bool zig_mulo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
1012static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
9101013#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
911 zig_i16 full_res;
1014 int16_t full_res;
9121015 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
9131016 *res = zig_wrap_i16(full_res, bits);
914 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
1017 return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
9151018#else
916 zig_i32 full_res;
1019 int32_t full_res;
9171020 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
918 *res = (zig_i16)full_res;
1021 *res = (int16_t)full_res;
9191022 return overflow;
9201023#endif
9211024}
9221025
923static inline void zig_vmulo_i16(zig_u8 *ov, zig_i16 *res, int n,
924 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
1026static inline void zig_vmulo_i16(uint8_t *ov, int16_t *res, int n,
1027 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
9251028{
9261029 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits);
9271030}
9281031
9291032#define zig_int_builtins(w) \
930 static inline bool zig_shlo_u##w(zig_u##w *res, zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
1033 static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
9311034 *res = zig_shlw_u##w(lhs, rhs, bits); \
932 return lhs > zig_maxInt(u##w, bits) >> rhs; \
1035 return lhs > zig_maxInt_u(w, bits) >> rhs; \
9331036 } \
9341037\
935 static inline bool zig_shlo_i##w(zig_i##w *res, zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
1038 static inline bool zig_shlo_i##w(int##w##_t *res, int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
9361039 *res = zig_shlw_i##w(lhs, rhs, bits); \
937 zig_i##w mask = (zig_i##w)(zig_maxInt_u##w << (bits - rhs - 1)); \
938 return (lhs & mask) != zig_as_i##w(0) && (lhs & mask) != mask; \
1040 int##w##_t mask = (int##w##_t)(UINT##w##_MAX << (bits - rhs - 1)); \
1041 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
9391042 } \
9401043\
941 static inline zig_u##w zig_shls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
942 zig_u##w res; \
943 if (rhs >= bits) return lhs != zig_as_u##w(0) ? zig_maxInt(u##w, bits) : lhs; \
944 return zig_shlo_u##w(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u##w, bits) : res; \
1044 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1045 uint##w##_t res; \
1046 if (rhs >= bits) return lhs != UINT##w##_C(0) ? zig_maxInt_u(w, bits) : lhs; \
1047 return zig_shlo_u##w(&res, lhs, (uint8_t)rhs, bits) ? zig_maxInt_u(w, bits) : res; \
9451048 } \
9461049\
947 static inline zig_i##w zig_shls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
948 zig_i##w res; \
949 if ((zig_u##w)rhs < (zig_u##w)bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
950 return lhs < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
1050 static inline int##w##_t zig_shls_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
1051 int##w##_t res; \
1052 if ((uint##w##_t)rhs < (uint##w##_t)bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
1053 return lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
9511054 } \
9521055\
953 static inline zig_u##w zig_adds_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
954 zig_u##w res; \
955 return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
1056 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1057 uint##w##_t res; \
1058 return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt_u(w, bits) : res; \
9561059 } \
9571060\
958 static inline zig_i##w zig_adds_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
959 zig_i##w res; \
1061 static inline int##w##_t zig_adds_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
1062 int##w##_t res; \
9601063 if (!zig_addo_i##w(&res, lhs, rhs, bits)) return res; \
961 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
1064 return res >= INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
9621065 } \
9631066\
964 static inline zig_u##w zig_subs_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
965 zig_u##w res; \
966 return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt(u##w, bits) : res; \
1067 static inline uint##w##_t zig_subs_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1068 uint##w##_t res; \
1069 return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt_u(w, bits) : res; \
9671070 } \
9681071\
969 static inline zig_i##w zig_subs_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
970 zig_i##w res; \
1072 static inline int##w##_t zig_subs_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
1073 int##w##_t res; \
9711074 if (!zig_subo_i##w(&res, lhs, rhs, bits)) return res; \
972 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
1075 return res >= INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
9731076 } \
9741077\
975 static inline zig_u##w zig_muls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
976 zig_u##w res; \
977 return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
1078 static inline uint##w##_t zig_muls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
1079 uint##w##_t res; \
1080 return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt_u(w, bits) : res; \
9781081 } \
9791082\
980 static inline zig_i##w zig_muls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
981 zig_i##w res; \
1083 static inline int##w##_t zig_muls_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
1084 int##w##_t res; \
9821085 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
983 return (lhs ^ rhs) < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
1086 return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
9841087 }
9851088zig_int_builtins(8)
9861089zig_int_builtins(16)
......@@ -988,89 +1091,89 @@ zig_int_builtins(32)
9881091zig_int_builtins(64)
9891092
9901093#define zig_builtin8(name, val) __builtin_##name(val)
991typedef zig_c_uint zig_Builtin8;
1094typedef unsigned int zig_Builtin8;
9921095
9931096#define zig_builtin16(name, val) __builtin_##name(val)
994typedef zig_c_uint zig_Builtin16;
1097typedef unsigned int zig_Builtin16;
9951098
9961099#if INT_MIN <= INT32_MIN
9971100#define zig_builtin32(name, val) __builtin_##name(val)
998typedef zig_c_uint zig_Builtin32;
1101typedef unsigned int zig_Builtin32;
9991102#elif LONG_MIN <= INT32_MIN
10001103#define zig_builtin32(name, val) __builtin_##name##l(val)
1001typedef zig_c_ulong zig_Builtin32;
1104typedef unsigned long zig_Builtin32;
10021105#endif
10031106
10041107#if INT_MIN <= INT64_MIN
10051108#define zig_builtin64(name, val) __builtin_##name(val)
1006typedef zig_c_uint zig_Builtin64;
1109typedef unsigned int zig_Builtin64;
10071110#elif LONG_MIN <= INT64_MIN
10081111#define zig_builtin64(name, val) __builtin_##name##l(val)
1009typedef zig_c_ulong zig_Builtin64;
1112typedef unsigned long zig_Builtin64;
10101113#elif LLONG_MIN <= INT64_MIN
10111114#define zig_builtin64(name, val) __builtin_##name##ll(val)
1012typedef zig_c_ulonglong zig_Builtin64;
1115typedef unsigned long long zig_Builtin64;
10131116#endif
10141117
1015static inline zig_u8 zig_byte_swap_u8(zig_u8 val, zig_u8 bits) {
1118static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
10161119 return zig_wrap_u8(val >> (8 - bits), bits);
10171120}
10181121
1019static inline zig_i8 zig_byte_swap_i8(zig_i8 val, zig_u8 bits) {
1020 return zig_wrap_i8((zig_i8)zig_byte_swap_u8((zig_u8)val, bits), bits);
1122static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {
1123 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);
10211124}
10221125
1023static inline zig_u16 zig_byte_swap_u16(zig_u16 val, zig_u8 bits) {
1024 zig_u16 full_res;
1126static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) {
1127 uint16_t full_res;
10251128#if zig_has_builtin(bswap16) || defined(zig_gnuc)
10261129 full_res = __builtin_bswap16(val);
10271130#else
1028 full_res = (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 0), 8) << 8 |
1029 (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 8), 8) >> 0;
1131 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |
1132 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;
10301133#endif
10311134 return zig_wrap_u16(full_res >> (16 - bits), bits);
10321135}
10331136
1034static inline zig_i16 zig_byte_swap_i16(zig_i16 val, zig_u8 bits) {
1035 return zig_wrap_i16((zig_i16)zig_byte_swap_u16((zig_u16)val, bits), bits);
1137static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {
1138 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);
10361139}
10371140
1038static inline zig_u32 zig_byte_swap_u32(zig_u32 val, zig_u8 bits) {
1039 zig_u32 full_res;
1141static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) {
1142 uint32_t full_res;
10401143#if zig_has_builtin(bswap32) || defined(zig_gnuc)
10411144 full_res = __builtin_bswap32(val);
10421145#else
1043 full_res = (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 0), 16) << 16 |
1044 (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 16), 16) >> 0;
1146 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |
1147 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;
10451148#endif
10461149 return zig_wrap_u32(full_res >> (32 - bits), bits);
10471150}
10481151
1049static inline zig_i32 zig_byte_swap_i32(zig_i32 val, zig_u8 bits) {
1050 return zig_wrap_i32((zig_i32)zig_byte_swap_u32((zig_u32)val, bits), bits);
1152static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {
1153 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);
10511154}
10521155
1053static inline zig_u64 zig_byte_swap_u64(zig_u64 val, zig_u8 bits) {
1054 zig_u64 full_res;
1156static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) {
1157 uint64_t full_res;
10551158#if zig_has_builtin(bswap64) || defined(zig_gnuc)
10561159 full_res = __builtin_bswap64(val);
10571160#else
1058 full_res = (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 0), 32) << 32 |
1059 (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 32), 32) >> 0;
1161 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |
1162 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;
10601163#endif
10611164 return zig_wrap_u64(full_res >> (64 - bits), bits);
10621165}
10631166
1064static inline zig_i64 zig_byte_swap_i64(zig_i64 val, zig_u8 bits) {
1065 return zig_wrap_i64((zig_i64)zig_byte_swap_u64((zig_u64)val, bits), bits);
1167static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {
1168 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);
10661169}
10671170
1068static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
1069 zig_u8 full_res;
1171static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) {
1172 uint8_t full_res;
10701173#if zig_has_builtin(bitreverse8)
10711174 full_res = __builtin_bitreverse8(val);
10721175#else
1073 static zig_u8 const lut[0x10] = {
1176 static uint8_t const lut[0x10] = {
10741177 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
10751178 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
10761179 };
......@@ -1079,62 +1182,62 @@ static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
10791182 return zig_wrap_u8(full_res >> (8 - bits), bits);
10801183}
10811184
1082static inline zig_i8 zig_bit_reverse_i8(zig_i8 val, zig_u8 bits) {
1083 return zig_wrap_i8((zig_i8)zig_bit_reverse_u8((zig_u8)val, bits), bits);
1185static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {
1186 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);
10841187}
10851188
1086static inline zig_u16 zig_bit_reverse_u16(zig_u16 val, zig_u8 bits) {
1087 zig_u16 full_res;
1189static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) {
1190 uint16_t full_res;
10881191#if zig_has_builtin(bitreverse16)
10891192 full_res = __builtin_bitreverse16(val);
10901193#else
1091 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0), 8) << 8 |
1092 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8), 8) >> 0;
1194 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |
1195 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;
10931196#endif
10941197 return zig_wrap_u16(full_res >> (16 - bits), bits);
10951198}
10961199
1097static inline zig_i16 zig_bit_reverse_i16(zig_i16 val, zig_u8 bits) {
1098 return zig_wrap_i16((zig_i16)zig_bit_reverse_u16((zig_u16)val, bits), bits);
1200static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {
1201 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);
10991202}
11001203
1101static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) {
1102 zig_u32 full_res;
1204static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) {
1205 uint32_t full_res;
11031206#if zig_has_builtin(bitreverse32)
11041207 full_res = __builtin_bitreverse32(val);
11051208#else
1106 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0), 16) << 16 |
1107 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16), 16) >> 0;
1209 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |
1210 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;
11081211#endif
11091212 return zig_wrap_u32(full_res >> (32 - bits), bits);
11101213}
11111214
1112static inline zig_i32 zig_bit_reverse_i32(zig_i32 val, zig_u8 bits) {
1113 return zig_wrap_i32((zig_i32)zig_bit_reverse_u32((zig_u32)val, bits), bits);
1215static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {
1216 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);
11141217}
11151218
1116static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) {
1117 zig_u64 full_res;
1219static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) {
1220 uint64_t full_res;
11181221#if zig_has_builtin(bitreverse64)
11191222 full_res = __builtin_bitreverse64(val);
11201223#else
1121 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0), 32) << 32 |
1122 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32), 32) >> 0;
1224 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |
1225 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;
11231226#endif
11241227 return zig_wrap_u64(full_res >> (64 - bits), bits);
11251228}
11261229
1127static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {
1128 return zig_wrap_i64((zig_i64)zig_bit_reverse_u64((zig_u64)val, bits), bits);
1230static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {
1231 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);
11291232}
11301233
11311234#define zig_builtin_popcount_common(w) \
1132 static inline zig_u8 zig_popcount_i##w(zig_i##w val, zig_u8 bits) { \
1133 return zig_popcount_u##w((zig_u##w)val, bits); \
1235 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \
1236 return zig_popcount_u##w((uint##w##_t)val, bits); \
11341237 }
11351238#if zig_has_builtin(popcount) || defined(zig_gnuc)
11361239#define zig_builtin_popcount(w) \
1137 static inline zig_u8 zig_popcount_u##w(zig_u##w val, zig_u8 bits) { \
1240 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
11381241 (void)bits; \
11391242 return zig_builtin##w(popcount, val); \
11401243 } \
......@@ -1142,12 +1245,12 @@ static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {
11421245 zig_builtin_popcount_common(w)
11431246#else
11441247#define zig_builtin_popcount(w) \
1145 static inline zig_u8 zig_popcount_u##w(zig_u##w val, zig_u8 bits) { \
1248 static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
11461249 (void)bits; \
1147 zig_u##w temp = val - ((val >> 1) & (zig_maxInt_u##w / 3)); \
1148 temp = (temp & (zig_maxInt_u##w / 5)) + ((temp >> 2) & (zig_maxInt_u##w / 5)); \
1149 temp = (temp + (temp >> 4)) & (zig_maxInt_u##w / 17); \
1150 return temp * (zig_maxInt_u##w / 255) >> (w - 8); \
1250 uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \
1251 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
1252 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
1253 return temp * (UINT##w##_MAX / 255) >> (w - 8); \
11511254 } \
11521255\
11531256 zig_builtin_popcount_common(w)
......@@ -1158,12 +1261,12 @@ zig_builtin_popcount(32)
11581261zig_builtin_popcount(64)
11591262
11601263#define zig_builtin_ctz_common(w) \
1161 static inline zig_u8 zig_ctz_i##w(zig_i##w val, zig_u8 bits) { \
1162 return zig_ctz_u##w((zig_u##w)val, bits); \
1264 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \
1265 return zig_ctz_u##w((uint##w##_t)val, bits); \
11631266 }
11641267#if zig_has_builtin(ctz) || defined(zig_gnuc)
11651268#define zig_builtin_ctz(w) \
1166 static inline zig_u8 zig_ctz_u##w(zig_u##w val, zig_u8 bits) { \
1269 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
11671270 if (val == 0) return bits; \
11681271 return zig_builtin##w(ctz, val); \
11691272 } \
......@@ -1171,7 +1274,7 @@ zig_builtin_popcount(64)
11711274 zig_builtin_ctz_common(w)
11721275#else
11731276#define zig_builtin_ctz(w) \
1174 static inline zig_u8 zig_ctz_u##w(zig_u##w val, zig_u8 bits) { \
1277 static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
11751278 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
11761279 } \
11771280\
......@@ -1183,12 +1286,12 @@ zig_builtin_ctz(32)
11831286zig_builtin_ctz(64)
11841287
11851288#define zig_builtin_clz_common(w) \
1186 static inline zig_u8 zig_clz_i##w(zig_i##w val, zig_u8 bits) { \
1187 return zig_clz_u##w((zig_u##w)val, bits); \
1289 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \
1290 return zig_clz_u##w((uint##w##_t)val, bits); \
11881291 }
11891292#if zig_has_builtin(clz) || defined(zig_gnuc)
11901293#define zig_builtin_clz(w) \
1191 static inline zig_u8 zig_clz_u##w(zig_u##w val, zig_u8 bits) { \
1294 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
11921295 if (val == 0) return bits; \
11931296 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
11941297 } \
......@@ -1196,7 +1299,7 @@ zig_builtin_ctz(64)
11961299 zig_builtin_clz_common(w)
11971300#else
11981301#define zig_builtin_clz(w) \
1199 static inline zig_u8 zig_clz_u##w(zig_u##w val, zig_u8 bits) { \
1302 static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
12001303 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
12011304 } \
12021305\
......@@ -1207,7 +1310,7 @@ zig_builtin_clz(16)
12071310zig_builtin_clz(32)
12081311zig_builtin_clz(64)
12091312
1210/* ======================== 128-bit Integer Routines ======================== */
1313/* ======================== 128-bit Integer Support ========================= */
12111314
12121315#if !defined(zig_has_int128)
12131316# if defined(__SIZEOF_INT128__)
......@@ -1222,18 +1325,18 @@ zig_builtin_clz(64)
12221325typedef unsigned __int128 zig_u128;
12231326typedef signed __int128 zig_i128;
12241327
1225#define zig_as_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1226#define zig_as_i128(hi, lo) ((zig_i128)zig_as_u128(hi, lo))
1227#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo)
1228#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo)
1229#define zig_hi_u128(val) ((zig_u64)((val) >> 64))
1230#define zig_lo_u128(val) ((zig_u64)((val) >> 0))
1231#define zig_hi_i128(val) ((zig_i64)((val) >> 64))
1232#define zig_lo_i128(val) ((zig_u64)((val) >> 0))
1328#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1329#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1330#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
1331#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
1332#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
1333#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
1334#define zig_hi_i128(val) (( int64_t)((val) >> 64))
1335#define zig_lo_i128(val) ((uint64_t)((val) >> 0))
12331336#define zig_bitcast_u128(val) ((zig_u128)(val))
12341337#define zig_bitcast_i128(val) ((zig_i128)(val))
12351338#define zig_cmp_int128(Type) \
1236 static inline zig_i32 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1339 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
12371340 return (lhs > rhs) - (lhs < rhs); \
12381341 }
12391342#define zig_bit_int128(Type, operation, operator) \
......@@ -1244,31 +1347,31 @@ typedef signed __int128 zig_i128;
12441347#else /* zig_has_int128 */
12451348
12461349#if __LITTLE_ENDIAN__ || _MSC_VER
1247typedef struct { zig_align(16) zig_u64 lo; zig_u64 hi; } zig_u128;
1248typedef struct { zig_align(16) zig_u64 lo; zig_i64 hi; } zig_i128;
1350typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
1351typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
12491352#else
1250typedef struct { zig_align(16) zig_u64 hi; zig_u64 lo; } zig_u128;
1251typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
1353typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
1354typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
12521355#endif
12531356
1254#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1255#define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
1357#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1358#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
12561359
1257#if _MSC_VER
1258#define zig_as_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1259#define zig_as_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1260#else
1261#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo)
1262#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo)
1360#if _MSC_VER /* MSVC doesn't allow struct literals in constant expressions */
1361#define zig_make_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1362#define zig_make_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1363#else /* But non-MSVC doesn't like the unprotected commas */
1364#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
1365#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
12631366#endif
12641367#define zig_hi_u128(val) ((val).hi)
12651368#define zig_lo_u128(val) ((val).lo)
12661369#define zig_hi_i128(val) ((val).hi)
12671370#define zig_lo_i128(val) ((val).lo)
1268#define zig_bitcast_u128(val) zig_as_u128((zig_u64)(val).hi, (val).lo)
1269#define zig_bitcast_i128(val) zig_as_i128((zig_i64)(val).hi, (val).lo)
1371#define zig_bitcast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)
1372#define zig_bitcast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo)
12701373#define zig_cmp_int128(Type) \
1271 static inline zig_i32 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1374 static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
12721375 return (lhs.hi == rhs.hi) \
12731376 ? (lhs.lo > rhs.lo) - (lhs.lo < rhs.lo) \
12741377 : (lhs.hi > rhs.hi) - (lhs.hi < rhs.hi); \
......@@ -1280,10 +1383,10 @@ typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
12801383
12811384#endif /* zig_has_int128 */
12821385
1283#define zig_minInt_u128 zig_as_u128(zig_minInt_u64, zig_minInt_u64)
1284#define zig_maxInt_u128 zig_as_u128(zig_maxInt_u64, zig_maxInt_u64)
1285#define zig_minInt_i128 zig_as_i128(zig_minInt_i64, zig_minInt_u64)
1286#define zig_maxInt_i128 zig_as_i128(zig_maxInt_i64, zig_maxInt_u64)
1386#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
1387#define zig_maxInt_u128 zig_make_u128(zig_maxInt_u64, zig_maxInt_u64)
1388#define zig_minInt_i128 zig_make_i128(zig_minInt_i64, zig_minInt_u64)
1389#define zig_maxInt_i128 zig_make_i128(zig_maxInt_i64, zig_maxInt_u64)
12871390
12881391zig_cmp_int128(u128)
12891392zig_cmp_int128(i128)
......@@ -1297,28 +1400,33 @@ zig_bit_int128(i128, or, |)
12971400zig_bit_int128(u128, xor, ^)
12981401zig_bit_int128(i128, xor, ^)
12991402
1300static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs);
1403static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs);
13011404
13021405#if zig_has_int128
13031406
1304static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1305 return val ^ zig_maxInt(u128, bits);
1407static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1408 return val ^ zig_maxInt_u(128, bits);
13061409}
13071410
1308static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1411static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
13091412 (void)bits;
13101413 return ~val;
13111414}
13121415
1313static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1416static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
13141417 return lhs >> rhs;
13151418}
13161419
1317static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1420static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
13181421 return lhs << rhs;
13191422}
13201423
1321static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1424static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1425 zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
1426 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
1427}
1428
1429static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
13221430 return lhs << rhs;
13231431}
13241432
......@@ -1363,40 +1471,46 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
13631471}
13641472
13651473static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1366 return zig_div_trunc_i128(lhs, rhs) - (((lhs ^ rhs) & zig_rem_i128(lhs, rhs)) < zig_as_i128(0, 0));
1474 return zig_div_trunc_i128(lhs, rhs) - (((lhs ^ rhs) & zig_rem_i128(lhs, rhs)) < zig_make_i128(0, 0));
13671475}
13681476
13691477static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
13701478 zig_i128 rem = zig_rem_i128(lhs, rhs);
1371 return rem + (((lhs ^ rhs) & rem) < zig_as_i128(0, 0) ? rhs : zig_as_i128(0, 0));
1479 return rem + (((lhs ^ rhs) & rem) < zig_make_i128(0, 0) ? rhs : zig_make_i128(0, 0));
13721480}
13731481
13741482#else /* zig_has_int128 */
13751483
1376static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1377 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
1484static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1485 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
1486}
1487
1488static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
1489 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
13781490}
13791491
1380static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1381 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
1492static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
1493 if (rhs == UINT8_C(0)) return lhs;
1494 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
1495 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
13821496}
13831497
1384static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1385 if (rhs == zig_as_u8(0)) return lhs;
1386 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - zig_as_u8(64)) };
1387 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (zig_as_u8(64) - rhs) | lhs.lo >> rhs };
1498static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1499 if (rhs == UINT8_C(0)) return lhs;
1500 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1501 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
13881502}
13891503
1390static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1391 if (rhs == zig_as_u8(0)) return lhs;
1392 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.lo << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1393 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1504static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1505 if (rhs == UINT8_C(0)) return lhs;
1506 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) };
1507 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
13941508}
13951509
1396static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1397 if (rhs == zig_as_u8(0)) return lhs;
1398 if (rhs >= zig_as_u8(64)) return (zig_i128){ .hi = lhs.lo << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1399 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1510static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
1511 if (rhs == UINT8_C(0)) return lhs;
1512 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1513 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
14001514}
14011515
14021516static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
......@@ -1424,14 +1538,14 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
14241538}
14251539
14261540zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
1427static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1428 return zig_bitcast_u128(__multi3(zig_bitcast_i128(lhs), zig_bitcast_i128(rhs)));
1429}
1430
14311541static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
14321542 return __multi3(lhs, rhs);
14331543}
14341544
1545static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1546 return zig_bitcast_u128(zig_mul_i128(zig_bitcast_i128(lhs), zig_bitcast_i128(rhs)));
1547}
1548
14351549zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
14361550static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
14371551 return __udivti3(lhs, rhs);
......@@ -1454,11 +1568,11 @@ static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
14541568
14551569static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
14561570 zig_i128 rem = zig_rem_i128(lhs, rhs);
1457 return zig_add_i128(rem, (((lhs.hi ^ rhs.hi) & rem.hi) < zig_as_i64(0) ? rhs : zig_as_i128(0, 0)));
1571 return zig_add_i128(rem, ((lhs.hi ^ rhs.hi) & rem.hi) < INT64_C(0) ? rhs : zig_make_i128(0, 0));
14581572}
14591573
14601574static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1461 return zig_sub_i128(zig_div_trunc_i128(lhs, rhs), zig_as_i128(0, zig_cmp_i128(zig_and_i128(zig_xor_i128(lhs, rhs), zig_rem_i128(lhs, rhs)), zig_as_i128(0, 0)) < zig_as_i32(0)));
1575 return zig_sub_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(0, zig_cmp_i128(zig_and_i128(zig_xor_i128(lhs, rhs), zig_rem_i128(lhs, rhs)), zig_make_i128(0, 0)) < INT32_C(0)));
14621576}
14631577
14641578#endif /* zig_has_int128 */
......@@ -1471,323 +1585,294 @@ static inline zig_u128 zig_nand_u128(zig_u128 lhs, zig_u128 rhs) {
14711585}
14721586
14731587static inline zig_u128 zig_min_u128(zig_u128 lhs, zig_u128 rhs) {
1474 return zig_cmp_u128(lhs, rhs) < zig_as_i32(0) ? lhs : rhs;
1588 return zig_cmp_u128(lhs, rhs) < INT32_C(0) ? lhs : rhs;
14751589}
14761590
14771591static inline zig_i128 zig_min_i128(zig_i128 lhs, zig_i128 rhs) {
1478 return zig_cmp_i128(lhs, rhs) < zig_as_i32(0) ? lhs : rhs;
1592 return zig_cmp_i128(lhs, rhs) < INT32_C(0) ? lhs : rhs;
14791593}
14801594
14811595static inline zig_u128 zig_max_u128(zig_u128 lhs, zig_u128 rhs) {
1482 return zig_cmp_u128(lhs, rhs) > zig_as_i32(0) ? lhs : rhs;
1596 return zig_cmp_u128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
14831597}
14841598
14851599static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
1486 return zig_cmp_i128(lhs, rhs) > zig_as_i32(0) ? lhs : rhs;
1487}
1488
1489static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
1490 zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_sub_i128(zig_as_i128(0, 0), zig_as_i128(0, 1)) : zig_as_i128(0, 0);
1491 return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
1600 return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
14921601}
14931602
1494static inline zig_u128 zig_wrap_u128(zig_u128 val, zig_u8 bits) {
1495 return zig_and_u128(val, zig_maxInt(u128, bits));
1603static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
1604 return zig_and_u128(val, zig_maxInt_u(128, bits));
14961605}
14971606
1498static inline zig_i128 zig_wrap_i128(zig_i128 val, zig_u8 bits) {
1499 return zig_as_i128(zig_wrap_i64(zig_hi_i128(val), bits - zig_as_u8(64)), zig_lo_i128(val));
1607static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
1608 return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
15001609}
15011610
1502static inline zig_u128 zig_shlw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1611static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {
15031612 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
15041613}
15051614
1506static inline zig_i128 zig_shlw_i128(zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1615static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {
15071616 return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), rhs)), bits);
15081617}
15091618
1510static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1619static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
15111620 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
15121621}
15131622
1514static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1623static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
15151624 return zig_wrap_i128(zig_bitcast_i128(zig_add_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
15161625}
15171626
1518static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1627static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
15191628 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
15201629}
15211630
1522static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1631static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
15231632 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
15241633}
15251634
1526static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1635static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
15271636 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
15281637}
15291638
1530static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1639static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
15311640 return zig_wrap_i128(zig_bitcast_i128(zig_mul_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
15321641}
15331642
15341643#if zig_has_int128
15351644
1536static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1645static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
15371646#if zig_has_builtin(add_overflow)
15381647 zig_u128 full_res;
15391648 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
15401649 *res = zig_wrap_u128(full_res, bits);
1541 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1650 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
15421651#else
15431652 *res = zig_addw_u128(lhs, rhs, bits);
15441653 return *res < lhs;
15451654#endif
15461655}
15471656
1548zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1549static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1657zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1658static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
15501659#if zig_has_builtin(add_overflow)
15511660 zig_i128 full_res;
15521661 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
15531662#else
1554 zig_c_int overflow_int;
1663 int overflow_int;
15551664 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
15561665 bool overflow = overflow_int != 0;
15571666#endif
15581667 *res = zig_wrap_i128(full_res, bits);
1559 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1668 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
15601669}
15611670
1562static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1671static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
15631672#if zig_has_builtin(sub_overflow)
15641673 zig_u128 full_res;
15651674 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
15661675 *res = zig_wrap_u128(full_res, bits);
1567 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1676 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
15681677#else
15691678 *res = zig_subw_u128(lhs, rhs, bits);
15701679 return *res > lhs;
15711680#endif
15721681}
15731682
1574zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1575static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1683zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1684static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
15761685#if zig_has_builtin(sub_overflow)
15771686 zig_i128 full_res;
15781687 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
15791688#else
1580 zig_c_int overflow_int;
1689 int overflow_int;
15811690 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
15821691 bool overflow = overflow_int != 0;
15831692#endif
15841693 *res = zig_wrap_i128(full_res, bits);
1585 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1694 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
15861695}
15871696
1588static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1697static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
15891698#if zig_has_builtin(mul_overflow)
15901699 zig_u128 full_res;
15911700 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
15921701 *res = zig_wrap_u128(full_res, bits);
1593 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1702 return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
15941703#else
15951704 *res = zig_mulw_u128(lhs, rhs, bits);
1596 return rhs != zig_as_u128(0, 0) && lhs > zig_maxInt(u128, bits) / rhs;
1705 return rhs != zig_make_u128(0, 0) && lhs > zig_maxInt_u(128, bits) / rhs;
15971706#endif
15981707}
15991708
1600zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1601static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1709zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1710static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
16021711#if zig_has_builtin(mul_overflow)
16031712 zig_i128 full_res;
16041713 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
16051714#else
1606 zig_c_int overflow_int;
1715 int overflow_int;
16071716 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
16081717 bool overflow = overflow_int != 0;
16091718#endif
16101719 *res = zig_wrap_i128(full_res, bits);
1611 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1720 return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
16121721}
16131722
16141723#else /* zig_has_int128 */
16151724
1616static inline bool zig_overflow_u128(bool overflow, zig_u128 full_res, zig_u8 bits) {
1617 return overflow ||
1618 zig_cmp_u128(full_res, zig_minInt(u128, bits)) < zig_as_i32(0) ||
1619 zig_cmp_u128(full_res, zig_maxInt(u128, bits)) > zig_as_i32(0);
1725static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
1726 uint64_t hi;
1727 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
1728 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
16201729}
16211730
1622static inline bool zig_overflow_i128(bool overflow, zig_i128 full_res, zig_u8 bits) {
1623 return overflow ||
1624 zig_cmp_i128(full_res, zig_minInt(i128, bits)) < zig_as_i32(0) ||
1625 zig_cmp_i128(full_res, zig_maxInt(i128, bits)) > zig_as_i32(0);
1731static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1732 int64_t hi;
1733 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
1734 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
16261735}
16271736
1628static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1629 zig_u128 full_res;
1630 bool overflow =
1631 zig_addo_u64(&full_res.hi, lhs.hi, rhs.hi, 64) |
1632 zig_addo_u64(&full_res.hi, full_res.hi, zig_addo_u64(&full_res.lo, lhs.lo, rhs.lo, 64), 64);
1633 *res = zig_wrap_u128(full_res, bits);
1634 return zig_overflow_u128(overflow, full_res, bits);
1737static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
1738 uint64_t hi;
1739 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
1740 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
16351741}
16361742
1637zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1638static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1639 zig_c_int overflow_int;
1640 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
1641 *res = zig_wrap_i128(full_res, bits);
1642 return zig_overflow_i128(overflow_int, full_res, bits);
1743static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1744 int64_t hi;
1745 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
1746 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
16431747}
16441748
1645static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1646 zig_u128 full_res;
1647 bool overflow =
1648 zig_subo_u64(&full_res.hi, lhs.hi, rhs.hi, 64) |
1649 zig_subo_u64(&full_res.hi, full_res.hi, zig_subo_u64(&full_res.lo, lhs.lo, rhs.lo, 64), 64);
1650 *res = zig_wrap_u128(full_res, bits);
1651 return zig_overflow_u128(overflow, full_res, bits);
1652}
1653
1654zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1655static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1656 zig_c_int overflow_int;
1657 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
1658 *res = zig_wrap_i128(full_res, bits);
1659 return zig_overflow_i128(overflow_int, full_res, bits);
1660}
1661
1662static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1749static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
16631750 *res = zig_mulw_u128(lhs, rhs, bits);
1664 return zig_cmp_u128(*res, zig_as_u128(0, 0)) != zig_as_i32(0) &&
1665 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt(u128, bits), rhs)) > zig_as_i32(0);
1751 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&
1752 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
16661753}
16671754
1668zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1669static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1670 zig_c_int overflow_int;
1755zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1756static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1757 int overflow_int;
16711758 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
1759 bool overflow = overflow_int != 0 ||
1760 zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
1761 zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);
16721762 *res = zig_wrap_i128(full_res, bits);
1673 return zig_overflow_i128(overflow_int, full_res, bits);
1763 return overflow;
16741764}
16751765
16761766#endif /* zig_has_int128 */
16771767
1678static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1768static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8_t bits) {
16791769 *res = zig_shlw_u128(lhs, rhs, bits);
1680 return zig_cmp_u128(lhs, zig_shr_u128(zig_maxInt(u128, bits), rhs)) > zig_as_i32(0);
1770 return zig_cmp_u128(lhs, zig_shr_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
16811771}
16821772
1683static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1773static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
16841774 *res = zig_shlw_i128(lhs, rhs, bits);
1685 zig_i128 mask = zig_bitcast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - zig_as_u8(1)));
1686 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_as_i128(0, 0)) != zig_as_i32(0) &&
1687 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != zig_as_i32(0);
1775 zig_i128 mask = zig_bitcast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)));
1776 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
1777 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
16881778}
16891779
1690static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1780static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
16911781 zig_u128 res;
1692 if (zig_cmp_u128(rhs, zig_as_u128(0, bits)) >= zig_as_i32(0))
1693 return zig_cmp_u128(lhs, zig_as_u128(0, 0)) != zig_as_i32(0) ? zig_maxInt(u128, bits) : lhs;
1694
1695#if zig_has_int128
1696 return zig_shlo_u128(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u128, bits) : res;
1697#else
1698 return zig_shlo_u128(&res, lhs, (zig_u8)rhs.lo, bits) ? zig_maxInt(u128, bits) : res;
1699#endif
1782 if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) >= INT32_C(0))
1783 return zig_cmp_u128(lhs, zig_make_u128(0, 0)) != INT32_C(0) ? zig_maxInt_u(128, bits) : lhs;
1784 return zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits) ? zig_maxInt_u(128, bits) : res;
17001785}
17011786
1702static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1787static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
17031788 zig_i128 res;
1704 if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_as_u128(0, bits)) < zig_as_i32(0) && !zig_shlo_i128(&res, lhs, zig_lo_i128(rhs), bits)) return res;
1705 return zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1789 if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_i128(rhs), bits)) return res;
1790 return zig_cmp_i128(lhs, zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
17061791}
17071792
1708static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1793static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
17091794 zig_u128 res;
1710 return zig_addo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1795 return zig_addo_u128(&res, lhs, rhs, bits) ? zig_maxInt_u(128, bits) : res;
17111796}
17121797
1713static inline zig_i128 zig_adds_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1798static inline zig_i128 zig_adds_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
17141799 zig_i128 res;
17151800 if (!zig_addo_i128(&res, lhs, rhs, bits)) return res;
1716 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1801 return zig_cmp_i128(res, zig_make_i128(0, 0)) >= INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
17171802}
17181803
1719static inline zig_u128 zig_subs_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1804static inline zig_u128 zig_subs_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
17201805 zig_u128 res;
1721 return zig_subo_u128(&res, lhs, rhs, bits) ? zig_minInt(u128, bits) : res;
1806 return zig_subo_u128(&res, lhs, rhs, bits) ? zig_minInt_u(128, bits) : res;
17221807}
17231808
1724static inline zig_i128 zig_subs_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1809static inline zig_i128 zig_subs_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
17251810 zig_i128 res;
17261811 if (!zig_subo_i128(&res, lhs, rhs, bits)) return res;
1727 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1812 return zig_cmp_i128(res, zig_make_i128(0, 0)) >= INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
17281813}
17291814
1730static inline zig_u128 zig_muls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1815static inline zig_u128 zig_muls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
17311816 zig_u128 res;
1732 return zig_mulo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1817 return zig_mulo_u128(&res, lhs, rhs, bits) ? zig_maxInt_u(128, bits) : res;
17331818}
17341819
1735static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1820static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
17361821 zig_i128 res;
17371822 if (!zig_mulo_i128(&res, lhs, rhs, bits)) return res;
1738 return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1823 return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
17391824}
17401825
1741static inline zig_u8 zig_clz_u128(zig_u128 val, zig_u8 bits) {
1742 if (bits <= zig_as_u8(64)) return zig_clz_u64(zig_lo_u128(val), bits);
1743 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - zig_as_u8(64));
1744 return zig_clz_u64(zig_lo_u128(val), zig_as_u8(64)) + (bits - zig_as_u8(64));
1826static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {
1827 if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);
1828 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));
1829 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));
17451830}
17461831
1747static inline zig_u8 zig_clz_i128(zig_i128 val, zig_u8 bits) {
1832static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {
17481833 return zig_clz_u128(zig_bitcast_u128(val), bits);
17491834}
17501835
1751static inline zig_u8 zig_ctz_u128(zig_u128 val, zig_u8 bits) {
1752 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), zig_as_u8(64));
1753 return zig_ctz_u64(zig_hi_u128(val), bits - zig_as_u8(64)) + zig_as_u8(64);
1836static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {
1837 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));
1838 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);
17541839}
17551840
1756static inline zig_u8 zig_ctz_i128(zig_i128 val, zig_u8 bits) {
1841static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {
17571842 return zig_ctz_u128(zig_bitcast_u128(val), bits);
17581843}
17591844
1760static inline zig_u8 zig_popcount_u128(zig_u128 val, zig_u8 bits) {
1761 return zig_popcount_u64(zig_hi_u128(val), bits - zig_as_u8(64)) +
1762 zig_popcount_u64(zig_lo_u128(val), zig_as_u8(64));
1845static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {
1846 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +
1847 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));
17631848}
17641849
1765static inline zig_u8 zig_popcount_i128(zig_i128 val, zig_u8 bits) {
1850static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {
17661851 return zig_popcount_u128(zig_bitcast_u128(val), bits);
17671852}
17681853
1769static inline zig_u128 zig_byte_swap_u128(zig_u128 val, zig_u8 bits) {
1854static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) {
17701855 zig_u128 full_res;
17711856#if zig_has_builtin(bswap128)
17721857 full_res = __builtin_bswap128(val);
17731858#else
1774 full_res = zig_as_u128(zig_byte_swap_u64(zig_lo_u128(val), zig_as_u8(64)),
1775 zig_byte_swap_u64(zig_hi_u128(val), zig_as_u8(64)));
1859 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),
1860 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));
17761861#endif
1777 return zig_shr_u128(full_res, zig_as_u8(128) - bits);
1862 return zig_shr_u128(full_res, UINT8_C(128) - bits);
17781863}
17791864
1780static inline zig_i128 zig_byte_swap_i128(zig_i128 val, zig_u8 bits) {
1865static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {
17811866 return zig_bitcast_i128(zig_byte_swap_u128(zig_bitcast_u128(val), bits));
17821867}
17831868
1784static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {
1785 return zig_shr_u128(zig_as_u128(zig_bit_reverse_u64(zig_lo_u128(val), zig_as_u8(64)),
1786 zig_bit_reverse_u64(zig_hi_u128(val), zig_as_u8(64))),
1787 zig_as_u8(128) - bits);
1869static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {
1870 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),
1871 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),
1872 UINT8_C(128) - bits);
17881873}
17891874
1790static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
1875static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
17911876 return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits));
17921877}
17931878
......@@ -1810,85 +1895,87 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
18101895
18111896#if (zig_has_builtin(nan) && zig_has_builtin(nans) && zig_has_builtin(inf)) || defined(zig_gnuc)
18121897#define zig_has_float_builtins 1
1813#define zig_as_special_f16(sign, name, arg, repr) sign zig_as_f16(__builtin_##name, )(arg)
1814#define zig_as_special_f32(sign, name, arg, repr) sign zig_as_f32(__builtin_##name, )(arg)
1815#define zig_as_special_f64(sign, name, arg, repr) sign zig_as_f64(__builtin_##name, )(arg)
1816#define zig_as_special_f80(sign, name, arg, repr) sign zig_as_f80(__builtin_##name, )(arg)
1817#define zig_as_special_f128(sign, name, arg, repr) sign zig_as_f128(__builtin_##name, )(arg)
1818#define zig_as_special_c_longdouble(sign, name, arg, repr) sign zig_as_c_longdouble(__builtin_##name, )(arg)
1898#define zig_make_special_f16(sign, name, arg, repr) sign zig_make_f16(__builtin_##name, )(arg)
1899#define zig_make_special_f32(sign, name, arg, repr) sign zig_make_f32(__builtin_##name, )(arg)
1900#define zig_make_special_f64(sign, name, arg, repr) sign zig_make_f64(__builtin_##name, )(arg)
1901#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80(__builtin_##name, )(arg)
1902#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
1903#define zig_make_special_c_longdouble(sign, name, arg, repr) sign zig_make_c_longdouble(__builtin_##name, )(arg)
18191904#else
18201905#define zig_has_float_builtins 0
1821#define zig_as_special_f16(sign, name, arg, repr) zig_float_from_repr_f16(repr)
1822#define zig_as_special_f32(sign, name, arg, repr) zig_float_from_repr_f32(repr)
1823#define zig_as_special_f64(sign, name, arg, repr) zig_float_from_repr_f64(repr)
1824#define zig_as_special_f80(sign, name, arg, repr) zig_float_from_repr_f80(repr)
1825#define zig_as_special_f128(sign, name, arg, repr) zig_float_from_repr_f128(repr)
1826#define zig_as_special_c_longdouble(sign, name, arg, repr) zig_float_from_repr_c_longdouble(repr)
1906#define zig_make_special_f16(sign, name, arg, repr) zig_float_from_repr_f16(repr)
1907#define zig_make_special_f32(sign, name, arg, repr) zig_float_from_repr_f32(repr)
1908#define zig_make_special_f64(sign, name, arg, repr) zig_float_from_repr_f64(repr)
1909#define zig_make_special_f80(sign, name, arg, repr) zig_float_from_repr_f80(repr)
1910#define zig_make_special_f128(sign, name, arg, repr) zig_float_from_repr_f128(repr)
1911#define zig_make_special_c_longdouble(sign, name, arg, repr) zig_float_from_repr_c_longdouble(repr)
18271912#endif
18281913
18291914#define zig_has_f16 1
18301915#define zig_bitSizeOf_f16 16
18311916#define zig_libc_name_f16(name) __##name##h
1832#define zig_as_special_constant_f16(sign, name, arg, repr) zig_as_special_f16(sign, name, arg, repr)
1917#define zig_make_special_constant_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
18331918#if FLT_MANT_DIG == 11
18341919typedef float zig_f16;
1835#define zig_as_f16(fp, repr) fp##f
1920#define zig_make_f16(fp, repr) fp##f
18361921#elif DBL_MANT_DIG == 11
18371922typedef double zig_f16;
1838#define zig_as_f16(fp, repr) fp
1923#define zig_make_f16(fp, repr) fp
18391924#elif LDBL_MANT_DIG == 11
18401925#define zig_bitSizeOf_c_longdouble 16
1926typedef uint16_t zig_repr_c_longdouble;
18411927typedef long double zig_f16;
1842#define zig_as_f16(fp, repr) fp##l
1928#define zig_make_f16(fp, repr) fp##l
18431929#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc))
18441930typedef _Float16 zig_f16;
1845#define zig_as_f16(fp, repr) fp##f16
1931#define zig_make_f16(fp, repr) fp##f16
18461932#elif defined(__SIZEOF_FP16__)
18471933typedef __fp16 zig_f16;
1848#define zig_as_f16(fp, repr) fp##f16
1934#define zig_make_f16(fp, repr) fp##f16
18491935#else
18501936#undef zig_has_f16
18511937#define zig_has_f16 0
1852#define zig_repr_f16 i16
1853typedef zig_i16 zig_f16;
1854#define zig_as_f16(fp, repr) repr
1855#undef zig_as_special_f16
1856#define zig_as_special_f16(sign, name, arg, repr) repr
1857#undef zig_as_special_constant_f16
1858#define zig_as_special_constant_f16(sign, name, arg, repr) repr
1938#define zig_bitSizeOf_repr_f16 16
1939typedef int16_t zig_f16;
1940#define zig_make_f16(fp, repr) repr
1941#undef zig_make_special_f16
1942#define zig_make_special_f16(sign, name, arg, repr) repr
1943#undef zig_make_special_constant_f16
1944#define zig_make_special_constant_f16(sign, name, arg, repr) repr
18591945#endif
18601946
18611947#define zig_has_f32 1
18621948#define zig_bitSizeOf_f32 32
18631949#define zig_libc_name_f32(name) name##f
18641950#if _MSC_VER
1865#define zig_as_special_constant_f32(sign, name, arg, repr) sign zig_as_f32(zig_msvc_flt_##name, )
1951#define zig_make_special_constant_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, )
18661952#else
1867#define zig_as_special_constant_f32(sign, name, arg, repr) zig_as_special_f32(sign, name, arg, repr)
1953#define zig_make_special_constant_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
18681954#endif
18691955#if FLT_MANT_DIG == 24
18701956typedef float zig_f32;
1871#define zig_as_f32(fp, repr) fp##f
1957#define zig_make_f32(fp, repr) fp##f
18721958#elif DBL_MANT_DIG == 24
18731959typedef double zig_f32;
1874#define zig_as_f32(fp, repr) fp
1960#define zig_make_f32(fp, repr) fp
18751961#elif LDBL_MANT_DIG == 24
18761962#define zig_bitSizeOf_c_longdouble 32
1963typedef uint32_t zig_repr_c_longdouble;
18771964typedef long double zig_f32;
1878#define zig_as_f32(fp, repr) fp##l
1965#define zig_make_f32(fp, repr) fp##l
18791966#elif FLT32_MANT_DIG == 24
18801967typedef _Float32 zig_f32;
1881#define zig_as_f32(fp, repr) fp##f32
1968#define zig_make_f32(fp, repr) fp##f32
18821969#else
18831970#undef zig_has_f32
18841971#define zig_has_f32 0
1885#define zig_repr_f32 i32
1886typedef zig_i32 zig_f32;
1887#define zig_as_f32(fp, repr) repr
1888#undef zig_as_special_f32
1889#define zig_as_special_f32(sign, name, arg, repr) repr
1890#undef zig_as_special_constant_f32
1891#define zig_as_special_constant_f32(sign, name, arg, repr) repr
1972#define zig_bitSizeOf_repr_f32 32
1973typedef int32_t zig_f32;
1974#define zig_make_f32(fp, repr) repr
1975#undef zig_make_special_f32
1976#define zig_make_special_f32(sign, name, arg, repr) repr
1977#undef zig_make_special_constant_f32
1978#define zig_make_special_constant_f32(sign, name, arg, repr) repr
18921979#endif
18931980
18941981#define zig_has_f64 1
......@@ -1897,109 +1984,113 @@ typedef zig_i32 zig_f32;
18971984#if _MSC_VER
18981985#ifdef ZIG_TARGET_ABI_MSVC
18991986#define zig_bitSizeOf_c_longdouble 64
1987typedef uint64_t zig_repr_c_longdouble;
19001988#endif
1901#define zig_as_special_constant_f64(sign, name, arg, repr) sign zig_as_f64(zig_msvc_flt_##name, )
1989#define zig_make_special_constant_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, )
19021990#else /* _MSC_VER */
1903#define zig_as_special_constant_f64(sign, name, arg, repr) zig_as_special_f64(sign, name, arg, repr)
1991#define zig_make_special_constant_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
19041992#endif /* _MSC_VER */
19051993#if FLT_MANT_DIG == 53
19061994typedef float zig_f64;
1907#define zig_as_f64(fp, repr) fp##f
1995#define zig_make_f64(fp, repr) fp##f
19081996#elif DBL_MANT_DIG == 53
19091997typedef double zig_f64;
1910#define zig_as_f64(fp, repr) fp
1998#define zig_make_f64(fp, repr) fp
19111999#elif LDBL_MANT_DIG == 53
19122000#define zig_bitSizeOf_c_longdouble 64
2001typedef uint64_t zig_repr_c_longdouble;
19132002typedef long double zig_f64;
1914#define zig_as_f64(fp, repr) fp##l
2003#define zig_make_f64(fp, repr) fp##l
19152004#elif FLT64_MANT_DIG == 53
19162005typedef _Float64 zig_f64;
1917#define zig_as_f64(fp, repr) fp##f64
2006#define zig_make_f64(fp, repr) fp##f64
19182007#elif FLT32X_MANT_DIG == 53
19192008typedef _Float32x zig_f64;
1920#define zig_as_f64(fp, repr) fp##f32x
2009#define zig_make_f64(fp, repr) fp##f32x
19212010#else
19222011#undef zig_has_f64
19232012#define zig_has_f64 0
1924#define zig_repr_f64 i64
1925typedef zig_i64 zig_f64;
1926#define zig_as_f64(fp, repr) repr
1927#undef zig_as_special_f64
1928#define zig_as_special_f64(sign, name, arg, repr) repr
1929#undef zig_as_special_constant_f64
1930#define zig_as_special_constant_f64(sign, name, arg, repr) repr
2013#define zig_bitSizeOf_repr_f64 64
2014typedef int64_t zig_f64;
2015#define zig_make_f64(fp, repr) repr
2016#undef zig_make_special_f64
2017#define zig_make_special_f64(sign, name, arg, repr) repr
2018#undef zig_make_special_constant_f64
2019#define zig_make_special_constant_f64(sign, name, arg, repr) repr
19312020#endif
19322021
19332022#define zig_has_f80 1
19342023#define zig_bitSizeOf_f80 80
19352024#define zig_libc_name_f80(name) __##name##x
1936#define zig_as_special_constant_f80(sign, name, arg, repr) zig_as_special_f80(sign, name, arg, repr)
2025#define zig_make_special_constant_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
19372026#if FLT_MANT_DIG == 64
19382027typedef float zig_f80;
1939#define zig_as_f80(fp, repr) fp##f
2028#define zig_make_f80(fp, repr) fp##f
19402029#elif DBL_MANT_DIG == 64
19412030typedef double zig_f80;
1942#define zig_as_f80(fp, repr) fp
2031#define zig_make_f80(fp, repr) fp
19432032#elif LDBL_MANT_DIG == 64
19442033#define zig_bitSizeOf_c_longdouble 80
2034typedef zig_u128 zig_repr_c_longdouble;
19452035typedef long double zig_f80;
1946#define zig_as_f80(fp, repr) fp##l
2036#define zig_make_f80(fp, repr) fp##l
19472037#elif FLT80_MANT_DIG == 64
19482038typedef _Float80 zig_f80;
1949#define zig_as_f80(fp, repr) fp##f80
2039#define zig_make_f80(fp, repr) fp##f80
19502040#elif FLT64X_MANT_DIG == 64
19512041typedef _Float64x zig_f80;
1952#define zig_as_f80(fp, repr) fp##f64x
2042#define zig_make_f80(fp, repr) fp##f64x
19532043#elif defined(__SIZEOF_FLOAT80__)
19542044typedef __float80 zig_f80;
1955#define zig_as_f80(fp, repr) fp##l
2045#define zig_make_f80(fp, repr) fp##l
19562046#else
19572047#undef zig_has_f80
19582048#define zig_has_f80 0
1959#define zig_repr_f80 i128
2049#define zig_bitSizeOf_repr_f80 128
19602050typedef zig_i128 zig_f80;
1961#define zig_as_f80(fp, repr) repr
1962#undef zig_as_special_f80
1963#define zig_as_special_f80(sign, name, arg, repr) repr
1964#undef zig_as_special_constant_f80
1965#define zig_as_special_constant_f80(sign, name, arg, repr) repr
2051#define zig_make_f80(fp, repr) repr
2052#undef zig_make_special_f80
2053#define zig_make_special_f80(sign, name, arg, repr) repr
2054#undef zig_make_special_constant_f80
2055#define zig_make_special_constant_f80(sign, name, arg, repr) repr
19662056#endif
19672057
19682058#define zig_has_f128 1
19692059#define zig_bitSizeOf_f128 128
19702060#define zig_libc_name_f128(name) name##q
1971#define zig_as_special_constant_f128(sign, name, arg, repr) zig_as_special_f128(sign, name, arg, repr)
2061#define zig_make_special_constant_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
19722062#if FLT_MANT_DIG == 113
19732063typedef float zig_f128;
1974#define zig_as_f128(fp, repr) fp##f
2064#define zig_make_f128(fp, repr) fp##f
19752065#elif DBL_MANT_DIG == 113
19762066typedef double zig_f128;
1977#define zig_as_f128(fp, repr) fp
2067#define zig_make_f128(fp, repr) fp
19782068#elif LDBL_MANT_DIG == 113
19792069#define zig_bitSizeOf_c_longdouble 128
2070typedef zig_u128 zig_repr_c_longdouble;
19802071typedef long double zig_f128;
1981#define zig_as_f128(fp, repr) fp##l
2072#define zig_make_f128(fp, repr) fp##l
19822073#elif FLT128_MANT_DIG == 113
19832074typedef _Float128 zig_f128;
1984#define zig_as_f128(fp, repr) fp##f128
2075#define zig_make_f128(fp, repr) fp##f128
19852076#elif FLT64X_MANT_DIG == 113
19862077typedef _Float64x zig_f128;
1987#define zig_as_f128(fp, repr) fp##f64x
2078#define zig_make_f128(fp, repr) fp##f64x
19882079#elif defined(__SIZEOF_FLOAT128__)
19892080typedef __float128 zig_f128;
1990#define zig_as_f128(fp, repr) fp##q
1991#undef zig_as_special_f128
1992#define zig_as_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
2081#define zig_make_f128(fp, repr) fp##q
2082#undef zig_make_special_f128
2083#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
19932084#else
19942085#undef zig_has_f128
19952086#define zig_has_f128 0
1996#define zig_repr_f128 i128
2087#define zig_bitSizeOf_repr_f128 128
19972088typedef zig_i128 zig_f128;
1998#define zig_as_f128(fp, repr) repr
1999#undef zig_as_special_f128
2000#define zig_as_special_f128(sign, name, arg, repr) repr
2001#undef zig_as_special_constant_f128
2002#define zig_as_special_constant_f128(sign, name, arg, repr) repr
2089#define zig_make_f128(fp, repr) repr
2090#undef zig_make_special_f128
2091#define zig_make_special_f128(sign, name, arg, repr) repr
2092#undef zig_make_special_constant_f128
2093#define zig_make_special_constant_f128(sign, name, arg, repr) repr
20032094#endif
20042095
20052096#define zig_has_c_longdouble 1
......@@ -2010,17 +2101,18 @@ typedef zig_i128 zig_f128;
20102101#define zig_libc_name_c_longdouble(name) name##l
20112102#endif
20122103
2013#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) zig_as_special_c_longdouble(sign, name, arg, repr)
2104#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) zig_make_special_c_longdouble(sign, name, arg, repr)
20142105#ifdef zig_bitSizeOf_c_longdouble
20152106
20162107#ifdef ZIG_TARGET_ABI_MSVC
2017typedef double zig_c_longdouble;
20182108#undef zig_bitSizeOf_c_longdouble
20192109#define zig_bitSizeOf_c_longdouble 64
2020#define zig_as_c_longdouble(fp, repr) fp
2110typedef uint64_t zig_repr_c_longdouble;
2111typedef zig_f64 zig_c_longdouble;
2112#define zig_make_c_longdouble(fp, repr) fp
20212113#else
20222114typedef long double zig_c_longdouble;
2023#define zig_as_c_longdouble(fp, repr) fp##l
2115#define zig_make_c_longdouble(fp, repr) fp##l
20242116#endif
20252117
20262118#else /* zig_bitSizeOf_c_longdouble */
......@@ -2028,34 +2120,32 @@ typedef long double zig_c_longdouble;
20282120#undef zig_has_c_longdouble
20292121#define zig_has_c_longdouble 0
20302122#define zig_bitSizeOf_c_longdouble 80
2123typedef zig_u128 zig_repr_c_longdouble;
20312124#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80
2032#define zig_repr_c_longdouble i128
2125#define zig_bitSizeOf_repr_c_longdouble 128
20332126typedef zig_i128 zig_c_longdouble;
2034#define zig_as_c_longdouble(fp, repr) repr
2035#undef zig_as_special_c_longdouble
2036#define zig_as_special_c_longdouble(sign, name, arg, repr) repr
2037#undef zig_as_special_constant_c_longdouble
2038#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) repr
2127#define zig_make_c_longdouble(fp, repr) repr
2128#undef zig_make_special_c_longdouble
2129#define zig_make_special_c_longdouble(sign, name, arg, repr) repr
2130#undef zig_make_special_constant_c_longdouble
2131#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) repr
20392132
20402133#endif /* zig_bitSizeOf_c_longdouble */
20412134
20422135#if !zig_has_float_builtins
20432136#define zig_float_from_repr(Type, ReprType) \
2044 static inline zig_##Type zig_float_from_repr_##Type(zig_##ReprType repr) { \
2045 return *((zig_##Type*)&repr); \
2137 static inline zig_##Type zig_float_from_repr_##Type(ReprType repr) { \
2138 zig_##Type result; \
2139 memcpy(&result, &repr, sizeof(result)); \
2140 return result; \
20462141 }
20472142
2048zig_float_from_repr(f16, u16)
2049zig_float_from_repr(f32, u32)
2050zig_float_from_repr(f64, u64)
2051zig_float_from_repr(f80, u128)
2052zig_float_from_repr(f128, u128)
2053#if zig_bitSizeOf_c_longdouble == 80
2054zig_float_from_repr(c_longdouble, u128)
2055#else
2056#define zig_expand_float_from_repr(Type, ReprType) zig_float_from_repr(Type, ReprType)
2057zig_expand_float_from_repr(c_longdouble, zig_expand_concat(u, zig_bitSizeOf_c_longdouble))
2058#endif
2143zig_float_from_repr(f16, uint16_t)
2144zig_float_from_repr(f32, uint32_t)
2145zig_float_from_repr(f64, uint64_t)
2146zig_float_from_repr(f80, zig_u128)
2147zig_float_from_repr(f128, zig_u128)
2148zig_float_from_repr(c_longdouble, zig_repr_c_longdouble)
20592149#endif
20602150
20612151#define zig_cast_f16 (zig_f16)
......@@ -2073,32 +2163,35 @@ zig_expand_float_from_repr(c_longdouble, zig_expand_concat(u, zig_bitSizeOf_c_lo
20732163#endif
20742164
20752165#define zig_convert_builtin(ResType, operation, ArgType, version) \
2076 zig_extern zig_##ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
2077 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(zig_##ArgType);
2078zig_convert_builtin(f16, trunc, f32, 2)
2079zig_convert_builtin(f16, trunc, f64, 2)
2080zig_convert_builtin(f16, trunc, f80, 2)
2081zig_convert_builtin(f16, trunc, f128, 2)
2082zig_convert_builtin(f32, extend, f16, 2)
2083zig_convert_builtin(f32, trunc, f64, 2)
2084zig_convert_builtin(f32, trunc, f80, 2)
2085zig_convert_builtin(f32, trunc, f128, 2)
2086zig_convert_builtin(f64, extend, f16, 2)
2087zig_convert_builtin(f64, extend, f32, 2)
2088zig_convert_builtin(f64, trunc, f80, 2)
2089zig_convert_builtin(f64, trunc, f128, 2)
2090zig_convert_builtin(f80, extend, f16, 2)
2091zig_convert_builtin(f80, extend, f32, 2)
2092zig_convert_builtin(f80, extend, f64, 2)
2093zig_convert_builtin(f80, trunc, f128, 2)
2094zig_convert_builtin(f128, extend, f16, 2)
2095zig_convert_builtin(f128, extend, f32, 2)
2096zig_convert_builtin(f128, extend, f64, 2)
2097zig_convert_builtin(f128, extend, f80, 2)
2166 zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
2167 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType);
2168zig_convert_builtin(zig_f16, trunc, zig_f32, 2)
2169zig_convert_builtin(zig_f16, trunc, zig_f64, 2)
2170zig_convert_builtin(zig_f16, trunc, zig_f80, 2)
2171zig_convert_builtin(zig_f16, trunc, zig_f128, 2)
2172zig_convert_builtin(zig_f32, extend, zig_f16, 2)
2173zig_convert_builtin(zig_f32, trunc, zig_f64, 2)
2174zig_convert_builtin(zig_f32, trunc, zig_f80, 2)
2175zig_convert_builtin(zig_f32, trunc, zig_f128, 2)
2176zig_convert_builtin(zig_f64, extend, zig_f16, 2)
2177zig_convert_builtin(zig_f64, extend, zig_f32, 2)
2178zig_convert_builtin(zig_f64, trunc, zig_f80, 2)
2179zig_convert_builtin(zig_f64, trunc, zig_f128, 2)
2180zig_convert_builtin(zig_f80, extend, zig_f16, 2)
2181zig_convert_builtin(zig_f80, extend, zig_f32, 2)
2182zig_convert_builtin(zig_f80, extend, zig_f64, 2)
2183zig_convert_builtin(zig_f80, trunc, zig_f128, 2)
2184zig_convert_builtin(zig_f128, extend, zig_f16, 2)
2185zig_convert_builtin(zig_f128, extend, zig_f32, 2)
2186zig_convert_builtin(zig_f128, extend, zig_f64, 2)
2187zig_convert_builtin(zig_f128, extend, zig_f80, 2)
20982188
20992189#define zig_float_negate_builtin_0(Type) \
21002190 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \
2101 return zig_expand_concat(zig_xor_, zig_repr_##Type)(arg, zig_expand_minInt(zig_repr_##Type, zig_bitSizeOf_##Type)); \
2191 return zig_expand_concat(zig_xor_i, zig_bitSizeOf_repr_##Type)( \
2192 arg, \
2193 zig_minInt_i(zig_bitSizeOf_repr_##Type, zig_bitSizeOf_##Type) \
2194 ); \
21022195 }
21032196#define zig_float_negate_builtin_1(Type) \
21042197 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \
......@@ -2106,28 +2199,28 @@ zig_convert_builtin(f128, extend, f80, 2)
21062199 }
21072200
21082201#define zig_float_less_builtin_0(Type, operation) \
2109 zig_extern zig_i32 zig_expand_concat(zig_expand_concat(__##operation, \
2110 zig_compiler_rt_abbrev_##Type), 2)(zig_##Type, zig_##Type); \
2111 static inline zig_i32 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2112 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 2)(lhs, rhs); \
2202 zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \
2203 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
2204 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2205 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
21132206 }
21142207#define zig_float_less_builtin_1(Type, operation) \
2115 static inline zig_i32 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2208 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
21162209 return (!(lhs <= rhs) - (lhs < rhs)); \
21172210 }
21182211
21192212#define zig_float_greater_builtin_0(Type, operation) \
21202213 zig_float_less_builtin_0(Type, operation)
21212214#define zig_float_greater_builtin_1(Type, operation) \
2122 static inline zig_i32 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2215 static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
21232216 return ((lhs > rhs) - !(lhs >= rhs)); \
21242217 }
21252218
21262219#define zig_float_binary_builtin_0(Type, operation, operator) \
21272220 zig_extern zig_##Type zig_expand_concat(zig_expand_concat(__##operation, \
2128 zig_compiler_rt_abbrev_##Type), 3)(zig_##Type, zig_##Type); \
2221 zig_compiler_rt_abbrev_zig_##Type), 3)(zig_##Type, zig_##Type); \
21292222 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2130 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 3)(lhs, rhs); \
2223 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 3)(lhs, rhs); \
21312224 }
21322225#define zig_float_binary_builtin_1(Type, operation, operator) \
21332226 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
......@@ -2135,18 +2228,18 @@ zig_convert_builtin(f128, extend, f80, 2)
21352228 }
21362229
21372230#define zig_float_builtins(Type) \
2138 zig_convert_builtin(i32, fix, Type, ) \
2139 zig_convert_builtin(u32, fixuns, Type, ) \
2140 zig_convert_builtin(i64, fix, Type, ) \
2141 zig_convert_builtin(u64, fixuns, Type, ) \
2142 zig_convert_builtin(i128, fix, Type, ) \
2143 zig_convert_builtin(u128, fixuns, Type, ) \
2144 zig_convert_builtin(Type, float, i32, ) \
2145 zig_convert_builtin(Type, floatun, u32, ) \
2146 zig_convert_builtin(Type, float, i64, ) \
2147 zig_convert_builtin(Type, floatun, u64, ) \
2148 zig_convert_builtin(Type, float, i128, ) \
2149 zig_convert_builtin(Type, floatun, u128, ) \
2231 zig_convert_builtin( int32_t, fix, zig_##Type, ) \
2232 zig_convert_builtin(uint32_t, fixuns, zig_##Type, ) \
2233 zig_convert_builtin( int64_t, fix, zig_##Type, ) \
2234 zig_convert_builtin(uint64_t, fixuns, zig_##Type, ) \
2235 zig_convert_builtin(zig_i128, fix, zig_##Type, ) \
2236 zig_convert_builtin(zig_u128, fixuns, zig_##Type, ) \
2237 zig_convert_builtin(zig_##Type, float, int32_t, ) \
2238 zig_convert_builtin(zig_##Type, floatun, uint32_t, ) \
2239 zig_convert_builtin(zig_##Type, float, int64_t, ) \
2240 zig_convert_builtin(zig_##Type, floatun, uint64_t, ) \
2241 zig_convert_builtin(zig_##Type, float, zig_i128, ) \
2242 zig_convert_builtin(zig_##Type, floatun, zig_u128, ) \
21502243 zig_expand_concat(zig_float_negate_builtin_, zig_has_##Type)(Type) \
21512244 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, cmp) \
21522245 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, ne) \
......@@ -2200,98 +2293,98 @@ zig_float_builtins(c_longdouble)
22002293
22012294// TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, and load 64 bit without interlocked on x64
22022295
2203#define zig_msvc_atomics(Type, suffix) \
2204 static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
2205 zig_##Type comparand = *expected; \
2206 zig_##Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \
2296#define zig_msvc_atomics(ZigType, Type, suffix) \
2297 static inline bool zig_msvc_cmpxchg_##ZigType(Type volatile* obj, Type* expected, Type desired) { \
2298 Type comparand = *expected; \
2299 Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \
22072300 bool exchanged = initial == comparand; \
22082301 if (!exchanged) { \
22092302 *expected = initial; \
22102303 } \
22112304 return exchanged; \
22122305 } \
2213 static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2306 static inline Type zig_msvc_atomicrmw_xchg_##ZigType(Type volatile* obj, Type value) { \
22142307 return _InterlockedExchange##suffix(obj, value); \
22152308 } \
2216 static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2309 static inline Type zig_msvc_atomicrmw_add_##ZigType(Type volatile* obj, Type value) { \
22172310 return _InterlockedExchangeAdd##suffix(obj, value); \
22182311 } \
2219 static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2312 static inline Type zig_msvc_atomicrmw_sub_##ZigType(Type volatile* obj, Type value) { \
22202313 bool success = false; \
2221 zig_##Type new; \
2222 zig_##Type prev; \
2314 Type new; \
2315 Type prev; \
22232316 while (!success) { \
22242317 prev = *obj; \
22252318 new = prev - value; \
2226 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2319 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
22272320 } \
22282321 return prev; \
22292322 } \
2230 static inline zig_##Type zig_msvc_atomicrmw_or_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2323 static inline Type zig_msvc_atomicrmw_or_##ZigType(Type volatile* obj, Type value) { \
22312324 return _InterlockedOr##suffix(obj, value); \
22322325 } \
2233 static inline zig_##Type zig_msvc_atomicrmw_xor_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2326 static inline Type zig_msvc_atomicrmw_xor_##ZigType(Type volatile* obj, Type value) { \
22342327 return _InterlockedXor##suffix(obj, value); \
22352328 } \
2236 static inline zig_##Type zig_msvc_atomicrmw_and_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2329 static inline Type zig_msvc_atomicrmw_and_##ZigType(Type volatile* obj, Type value) { \
22372330 return _InterlockedAnd##suffix(obj, value); \
22382331 } \
2239 static inline zig_##Type zig_msvc_atomicrmw_nand_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2332 static inline Type zig_msvc_atomicrmw_nand_##ZigType(Type volatile* obj, Type value) { \
22402333 bool success = false; \
2241 zig_##Type new; \
2242 zig_##Type prev; \
2334 Type new; \
2335 Type prev; \
22432336 while (!success) { \
22442337 prev = *obj; \
22452338 new = ~(prev & value); \
2246 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2339 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
22472340 } \
22482341 return prev; \
22492342 } \
2250 static inline zig_##Type zig_msvc_atomicrmw_min_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2343 static inline Type zig_msvc_atomicrmw_min_##ZigType(Type volatile* obj, Type value) { \
22512344 bool success = false; \
2252 zig_##Type new; \
2253 zig_##Type prev; \
2345 Type new; \
2346 Type prev; \
22542347 while (!success) { \
22552348 prev = *obj; \
22562349 new = value < prev ? value : prev; \
2257 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2350 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
22582351 } \
22592352 return prev; \
22602353 } \
2261 static inline zig_##Type zig_msvc_atomicrmw_max_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2354 static inline Type zig_msvc_atomicrmw_max_##ZigType(Type volatile* obj, Type value) { \
22622355 bool success = false; \
2263 zig_##Type new; \
2264 zig_##Type prev; \
2356 Type new; \
2357 Type prev; \
22652358 while (!success) { \
22662359 prev = *obj; \
22672360 new = value > prev ? value : prev; \
2268 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2361 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
22692362 } \
22702363 return prev; \
22712364 } \
2272 static inline void zig_msvc_atomic_store_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2365 static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
22732366 _InterlockedExchange##suffix(obj, value); \
22742367 } \
2275 static inline zig_##Type zig_msvc_atomic_load_##Type(zig_##Type volatile* obj) { \
2368 static inline Type zig_msvc_atomic_load_##ZigType(Type volatile* obj) { \
22762369 return _InterlockedOr##suffix(obj, 0); \
22772370 }
22782371
2279zig_msvc_atomics(u8, 8)
2280zig_msvc_atomics(i8, 8)
2281zig_msvc_atomics(u16, 16)
2282zig_msvc_atomics(i16, 16)
2283zig_msvc_atomics(u32, )
2284zig_msvc_atomics(i32, )
2372zig_msvc_atomics( u8, uint8_t, 8)
2373zig_msvc_atomics( i8, int8_t, 8)
2374zig_msvc_atomics(u16, uint16_t, 16)
2375zig_msvc_atomics(i16, int16_t, 16)
2376zig_msvc_atomics(u32, uint32_t, )
2377zig_msvc_atomics(i32, int32_t, )
22852378
22862379#if _M_X64
2287zig_msvc_atomics(u64, 64)
2288zig_msvc_atomics(i64, 64)
2380zig_msvc_atomics(u64, uint64_t, 64)
2381zig_msvc_atomics(i64, int64_t, 64)
22892382#endif
22902383
22912384#define zig_msvc_flt_atomics(Type, ReprType, suffix) \
22922385 static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
2293 zig_##ReprType comparand = *((zig_##ReprType*)expected); \
2294 zig_##ReprType initial = _InterlockedCompareExchange##suffix((zig_##ReprType volatile*)obj, *((zig_##ReprType*)&desired), comparand); \
2386 ReprType comparand = *((ReprType*)expected); \
2387 ReprType initial = _InterlockedCompareExchange##suffix((ReprType volatile*)obj, *((ReprType*)&desired), comparand); \
22952388 bool exchanged = initial == comparand; \
22962389 if (!exchanged) { \
22972390 *expected = *((zig_##Type*)&initial); \
......@@ -2299,50 +2392,50 @@ zig_msvc_atomics(i64, 64)
22992392 return exchanged; \
23002393 } \
23012394 static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2302 zig_##ReprType initial = _InterlockedExchange##suffix((zig_##ReprType volatile*)obj, *((zig_##ReprType*)&value)); \
2395 ReprType initial = _InterlockedExchange##suffix((ReprType volatile*)obj, *((ReprType*)&value)); \
23032396 return *((zig_##Type*)&initial); \
23042397 } \
23052398 static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \
23062399 bool success = false; \
2307 zig_##ReprType new; \
2400 ReprType new; \
23082401 zig_##Type prev; \
23092402 while (!success) { \
23102403 prev = *obj; \
23112404 new = prev + value; \
2312 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \
2405 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((ReprType*)&new)); \
23132406 } \
23142407 return prev; \
23152408 } \
23162409 static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \
23172410 bool success = false; \
2318 zig_##ReprType new; \
2411 ReprType new; \
23192412 zig_##Type prev; \
23202413 while (!success) { \
23212414 prev = *obj; \
23222415 new = prev - value; \
2323 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \
2416 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((ReprType*)&new)); \
23242417 } \
23252418 return prev; \
23262419 }
23272420
2328zig_msvc_flt_atomics(f32, u32, )
2421zig_msvc_flt_atomics(f32, uint32_t, )
23292422#if _M_X64
2330zig_msvc_flt_atomics(f64, u64, 64)
2423zig_msvc_flt_atomics(f64, uint64_t, 64)
23312424#endif
23322425
23332426#if _M_IX86
23342427static inline void zig_msvc_atomic_barrier() {
2335 zig_i32 barrier;
2428 int32_t barrier;
23362429 __asm {
23372430 xchg barrier, eax
23382431 }
23392432}
23402433
2341static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, zig_u32* arg) {
2434static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, void* arg) {
23422435 return _InterlockedExchangePointer(obj, arg);
23432436}
23442437
2345static inline void zig_msvc_atomic_store_p32(void** obj, zig_u32* arg) {
2438static inline void zig_msvc_atomic_store_p32(void** obj, void* arg) {
23462439 _InterlockedExchangePointer(obj, arg);
23472440}
23482441
......@@ -2360,11 +2453,11 @@ static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desir
23602453 return exchanged;
23612454}
23622455#else /* _M_IX86 */
2363static inline void* zig_msvc_atomicrmw_xchg_p64(void** obj, zig_u64* arg) {
2456static inline void* zig_msvc_atomicrmw_xchg_p64(void** obj, void* arg) {
23642457 return _InterlockedExchangePointer(obj, arg);
23652458}
23662459
2367static inline void zig_msvc_atomic_store_p64(void** obj, zig_u64* arg) {
2460static inline void zig_msvc_atomic_store_p64(void** obj, void* arg) {
23682461 _InterlockedExchangePointer(obj, arg);
23692462}
23702463
......@@ -2383,11 +2476,11 @@ static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desir
23832476}
23842477
23852478static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expected, zig_u128 desired) {
2386 return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_i64*)expected);
2479 return _InterlockedCompareExchange128((int64_t volatile*)obj, desired.hi, desired.lo, (int64_t*)expected);
23872480}
23882481
23892482static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {
2390 return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_u64*)expected);
2483 return _InterlockedCompareExchange128((int64_t volatile*)obj, desired.hi, desired.lo, (uint64_t*)expected);
23912484}
23922485
23932486#define zig_msvc_atomics_128xchg(Type) \
......@@ -2429,7 +2522,7 @@ zig_msvc_atomics_128op(u128, max)
24292522
24302523#endif /* _MSC_VER && (_M_IX86 || _M_X64) */
24312524
2432/* ========================= Special Case Intrinsics ========================= */
2525/* ======================== Special Case Intrinsics ========================= */
24332526
24342527#if (_MSC_VER && _M_X64) || defined(__x86_64__)
24352528
......@@ -2459,8 +2552,8 @@ static inline void* zig_x86_windows_teb(void) {
24592552
24602553#if (_MSC_VER && (_M_IX86 || _M_X64)) || defined(__i386__) || defined(__x86_64__)
24612554
2462static inline void zig_x86_cpuid(zig_u32 leaf_id, zig_u32 subid, zig_u32* eax, zig_u32* ebx, zig_u32* ecx, zig_u32* edx) {
2463 zig_u32 cpu_info[4];
2555static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
2556 uint32_t cpu_info[4];
24642557#if _MSC_VER
24652558 __cpuidex(cpu_info, leaf_id, subid);
24662559#else
......@@ -2472,12 +2565,12 @@ static inline void zig_x86_cpuid(zig_u32 leaf_id, zig_u32 subid, zig_u32* eax, z
24722565 *edx = cpu_info[3];
24732566}
24742567
2475static inline zig_u32 zig_x86_get_xcr0(void) {
2568static inline uint32_t zig_x86_get_xcr0(void) {
24762569#if _MSC_VER
2477 return (zig_u32)_xgetbv(0);
2570 return (uint32_t)_xgetbv(0);
24782571#else
2479 zig_u32 eax;
2480 zig_u32 edx;
2572 uint32_t eax;
2573 uint32_t edx;
24812574 __asm__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
24822575 return eax;
24832576#endif
src/Compilation.zig+5-9
......@@ -3325,24 +3325,20 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
33253325 const decl_emit_h = emit_h.declPtr(decl_index);
33263326 const fwd_decl = &decl_emit_h.fwd_decl;
33273327 fwd_decl.shrinkRetainingCapacity(0);
3328 var typedefs_arena = std.heap.ArenaAllocator.init(gpa);
3329 defer typedefs_arena.deinit();
3328 var ctypes_arena = std.heap.ArenaAllocator.init(gpa);
3329 defer ctypes_arena.deinit();
33303330
33313331 var dg: c_codegen.DeclGen = .{
33323332 .gpa = gpa,
33333333 .module = module,
33343334 .error_msg = null,
3335 .decl_index = decl_index,
3335 .decl_index = decl_index.toOptional(),
33363336 .decl = decl,
33373337 .fwd_decl = fwd_decl.toManaged(gpa),
3338 .typedefs = c_codegen.TypedefMap.initContext(gpa, .{ .mod = module }),
3339 .typedefs_arena = typedefs_arena.allocator(),
3338 .ctypes = .{},
33403339 };
33413340 defer {
3342 for (dg.typedefs.values()) |typedef| {
3343 module.gpa.free(typedef.rendered);
3344 }
3345 dg.typedefs.deinit();
3341 dg.ctypes.deinit(gpa);
33463342 dg.fwd_decl.deinit();
33473343 }
33483344
src/codegen/c.zig+890-1103
......@@ -23,12 +23,15 @@ const libcFloatSuffix = target_util.libcFloatSuffix;
2323const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
2424const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
2525
26const Mutability = enum { Const, ConstArgument, Mut };
26const Mutability = enum { @"const", mut };
2727const BigIntLimb = std.math.big.Limb;
2828const BigInt = std.math.big.int;
2929
30pub const CType = @import("c/type.zig").CType;
31
3032pub const CValue = union(enum) {
3133 none: void,
34 new_local: LocalIndex,
3235 local: LocalIndex,
3336 /// Address of a local.
3437 local_ref: LocalIndex,
......@@ -36,6 +39,8 @@ pub const CValue = union(enum) {
3639 constant: Air.Inst.Ref,
3740 /// Index into the parameters
3841 arg: usize,
42 /// The payload field of a parameter
43 arg_array: usize,
3944 /// Index into a tuple's fields
4045 field: usize,
4146 /// By-value
......@@ -61,12 +66,17 @@ const TypedefKind = enum {
6166};
6267
6368pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
64pub const TypedefMap = std.ArrayHashMap(
65 Type,
66 struct { name: []const u8, rendered: []u8 },
67 Type.HashContext32,
68 true,
69);
69
70pub const LazyFnKey = union(enum) {
71 tag_name: Decl.Index,
72};
73pub const LazyFnValue = struct {
74 fn_name: []const u8,
75 data: union {
76 tag_name: Type,
77 },
78};
79pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);
7080
7181const LoopDepth = u16;
7282const Local = struct {
......@@ -81,11 +91,6 @@ const LocalsList = std.ArrayListUnmanaged(LocalIndex);
8191const LocalsMap = std.ArrayHashMapUnmanaged(Type, LocalsList, Type.HashContext32, true);
8292const LocalsStack = std.ArrayListUnmanaged(LocalsMap);
8393
84const FormatTypeAsCIdentContext = struct {
85 ty: Type,
86 mod: *Module,
87};
88
8994const ValueRenderLocation = enum {
9095 FunctionArgument,
9196 Initializer,
......@@ -106,26 +111,6 @@ const BuiltinInfo = enum {
106111 Bits,
107112};
108113
109fn formatTypeAsCIdentifier(
110 data: FormatTypeAsCIdentContext,
111 comptime fmt: []const u8,
112 options: std.fmt.FormatOptions,
113 writer: anytype,
114) !void {
115 var stack = std.heap.stackFallback(128, data.mod.gpa);
116 const allocator = stack.get();
117 const str = std.fmt.allocPrint(allocator, "{}", .{data.ty.fmt(data.mod)}) catch "";
118 defer allocator.free(str);
119 return formatIdent(str, fmt, options, writer);
120}
121
122pub fn typeToCIdentifier(ty: Type, mod: *Module) std.fmt.Formatter(formatTypeAsCIdentifier) {
123 return .{ .data = .{
124 .ty = ty,
125 .mod = mod,
126 } };
127}
128
129114const reserved_idents = std.ComptimeStringMap(void, .{
130115 // C language
131116 .{ "alignas", {
......@@ -281,6 +266,7 @@ pub const Function = struct {
281266 next_arg_index: usize = 0,
282267 next_block_index: usize = 0,
283268 object: Object,
269 lazy_fns: LazyFnMap,
284270 func: *Module.Fn,
285271 /// All the locals, to be emitted at the top of the function.
286272 locals: std.ArrayListUnmanaged(Local) = .{},
......@@ -315,9 +301,9 @@ pub const Function = struct {
315301 const alignment = 0;
316302 const decl_c_value = try f.allocLocalValue(ty, alignment);
317303 const gpa = f.object.dg.gpa;
318 try f.allocs.put(gpa, decl_c_value.local, true);
304 try f.allocs.put(gpa, decl_c_value.new_local, true);
319305 try writer.writeAll("static ");
320 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .Const, alignment, .Complete);
306 try f.object.dg.renderTypeAndName(writer, ty, decl_c_value, .@"const", alignment, .Complete);
321307 try writer.writeAll(" = ");
322308 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
323309 try writer.writeAll(";\n ");
......@@ -347,12 +333,12 @@ pub const Function = struct {
347333 .alignment = alignment,
348334 .loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1),
349335 });
350 return CValue{ .local = @intCast(LocalIndex, f.locals.items.len - 1) };
336 return CValue{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) };
351337 }
352338
353339 fn allocLocal(f: *Function, inst: Air.Inst.Index, ty: Type) !CValue {
354 const result = try f.allocAlignedLocal(ty, .Mut, 0);
355 log.debug("%{d}: allocating t{d}", .{ inst, result.local });
340 const result = try f.allocAlignedLocal(ty, .mut, 0);
341 log.debug("%{d}: allocating t{d}", .{ inst, result.new_local });
356342 return result;
357343 }
358344
......@@ -366,7 +352,7 @@ pub const Function = struct {
366352 if (local.alignment >= alignment) {
367353 local.loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1);
368354 _ = locals_list.swapRemove(i);
369 return CValue{ .local = local_index };
355 return CValue{ .new_local = local_index };
370356 }
371357 }
372358 }
......@@ -446,7 +432,31 @@ pub const Function = struct {
446432 return f.object.dg.fmtIntLiteral(ty, val);
447433 }
448434
449 pub fn deinit(f: *Function, gpa: mem.Allocator) void {
435 fn getTagNameFn(f: *Function, enum_ty: Type) ![]const u8 {
436 const gpa = f.object.dg.gpa;
437 const owner_decl = enum_ty.getOwnerDecl();
438
439 const gop = try f.lazy_fns.getOrPut(gpa, .{ .tag_name = owner_decl });
440 if (!gop.found_existing) {
441 errdefer _ = f.lazy_fns.pop();
442
443 var promoted = f.object.dg.ctypes.promote(gpa);
444 defer f.object.dg.ctypes.demote(promoted);
445 const arena = promoted.arena.allocator();
446
447 gop.value_ptr.* = .{
448 .fn_name = try std.fmt.allocPrint(arena, "zig_tagName_{}__{d}", .{
449 fmtIdent(mem.span(f.object.dg.module.declPtr(owner_decl).name)),
450 @enumToInt(owner_decl),
451 }),
452 .data = .{ .tag_name = try enum_ty.copy(arena) },
453 };
454 }
455 return gop.value_ptr.fn_name;
456 }
457
458 pub fn deinit(f: *Function) void {
459 const gpa = f.object.dg.gpa;
450460 f.allocs.deinit(gpa);
451461 f.locals.deinit(gpa);
452462 for (f.free_locals_stack.items) |*free_locals| {
......@@ -455,11 +465,9 @@ pub const Function = struct {
455465 f.free_locals_stack.deinit(gpa);
456466 f.blocks.deinit(gpa);
457467 f.value_map.deinit();
468 f.lazy_fns.deinit(gpa);
458469 f.object.code.deinit();
459 for (f.object.dg.typedefs.values()) |typedef| {
460 gpa.free(typedef.rendered);
461 }
462 f.object.dg.typedefs.deinit();
470 f.object.dg.ctypes.deinit(gpa);
463471 f.object.dg.fwd_decl.deinit();
464472 f.arena.deinit();
465473 }
......@@ -483,30 +491,20 @@ pub const Object = struct {
483491pub const DeclGen = struct {
484492 gpa: std.mem.Allocator,
485493 module: *Module,
486 decl: *Decl,
487 decl_index: Decl.Index,
494 decl: ?*Decl,
495 decl_index: Decl.OptionalIndex,
488496 fwd_decl: std.ArrayList(u8),
489497 error_msg: ?*Module.ErrorMsg,
490 /// The key of this map is Type which has references to typedefs_arena.
491 typedefs: TypedefMap,
492 typedefs_arena: std.mem.Allocator,
498 ctypes: CType.Store,
493499
494500 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
495501 @setCold(true);
496502 const src = LazySrcLoc.nodeOffset(0);
497 const src_loc = src.toSrcLoc(dg.decl);
503 const src_loc = src.toSrcLoc(dg.decl.?);
498504 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
499505 return error.AnalysisFail;
500506 }
501507
502 fn getTypedefName(dg: *DeclGen, t: Type) ?[]const u8 {
503 if (dg.typedefs.get(t)) |typedef| {
504 return typedef.name;
505 } else {
506 return null;
507 }
508 }
509
510508 fn renderDeclValue(
511509 dg: *DeclGen,
512510 writer: anytype,
......@@ -747,7 +745,7 @@ pub const DeclGen = struct {
747745
748746 try writer.writeAll("zig_cast_");
749747 try dg.renderTypeForBuiltinFnName(writer, ty);
750 try writer.writeAll(" zig_as_");
748 try writer.writeAll(" zig_make_");
751749 try dg.renderTypeForBuiltinFnName(writer, ty);
752750 try writer.writeByte('(');
753751 switch (bits) {
......@@ -821,7 +819,7 @@ pub const DeclGen = struct {
821819
822820 empty = false;
823821 }
824 if (empty) try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});
822
825823 return writer.writeByte('}');
826824 },
827825 .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}),
......@@ -957,7 +955,7 @@ pub const DeclGen = struct {
957955 try writer.writeByte(' ');
958956 var empty = true;
959957 if (std.math.isFinite(f128_val)) {
960 try writer.writeAll("zig_as_");
958 try writer.writeAll("zig_make_");
961959 try dg.renderTypeForBuiltinFnName(writer, ty);
962960 try writer.writeByte('(');
963961 switch (bits) {
......@@ -992,7 +990,7 @@ pub const DeclGen = struct {
992990 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});
993991 }
994992
995 try writer.writeAll("zig_as_special_");
993 try writer.writeAll("zig_make_special_");
996994 if (location == .StaticInitializer) try writer.writeAll("constant_");
997995 try dg.renderTypeForBuiltinFnName(writer, ty);
998996 try writer.writeByte('(');
......@@ -1292,7 +1290,6 @@ pub const DeclGen = struct {
12921290
12931291 empty = false;
12941292 }
1295 if (empty) try writer.print("{}", .{try dg.fmtIntLiteral(Type.u8, Value.zero)});
12961293 try writer.writeByte('}');
12971294 },
12981295 .Packed => {
......@@ -1309,7 +1306,7 @@ pub const DeclGen = struct {
13091306 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
13101307
13111308 var eff_num_fields: usize = 0;
1312 for (field_vals, 0..) |_, index| {
1309 for (0..field_vals.len) |index| {
13131310 const field_ty = ty.structFieldType(index);
13141311 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
13151312
......@@ -1413,6 +1410,7 @@ pub const DeclGen = struct {
14131410 return;
14141411 }
14151412
1413 var has_payload_init = false;
14161414 try writer.writeByte('{');
14171415 if (ty.unionTagTypeSafety()) |tag_ty| {
14181416 const layout = ty.unionGetLayout(target);
......@@ -1421,7 +1419,10 @@ pub const DeclGen = struct {
14211419 try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type);
14221420 try writer.writeAll(", ");
14231421 }
1424 try writer.writeAll(".payload = {");
1422 if (!ty.unionHasAllZeroBitFieldTypes()) {
1423 try writer.writeAll(".payload = {");
1424 has_payload_init = true;
1425 }
14251426 }
14261427
14271428 var it = ty.unionFields().iterator();
......@@ -1433,8 +1434,8 @@ pub const DeclGen = struct {
14331434 try writer.print(".{ } = ", .{fmtIdent(field.key_ptr.*)});
14341435 try dg.renderValue(writer, field.value_ptr.ty, Value.undef, initializer_type);
14351436 break;
1436 } else try writer.writeAll(".empty_union = 0");
1437 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
1437 }
1438 if (has_payload_init) try writer.writeByte('}');
14381439 try writer.writeByte('}');
14391440 },
14401441
......@@ -1457,496 +1458,62 @@ pub const DeclGen = struct {
14571458 }
14581459
14591460 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind, export_index: u32) !void {
1460 const fn_info = dg.decl.ty.fnInfo();
1461 const store = &dg.ctypes.set;
1462 const module = dg.module;
1463
1464 const fn_ty = dg.decl.?.ty;
1465 const fn_cty_idx = try dg.typeToIndex(fn_ty, switch (kind) {
1466 .Forward => .forward,
1467 .Complete => .complete,
1468 });
1469
1470 const fn_info = fn_ty.fnInfo();
14611471 if (fn_info.cc == .Naked) {
14621472 switch (kind) {
14631473 .Forward => try w.writeAll("zig_naked_decl "),
14641474 .Complete => try w.writeAll("zig_naked "),
14651475 }
14661476 }
1467 if (dg.decl.val.castTag(.function)) |func_payload|
1477 if (dg.decl.?.val.castTag(.function)) |func_payload|
14681478 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1469
1470 const target = dg.module.getTarget();
1471 var ret_buf: LowerFnRetTyBuffer = undefined;
1472 const ret_ty = lowerFnRetTy(fn_info.return_type, &ret_buf, target);
1473
1474 try dg.renderType(w, ret_ty, kind);
1475 try w.writeByte(' ');
1479 if (fn_info.return_type.tag() == .noreturn) try w.writeAll("zig_noreturn ");
1480
1481 const trailing = try renderTypePrefix(
1482 dg.decl_index,
1483 store.*,
1484 module,
1485 w,
1486 fn_cty_idx,
1487 .suffix,
1488 CQualifiers.init(.{}),
1489 );
1490 try w.print("{}", .{trailing});
14761491
14771492 if (toCallingConvention(fn_info.cc)) |call_conv| {
14781493 try w.print("zig_callconv({s}) ", .{call_conv});
14791494 }
14801495
1481 if (fn_info.alignment > 0 and kind == .Complete) try w.print(" zig_align_fn({})", .{fn_info.alignment});
1482
1483 try dg.renderDeclName(w, dg.decl_index, export_index);
1484 try w.writeByte('(');
1485
1486 var index: usize = 0;
1487 for (fn_info.param_types) |param_type| {
1488 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1489 if (index > 0) try w.writeAll(", ");
1490 const name = CValue{ .arg = index };
1491 try dg.renderTypeAndName(w, param_type, name, .ConstArgument, 0, kind);
1492 index += 1;
1496 if (fn_info.alignment > 0 and kind == .Complete) {
1497 try w.print(" zig_align_fn({})", .{fn_info.alignment});
14931498 }
14941499
1495 if (fn_info.is_var_args) {
1496 if (index > 0) try w.writeAll(", ");
1497 try w.writeAll("...");
1498 } else if (index == 0) {
1499 try dg.renderType(w, Type.void, kind);
1500 }
1501 try w.writeByte(')');
1502 if (fn_info.alignment > 0 and kind == .Forward) try w.print(" zig_align_fn({})", .{fn_info.alignment});
1503 }
1504
1505 fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1506 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1507 defer buffer.deinit();
1508 const bw = buffer.writer();
1500 try dg.renderDeclName(w, dg.decl_index.unwrap().?, export_index);
15091501
1510 const fn_info = t.fnInfo();
1502 try renderTypeSuffix(dg.decl_index, store.*, module, w, fn_cty_idx, .suffix);
15111503
1512 const target = dg.module.getTarget();
1513 var ret_buf: LowerFnRetTyBuffer = undefined;
1514 const ret_ty = lowerFnRetTy(fn_info.return_type, &ret_buf, target);
1515
1516 try bw.writeAll("typedef ");
1517 try dg.renderType(bw, ret_ty, .Forward);
1518 try bw.writeAll(" (*");
1519 const name_begin = buffer.items.len;
1520 try bw.print("zig_F_{}", .{typeToCIdentifier(t, dg.module)});
1521 const name_end = buffer.items.len;
1522 try bw.writeAll(")(");
1523
1524 const param_len = fn_info.param_types.len;
1525
1526 var params_written: usize = 0;
1527 var index: usize = 0;
1528 while (index < param_len) : (index += 1) {
1529 const param_ty = fn_info.param_types[index];
1530 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
1531 if (params_written > 0) {
1532 try bw.writeAll(", ");
1533 }
1534 try dg.renderTypeAndName(bw, param_ty, .{ .bytes = "" }, .Mut, 0, .Forward);
1535 params_written += 1;
1504 if (fn_info.alignment > 0 and kind == .Forward) {
1505 try w.print(" zig_align_fn({})", .{fn_info.alignment});
15361506 }
1537
1538 if (fn_info.is_var_args) {
1539 if (params_written != 0) try bw.writeAll(", ");
1540 try bw.writeAll("...");
1541 } else if (params_written == 0) {
1542 try dg.renderType(bw, Type.void, .Forward);
1543 }
1544 try bw.writeAll(");\n");
1545
1546 const rendered = try buffer.toOwnedSlice();
1547 errdefer dg.typedefs.allocator.free(rendered);
1548 const name = rendered[name_begin..name_end];
1549
1550 try dg.typedefs.ensureUnusedCapacity(1);
1551 dg.typedefs.putAssumeCapacityNoClobber(
1552 try t.copy(dg.typedefs_arena),
1553 .{ .name = name, .rendered = rendered },
1554 );
1555
1556 return name;
15571507 }
15581508
1559 fn renderSliceTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1560 std.debug.assert(t.sentinel() == null); // expected canonical type
1561
1562 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1563 defer buffer.deinit();
1564 const bw = buffer.writer();
1565
1566 var ptr_ty_buf: Type.SlicePtrFieldTypeBuffer = undefined;
1567 const ptr_ty = t.slicePtrFieldType(&ptr_ty_buf);
1568 const ptr_name = CValue{ .identifier = "ptr" };
1569 const len_ty = Type.usize;
1570 const len_name = CValue{ .identifier = "len" };
1571
1572 try bw.writeAll("typedef struct {\n ");
1573 try dg.renderTypeAndName(bw, ptr_ty, ptr_name, .Mut, 0, .Complete);
1574 try bw.writeAll(";\n ");
1575 try dg.renderTypeAndName(bw, len_ty, len_name, .Mut, 0, .Complete);
1576
1577 try bw.writeAll(";\n} ");
1578 const name_begin = buffer.items.len;
1579 try bw.print("zig_{c}_{}", .{
1580 @as(u8, if (t.isConstPtr()) 'L' else 'M'),
1581 typeToCIdentifier(t.childType(), dg.module),
1582 });
1583 const name_end = buffer.items.len;
1584 try bw.writeAll(";\n");
1585
1586 const rendered = try buffer.toOwnedSlice();
1587 errdefer dg.typedefs.allocator.free(rendered);
1588 const name = rendered[name_begin..name_end];
1589
1590 try dg.typedefs.ensureUnusedCapacity(1);
1591 dg.typedefs.putAssumeCapacityNoClobber(
1592 try t.copy(dg.typedefs_arena),
1593 .{ .name = name, .rendered = rendered },
1594 );
1595
1596 return name;
1509 fn indexToCType(dg: *DeclGen, idx: CType.Index) CType {
1510 return dg.ctypes.indexToCType(idx);
15971511 }
1598
1599 fn renderFwdTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1600 // The forward declaration for T is stored with a key of *const T.
1601 const child_ty = t.childType();
1602
1603 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1604 defer buffer.deinit();
1605 const bw = buffer.writer();
1606
1607 const tag = switch (child_ty.zigTypeTag()) {
1608 .Struct, .ErrorUnion, .Optional => "struct",
1609 .Union => if (child_ty.unionTagTypeSafety()) |_| "struct" else "union",
1610 else => unreachable,
1611 };
1612 try bw.writeAll("typedef ");
1613 try bw.writeAll(tag);
1614 const name_begin = buffer.items.len + " ".len;
1615 try bw.writeAll(" zig_");
1616 switch (child_ty.zigTypeTag()) {
1617 .Struct, .Union => {
1618 var fqn_buf = std.ArrayList(u8).init(dg.typedefs.allocator);
1619 defer fqn_buf.deinit();
1620
1621 const owner_decl_index = child_ty.getOwnerDecl();
1622 const owner_decl = dg.module.declPtr(owner_decl_index);
1623 try owner_decl.renderFullyQualifiedName(dg.module, fqn_buf.writer());
1624
1625 try bw.print("S_{}__{d}", .{ fmtIdent(fqn_buf.items), @enumToInt(owner_decl_index) });
1626 },
1627 .ErrorUnion => {
1628 try bw.print("E_{}", .{typeToCIdentifier(child_ty.errorUnionPayload(), dg.module)});
1629 },
1630 .Optional => {
1631 var opt_buf: Type.Payload.ElemType = undefined;
1632 try bw.print("Q_{}", .{typeToCIdentifier(child_ty.optionalChild(&opt_buf), dg.module)});
1633 },
1634 else => unreachable,
1635 }
1636 const name_end = buffer.items.len;
1637 try buffer.ensureUnusedCapacity(" ".len + (name_end - name_begin) + ";\n".len);
1638 buffer.appendAssumeCapacity(' ');
1639 buffer.appendSliceAssumeCapacity(buffer.items[name_begin..name_end]);
1640 buffer.appendSliceAssumeCapacity(";\n");
1641
1642 const rendered = try buffer.toOwnedSlice();
1643 errdefer dg.typedefs.allocator.free(rendered);
1644 const name = rendered[name_begin..name_end];
1645
1646 try dg.typedefs.ensureUnusedCapacity(1);
1647 dg.typedefs.putAssumeCapacityNoClobber(
1648 try t.copy(dg.typedefs_arena),
1649 .{ .name = name, .rendered = rendered },
1650 );
1651
1652 return name;
1512 fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index {
1513 return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind);
16531514 }
1654
1655 fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1656 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1657 const ptr_ty = Type.initPayload(&ptr_pl.base);
1658 const name = dg.getTypedefName(ptr_ty) orelse
1659 try dg.renderFwdTypedef(ptr_ty);
1660
1661 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1662 defer buffer.deinit();
1663
1664 try buffer.appendSlice("struct ");
1665
1666 var needs_pack_attr = false;
1667 {
1668 var it = t.structFields().iterator();
1669 while (it.next()) |field| {
1670 const field_ty = field.value_ptr.ty;
1671 if (!field_ty.hasRuntimeBits()) continue;
1672 const alignment = field.value_ptr.abi_align;
1673 if (alignment != 0 and alignment < field_ty.abiAlignment(dg.module.getTarget())) {
1674 needs_pack_attr = true;
1675 try buffer.appendSlice("zig_packed(");
1676 break;
1677 }
1678 }
1679 }
1680
1681 try buffer.appendSlice(name);
1682 try buffer.appendSlice(" {\n");
1683 {
1684 var it = t.structFields().iterator();
1685 var empty = true;
1686 while (it.next()) |field| {
1687 const field_ty = field.value_ptr.ty;
1688 if (!field_ty.hasRuntimeBits()) continue;
1689
1690 const alignment = field.value_ptr.alignment(dg.module.getTarget(), t.containerLayout());
1691 const field_name = CValue{ .identifier = field.key_ptr.* };
1692 try buffer.append(' ');
1693 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete);
1694 try buffer.appendSlice(";\n");
1695
1696 empty = false;
1697 }
1698 if (empty) try buffer.appendSlice(" char empty_struct;\n");
1699 }
1700 if (needs_pack_attr) try buffer.appendSlice("});\n") else try buffer.appendSlice("};\n");
1701
1702 const rendered = try buffer.toOwnedSlice();
1703 errdefer dg.typedefs.allocator.free(rendered);
1704
1705 try dg.typedefs.ensureUnusedCapacity(1);
1706 dg.typedefs.putAssumeCapacityNoClobber(
1707 try t.copy(dg.typedefs_arena),
1708 .{ .name = name, .rendered = rendered },
1709 );
1710
1711 return name;
1712 }
1713
1714 fn renderTupleTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1715 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1716 defer buffer.deinit();
1717
1718 try buffer.appendSlice("typedef struct {\n");
1719 {
1720 const fields = t.tupleFields();
1721 var field_id: usize = 0;
1722 for (fields.types, 0..) |field_ty, i| {
1723 if (!field_ty.hasRuntimeBits() or fields.values[i].tag() != .unreachable_value) continue;
1724
1725 try buffer.append(' ');
1726 try dg.renderTypeAndName(buffer.writer(), field_ty, .{ .field = field_id }, .Mut, 0, .Complete);
1727 try buffer.appendSlice(";\n");
1728
1729 field_id += 1;
1730 }
1731 if (field_id == 0) try buffer.appendSlice(" char empty_tuple;\n");
1732 }
1733 const name_begin = buffer.items.len + "} ".len;
1734 try buffer.writer().print("}} zig_T_{}_{d};\n", .{ typeToCIdentifier(t, dg.module), @truncate(u16, t.hash(dg.module)) });
1735 const name_end = buffer.items.len - ";\n".len;
1736
1737 const rendered = try buffer.toOwnedSlice();
1738 errdefer dg.typedefs.allocator.free(rendered);
1739 const name = rendered[name_begin..name_end];
1740
1741 try dg.typedefs.ensureUnusedCapacity(1);
1742 dg.typedefs.putAssumeCapacityNoClobber(
1743 try t.copy(dg.typedefs_arena),
1744 .{ .name = name, .rendered = rendered },
1745 );
1746
1747 return name;
1748 }
1749
1750 fn renderUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1751 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1752 const ptr_ty = Type.initPayload(&ptr_pl.base);
1753 const name = dg.getTypedefName(ptr_ty) orelse
1754 try dg.renderFwdTypedef(ptr_ty);
1755
1756 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1757 defer buffer.deinit();
1758
1759 try buffer.appendSlice(if (t.unionTagTypeSafety()) |_| "struct " else "union ");
1760 try buffer.appendSlice(name);
1761 try buffer.appendSlice(" {\n");
1762
1763 const indent = if (t.unionTagTypeSafety()) |tag_ty| indent: {
1764 const target = dg.module.getTarget();
1765 const layout = t.unionGetLayout(target);
1766 if (layout.tag_size != 0) {
1767 try buffer.append(' ');
1768 try dg.renderTypeAndName(buffer.writer(), tag_ty, .{ .identifier = "tag" }, .Mut, 0, .Complete);
1769 try buffer.appendSlice(";\n");
1770 }
1771 try buffer.appendSlice(" union {\n");
1772 break :indent " ";
1773 } else " ";
1774
1775 {
1776 var it = t.unionFields().iterator();
1777 var empty = true;
1778 while (it.next()) |field| {
1779 const field_ty = field.value_ptr.ty;
1780 if (!field_ty.hasRuntimeBits()) continue;
1781
1782 const alignment = field.value_ptr.abi_align;
1783 const field_name = CValue{ .identifier = field.key_ptr.* };
1784 try buffer.appendSlice(indent);
1785 try dg.renderTypeAndName(buffer.writer(), field_ty, field_name, .Mut, alignment, .Complete);
1786 try buffer.appendSlice(";\n");
1787
1788 empty = false;
1789 }
1790 if (empty) {
1791 try buffer.appendSlice(indent);
1792 try buffer.appendSlice("char empty_union;\n");
1793 }
1794 }
1795
1796 if (t.unionTagTypeSafety()) |_| try buffer.appendSlice(" } payload;\n");
1797 try buffer.appendSlice("};\n");
1798
1799 const rendered = try buffer.toOwnedSlice();
1800 errdefer dg.typedefs.allocator.free(rendered);
1801
1802 try dg.typedefs.ensureUnusedCapacity(1);
1803 dg.typedefs.putAssumeCapacityNoClobber(
1804 try t.copy(dg.typedefs_arena),
1805 .{ .name = name, .rendered = rendered },
1806 );
1807
1808 return name;
1809 }
1810
1811 fn renderErrorUnionTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1812 assert(t.errorUnionSet().tag() == .anyerror);
1813
1814 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1815 const ptr_ty = Type.initPayload(&ptr_pl.base);
1816 const name = dg.getTypedefName(ptr_ty) orelse
1817 try dg.renderFwdTypedef(ptr_ty);
1818
1819 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1820 defer buffer.deinit();
1821 const bw = buffer.writer();
1822
1823 const payload_ty = t.errorUnionPayload();
1824 const payload_name = CValue{ .identifier = "payload" };
1825 const error_ty = t.errorUnionSet();
1826 const error_name = CValue{ .identifier = "error" };
1827
1828 const target = dg.module.getTarget();
1829 const payload_align = payload_ty.abiAlignment(target);
1830 const error_align = error_ty.abiAlignment(target);
1831 try bw.writeAll("struct ");
1832 try bw.writeAll(name);
1833 try bw.writeAll(" {\n ");
1834 if (error_align > payload_align) {
1835 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1836 try bw.writeAll(";\n ");
1837 try dg.renderTypeAndName(bw, error_ty, error_name, .Mut, 0, .Complete);
1838 } else {
1839 try dg.renderTypeAndName(bw, error_ty, error_name, .Mut, 0, .Complete);
1840 try bw.writeAll(";\n ");
1841 try dg.renderTypeAndName(bw, payload_ty, payload_name, .Mut, 0, .Complete);
1842 }
1843 try bw.writeAll(";\n};\n");
1844
1845 const rendered = try buffer.toOwnedSlice();
1846 errdefer dg.typedefs.allocator.free(rendered);
1847
1848 try dg.typedefs.ensureUnusedCapacity(1);
1849 dg.typedefs.putAssumeCapacityNoClobber(
1850 try t.copy(dg.typedefs_arena),
1851 .{ .name = name, .rendered = rendered },
1852 );
1853
1854 return name;
1855 }
1856
1857 fn renderArrayTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1858 const info = t.arrayInfo();
1859 std.debug.assert(info.sentinel == null); // expected canonical type
1860
1861 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1862 defer buffer.deinit();
1863 const bw = buffer.writer();
1864
1865 try bw.writeAll("typedef ");
1866 try dg.renderType(bw, info.elem_type, .Complete);
1867
1868 const name_begin = buffer.items.len + " ".len;
1869 try bw.print(" zig_A_{}_{d}", .{ typeToCIdentifier(info.elem_type, dg.module), info.len });
1870 const name_end = buffer.items.len;
1871
1872 const c_len = if (info.len > 0) info.len else 1;
1873 var c_len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = c_len };
1874 const c_len_val = Value.initPayload(&c_len_pl.base);
1875 try bw.print("[{}];\n", .{try dg.fmtIntLiteral(Type.usize, c_len_val)});
1876
1877 const rendered = try buffer.toOwnedSlice();
1878 errdefer dg.typedefs.allocator.free(rendered);
1879 const name = rendered[name_begin..name_end];
1880
1881 try dg.typedefs.ensureUnusedCapacity(1);
1882 dg.typedefs.putAssumeCapacityNoClobber(
1883 try t.copy(dg.typedefs_arena),
1884 .{ .name = name, .rendered = rendered },
1885 );
1886
1887 return name;
1888 }
1889
1890 fn renderOptionalTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1891 var ptr_pl = Type.Payload.ElemType{ .base = .{ .tag = .single_const_pointer }, .data = t };
1892 const ptr_ty = Type.initPayload(&ptr_pl.base);
1893 const name = dg.getTypedefName(ptr_ty) orelse
1894 try dg.renderFwdTypedef(ptr_ty);
1895
1896 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1897 defer buffer.deinit();
1898 const bw = buffer.writer();
1899
1900 var opt_buf: Type.Payload.ElemType = undefined;
1901 const child_ty = t.optionalChild(&opt_buf);
1902
1903 try bw.writeAll("struct ");
1904 try bw.writeAll(name);
1905 try bw.writeAll(" {\n");
1906 try dg.renderTypeAndName(bw, child_ty, .{ .identifier = "payload" }, .Mut, 0, .Complete);
1907 try bw.writeAll(";\n ");
1908 try dg.renderTypeAndName(bw, Type.bool, .{ .identifier = "is_null" }, .Mut, 0, .Complete);
1909 try bw.writeAll(";\n};\n");
1910
1911 const rendered = try buffer.toOwnedSlice();
1912 errdefer dg.typedefs.allocator.free(rendered);
1913
1914 try dg.typedefs.ensureUnusedCapacity(1);
1915 dg.typedefs.putAssumeCapacityNoClobber(
1916 try t.copy(dg.typedefs_arena),
1917 .{ .name = name, .rendered = rendered },
1918 );
1919
1920 return name;
1921 }
1922
1923 fn renderOpaqueTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
1924 const opaque_ty = t.cast(Type.Payload.Opaque).?.data;
1925 const unqualified_name = dg.module.declPtr(opaque_ty.owner_decl).name;
1926 const fqn = try opaque_ty.getFullyQualifiedName(dg.module);
1927 defer dg.typedefs.allocator.free(fqn);
1928
1929 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
1930 defer buffer.deinit();
1931
1932 try buffer.writer().print("typedef struct { } ", .{fmtIdent(std.mem.span(unqualified_name))});
1933
1934 const name_begin = buffer.items.len;
1935 try buffer.writer().print("zig_O_{}", .{fmtIdent(fqn)});
1936 const name_end = buffer.items.len;
1937 try buffer.appendSlice(";\n");
1938
1939 const rendered = try buffer.toOwnedSlice();
1940 errdefer dg.typedefs.allocator.free(rendered);
1941 const name = rendered[name_begin..name_end];
1942
1943 try dg.typedefs.ensureUnusedCapacity(1);
1944 dg.typedefs.putAssumeCapacityNoClobber(
1945 try t.copy(dg.typedefs_arena),
1946 .{ .name = name, .rendered = rendered },
1947 );
1948
1949 return name;
1515 fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType {
1516 return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind);
19501517 }
19511518
19521519 /// Renders a type as a single identifier, generating intermediate typedefs
......@@ -1959,275 +1526,27 @@ pub const DeclGen = struct {
19591526 /// |---------------------|-----------------|---------------------|
19601527 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
19611528 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
1962 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
1529 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
19631530 ///
19641531 fn renderType(
19651532 dg: *DeclGen,
19661533 w: anytype,
19671534 t: Type,
1968 kind: TypedefKind,
1969 ) error{ OutOfMemory, AnalysisFail }!void {
1970 const target = dg.module.getTarget();
1971
1972 switch (t.zigTypeTag()) {
1973 .Void => try w.writeAll("void"),
1974 .Bool => try w.writeAll("bool"),
1975 .NoReturn, .Float => {
1976 try w.writeAll("zig_");
1977 try t.print(w, dg.module);
1978 },
1979 .Int => {
1980 if (t.isNamedInt()) {
1981 try w.writeAll("zig_");
1982 try t.print(w, dg.module);
1983 } else {
1984 return renderTypeUnnamed(dg, w, t, kind);
1985 }
1986 },
1987 .ErrorSet => {
1988 return renderTypeUnnamed(dg, w, t, kind);
1989 },
1990 .Pointer => {
1991 const ptr_info = t.ptrInfo().data;
1992 if (ptr_info.size == .Slice) {
1993 var slice_pl = Type.Payload.ElemType{
1994 .base = .{ .tag = if (t.ptrIsMutable()) .mut_slice else .const_slice },
1995 .data = ptr_info.pointee_type,
1996 };
1997 const slice_ty = Type.initPayload(&slice_pl.base);
1998
1999 const name = dg.getTypedefName(slice_ty) orelse
2000 try dg.renderSliceTypedef(slice_ty);
2001
2002 return w.writeAll(name);
2003 }
2004
2005 if (ptr_info.pointee_type.zigTypeTag() == .Fn) {
2006 const name = dg.getTypedefName(ptr_info.pointee_type) orelse
2007 try dg.renderPtrToFnTypedef(ptr_info.pointee_type);
2008
2009 return w.writeAll(name);
2010 }
2011
2012 if (ptr_info.host_size != 0) {
2013 var host_pl = Type.Payload.Bits{
2014 .base = .{ .tag = .int_unsigned },
2015 .data = ptr_info.host_size * 8,
2016 };
2017 const host_ty = Type.initPayload(&host_pl.base);
2018
2019 try dg.renderType(w, host_ty, .Forward);
2020 } else if (t.isCPtr() and ptr_info.pointee_type.eql(Type.u8, dg.module) and
2021 (dg.decl.val.tag() == .extern_fn or
2022 std.mem.eql(u8, std.mem.span(dg.decl.name), "main")))
2023 {
2024 // This is a hack, since the c compiler expects a lot of external
2025 // library functions to have char pointers in their signatures, but
2026 // u8 and i8 produce unsigned char and signed char respectively,
2027 // which in C are (not very usefully) different than char.
2028 try w.writeAll("char");
2029 } else try dg.renderType(w, switch (ptr_info.pointee_type.tag()) {
2030 .anyopaque => Type.void,
2031 else => ptr_info.pointee_type,
2032 }, .Forward);
2033 if (t.isConstPtr()) try w.writeAll(" const");
2034 if (t.isVolatilePtr()) try w.writeAll(" volatile");
2035 return w.writeAll(" *");
2036 },
2037 .Array, .Vector => {
2038 var array_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{
2039 .len = t.arrayLenIncludingSentinel(),
2040 .elem_type = t.childType(),
2041 } };
2042 const array_ty = Type.initPayload(&array_pl.base);
2043
2044 const name = dg.getTypedefName(array_ty) orelse
2045 try dg.renderArrayTypedef(array_ty);
2046
2047 return w.writeAll(name);
2048 },
2049 .Optional => {
2050 var opt_buf: Type.Payload.ElemType = undefined;
2051 const child_ty = t.optionalChild(&opt_buf);
2052
2053 if (!child_ty.hasRuntimeBitsIgnoreComptime())
2054 return dg.renderType(w, Type.bool, kind);
2055
2056 if (t.optionalReprIsPayload())
2057 return dg.renderType(w, child_ty, kind);
2058
2059 switch (kind) {
2060 .Complete => {
2061 const name = dg.getTypedefName(t) orelse
2062 try dg.renderOptionalTypedef(t);
2063
2064 try w.writeAll(name);
2065 },
2066 .Forward => {
2067 var ptr_pl = Type.Payload.ElemType{
2068 .base = .{ .tag = .single_const_pointer },
2069 .data = t,
2070 };
2071 const ptr_ty = Type.initPayload(&ptr_pl.base);
2072
2073 const name = dg.getTypedefName(ptr_ty) orelse
2074 try dg.renderFwdTypedef(ptr_ty);
2075
2076 try w.writeAll(name);
2077 },
2078 }
2079 },
2080 .ErrorUnion => {
2081 const payload_ty = t.errorUnionPayload();
2082
2083 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
2084 return dg.renderType(w, Type.anyerror, kind);
2085
2086 var error_union_pl = Type.Payload.ErrorUnion{
2087 .data = .{ .error_set = Type.anyerror, .payload = payload_ty },
2088 };
2089 const error_union_ty = Type.initPayload(&error_union_pl.base);
2090
2091 switch (kind) {
2092 .Complete => {
2093 const name = dg.getTypedefName(error_union_ty) orelse
2094 try dg.renderErrorUnionTypedef(error_union_ty);
2095
2096 try w.writeAll(name);
2097 },
2098 .Forward => {
2099 var ptr_pl = Type.Payload.ElemType{
2100 .base = .{ .tag = .single_const_pointer },
2101 .data = error_union_ty,
2102 };
2103 const ptr_ty = Type.initPayload(&ptr_pl.base);
2104
2105 const name = dg.getTypedefName(ptr_ty) orelse
2106 try dg.renderFwdTypedef(ptr_ty);
2107
2108 try w.writeAll(name);
2109 },
2110 }
2111 },
2112 .Struct, .Union => |tag| if (t.containerLayout() == .Packed) {
2113 if (t.castTag(.@"struct")) |struct_obj| {
2114 try dg.renderType(w, struct_obj.data.backing_int_ty, kind);
2115 } else {
2116 var buf: Type.Payload.Bits = .{
2117 .base = .{ .tag = .int_unsigned },
2118 .data = @intCast(u16, t.bitSize(target)),
2119 };
2120 try dg.renderType(w, Type.initPayload(&buf.base), kind);
2121 }
2122 } else if (t.isSimpleTupleOrAnonStruct()) {
2123 const ExpectedContents = struct { types: [8]Type, values: [8]Value };
2124 var stack align(@alignOf(ExpectedContents)) =
2125 std.heap.stackFallback(@sizeOf(ExpectedContents), dg.gpa);
2126 const allocator = stack.get();
2127
2128 var tuple_storage = std.MultiArrayList(struct { type: Type, value: Value }){};
2129 defer tuple_storage.deinit(allocator);
2130 try tuple_storage.ensureTotalCapacity(allocator, t.structFieldCount());
2131
2132 const fields = t.tupleFields();
2133 for (fields.values, 0..) |value, index|
2134 if (value.tag() == .unreachable_value)
2135 tuple_storage.appendAssumeCapacity(.{
2136 .type = fields.types[index],
2137 .value = value,
2138 });
2139
2140 const tuple_slice = tuple_storage.slice();
2141 var tuple_pl = Type.Payload.Tuple{ .data = .{
2142 .types = tuple_slice.items(.type),
2143 .values = tuple_slice.items(.value),
2144 } };
2145 const tuple_ty = Type.initPayload(&tuple_pl.base);
2146
2147 const name = dg.getTypedefName(tuple_ty) orelse
2148 try dg.renderTupleTypedef(tuple_ty);
2149
2150 try w.writeAll(name);
2151 } else switch (kind) {
2152 .Complete => {
2153 const name = dg.getTypedefName(t) orelse switch (tag) {
2154 .Struct => try dg.renderStructTypedef(t),
2155 .Union => try dg.renderUnionTypedef(t),
2156 else => unreachable,
2157 };
2158
2159 try w.writeAll(name);
2160 },
2161 .Forward => {
2162 var ptr_pl = Type.Payload.ElemType{
2163 .base = .{ .tag = .single_const_pointer },
2164 .data = t,
2165 };
2166 const ptr_ty = Type.initPayload(&ptr_pl.base);
2167
2168 const name = dg.getTypedefName(ptr_ty) orelse
2169 try dg.renderFwdTypedef(ptr_ty);
2170
2171 try w.writeAll(name);
2172 },
2173 },
2174 .Enum => {
2175 // For enums, we simply use the integer tag type.
2176 var int_tag_buf: Type.Payload.Bits = undefined;
2177 const int_tag_ty = t.intTagType(&int_tag_buf);
2178
2179 try dg.renderType(w, int_tag_ty, kind);
2180 },
2181 .Opaque => switch (t.tag()) {
2182 .@"opaque" => {
2183 const name = dg.getTypedefName(t) orelse
2184 try dg.renderOpaqueTypedef(t);
2185
2186 try w.writeAll(name);
2187 },
2188 else => unreachable,
2189 },
2190
2191 .Frame,
2192 .AnyFrame,
2193 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
2194 @tagName(tag),
2195 }),
2196
2197 .Fn => unreachable, // This is a function body, not a function pointer.
2198
2199 .Null,
2200 .Undefined,
2201 .EnumLiteral,
2202 .ComptimeFloat,
2203 .ComptimeInt,
2204 .Type,
2205 => unreachable, // must be const or comptime
2206 }
2207 }
2208
2209 fn renderTypeUnnamed(
2210 dg: *DeclGen,
2211 w: anytype,
2212 t: Type,
2213 kind: TypedefKind,
1535 _: TypedefKind,
22141536 ) error{ OutOfMemory, AnalysisFail }!void {
2215 const target = dg.module.getTarget();
2216 const int_info = t.intInfo(target);
2217 if (toCIntBits(int_info.bits)) |c_bits|
2218 return w.print("zig_{c}{d}", .{ signAbbrev(int_info.signedness), c_bits })
2219 else if (loweredArrayInfo(t, target)) |array_info| {
2220 assert(array_info.sentinel == null);
2221 var array_pl = Type.Payload.Array{
2222 .base = .{ .tag = .array },
2223 .data = .{ .len = array_info.len, .elem_type = array_info.elem_type },
2224 };
2225 const array_ty = Type.initPayload(&array_pl.base);
2226
2227 return dg.renderType(w, array_ty, kind);
2228 } else return dg.fail("C backend: Unable to lower unnamed integer type {}", .{
2229 t.fmt(dg.module),
2230 });
1537 const store = &dg.ctypes.set;
1538 const module = dg.module;
1539 const idx = try dg.typeToIndex(t, .complete);
1540 _ = try renderTypePrefix(
1541 dg.decl_index,
1542 store.*,
1543 module,
1544 w,
1545 idx,
1546 .suffix,
1547 CQualifiers.init(.{}),
1548 );
1549 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix);
22311550 }
22321551
22331552 const IntCastContext = union(enum) {
......@@ -2254,16 +1573,16 @@ pub const DeclGen = struct {
22541573 /// Renders a cast to an int type, from either an int or a pointer.
22551574 ///
22561575 /// Some platforms don't have 128 bit integers, so we need to use
2257 /// the zig_as_ and zig_lo_ macros in those cases.
1576 /// the zig_make_ and zig_lo_ macros in those cases.
22581577 ///
22591578 /// | Dest type bits | Src type | Result
22601579 /// |------------------|------------------|---------------------------|
22611580 /// | < 64 bit integer | pointer | (zig_<dest_ty>)(zig_<u|i>size)src
22621581 /// | < 64 bit integer | < 64 bit integer | (zig_<dest_ty>)src
22631582 /// | < 64 bit integer | > 64 bit integer | zig_lo(src)
2264 /// | > 64 bit integer | pointer | zig_as_<dest_ty>(0, (zig_<u|i>size)src)
2265 /// | > 64 bit integer | < 64 bit integer | zig_as_<dest_ty>(0, src)
2266 /// | > 64 bit integer | > 64 bit integer | zig_as_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
1583 /// | > 64 bit integer | pointer | zig_make_<dest_ty>(0, (zig_<u|i>size)src)
1584 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
1585 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
22671586 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {
22681587 const target = dg.module.getTarget();
22691588 const dest_bits = dest_ty.bitSize(target);
......@@ -2301,7 +1620,7 @@ pub const DeclGen = struct {
23011620 try context.writeValue(dg, w, src_ty, .FunctionArgument);
23021621 try w.writeByte(')');
23031622 } else if (dest_bits > 64 and src_bits <= 64) {
2304 try w.writeAll("zig_as_");
1623 try w.writeAll("zig_make_");
23051624 try dg.renderTypeForBuiltinFnName(w, dest_ty);
23061625 try w.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral?
23071626 if (src_is_ptr) {
......@@ -2313,7 +1632,7 @@ pub const DeclGen = struct {
23131632 try w.writeByte(')');
23141633 } else {
23151634 assert(!src_is_ptr);
2316 try w.writeAll("zig_as_");
1635 try w.writeAll("zig_make_");
23171636 try dg.renderTypeForBuiltinFnName(w, dest_ty);
23181637 try w.writeAll("(zig_hi_");
23191638 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
......@@ -2337,10 +1656,10 @@ pub const DeclGen = struct {
23371656 /// |---------------------|-----------------|---------------------|
23381657 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
23391658 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2340 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
1659 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
23411660 ///
23421661 fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void {
2343 return renderTypeAndName(dg, w, ty, .{ .bytes = "" }, .Mut, 0, .Complete);
1662 try dg.renderType(w, ty, undefined);
23441663 }
23451664
23461665 /// Renders a type and name in field declaration/definition format.
......@@ -2350,7 +1669,7 @@ pub const DeclGen = struct {
23501669 /// |---------------------|-----------------|---------------------|
23511670 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
23521671 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2353 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |
1672 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
23541673 ///
23551674 fn renderTypeAndName(
23561675 dg: *DeclGen,
......@@ -2359,65 +1678,45 @@ pub const DeclGen = struct {
23591678 name: CValue,
23601679 mutability: Mutability,
23611680 alignment: u32,
2362 kind: TypedefKind,
1681 _: TypedefKind,
23631682 ) error{ OutOfMemory, AnalysisFail }!void {
2364 var suffix = std.ArrayList(u8).init(dg.gpa);
2365 defer suffix.deinit();
2366 const suffix_writer = suffix.writer();
2367
2368 // Any top-level array types are rendered here as a suffix, which
2369 // avoids creating typedefs for every array type
2370 const target = dg.module.getTarget();
2371 var render_ty = ty;
2372 var depth: u32 = 0;
2373 while (loweredArrayInfo(render_ty, target)) |array_info| {
2374 const c_len = array_info.len + @boolToInt(array_info.sentinel != null);
2375 var c_len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = c_len };
2376 const c_len_val = Value.initPayload(&c_len_pl.base);
2377
2378 try suffix_writer.writeByte('[');
2379 if (mutability == .ConstArgument and depth == 0) try suffix_writer.writeAll("zig_const_arr ");
2380 try suffix.writer().print("{}]", .{try dg.fmtIntLiteral(Type.usize, c_len_val)});
2381 render_ty = array_info.elem_type;
2382 depth += 1;
2383 }
2384
2385 if (alignment != 0) {
2386 const abi_alignment = ty.abiAlignment(target);
2387 if (alignment < abi_alignment) {
2388 try w.print("zig_under_align({}) ", .{alignment});
2389 } else if (alignment > abi_alignment) {
2390 try w.print("zig_align({}) ", .{alignment});
2391 }
2392 }
2393 try dg.renderType(w, render_ty, kind);
1683 const store = &dg.ctypes.set;
1684 const module = dg.module;
23941685
2395 const const_prefix = switch (mutability) {
2396 .Const, .ConstArgument => "const ",
2397 .Mut => "",
1686 if (alignment != 0) switch (std.math.order(alignment, ty.abiAlignment(dg.module.getTarget()))) {
1687 .lt => try w.print("zig_under_align({}) ", .{alignment}),
1688 .eq => {},
1689 .gt => try w.print("zig_align({}) ", .{alignment}),
23981690 };
2399 try w.print(" {s}", .{const_prefix});
1691
1692 const idx = try dg.typeToIndex(ty, .complete);
1693 const trailing = try renderTypePrefix(
1694 dg.decl_index,
1695 store.*,
1696 module,
1697 w,
1698 idx,
1699 .suffix,
1700 CQualifiers.init(.{ .@"const" = mutability == .@"const" }),
1701 );
1702 try w.print("{}", .{trailing});
24001703 try dg.writeCValue(w, name);
2401 try w.writeAll(suffix.items);
1704 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix);
24021705 }
24031706
2404 fn renderTagNameFn(dg: *DeclGen, enum_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {
2405 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
2406 defer buffer.deinit();
2407 const bw = buffer.writer();
2408
1707 fn renderTagNameFn(dg: *DeclGen, w: anytype, fn_name: []const u8, enum_ty: Type) !void {
24091708 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
24101709
2411 try buffer.appendSlice("static ");
2412 try dg.renderType(bw, name_slice_ty, .Complete);
2413 const name_begin = buffer.items.len + " ".len;
2414 try bw.print(" zig_tagName_{}_{d}(", .{ typeToCIdentifier(enum_ty, dg.module), @enumToInt(enum_ty.getOwnerDecl()) });
2415 const name_end = buffer.items.len - "(".len;
2416 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0, .Complete);
2417 try buffer.appendSlice(") {\n switch (tag) {\n");
1710 try w.writeAll("static ");
1711 try dg.renderType(w, name_slice_ty, .Complete);
1712 try w.writeByte(' ');
1713 try w.writeAll(fn_name);
1714 try w.writeByte('(');
1715 try dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, .@"const", 0, .Complete);
1716 try w.writeAll(") {\n switch (tag) {\n");
24181717 for (enum_ty.enumFields().keys(), 0..) |name, index| {
2419 const name_z = try dg.typedefs.allocator.dupeZ(u8, name);
2420 defer dg.typedefs.allocator.free(name_z);
1718 const name_z = try dg.gpa.dupeZ(u8, name);
1719 defer dg.gpa.free(name_z);
24211720 const name_bytes = name_z[0 .. name_z.len + 1];
24221721
24231722 var tag_pl: Value.Payload.U32 = .{
......@@ -2438,40 +1737,23 @@ pub const DeclGen = struct {
24381737 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
24391738 const len_val = Value.initPayload(&len_pl.base);
24401739
2441 try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});
2442 try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0, .Complete);
2443 try buffer.appendSlice(" = ");
2444 try dg.renderValue(bw, name_ty, name_val, .Initializer);
2445 try buffer.appendSlice(";\n return (");
2446 try dg.renderTypecast(bw, name_slice_ty);
2447 try bw.print("){{{}, {}}};\n", .{
1740 try w.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});
1741 try dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, .@"const", 0, .Complete);
1742 try w.writeAll(" = ");
1743 try dg.renderValue(w, name_ty, name_val, .Initializer);
1744 try w.writeAll(";\n return (");
1745 try dg.renderTypecast(w, name_slice_ty);
1746 try w.print("){{{}, {}}};\n", .{
24481747 fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val),
24491748 });
24501749
2451 try buffer.appendSlice(" }\n");
1750 try w.writeAll(" }\n");
24521751 }
2453 try buffer.appendSlice(" }\n while (");
2454 try dg.renderValue(bw, Type.bool, Value.true, .Other);
2455 try buffer.appendSlice(") ");
2456 _ = try airBreakpoint(bw);
2457 try buffer.appendSlice("}\n");
2458
2459 const rendered = try buffer.toOwnedSlice();
2460 errdefer dg.typedefs.allocator.free(rendered);
2461 const name = rendered[name_begin..name_end];
2462
2463 try dg.typedefs.ensureUnusedCapacity(1);
2464 dg.typedefs.putAssumeCapacityNoClobber(
2465 try enum_ty.copy(dg.typedefs_arena),
2466 .{ .name = name, .rendered = rendered },
2467 );
2468
2469 return name;
2470 }
2471
2472 fn getTagNameFn(dg: *DeclGen, enum_ty: Type) ![]const u8 {
2473 return dg.getTypedefName(enum_ty) orelse
2474 try dg.renderTagNameFn(enum_ty);
1752 try w.writeAll(" }\n while (");
1753 try dg.renderValue(w, Type.bool, Value.true, .Other);
1754 try w.writeAll(") ");
1755 _ = try airBreakpoint(w);
1756 try w.writeAll("}\n");
24751757 }
24761758
24771759 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
......@@ -2492,10 +1774,11 @@ pub const DeclGen = struct {
24921774 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
24931775 switch (c_value) {
24941776 .none => unreachable,
2495 .local => |i| return w.print("t{d}", .{i}),
1777 .local, .new_local => |i| return w.print("t{d}", .{i}),
24961778 .local_ref => |i| return w.print("&t{d}", .{i}),
24971779 .constant => unreachable,
24981780 .arg => |i| return w.print("a{d}", .{i}),
1781 .arg_array => |i| return dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }),
24991782 .field => |i| return w.print("f{d}", .{i}),
25001783 .decl => |decl| return dg.renderDeclName(w, decl, 0),
25011784 .decl_ref => |decl| {
......@@ -2511,10 +1794,15 @@ pub const DeclGen = struct {
25111794 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
25121795 switch (c_value) {
25131796 .none => unreachable,
2514 .local => |i| return w.print("(*t{d})", .{i}),
1797 .local, .new_local => |i| return w.print("(*t{d})", .{i}),
25151798 .local_ref => |i| return w.print("t{d}", .{i}),
25161799 .constant => unreachable,
25171800 .arg => |i| return w.print("(*a{d})", .{i}),
1801 .arg_array => |i| {
1802 try w.writeAll("(*");
1803 try dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" });
1804 return w.writeByte(')');
1805 },
25181806 .field => |i| return w.print("f{d}", .{i}),
25191807 .decl => |decl| {
25201808 try w.writeAll("(*");
......@@ -2541,7 +1829,7 @@ pub const DeclGen = struct {
25411829 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
25421830 switch (c_value) {
25431831 .none, .constant, .field, .undef => unreachable,
2544 .local, .arg, .decl, .identifier, .bytes => {
1832 .new_local, .local, .arg, .arg_array, .decl, .identifier, .bytes => {
25451833 try dg.writeCValue(writer, c_value);
25461834 try writer.writeAll("->");
25471835 },
......@@ -2668,10 +1956,493 @@ pub const DeclGen = struct {
26681956 }
26691957};
26701958
2671pub fn genGlobalAsm(mod: *Module, code: *std.ArrayList(u8)) !void {
1959const CTypeFix = enum { prefix, suffix };
1960const CQualifiers = std.enums.EnumSet(enum { @"const", @"volatile", restrict });
1961const CTypeRenderTrailing = enum {
1962 no_space,
1963 maybe_space,
1964
1965 pub fn format(
1966 self: @This(),
1967 comptime fmt: []const u8,
1968 _: std.fmt.FormatOptions,
1969 w: anytype,
1970 ) @TypeOf(w).Error!void {
1971 if (fmt.len != 0)
1972 @compileError("invalid format string '" ++ fmt ++ "' for type '" ++
1973 @typeName(@This()) ++ "'");
1974 comptime assert(fmt.len == 0);
1975 switch (self) {
1976 .no_space => {},
1977 .maybe_space => try w.writeByte(' '),
1978 }
1979 }
1980};
1981fn renderTypeName(
1982 mod: *Module,
1983 w: anytype,
1984 idx: CType.Index,
1985 cty: CType,
1986 attributes: []const u8,
1987) !void {
1988 switch (cty.tag()) {
1989 else => unreachable,
1990
1991 .fwd_anon_struct,
1992 .fwd_anon_union,
1993 => |tag| try w.print("{s} {s}anon__lazy_{d}", .{
1994 @tagName(tag)["fwd_anon_".len..],
1995 attributes,
1996 idx,
1997 }),
1998
1999 .fwd_struct,
2000 .fwd_union,
2001 => |tag| {
2002 const owner_decl = cty.cast(CType.Payload.FwdDecl).?.data;
2003 try w.print("{s} {s}{}__{d}", .{
2004 @tagName(tag)["fwd_".len..],
2005 attributes,
2006 fmtIdent(mem.span(mod.declPtr(owner_decl).name)),
2007 @enumToInt(owner_decl),
2008 });
2009 },
2010 }
2011}
2012fn renderTypePrefix(
2013 decl: Decl.OptionalIndex,
2014 store: CType.Store.Set,
2015 mod: *Module,
2016 w: anytype,
2017 idx: CType.Index,
2018 parent_fix: CTypeFix,
2019 qualifiers: CQualifiers,
2020) @TypeOf(w).Error!CTypeRenderTrailing {
2021 var trailing = CTypeRenderTrailing.maybe_space;
2022
2023 const cty = store.indexToCType(idx);
2024 switch (cty.tag()) {
2025 .void,
2026 .char,
2027 .@"signed char",
2028 .short,
2029 .int,
2030 .long,
2031 .@"long long",
2032 ._Bool,
2033 .@"unsigned char",
2034 .@"unsigned short",
2035 .@"unsigned int",
2036 .@"unsigned long",
2037 .@"unsigned long long",
2038 .float,
2039 .double,
2040 .@"long double",
2041 .bool,
2042 .size_t,
2043 .ptrdiff_t,
2044 .uint8_t,
2045 .int8_t,
2046 .uint16_t,
2047 .int16_t,
2048 .uint32_t,
2049 .int32_t,
2050 .uint64_t,
2051 .int64_t,
2052 .uintptr_t,
2053 .intptr_t,
2054 .zig_u128,
2055 .zig_i128,
2056 .zig_f16,
2057 .zig_f32,
2058 .zig_f64,
2059 .zig_f80,
2060 .zig_f128,
2061 .zig_c_longdouble,
2062 => |tag| try w.writeAll(@tagName(tag)),
2063
2064 .pointer,
2065 .pointer_const,
2066 .pointer_volatile,
2067 .pointer_const_volatile,
2068 => |tag| {
2069 const child_idx = cty.cast(CType.Payload.Child).?.data;
2070 const child_trailing = try renderTypePrefix(
2071 decl,
2072 store,
2073 mod,
2074 w,
2075 child_idx,
2076 .prefix,
2077 CQualifiers.init(.{ .@"const" = switch (tag) {
2078 .pointer, .pointer_volatile => false,
2079 .pointer_const, .pointer_const_volatile => true,
2080 else => unreachable,
2081 }, .@"volatile" = switch (tag) {
2082 .pointer, .pointer_const => false,
2083 .pointer_volatile, .pointer_const_volatile => true,
2084 else => unreachable,
2085 } }),
2086 );
2087 try w.print("{}*", .{child_trailing});
2088 trailing = .no_space;
2089 },
2090
2091 .array,
2092 .vector,
2093 => {
2094 const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type;
2095 const child_trailing = try renderTypePrefix(
2096 decl,
2097 store,
2098 mod,
2099 w,
2100 child_idx,
2101 .suffix,
2102 qualifiers,
2103 );
2104 switch (parent_fix) {
2105 .prefix => {
2106 try w.print("{}(", .{child_trailing});
2107 return .no_space;
2108 },
2109 .suffix => return child_trailing,
2110 }
2111 },
2112
2113 .fwd_anon_struct,
2114 .fwd_anon_union,
2115 => if (decl.unwrap()) |decl_index|
2116 try w.print("anon__{d}_{d}", .{ @enumToInt(decl_index), idx })
2117 else
2118 try renderTypeName(mod, w, idx, cty, ""),
2119
2120 .fwd_struct,
2121 .fwd_union,
2122 => try renderTypeName(mod, w, idx, cty, ""),
2123
2124 .unnamed_struct,
2125 .unnamed_union,
2126 .packed_unnamed_struct,
2127 .packed_unnamed_union,
2128 => |tag| {
2129 try w.print("{s} {s}", .{
2130 @tagName(tag)["unnamed_".len..],
2131 if (cty.isPacked()) "zig_packed(" else "",
2132 });
2133 try renderAggregateFields(mod, w, store, cty, 1);
2134 if (cty.isPacked()) try w.writeByte(')');
2135 },
2136
2137 .anon_struct,
2138 .anon_union,
2139 .@"struct",
2140 .@"union",
2141 .packed_struct,
2142 .packed_union,
2143 => return renderTypePrefix(
2144 decl,
2145 store,
2146 mod,
2147 w,
2148 cty.cast(CType.Payload.Aggregate).?.data.fwd_decl,
2149 parent_fix,
2150 qualifiers,
2151 ),
2152
2153 .function,
2154 .varargs_function,
2155 => {
2156 const child_trailing = try renderTypePrefix(
2157 decl,
2158 store,
2159 mod,
2160 w,
2161 cty.cast(CType.Payload.Function).?.data.return_type,
2162 .suffix,
2163 CQualifiers.init(.{}),
2164 );
2165 switch (parent_fix) {
2166 .prefix => {
2167 try w.print("{}(", .{child_trailing});
2168 return .no_space;
2169 },
2170 .suffix => return child_trailing,
2171 }
2172 },
2173 }
2174
2175 var qualifier_it = qualifiers.iterator();
2176 while (qualifier_it.next()) |qualifier| {
2177 try w.print("{}{s}", .{ trailing, @tagName(qualifier) });
2178 trailing = .maybe_space;
2179 }
2180
2181 return trailing;
2182}
2183fn renderTypeSuffix(
2184 decl: Decl.OptionalIndex,
2185 store: CType.Store.Set,
2186 mod: *Module,
2187 w: anytype,
2188 idx: CType.Index,
2189 parent_fix: CTypeFix,
2190) @TypeOf(w).Error!void {
2191 const cty = store.indexToCType(idx);
2192 switch (cty.tag()) {
2193 .void,
2194 .char,
2195 .@"signed char",
2196 .short,
2197 .int,
2198 .long,
2199 .@"long long",
2200 ._Bool,
2201 .@"unsigned char",
2202 .@"unsigned short",
2203 .@"unsigned int",
2204 .@"unsigned long",
2205 .@"unsigned long long",
2206 .float,
2207 .double,
2208 .@"long double",
2209 .bool,
2210 .size_t,
2211 .ptrdiff_t,
2212 .uint8_t,
2213 .int8_t,
2214 .uint16_t,
2215 .int16_t,
2216 .uint32_t,
2217 .int32_t,
2218 .uint64_t,
2219 .int64_t,
2220 .uintptr_t,
2221 .intptr_t,
2222 .zig_u128,
2223 .zig_i128,
2224 .zig_f16,
2225 .zig_f32,
2226 .zig_f64,
2227 .zig_f80,
2228 .zig_f128,
2229 .zig_c_longdouble,
2230 => {},
2231
2232 .pointer,
2233 .pointer_const,
2234 .pointer_volatile,
2235 .pointer_const_volatile,
2236 => try renderTypeSuffix(decl, store, mod, w, cty.cast(CType.Payload.Child).?.data, .prefix),
2237
2238 .array,
2239 .vector,
2240 => {
2241 switch (parent_fix) {
2242 .prefix => try w.writeByte(')'),
2243 .suffix => {},
2244 }
2245
2246 try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len});
2247 try renderTypeSuffix(
2248 decl,
2249 store,
2250 mod,
2251 w,
2252 cty.cast(CType.Payload.Sequence).?.data.elem_type,
2253 .suffix,
2254 );
2255 },
2256
2257 .fwd_anon_struct,
2258 .fwd_anon_union,
2259 .fwd_struct,
2260 .fwd_union,
2261 .unnamed_struct,
2262 .unnamed_union,
2263 .packed_unnamed_struct,
2264 .packed_unnamed_union,
2265 .anon_struct,
2266 .anon_union,
2267 .@"struct",
2268 .@"union",
2269 .packed_struct,
2270 .packed_union,
2271 => {},
2272
2273 .function,
2274 .varargs_function,
2275 => |tag| {
2276 switch (parent_fix) {
2277 .prefix => try w.writeByte(')'),
2278 .suffix => {},
2279 }
2280
2281 const data = cty.cast(CType.Payload.Function).?.data;
2282
2283 try w.writeByte('(');
2284 var need_comma = false;
2285 for (data.param_types, 0..) |param_type, param_i| {
2286 if (need_comma) try w.writeAll(", ");
2287 need_comma = true;
2288 const trailing = try renderTypePrefix(
2289 decl,
2290 store,
2291 mod,
2292 w,
2293 param_type,
2294 .suffix,
2295 CQualifiers.init(.{ .@"const" = true }),
2296 );
2297 try w.print("{}a{d}", .{ trailing, param_i });
2298 try renderTypeSuffix(decl, store, mod, w, param_type, .suffix);
2299 }
2300 switch (tag) {
2301 .function => {},
2302 .varargs_function => {
2303 if (need_comma) try w.writeAll(", ");
2304 need_comma = true;
2305 try w.writeAll("...");
2306 },
2307 else => unreachable,
2308 }
2309 if (!need_comma) try w.writeAll("void");
2310 try w.writeByte(')');
2311
2312 try renderTypeSuffix(decl, store, mod, w, data.return_type, .suffix);
2313 },
2314 }
2315}
2316fn renderAggregateFields(
2317 mod: *Module,
2318 writer: anytype,
2319 store: CType.Store.Set,
2320 cty: CType,
2321 indent: usize,
2322) !void {
2323 try writer.writeAll("{\n");
2324 const fields = cty.fields();
2325 for (fields) |field| {
2326 try writer.writeByteNTimes(' ', indent + 1);
2327 switch (std.math.order(field.alignas.@"align", field.alignas.abi)) {
2328 .lt => try writer.print("zig_under_align({}) ", .{field.alignas.getAlign()}),
2329 .eq => {},
2330 .gt => try writer.print("zig_align({}) ", .{field.alignas.getAlign()}),
2331 }
2332 const trailing = try renderTypePrefix(
2333 .none,
2334 store,
2335 mod,
2336 writer,
2337 field.type,
2338 .suffix,
2339 CQualifiers.init(.{}),
2340 );
2341 try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) });
2342 try renderTypeSuffix(.none, store, mod, writer, field.type, .suffix);
2343 try writer.writeAll(";\n");
2344 }
2345 try writer.writeByteNTimes(' ', indent);
2346 try writer.writeByte('}');
2347}
2348
2349pub fn genTypeDecl(
2350 mod: *Module,
2351 writer: anytype,
2352 global_store: CType.Store.Set,
2353 global_idx: CType.Index,
2354 decl: Decl.OptionalIndex,
2355 decl_store: CType.Store.Set,
2356 decl_idx: CType.Index,
2357 found_existing: bool,
2358) !void {
2359 const global_cty = global_store.indexToCType(global_idx);
2360 switch (global_cty.tag()) {
2361 .fwd_anon_struct => if (decl != .none) {
2362 try writer.writeAll("typedef ");
2363 _ = try renderTypePrefix(
2364 .none,
2365 global_store,
2366 mod,
2367 writer,
2368 global_idx,
2369 .suffix,
2370 CQualifiers.init(.{}),
2371 );
2372 try writer.writeByte(' ');
2373 _ = try renderTypePrefix(
2374 decl,
2375 decl_store,
2376 mod,
2377 writer,
2378 decl_idx,
2379 .suffix,
2380 CQualifiers.init(.{}),
2381 );
2382 try writer.writeAll(";\n");
2383 },
2384
2385 .fwd_struct,
2386 .fwd_union,
2387 .anon_struct,
2388 .anon_union,
2389 .@"struct",
2390 .@"union",
2391 .packed_struct,
2392 .packed_union,
2393 => |tag| if (!found_existing) {
2394 switch (tag) {
2395 .fwd_struct,
2396 .fwd_union,
2397 => {
2398 const owner_decl = global_cty.cast(CType.Payload.FwdDecl).?.data;
2399 _ = try renderTypePrefix(
2400 .none,
2401 global_store,
2402 mod,
2403 writer,
2404 global_idx,
2405 .suffix,
2406 CQualifiers.init(.{}),
2407 );
2408 try writer.writeAll("; // ");
2409 try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer);
2410 try writer.writeByte('\n');
2411 },
2412
2413 .anon_struct,
2414 .anon_union,
2415 .@"struct",
2416 .@"union",
2417 .packed_struct,
2418 .packed_union,
2419 => {
2420 const fwd_idx = global_cty.cast(CType.Payload.Aggregate).?.data.fwd_decl;
2421 try renderTypeName(
2422 mod,
2423 writer,
2424 fwd_idx,
2425 global_store.indexToCType(fwd_idx),
2426 if (global_cty.isPacked()) "zig_packed(" else "",
2427 );
2428 try writer.writeByte(' ');
2429 try renderAggregateFields(mod, writer, global_store, global_cty, 0);
2430 if (global_cty.isPacked()) try writer.writeByte(')');
2431 try writer.writeAll(";\n");
2432 },
2433
2434 else => unreachable,
2435 }
2436 },
2437
2438 else => {},
2439 }
2440}
2441
2442pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {
26722443 var it = mod.global_assembly.valueIterator();
26732444 while (it.next()) |asm_source| {
2674 try code.writer().print("__asm({s});\n", .{fmtStringLiteral(asm_source.*)});
2445 try writer.print("__asm({s});\n", .{fmtStringLiteral(asm_source.*)});
26752446 }
26762447}
26772448
......@@ -2709,7 +2480,7 @@ pub fn genErrDecls(o: *Object) !void {
27092480 const name_val = Value.initPayload(&name_pl.base);
27102481
27112482 try writer.writeAll("static ");
2712 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0, .Complete);
2483 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .@"const", 0, .Complete);
27132484 try writer.writeAll(" = ");
27142485 try o.dg.renderValue(writer, name_ty, name_val, .StaticInitializer);
27152486 try writer.writeAll(";\n");
......@@ -2722,7 +2493,7 @@ pub fn genErrDecls(o: *Object) !void {
27222493 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
27232494
27242495 try writer.writeAll("static ");
2725 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .Const, 0, .Complete);
2496 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = name_prefix }, .@"const", 0, .Complete);
27262497 try writer.writeAll(" = {");
27272498 for (o.dg.module.error_name_list.items, 0..) |name, value| {
27282499 if (value != 0) try writer.writeByte(',');
......@@ -2742,14 +2513,27 @@ fn genExports(o: *Object) !void {
27422513 defer tracy.end();
27432514
27442515 const fwd_decl_writer = o.dg.fwd_decl.writer();
2745 if (o.dg.module.decl_exports.get(o.dg.decl_index)) |exports| for (exports.items[1..], 0..) |@"export", i| {
2746 try fwd_decl_writer.writeAll("zig_export(");
2747 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, 1 + i));
2748 try fwd_decl_writer.print(", {s}, {s});\n", .{
2749 fmtStringLiteral(exports.items[0].options.name),
2750 fmtStringLiteral(@"export".options.name),
2751 });
2752 };
2516 if (o.dg.module.decl_exports.get(o.dg.decl_index.unwrap().?)) |exports| {
2517 for (exports.items[1..], 1..) |@"export", i| {
2518 try fwd_decl_writer.writeAll("zig_export(");
2519 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, i));
2520 try fwd_decl_writer.print(", {s}, {s});\n", .{
2521 fmtStringLiteral(exports.items[0].options.name),
2522 fmtStringLiteral(@"export".options.name),
2523 });
2524 }
2525 }
2526}
2527
2528pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2529 const writer = o.writer();
2530 switch (lazy_fn.key_ptr.*) {
2531 .tag_name => _ = try o.dg.renderTagNameFn(
2532 writer,
2533 lazy_fn.value_ptr.fn_name,
2534 lazy_fn.value_ptr.data.tag_name,
2535 ),
2536 }
27532537}
27542538
27552539pub fn genFunc(f: *Function) !void {
......@@ -2759,8 +2543,8 @@ pub fn genFunc(f: *Function) !void {
27592543 const o = &f.object;
27602544 const gpa = o.dg.gpa;
27612545 const tv: TypedValue = .{
2762 .ty = o.dg.decl.ty,
2763 .val = o.dg.decl.val,
2546 .ty = o.dg.decl.?.ty,
2547 .val = o.dg.decl.?.val,
27642548 };
27652549
27662550 o.code_header = std.ArrayList(u8).init(gpa);
......@@ -2799,9 +2583,8 @@ pub fn genFunc(f: *Function) !void {
27992583 // missing. These are added now to complete the map. Then we can sort by
28002584 // alignment, descending.
28012585 const free_locals = f.getFreeLocals();
2802 const values = f.allocs.values();
2803 for (f.allocs.keys(), 0..) |local_index, i| {
2804 if (values[i]) continue; // static
2586 for (f.allocs.keys(), f.allocs.values()) |local_index, value| {
2587 if (value) continue; // static
28052588 const local = f.locals.items[local_index];
28062589 log.debug("inserting local {d} into free_locals", .{local_index});
28072590 const gop = try free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());
......@@ -2830,7 +2613,7 @@ pub fn genFunc(f: *Function) !void {
28302613 w,
28312614 local.ty,
28322615 .{ .local = local_index },
2833 .Mut,
2616 .mut,
28342617 local.alignment,
28352618 .Complete,
28362619 );
......@@ -2850,10 +2633,10 @@ pub fn genDecl(o: *Object) !void {
28502633 const tracy = trace(@src());
28512634 defer tracy.end();
28522635
2853 const tv: TypedValue = .{
2854 .ty = o.dg.decl.ty,
2855 .val = o.dg.decl.val,
2856 };
2636 const decl = o.dg.decl.?;
2637 const decl_c_value: CValue = .{ .decl = o.dg.decl_index.unwrap().? };
2638 const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val };
2639
28572640 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime()) return;
28582641 if (tv.val.tag() == .extern_fn) {
28592642 const fwd_decl_writer = o.dg.fwd_decl.writer();
......@@ -2867,11 +2650,9 @@ pub fn genDecl(o: *Object) !void {
28672650 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
28682651 const fwd_decl_writer = o.dg.fwd_decl.writer();
28692652
2870 const decl_c_value = CValue{ .decl = o.dg.decl_index };
2871
28722653 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
28732654 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");
2874 try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2655 try o.dg.renderTypeAndName(fwd_decl_writer, decl.ty, decl_c_value, .mut, decl.@"align", .Complete);
28752656 try fwd_decl_writer.writeAll(";\n");
28762657 try genExports(o);
28772658
......@@ -2880,27 +2661,26 @@ pub fn genDecl(o: *Object) !void {
28802661 const w = o.writer();
28812662 if (!is_global) try w.writeAll("static ");
28822663 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
2883 if (o.dg.decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});
2884 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2885 if (o.dg.decl.@"linksection" != null) try w.writeAll(", read, write)");
2664 if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});
2665 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .mut, decl.@"align", .Complete);
2666 if (decl.@"linksection" != null) try w.writeAll(", read, write)");
28862667 try w.writeAll(" = ");
28872668 try o.dg.renderValue(w, tv.ty, variable.init, .StaticInitializer);
28882669 try w.writeByte(';');
28892670 try o.indent_writer.insertNewline();
28902671 } else {
2891 const is_global = o.dg.module.decl_exports.contains(o.dg.decl_index);
2672 const is_global = o.dg.module.decl_exports.contains(decl_c_value.decl);
28922673 const fwd_decl_writer = o.dg.fwd_decl.writer();
2893 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
28942674
28952675 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2896 try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, .Const, o.dg.decl.@"align", .Complete);
2676 try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, .@"const", decl.@"align", .Complete);
28972677 try fwd_decl_writer.writeAll(";\n");
28982678
28992679 const w = o.writer();
29002680 if (!is_global) try w.writeAll("static ");
2901 if (o.dg.decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});
2902 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .Const, o.dg.decl.@"align", .Complete);
2903 if (o.dg.decl.@"linksection" != null) try w.writeAll(", read)");
2681 if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});
2682 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .@"const", decl.@"align", .Complete);
2683 if (decl.@"linksection" != null) try w.writeAll(", read)");
29042684 try w.writeAll(" = ");
29052685 try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer);
29062686 try w.writeAll(";\n");
......@@ -2912,8 +2692,8 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
29122692 defer tracy.end();
29132693
29142694 const tv: TypedValue = .{
2915 .ty = dg.decl.ty,
2916 .val = dg.decl.val,
2695 .ty = dg.decl.?.ty,
2696 .val = dg.decl.?.val,
29172697 };
29182698 const writer = dg.fwd_decl.writer();
29192699
......@@ -2951,7 +2731,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
29512731 // zig fmt: off
29522732 .constant => unreachable, // excluded from function bodies
29532733 .const_ty => unreachable, // excluded from function bodies
2954 .arg => airArg(f),
2734 .arg => try airArg(f, inst),
29552735
29562736 .breakpoint => try airBreakpoint(f.object.writer()),
29572737 .ret_addr => try airRetAddr(f, inst),
......@@ -3200,13 +2980,14 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
32002980 .c_va_start => return f.fail("TODO implement c_va_start", .{}),
32012981 // zig fmt: on
32022982 };
3203 if (result_value == .local) {
3204 log.debug("map %{d} to t{d}", .{ inst, result_value.local });
3205 }
3206 switch (result_value) {
3207 .none => {},
3208 else => try f.value_map.putNoClobber(Air.indexToRef(inst), result_value),
2983 if (result_value == .new_local) {
2984 log.debug("map %{d} to t{d}", .{ inst, result_value.new_local });
32092985 }
2986 try f.value_map.putNoClobber(Air.indexToRef(inst), switch (result_value) {
2987 .none => continue,
2988 .new_local => |i| .{ .local = i },
2989 else => result_value,
2990 });
32102991 }
32112992}
32122993
......@@ -3283,6 +3064,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
32833064 return CValue.none;
32843065 }
32853066
3067 const inst_ty = f.air.typeOfIndex(inst);
32863068 const ptr_ty = f.air.typeOf(bin_op.lhs);
32873069 const child_ty = ptr_ty.childType();
32883070
......@@ -3297,7 +3079,9 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
32973079 const writer = f.object.writer();
32983080 const local = try f.allocLocal(inst, f.air.typeOfIndex(inst));
32993081 try f.writeCValue(writer, local, .Other);
3300 try writer.writeAll(" = &(");
3082 try writer.writeAll(" = (");
3083 try f.renderTypecast(writer, inst_ty);
3084 try writer.writeAll(")&(");
33013085 if (ptr_ty.ptrSize() == .One) {
33023086 // It's a pointer to an array, so we need to de-reference.
33033087 try f.writeCValueDeref(writer, ptr);
......@@ -3428,13 +3212,13 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
34283212 return CValue{ .undef = inst_ty };
34293213 }
34303214
3431 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;
3215 const mutability: Mutability = if (inst_ty.isConstPtr()) .@"const" else .mut;
34323216 const target = f.object.dg.module.getTarget();
34333217 const local = try f.allocAlignedLocal(elem_type, mutability, inst_ty.ptrAlignment(target));
3434 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.local });
3218 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
34353219 const gpa = f.object.dg.module.gpa;
3436 try f.allocs.put(gpa, local.local, false);
3437 return CValue{ .local_ref = local.local };
3220 try f.allocs.put(gpa, local.new_local, false);
3221 return CValue{ .local_ref = local.new_local };
34383222}
34393223
34403224fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -3445,19 +3229,25 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
34453229 return CValue{ .undef = inst_ty };
34463230 }
34473231
3448 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;
3232 const mutability: Mutability = if (inst_ty.isConstPtr()) .@"const" else .mut;
34493233 const target = f.object.dg.module.getTarget();
34503234 const local = try f.allocAlignedLocal(elem_ty, mutability, inst_ty.ptrAlignment(target));
3451 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.local });
3235 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
34523236 const gpa = f.object.dg.module.gpa;
3453 try f.allocs.put(gpa, local.local, false);
3454 return CValue{ .local_ref = local.local };
3237 try f.allocs.put(gpa, local.new_local, false);
3238 return CValue{ .local_ref = local.new_local };
34553239}
34563240
3457fn airArg(f: *Function) CValue {
3241fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
3242 const inst_ty = f.air.typeOfIndex(inst);
3243 const inst_cty = try f.object.dg.typeToIndex(inst_ty, .parameter);
3244
34583245 const i = f.next_arg_index;
34593246 f.next_arg_index += 1;
3460 return .{ .arg = i };
3247 return if (inst_cty != try f.object.dg.typeToIndex(inst_ty, .complete))
3248 .{ .arg_array = i }
3249 else
3250 .{ .arg = i };
34613251}
34623252
34633253fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
......@@ -3567,7 +3357,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
35673357 const ret_val = if (is_array) ret_val: {
35683358 const array_local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator()));
35693359 try writer.writeAll("memcpy(");
3570 try f.writeCValueMember(writer, array_local, .{ .field = 0 });
3360 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
35713361 try writer.writeAll(", ");
35723362 if (deref)
35733363 try f.writeCValueDeref(writer, operand)
......@@ -3587,14 +3377,13 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
35873377 try f.writeCValue(writer, ret_val, .Other);
35883378 try writer.writeAll(";\n");
35893379 if (is_array) {
3590 try freeLocal(f, inst, ret_val.local, 0);
3380 try freeLocal(f, inst, ret_val.new_local, 0);
35913381 }
35923382 } else {
35933383 try reap(f, inst, &.{un_op});
3594 if (f.object.dg.decl.ty.fnCallingConvention() != .Naked) {
3384 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() != .Naked)
35953385 // Not even allowed to return void in a naked function.
35963386 try writer.writeAll("return;\n");
3597 }
35983387 }
35993388 return CValue.none;
36003389}
......@@ -3796,7 +3585,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
37963585 try f.renderTypecast(writer, src_ty);
37973586 try writer.writeAll("))");
37983587 if (src_val == .constant) {
3799 try freeLocal(f, inst, array_src.local, 0);
3588 try freeLocal(f, inst, array_src.new_local, 0);
38003589 }
38013590 } else if (ptr_info.host_size != 0) {
38023591 const host_bits = ptr_info.host_size * 8;
......@@ -3847,7 +3636,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
38473636 const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64;
38483637 if (cant_cast) {
38493638 if (src_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
3850 try writer.writeAll("zig_as_");
3639 try writer.writeAll("zig_make_");
38513640 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
38523641 try writer.writeAll("(0, ");
38533642 } else {
......@@ -4118,32 +3907,31 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
41183907 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
41193908
41203909 const inst_ty = f.air.typeOfIndex(inst);
4121 const elem_ty = switch (inst_ty.ptrSize()) {
4122 .One => blk: {
4123 const array_ty = inst_ty.childType();
4124 break :blk array_ty.childType();
4125 },
4126 else => inst_ty.childType(),
4127 };
3910 const elem_ty = inst_ty.elemType2();
41283911
4129 // We must convert to and from integer types to prevent UB if the operation
4130 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
4131 // if the result is NULL and then dereferenced.
41323912 const local = try f.allocLocal(inst, inst_ty);
41333913 const writer = f.object.writer();
41343914 try f.writeCValue(writer, local, .Other);
4135 try writer.writeAll(" = (");
4136 try f.renderTypecast(writer, inst_ty);
4137 try writer.writeAll(")(((uintptr_t)");
4138 try f.writeCValue(writer, lhs, .Other);
4139 try writer.writeAll(") ");
4140 try writer.writeByte(operator);
4141 try writer.writeAll(" (");
4142 try f.writeCValue(writer, rhs, .Other);
4143 try writer.writeAll("*sizeof(");
4144 try f.renderTypecast(writer, elem_ty);
4145 try writer.writeAll(")));\n");
3915 try writer.writeAll(" = ");
3916
3917 if (elem_ty.hasRuntimeBitsIgnoreComptime()) {
3918 // We must convert to and from integer types to prevent UB if the operation
3919 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
3920 // if the result is NULL and then dereferenced.
3921 try writer.writeByte('(');
3922 try f.renderTypecast(writer, inst_ty);
3923 try writer.writeAll(")(((uintptr_t)");
3924 try f.writeCValue(writer, lhs, .Other);
3925 try writer.writeAll(") ");
3926 try writer.writeByte(operator);
3927 try writer.writeAll(" (");
3928 try f.writeCValue(writer, rhs, .Other);
3929 try writer.writeAll("*sizeof(");
3930 try f.renderTypecast(writer, elem_ty);
3931 try writer.writeAll(")))");
3932 } else try f.writeCValue(writer, lhs, .Initializer);
41463933
3934 try writer.writeAll(";\n");
41473935 return local;
41483936}
41493937
......@@ -4222,8 +4010,12 @@ fn airCall(
42224010 modifier: std.builtin.CallModifier,
42234011) !CValue {
42244012 // Not even allowed to call panic in a naked function.
4225 if (f.object.dg.decl.ty.fnCallingConvention() == .Naked) return .none;
4013 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none;
4014
42264015 const gpa = f.object.dg.gpa;
4016 const module = f.object.dg.module;
4017 const target = module.getTarget();
4018 const writer = f.object.writer();
42274019
42284020 switch (modifier) {
42294021 .auto => {},
......@@ -4238,8 +4030,28 @@ fn airCall(
42384030
42394031 const resolved_args = try gpa.alloc(CValue, args.len);
42404032 defer gpa.free(resolved_args);
4241 for (args, 0..) |arg, i| {
4242 resolved_args[i] = try f.resolveInst(arg);
4033 for (resolved_args, args) |*resolved_arg, arg| {
4034 const arg_ty = f.air.typeOf(arg);
4035 const arg_cty = try f.object.dg.typeToIndex(arg_ty, .parameter);
4036 if (f.object.dg.indexToCType(arg_cty).tag() == .void) {
4037 resolved_arg.* = .none;
4038 continue;
4039 }
4040 resolved_arg.* = try f.resolveInst(arg);
4041 if (arg_cty != try f.object.dg.typeToIndex(arg_ty, .complete)) {
4042 var lowered_arg_buf: LowerFnRetTyBuffer = undefined;
4043 const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, target);
4044
4045 const array_local = try f.allocLocal(inst, try lowered_arg_ty.copy(f.arena.allocator()));
4046 try writer.writeAll("memcpy(");
4047 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
4048 try writer.writeAll(", ");
4049 try f.writeCValue(writer, resolved_arg.*, .FunctionArgument);
4050 try writer.writeAll(", sizeof(");
4051 try f.renderTypecast(writer, lowered_arg_ty);
4052 try writer.writeAll("));\n");
4053 resolved_arg.* = array_local;
4054 }
42434055 }
42444056
42454057 const callee = try f.resolveInst(pl_op.operand);
......@@ -4256,9 +4068,7 @@ fn airCall(
42564068 .Pointer => callee_ty.childType(),
42574069 else => unreachable,
42584070 };
4259 const writer = f.object.writer();
42604071
4261 const target = f.object.dg.module.getTarget();
42624072 const ret_ty = fn_ty.fnReturnType();
42634073 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
42644074 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
......@@ -4293,7 +4103,7 @@ fn airCall(
42934103 else => break :known,
42944104 };
42954105 };
4296 name = f.object.dg.module.declPtr(fn_decl).name;
4106 name = module.declPtr(fn_decl).name;
42974107 try f.object.dg.renderDeclName(writer, fn_decl, 0);
42984108 break :callee;
42994109 }
......@@ -4303,22 +4113,11 @@ fn airCall(
43034113
43044114 try writer.writeByte('(');
43054115 var args_written: usize = 0;
4306 for (args, 0..) |arg, arg_i| {
4307 const ty = f.air.typeOf(arg);
4308 if (!ty.hasRuntimeBitsIgnoreComptime()) continue;
4309 if (args_written != 0) {
4310 try writer.writeAll(", ");
4311 }
4312 if ((is_extern or std.mem.eql(u8, std.mem.span(name), "main")) and
4313 ty.isCPtr() and ty.childType().tag() == .u8)
4314 {
4315 // Corresponds with hack in renderType .Pointer case.
4316 try writer.writeAll("(char");
4317 if (ty.isConstPtr()) try writer.writeAll(" const");
4318 if (ty.isVolatilePtr()) try writer.writeAll(" volatile");
4319 try writer.writeAll(" *)");
4320 }
4321 try f.writeCValue(writer, resolved_args[arg_i], .FunctionArgument);
4116 for (resolved_args) |resolved_arg| {
4117 if (resolved_arg == .none) continue;
4118 if (args_written != 0) try writer.writeAll(", ");
4119 try f.writeCValue(writer, resolved_arg, .FunctionArgument);
4120 if (resolved_arg == .new_local) try freeLocal(f, inst, resolved_arg.new_local, 0);
43224121 args_written += 1;
43234122 }
43244123 try writer.writeAll(");\n");
......@@ -4331,11 +4130,11 @@ fn airCall(
43314130 try writer.writeAll("memcpy(");
43324131 try f.writeCValue(writer, array_local, .FunctionArgument);
43334132 try writer.writeAll(", ");
4334 try f.writeCValueMember(writer, result_local, .{ .field = 0 });
4133 try f.writeCValueMember(writer, result_local, .{ .identifier = "array" });
43354134 try writer.writeAll(", sizeof(");
43364135 try f.renderTypecast(writer, ret_ty);
43374136 try writer.writeAll("));\n");
4338 try freeLocal(f, inst, result_local.local, 0);
4137 try freeLocal(f, inst, result_local.new_local, 0);
43394138 break :r array_local;
43404139 };
43414140
......@@ -4599,7 +4398,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
45994398 }
46004399
46014400 if (operand == .constant) {
4602 try freeLocal(f, inst, operand_lval.local, 0);
4401 try freeLocal(f, inst, operand_lval.new_local, 0);
46034402 }
46044403
46054404 return local;
......@@ -4645,7 +4444,7 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
46454444
46464445fn airUnreach(f: *Function) !CValue {
46474446 // Not even allowed to call unreachable in a naked function.
4648 if (f.object.dg.decl.ty.fnCallingConvention() == .Naked) return .none;
4447 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none;
46494448
46504449 try f.object.writer().writeAll("zig_unreachable();\n");
46514450 return CValue.none;
......@@ -4922,7 +4721,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49224721 writer,
49234722 output_ty,
49244723 local_value,
4925 .Mut,
4724 .mut,
49264725 alignment,
49274726 .Complete,
49284727 );
......@@ -4961,7 +4760,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49614760 writer,
49624761 input_ty,
49634762 local_value,
4964 .Const,
4763 .@"const",
49654764 alignment,
49664765 .Complete,
49674766 );
......@@ -5119,7 +4918,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
51194918 const is_reg = constraint[1] == '{';
51204919 if (is_reg) {
51214920 try f.writeCValueDeref(writer, if (output == .none)
5122 CValue{ .local_ref = local.local }
4921 CValue{ .local_ref = local.new_local }
51234922 else
51244923 try f.resolveInst(output));
51254924 try writer.writeAll(" = ");
......@@ -5425,18 +5224,20 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
54255224 else => .none,
54265225 };
54275226
5428 const FieldLoc = union(enum) {
5227 const field_loc: union(enum) {
54295228 begin: void,
54305229 field: CValue,
54315230 end: void,
5432 };
5433 const field_loc = switch (struct_ty.tag()) {
5434 .@"struct" => switch (struct_ty.containerLayout()) {
5435 .Auto, .Extern => for (struct_ty.structFields().values()[index..], 0..) |field, offset| {
5436 if (field.ty.hasRuntimeBitsIgnoreComptime()) break FieldLoc{ .field = .{
5437 .identifier = struct_ty.structFieldName(index + offset),
5438 } };
5439 } else @as(FieldLoc, .end),
5231 } = switch (struct_ty.tag()) {
5232 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {
5233 .Auto, .Extern => for (index..struct_ty.structFieldCount()) |field_i| {
5234 if (!struct_ty.structFieldIsComptime(field_i) and
5235 struct_ty.structFieldType(field_i).hasRuntimeBitsIgnoreComptime())
5236 break .{ .field = if (struct_ty.isSimpleTuple())
5237 .{ .field = field_i }
5238 else
5239 .{ .identifier = struct_ty.structFieldName(field_i) } };
5240 } else .end,
54405241 .Packed => if (field_ptr_info.data.host_size == 0) {
54415242 const target = f.object.dg.module.getTarget();
54425243
......@@ -5461,45 +5262,33 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
54615262 try f.writeCValue(writer, struct_ptr, .Other);
54625263 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
54635264 return local;
5464 } else @as(FieldLoc, .begin),
5265 } else .begin,
54655266 },
54665267 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
54675268 try f.writeCValue(writer, struct_ptr, .Other);
54685269 try writer.writeAll(";\n");
54695270 return local;
5470 } else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{
5271 } else if (field_ty.hasRuntimeBitsIgnoreComptime()) .{ .field = .{
54715272 .identifier = struct_ty.unionFields().keys()[index],
5472 } } else @as(FieldLoc, .end),
5473 .tuple, .anon_struct => field_name: {
5474 const tuple = struct_ty.tupleFields();
5475 if (tuple.values[index].tag() != .unreachable_value) return CValue.none;
5476
5477 var id: usize = 0;
5478 break :field_name for (tuple.values, 0..) |value, i| {
5479 if (value.tag() != .unreachable_value) continue;
5480 if (!tuple.types[i].hasRuntimeBitsIgnoreComptime()) continue;
5481 if (i >= index) break FieldLoc{ .field = .{ .field = id } };
5482 id += 1;
5483 } else @as(FieldLoc, .end);
5484 },
5273 } } else .end,
54855274 else => unreachable,
54865275 };
54875276
5488 try writer.writeByte('&');
5489 switch (field_loc) {
5490 .begin, .end => {
5491 try writer.writeByte('(');
5492 try f.writeCValue(writer, struct_ptr, .Other);
5493 try writer.print(")[{}]", .{
5494 @boolToInt(field_loc == .end and struct_ty.hasRuntimeBitsIgnoreComptime()),
5495 });
5496 },
5497 .field => |field| if (extra_name != .none) {
5498 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
5499 try writer.writeByte('.');
5500 try f.writeCValue(writer, field, .Other);
5501 } else try f.writeCValueDerefMember(writer, struct_ptr, field),
5502 }
5277 if (struct_ty.hasRuntimeBitsIgnoreComptime()) {
5278 try writer.writeByte('&');
5279 switch (field_loc) {
5280 .begin, .end => {
5281 try writer.writeByte('(');
5282 try f.writeCValue(writer, struct_ptr, .Other);
5283 try writer.print(")[{}]", .{@boolToInt(field_loc == .end)});
5284 },
5285 .field => |field| if (extra_name != .none) {
5286 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
5287 try writer.writeByte('.');
5288 try f.writeCValue(writer, field, .Other);
5289 } else try f.writeCValueDerefMember(writer, struct_ptr, field),
5290 }
5291 } else try f.writeCValue(writer, struct_ptr, .Other);
55035292 try writer.writeAll(";\n");
55045293 return local;
55055294}
......@@ -5534,8 +5323,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
55345323 };
55355324
55365325 const field_name: CValue = switch (struct_ty.tag()) {
5537 .@"struct" => switch (struct_ty.containerLayout()) {
5538 .Auto, .Extern => .{ .identifier = struct_ty.structFieldName(extra.field_index) },
5326 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {
5327 .Auto, .Extern => if (struct_ty.isSimpleTuple())
5328 .{ .field = extra.field_index }
5329 else
5330 .{ .identifier = struct_ty.structFieldName(extra.field_index) },
55395331 .Packed => {
55405332 const struct_obj = struct_ty.castTag(.@"struct").?.data;
55415333 const int_info = struct_ty.intInfo(target);
......@@ -5593,13 +5385,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
55935385
55945386 const local = try f.allocLocal(inst, inst_ty);
55955387 try writer.writeAll("memcpy(");
5596 try f.writeCValue(writer, .{ .local_ref = local.local }, .FunctionArgument);
5388 try f.writeCValue(writer, .{ .local_ref = local.new_local }, .FunctionArgument);
55975389 try writer.writeAll(", ");
5598 try f.writeCValue(writer, .{ .local_ref = temp_local.local }, .FunctionArgument);
5390 try f.writeCValue(writer, .{ .local_ref = temp_local.new_local }, .FunctionArgument);
55995391 try writer.writeAll(", sizeof(");
56005392 try f.renderTypecast(writer, inst_ty);
56015393 try writer.writeAll("));\n");
5602 try freeLocal(f, inst, temp_local.local, 0);
5394 try freeLocal(f, inst, temp_local.new_local, 0);
56035395 return local;
56045396 },
56055397 },
......@@ -5623,22 +5415,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
56235415 try writer.writeAll("));\n");
56245416
56255417 if (struct_byval == .constant) {
5626 try freeLocal(f, inst, operand_lval.local, 0);
5418 try freeLocal(f, inst, operand_lval.new_local, 0);
56275419 }
56285420
56295421 return local;
56305422 } else .{
56315423 .identifier = struct_ty.unionFields().keys()[extra.field_index],
56325424 },
5633 .tuple, .anon_struct => blk: {
5634 const tuple = struct_ty.tupleFields();
5635 if (tuple.values[extra.field_index].tag() != .unreachable_value) return CValue.none;
5636
5637 var id: usize = 0;
5638 for (tuple.values[0..extra.field_index]) |value|
5639 id += @boolToInt(value.tag() == .unreachable_value);
5640 break :blk .{ .field = id };
5641 },
56425425 else => unreachable,
56435426 };
56445427
......@@ -5965,26 +5748,28 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
59655748 const inst_ty = f.air.typeOfIndex(inst);
59665749 const writer = f.object.writer();
59675750 const local = try f.allocLocal(inst, inst_ty);
5968 try f.writeCValue(writer, local, .Other);
5969 const array_len = f.air.typeOf(ty_op.operand).elemType().arrayLen();
5751 const array_ty = f.air.typeOf(ty_op.operand).childType();
59705752
5971 try writer.writeAll(".ptr = ");
5753 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
5754 try writer.writeAll(" = ");
5755 // Unfortunately, C does not support any equivalent to
5756 // &(*(void *)p)[0], although LLVM does via GetElementPtr
59725757 if (operand == .undef) {
5973 // Unfortunately, C does not support any equivalent to
5974 // &(*(void *)p)[0], although LLVM does via GetElementPtr
59755758 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
59765759 try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer);
5977 } else {
5760 } else if (array_ty.hasRuntimeBitsIgnoreComptime()) {
59785761 try writer.writeAll("&(");
59795762 try f.writeCValueDeref(writer, operand);
59805763 try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
5981 }
5764 } else try f.writeCValue(writer, operand, .Initializer);
5765 try writer.writeAll("; ");
59825766
5767 const array_len = array_ty.arrayLen();
59835768 var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len };
59845769 const len_val = Value.initPayload(&len_pl.base);
5985 try writer.writeAll("; ");
5986 try f.writeCValue(writer, local, .Other);
5987 try writer.print(".len = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
5770 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
5771 try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
5772
59885773 return local;
59895774}
59905775
......@@ -6223,7 +6008,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
62236008 }
62246009
62256010 if (f.liveness.isUnused(inst)) {
6226 try freeLocal(f, inst, local.local, 0);
6011 try freeLocal(f, inst, local.new_local, 0);
62276012 return CValue.none;
62286013 }
62296014
......@@ -6266,7 +6051,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
62666051 try writer.writeAll(");\n");
62676052
62686053 if (f.liveness.isUnused(inst)) {
6269 try freeLocal(f, inst, local.local, 0);
6054 try freeLocal(f, inst, local.new_local, 0);
62706055 return CValue.none;
62716056 }
62726057
......@@ -6363,7 +6148,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {
63636148 try writer.writeAll(";\n");
63646149
63656150 try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs });
6366 try freeLocal(f, inst, index.local, 0);
6151 try freeLocal(f, inst, index.new_local, 0);
63676152
63686153 return CValue.none;
63696154 }
......@@ -6465,7 +6250,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
64656250 const writer = f.object.writer();
64666251 const local = try f.allocLocal(inst, inst_ty);
64676252 try f.writeCValue(writer, local, .Other);
6468 try writer.print(" = {s}(", .{try f.object.dg.getTagNameFn(enum_ty)});
6253 try writer.print(" = {s}(", .{try f.getTagNameFn(enum_ty)});
64696254 try f.writeCValue(writer, operand, .Other);
64706255 try writer.writeAll(");\n");
64716256
......@@ -6680,7 +6465,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66806465
66816466 try writer.writeAll(";\n");
66826467
6683 try freeLocal(f, inst, it.local, 0);
6468 try freeLocal(f, inst, it.new_local, 0);
66846469
66856470 return accum;
66866471}
......@@ -6693,8 +6478,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
66936478 const gpa = f.object.dg.gpa;
66946479 const resolved_elements = try gpa.alloc(CValue, elements.len);
66956480 defer gpa.free(resolved_elements);
6696 for (elements, 0..) |element, i| {
6697 resolved_elements[i] = try f.resolveInst(element);
6481 for (resolved_elements, elements) |*resolved_element, element| {
6482 resolved_element.* = try f.resolveInst(element);
66986483 }
66996484 {
67006485 var bt = iterateBigTomb(f, inst);
......@@ -6733,46 +6518,47 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
67336518 try writer.writeAll(")");
67346519 try writer.writeByte('{');
67356520 var empty = true;
6736 for (elements, 0..) |element, index| {
6737 if (inst_ty.structFieldValueComptime(index)) |_| continue;
6521 for (elements, resolved_elements, 0..) |element, resolved_element, field_i| {
6522 if (inst_ty.structFieldValueComptime(field_i)) |_| continue;
67386523
67396524 if (!empty) try writer.writeAll(", ");
6740 if (!inst_ty.isTupleOrAnonStruct()) {
6741 try writer.print(".{ } = ", .{fmtIdent(inst_ty.structFieldName(index))});
6742 }
6525
6526 const field_name: CValue = if (inst_ty.isSimpleTuple())
6527 .{ .field = field_i }
6528 else
6529 .{ .identifier = inst_ty.structFieldName(field_i) };
6530 try writer.writeByte('.');
6531 try f.object.dg.writeCValue(writer, field_name);
6532 try writer.writeAll(" = ");
67436533
67446534 const element_ty = f.air.typeOf(element);
67456535 try f.writeCValue(writer, switch (element_ty.zigTypeTag()) {
67466536 .Array => CValue{ .undef = element_ty },
6747 else => resolved_elements[index],
6537 else => resolved_element,
67486538 }, .Initializer);
67496539 empty = false;
67506540 }
6751 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});
67526541 try writer.writeAll("};\n");
67536542
6754 var field_id: usize = 0;
6755 for (elements, 0..) |element, index| {
6756 if (inst_ty.structFieldValueComptime(index)) |_| continue;
6543 for (elements, resolved_elements, 0..) |element, resolved_element, field_i| {
6544 if (inst_ty.structFieldValueComptime(field_i)) |_| continue;
67576545
67586546 const element_ty = f.air.typeOf(element);
67596547 if (element_ty.zigTypeTag() != .Array) continue;
67606548
6761 const field_name = if (inst_ty.isTupleOrAnonStruct())
6762 CValue{ .field = field_id }
6549 const field_name: CValue = if (inst_ty.isSimpleTuple())
6550 .{ .field = field_i }
67636551 else
6764 CValue{ .identifier = inst_ty.structFieldName(index) };
6552 .{ .identifier = inst_ty.structFieldName(field_i) };
67656553
67666554 try writer.writeAll(";\n");
67676555 try writer.writeAll("memcpy(");
67686556 try f.writeCValueMember(writer, local, field_name);
67696557 try writer.writeAll(", ");
6770 try f.writeCValue(writer, resolved_elements[index], .FunctionArgument);
6558 try f.writeCValue(writer, resolved_element, .FunctionArgument);
67716559 try writer.writeAll(", sizeof(");
67726560 try f.renderTypecast(writer, element_ty);
67736561 try writer.writeAll("));\n");
6774
6775 field_id += 1;
67766562 }
67776563 },
67786564 .Packed => {
......@@ -6790,7 +6576,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
67906576 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
67916577
67926578 var empty = true;
6793 for (elements, 0..) |_, index| {
6579 for (0..elements.len) |index| {
67946580 const field_ty = inst_ty.structFieldType(index);
67956581 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
67966582
......@@ -6839,13 +6625,6 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68396625 empty = false;
68406626 }
68416627
6842 if (empty) {
6843 try writer.writeByte('(');
6844 try f.renderTypecast(writer, inst_ty);
6845 try writer.writeByte(')');
6846 try f.writeCValue(writer, .{ .undef = inst_ty }, .Initializer);
6847 }
6848
68496628 try writer.writeAll(";\n");
68506629 },
68516630 },
......@@ -7350,7 +7129,7 @@ fn formatIntLiteral(
73507129 use_twos_comp = true;
73517130 } else {
73527131 // TODO: Use fmtIntLiteral for 0?
7353 try writer.print("zig_sub_{c}{d}(zig_as_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits });
7132 try writer.print("zig_sub_{c}{d}(zig_make_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits });
73547133 }
73557134 } else {
73567135 try writer.writeByte('-');
......@@ -7360,11 +7139,16 @@ fn formatIntLiteral(
73607139 switch (data.ty.tag()) {
73617140 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
73627141 else => {
7363 if (int_info.bits > 64 and data.location != null and data.location.? == .StaticInitializer) {
7142 if (int_info.bits <= 64) {
7143 try writer.print("{s}INT{d}_C(", .{ switch (int_info.signedness) {
7144 .signed => "",
7145 .unsigned => "U",
7146 }, c_bits });
7147 } else if (data.location != null and data.location.? == .StaticInitializer) {
73647148 // MSVC treats casting the struct initializer as not constant (C2099), so an alternate form is used in global initializers
7365 try writer.print("zig_as_constant_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
7149 try writer.print("zig_make_constant_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
73667150 } else {
7367 try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
7151 try writer.print("zig_make_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits });
73687152 }
73697153 },
73707154 }
......@@ -7473,17 +7257,20 @@ fn isByRef(ty: Type) bool {
74737257}
74747258
74757259const LowerFnRetTyBuffer = struct {
7260 names: [1][]const u8,
74767261 types: [1]Type,
74777262 values: [1]Value,
7478 payload: Type.Payload.Tuple,
7263 payload: Type.Payload.AnonStruct,
74797264};
74807265fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {
74817266 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);
74827267
74837268 if (lowersToArray(ret_ty, target)) {
7269 buffer.names = [1][]const u8{"array"};
74847270 buffer.types = [1]Type{ret_ty};
74857271 buffer.values = [1]Value{Value.initTag(.unreachable_value)};
74867272 buffer.payload = .{ .data = .{
7273 .names = &buffer.names,
74877274 .types = &buffer.types,
74887275 .values = &buffer.values,
74897276 } };
......@@ -7539,7 +7326,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
75397326 if (f.air.instructions.items(.tag)[ref_inst] == .constant) return;
75407327 const c_value = (f.value_map.fetchRemove(ref) orelse return).value;
75417328 const local_index = switch (c_value) {
7542 .local => |l| l,
7329 .local, .new_local => |l| l,
75437330 else => return,
75447331 };
75457332 try freeLocal(f, inst, local_index, ref_inst);
......@@ -7614,8 +7401,8 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {
76147401}
76157402
76167403fn noticeBranchFrees(f: *Function, pre_locals_len: LocalIndex, inst: Air.Inst.Index) !void {
7617 for (f.locals.items[pre_locals_len..], 0..) |*local, local_offset| {
7618 const local_index = pre_locals_len + @intCast(LocalIndex, local_offset);
7404 for (f.locals.items[pre_locals_len..], pre_locals_len..) |*local, local_i| {
7405 const local_index = @intCast(LocalIndex, local_i);
76197406 if (f.allocs.contains(local_index)) continue; // allocs are not freeable
76207407
76217408 // free more deeply nested locals from other branches at current depth
src/codegen/c/type.zig created+1919
......@@ -0,0 +1,1919 @@
1const std = @import("std");
2const cstr = std.cstr;
3const mem = std.mem;
4const Allocator = mem.Allocator;
5const assert = std.debug.assert;
6const autoHash = std.hash.autoHash;
7const Target = std.Target;
8
9const Module = @import("../../Module.zig");
10const Type = @import("../../type.zig").Type;
11
12pub const CType = extern union {
13 /// If the tag value is less than Tag.no_payload_count, then no pointer
14 /// dereference is needed.
15 tag_if_small_enough: Tag,
16 ptr_otherwise: *const Payload,
17
18 pub fn initTag(small_tag: Tag) CType {
19 assert(!small_tag.hasPayload());
20 return .{ .tag_if_small_enough = small_tag };
21 }
22
23 pub fn initPayload(pl: anytype) CType {
24 const T = @typeInfo(@TypeOf(pl)).Pointer.child;
25 return switch (pl.base.tag) {
26 inline else => |t| if (comptime t.hasPayload() and t.Type() == T) .{
27 .ptr_otherwise = &pl.base,
28 } else unreachable,
29 };
30 }
31
32 pub fn hasPayload(self: CType) bool {
33 return self.tag_if_small_enough.hasPayload();
34 }
35
36 pub fn tag(self: CType) Tag {
37 return if (self.hasPayload()) self.ptr_otherwise.tag else self.tag_if_small_enough;
38 }
39
40 pub fn cast(self: CType, comptime T: type) ?*const T {
41 if (!self.hasPayload()) return null;
42 const pl = self.ptr_otherwise;
43 return switch (pl.tag) {
44 inline else => |t| if (comptime t.hasPayload() and t.Type() == T)
45 @fieldParentPtr(T, "base", pl)
46 else
47 null,
48 };
49 }
50
51 pub fn castTag(self: CType, comptime t: Tag) ?*const t.Type() {
52 return if (self.tag() == t) @fieldParentPtr(t.Type(), "base", self.ptr_otherwise) else null;
53 }
54
55 pub const Tag = enum(usize) {
56 // The first section of this enum are tags that require no payload.
57 void,
58
59 // C basic types
60 char,
61
62 @"signed char",
63 short,
64 int,
65 long,
66 @"long long",
67
68 _Bool,
69 @"unsigned char",
70 @"unsigned short",
71 @"unsigned int",
72 @"unsigned long",
73 @"unsigned long long",
74
75 float,
76 double,
77 @"long double",
78
79 // C header types
80 // - stdbool.h
81 bool,
82 // - stddef.h
83 size_t,
84 ptrdiff_t,
85 // - stdint.h
86 uint8_t,
87 int8_t,
88 uint16_t,
89 int16_t,
90 uint32_t,
91 int32_t,
92 uint64_t,
93 int64_t,
94 uintptr_t,
95 intptr_t,
96
97 // zig.h types
98 zig_u128,
99 zig_i128,
100 zig_f16,
101 zig_f32,
102 zig_f64,
103 zig_f80,
104 zig_f128,
105 zig_c_longdouble, // Keep last_no_payload_tag updated!
106
107 // After this, the tag requires a payload.
108 pointer,
109 pointer_const,
110 pointer_volatile,
111 pointer_const_volatile,
112 array,
113 vector,
114 fwd_anon_struct,
115 fwd_anon_union,
116 fwd_struct,
117 fwd_union,
118 unnamed_struct,
119 unnamed_union,
120 packed_unnamed_struct,
121 packed_unnamed_union,
122 anon_struct,
123 anon_union,
124 @"struct",
125 @"union",
126 packed_struct,
127 packed_union,
128 function,
129 varargs_function,
130
131 pub const last_no_payload_tag = Tag.zig_c_longdouble;
132 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
133
134 pub fn hasPayload(self: Tag) bool {
135 return @enumToInt(self) >= no_payload_count;
136 }
137
138 pub fn toIndex(self: Tag) Index {
139 assert(!self.hasPayload());
140 return @intCast(Index, @enumToInt(self));
141 }
142
143 pub fn Type(comptime self: Tag) type {
144 return switch (self) {
145 .void,
146 .char,
147 .@"signed char",
148 .short,
149 .int,
150 .long,
151 .@"long long",
152 ._Bool,
153 .@"unsigned char",
154 .@"unsigned short",
155 .@"unsigned int",
156 .@"unsigned long",
157 .@"unsigned long long",
158 .float,
159 .double,
160 .@"long double",
161 .bool,
162 .size_t,
163 .ptrdiff_t,
164 .uint8_t,
165 .int8_t,
166 .uint16_t,
167 .int16_t,
168 .uint32_t,
169 .int32_t,
170 .uint64_t,
171 .int64_t,
172 .uintptr_t,
173 .intptr_t,
174 .zig_u128,
175 .zig_i128,
176 .zig_f16,
177 .zig_f32,
178 .zig_f64,
179 .zig_f80,
180 .zig_f128,
181 .zig_c_longdouble,
182 => @compileError("Type Tag " ++ @tagName(self) ++ " has no payload"),
183
184 .pointer,
185 .pointer_const,
186 .pointer_volatile,
187 .pointer_const_volatile,
188 => Payload.Child,
189
190 .array,
191 .vector,
192 => Payload.Sequence,
193
194 .fwd_anon_struct,
195 .fwd_anon_union,
196 => Payload.Fields,
197
198 .fwd_struct,
199 .fwd_union,
200 => Payload.FwdDecl,
201
202 .unnamed_struct,
203 .unnamed_union,
204 .packed_unnamed_struct,
205 .packed_unnamed_union,
206 => Payload.Unnamed,
207
208 .anon_struct,
209 .anon_union,
210 .@"struct",
211 .@"union",
212 .packed_struct,
213 .packed_union,
214 => Payload.Aggregate,
215
216 .function,
217 .varargs_function,
218 => Payload.Function,
219 };
220 }
221 };
222
223 pub const Payload = struct {
224 tag: Tag,
225
226 pub const Child = struct {
227 base: Payload,
228 data: Index,
229 };
230
231 pub const Sequence = struct {
232 base: Payload,
233 data: struct {
234 len: u64,
235 elem_type: Index,
236 },
237 };
238
239 pub const FwdDecl = struct {
240 base: Payload,
241 data: Module.Decl.Index,
242 };
243
244 pub const Fields = struct {
245 base: Payload,
246 data: Data,
247
248 pub const Data = []const Field;
249 pub const Field = struct {
250 name: [*:0]const u8,
251 type: Index,
252 alignas: AlignAs,
253 };
254 pub const AlignAs = struct {
255 @"align": std.math.Log2Int(u32),
256 abi: std.math.Log2Int(u32),
257
258 pub fn init(alignment: u32, abi_alignment: u32) AlignAs {
259 assert(std.math.isPowerOfTwo(alignment));
260 assert(std.math.isPowerOfTwo(abi_alignment));
261 return .{
262 .@"align" = std.math.log2_int(u32, alignment),
263 .abi = std.math.log2_int(u32, abi_alignment),
264 };
265 }
266 pub fn abiAlign(ty: Type, target: Target) AlignAs {
267 const abi_align = ty.abiAlignment(target);
268 return init(abi_align, abi_align);
269 }
270 pub fn fieldAlign(struct_ty: Type, field_i: usize, target: Target) AlignAs {
271 return init(
272 struct_ty.structFieldAlign(field_i, target),
273 struct_ty.structFieldType(field_i).abiAlignment(target),
274 );
275 }
276 pub fn unionPayloadAlign(union_ty: Type, target: Target) AlignAs {
277 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
278 const union_payload_align = union_obj.abiAlignment(target, false);
279 return init(union_payload_align, union_payload_align);
280 }
281
282 pub fn getAlign(self: AlignAs) u32 {
283 return @as(u32, 1) << self.@"align";
284 }
285 };
286 };
287
288 pub const Unnamed = struct {
289 base: Payload,
290 data: struct {
291 fields: Fields.Data,
292 owner_decl: Module.Decl.Index,
293 id: u32,
294 },
295 };
296
297 pub const Aggregate = struct {
298 base: Payload,
299 data: struct {
300 fields: Fields.Data,
301 fwd_decl: Index,
302 },
303 };
304
305 pub const Function = struct {
306 base: Payload,
307 data: struct {
308 return_type: Index,
309 param_types: []const Index,
310 },
311 };
312 };
313
314 pub const Index = u32;
315 pub const Store = struct {
316 arena: std.heap.ArenaAllocator.State = .{},
317 set: Set = .{},
318
319 pub const Set = struct {
320 pub const Map = std.ArrayHashMapUnmanaged(CType, void, HashContext32, true);
321
322 map: Map = .{},
323
324 pub fn indexToCType(self: Set, index: Index) CType {
325 if (index < Tag.no_payload_count) return initTag(@intToEnum(Tag, index));
326 return self.map.keys()[index - Tag.no_payload_count];
327 }
328
329 pub fn indexToHash(self: Set, index: Index) Map.Hash {
330 if (index < Tag.no_payload_count)
331 return (HashContext32{ .store = &self }).hash(self.indexToCType(index));
332 return self.map.entries.items(.hash)[index - Tag.no_payload_count];
333 }
334
335 pub fn typeToIndex(self: Set, ty: Type, target: Target, kind: Kind) ?Index {
336 const lookup = Convert.Lookup{ .imm = .{ .set = &self, .target = target } };
337
338 var convert: Convert = undefined;
339 convert.initType(ty, kind, lookup) catch unreachable;
340
341 const t = convert.tag();
342 if (!t.hasPayload()) return t.toIndex();
343
344 return if (self.map.getIndexAdapted(
345 ty,
346 TypeAdapter32{ .kind = kind, .lookup = lookup, .convert = &convert },
347 )) |idx| @intCast(Index, Tag.no_payload_count + idx) else null;
348 }
349 };
350
351 pub const Promoted = struct {
352 arena: std.heap.ArenaAllocator,
353 set: Set,
354
355 pub fn gpa(self: *Promoted) Allocator {
356 return self.arena.child_allocator;
357 }
358
359 pub fn cTypeToIndex(self: *Promoted, cty: CType) Allocator.Error!Index {
360 const t = cty.tag();
361 if (@enumToInt(t) < Tag.no_payload_count) return @intCast(Index, @enumToInt(t));
362
363 const gop = try self.set.map.getOrPutContext(self.gpa(), cty, .{ .store = &self.set });
364 if (!gop.found_existing) gop.key_ptr.* = cty;
365 if (std.debug.runtime_safety) {
366 const key = &self.set.map.entries.items(.key)[gop.index];
367 assert(key == gop.key_ptr);
368 assert(cty.eql(key.*));
369 assert(cty.hash(self.set) == key.hash(self.set));
370 }
371 return @intCast(Index, Tag.no_payload_count + gop.index);
372 }
373
374 pub fn typeToIndex(
375 self: *Promoted,
376 ty: Type,
377 mod: *Module,
378 kind: Kind,
379 ) Allocator.Error!Index {
380 const lookup = Convert.Lookup{ .mut = .{ .promoted = self, .mod = mod } };
381
382 var convert: Convert = undefined;
383 try convert.initType(ty, kind, lookup);
384
385 const t = convert.tag();
386 if (!t.hasPayload()) return t.toIndex();
387
388 const gop = try self.set.map.getOrPutContextAdapted(
389 self.gpa(),
390 ty,
391 TypeAdapter32{ .kind = kind, .lookup = lookup.freeze(), .convert = &convert },
392 .{ .store = &self.set },
393 );
394 if (!gop.found_existing) {
395 errdefer _ = self.set.map.pop();
396 gop.key_ptr.* = try createFromConvert(self, ty, lookup.getTarget(), kind, convert);
397 }
398 if (std.debug.runtime_safety) {
399 const adapter = TypeAdapter64{
400 .kind = kind,
401 .lookup = lookup.freeze(),
402 .convert = &convert,
403 };
404 const cty = &self.set.map.entries.items(.key)[gop.index];
405 assert(cty == gop.key_ptr);
406 assert(adapter.eql(ty, cty.*));
407 assert(adapter.hash(ty) == cty.hash(self.set));
408 }
409 return @intCast(Index, Tag.no_payload_count + gop.index);
410 }
411 };
412
413 pub fn promote(self: Store, gpa: Allocator) Promoted {
414 return .{ .arena = self.arena.promote(gpa), .set = self.set };
415 }
416
417 pub fn demote(self: *Store, promoted: Promoted) void {
418 self.arena = promoted.arena.state;
419 self.set = promoted.set;
420 }
421
422 pub fn indexToCType(self: Store, index: Index) CType {
423 return self.set.indexToCType(index);
424 }
425
426 pub fn indexToHash(self: Store, index: Index) Set.Map.Hash {
427 return self.set.indexToHash(index);
428 }
429
430 pub fn cTypeToIndex(self: *Store, gpa: Allocator, cty: CType) !Index {
431 var promoted = self.promote(gpa);
432 defer self.demote(promoted);
433 return promoted.cTypeToIndex(cty);
434 }
435
436 pub fn typeToCType(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !CType {
437 const idx = try self.typeToIndex(gpa, ty, mod, kind);
438 return self.indexToCType(idx);
439 }
440
441 pub fn typeToIndex(self: *Store, gpa: Allocator, ty: Type, mod: *Module, kind: Kind) !Index {
442 var promoted = self.promote(gpa);
443 defer self.demote(promoted);
444 return promoted.typeToIndex(ty, mod, kind);
445 }
446
447 pub fn clearRetainingCapacity(self: *Store, gpa: Allocator) void {
448 var promoted = self.promote(gpa);
449 defer self.demote(promoted);
450 promoted.set.map.clearRetainingCapacity();
451 _ = promoted.arena.reset(.retain_capacity);
452 }
453
454 pub fn clearAndFree(self: *Store, gpa: Allocator) void {
455 var promoted = self.promote(gpa);
456 defer self.demote(promoted);
457 promoted.set.map.clearAndFree(gpa);
458 _ = promoted.arena.reset(.free_all);
459 }
460
461 pub fn shrinkRetainingCapacity(self: *Store, gpa: Allocator, new_len: usize) void {
462 self.set.map.shrinkRetainingCapacity(gpa, new_len);
463 }
464
465 pub fn shrinkAndFree(self: *Store, gpa: Allocator, new_len: usize) void {
466 self.set.map.shrinkAndFree(gpa, new_len);
467 }
468
469 pub fn count(self: Store) usize {
470 return self.set.map.count();
471 }
472
473 pub fn move(self: *Store) Store {
474 const moved = self.*;
475 self.* = .{};
476 return moved;
477 }
478
479 pub fn deinit(self: *Store, gpa: Allocator) void {
480 var promoted = self.promote(gpa);
481 promoted.set.map.deinit(gpa);
482 _ = promoted.arena.deinit();
483 self.* = undefined;
484 }
485 };
486
487 pub fn isPacked(self: CType) bool {
488 return switch (self.tag()) {
489 else => false,
490 .packed_unnamed_struct,
491 .packed_unnamed_union,
492 .packed_struct,
493 .packed_union,
494 => true,
495 };
496 }
497
498 pub fn fields(self: CType) Payload.Fields.Data {
499 return if (self.cast(Payload.Aggregate)) |pl|
500 pl.data.fields
501 else if (self.cast(Payload.Unnamed)) |pl|
502 pl.data.fields
503 else if (self.cast(Payload.Fields)) |pl|
504 pl.data
505 else
506 unreachable;
507 }
508
509 pub fn eql(lhs: CType, rhs: CType) bool {
510 return lhs.eqlContext(rhs, struct {
511 pub fn eqlIndex(_: @This(), lhs_idx: Index, rhs_idx: Index) bool {
512 return lhs_idx == rhs_idx;
513 }
514 }{});
515 }
516
517 pub fn eqlContext(lhs: CType, rhs: CType, ctx: anytype) bool {
518 // As a shortcut, if the small tags / addresses match, we're done.
519 if (lhs.tag_if_small_enough == rhs.tag_if_small_enough) return true;
520
521 const lhs_tag = lhs.tag();
522 const rhs_tag = rhs.tag();
523 if (lhs_tag != rhs_tag) return false;
524
525 return switch (lhs_tag) {
526 .void,
527 .char,
528 .@"signed char",
529 .short,
530 .int,
531 .long,
532 .@"long long",
533 ._Bool,
534 .@"unsigned char",
535 .@"unsigned short",
536 .@"unsigned int",
537 .@"unsigned long",
538 .@"unsigned long long",
539 .float,
540 .double,
541 .@"long double",
542 .bool,
543 .size_t,
544 .ptrdiff_t,
545 .uint8_t,
546 .int8_t,
547 .uint16_t,
548 .int16_t,
549 .uint32_t,
550 .int32_t,
551 .uint64_t,
552 .int64_t,
553 .uintptr_t,
554 .intptr_t,
555 .zig_u128,
556 .zig_i128,
557 .zig_f16,
558 .zig_f32,
559 .zig_f64,
560 .zig_f80,
561 .zig_f128,
562 .zig_c_longdouble,
563 => false,
564
565 .pointer,
566 .pointer_const,
567 .pointer_volatile,
568 .pointer_const_volatile,
569 => ctx.eqlIndex(lhs.cast(Payload.Child).?.data, rhs.cast(Payload.Child).?.data),
570
571 .array,
572 .vector,
573 => {
574 const lhs_data = lhs.cast(Payload.Sequence).?.data;
575 const rhs_data = rhs.cast(Payload.Sequence).?.data;
576 return lhs_data.len == rhs_data.len and
577 ctx.eqlIndex(lhs_data.elem_type, rhs_data.elem_type);
578 },
579
580 .fwd_anon_struct,
581 .fwd_anon_union,
582 => {
583 const lhs_data = lhs.cast(Payload.Fields).?.data;
584 const rhs_data = rhs.cast(Payload.Fields).?.data;
585 if (lhs_data.len != rhs_data.len) return false;
586 for (lhs_data, rhs_data) |lhs_field, rhs_field| {
587 if (!ctx.eqlIndex(lhs_field.type, rhs_field.type)) return false;
588 if (lhs_field.alignas.@"align" != rhs_field.alignas.@"align") return false;
589 if (cstr.cmp(lhs_field.name, rhs_field.name) != 0) return false;
590 }
591 return true;
592 },
593
594 .fwd_struct,
595 .fwd_union,
596 => lhs.cast(Payload.FwdDecl).?.data == rhs.cast(Payload.FwdDecl).?.data,
597
598 .unnamed_struct,
599 .unnamed_union,
600 .packed_unnamed_struct,
601 .packed_unnamed_union,
602 => {
603 const lhs_data = lhs.cast(Payload.Unnamed).?.data;
604 const rhs_data = rhs.cast(Payload.Unnamed).?.data;
605 return lhs_data.owner_decl == rhs_data.owner_decl and lhs_data.id == rhs_data.id;
606 },
607
608 .anon_struct,
609 .anon_union,
610 .@"struct",
611 .@"union",
612 .packed_struct,
613 .packed_union,
614 => ctx.eqlIndex(
615 lhs.cast(Payload.Aggregate).?.data.fwd_decl,
616 rhs.cast(Payload.Aggregate).?.data.fwd_decl,
617 ),
618
619 .function,
620 .varargs_function,
621 => {
622 const lhs_data = lhs.cast(Payload.Function).?.data;
623 const rhs_data = rhs.cast(Payload.Function).?.data;
624 if (lhs_data.param_types.len != rhs_data.param_types.len) return false;
625 if (!ctx.eqlIndex(lhs_data.return_type, rhs_data.return_type)) return false;
626 for (lhs_data.param_types, rhs_data.param_types) |lhs_param_idx, rhs_param_idx| {
627 if (!ctx.eqlIndex(lhs_param_idx, rhs_param_idx)) return false;
628 }
629 return true;
630 },
631 };
632 }
633
634 pub fn hash(self: CType, store: Store.Set) u64 {
635 var hasher = std.hash.Wyhash.init(0);
636 self.updateHasher(&hasher, store);
637 return hasher.final();
638 }
639
640 pub fn updateHasher(self: CType, hasher: anytype, store: Store.Set) void {
641 const t = self.tag();
642 autoHash(hasher, t);
643 switch (t) {
644 .void,
645 .char,
646 .@"signed char",
647 .short,
648 .int,
649 .long,
650 .@"long long",
651 ._Bool,
652 .@"unsigned char",
653 .@"unsigned short",
654 .@"unsigned int",
655 .@"unsigned long",
656 .@"unsigned long long",
657 .float,
658 .double,
659 .@"long double",
660 .bool,
661 .size_t,
662 .ptrdiff_t,
663 .uint8_t,
664 .int8_t,
665 .uint16_t,
666 .int16_t,
667 .uint32_t,
668 .int32_t,
669 .uint64_t,
670 .int64_t,
671 .uintptr_t,
672 .intptr_t,
673 .zig_u128,
674 .zig_i128,
675 .zig_f16,
676 .zig_f32,
677 .zig_f64,
678 .zig_f80,
679 .zig_f128,
680 .zig_c_longdouble,
681 => {},
682
683 .pointer,
684 .pointer_const,
685 .pointer_volatile,
686 .pointer_const_volatile,
687 => store.indexToCType(self.cast(Payload.Child).?.data).updateHasher(hasher, store),
688
689 .array,
690 .vector,
691 => {
692 const data = self.cast(Payload.Sequence).?.data;
693 autoHash(hasher, data.len);
694 store.indexToCType(data.elem_type).updateHasher(hasher, store);
695 },
696
697 .fwd_anon_struct,
698 .fwd_anon_union,
699 => for (self.cast(Payload.Fields).?.data) |field| {
700 store.indexToCType(field.type).updateHasher(hasher, store);
701 hasher.update(mem.span(field.name));
702 autoHash(hasher, field.alignas.@"align");
703 },
704
705 .fwd_struct,
706 .fwd_union,
707 => autoHash(hasher, self.cast(Payload.FwdDecl).?.data),
708
709 .unnamed_struct,
710 .unnamed_union,
711 .packed_unnamed_struct,
712 .packed_unnamed_union,
713 => {
714 const data = self.cast(Payload.Unnamed).?.data;
715 autoHash(hasher, data.owner_decl);
716 autoHash(hasher, data.id);
717 },
718
719 .anon_struct,
720 .anon_union,
721 .@"struct",
722 .@"union",
723 .packed_struct,
724 .packed_union,
725 => store.indexToCType(self.cast(Payload.Aggregate).?.data.fwd_decl)
726 .updateHasher(hasher, store),
727
728 .function,
729 .varargs_function,
730 => {
731 const data = self.cast(Payload.Function).?.data;
732 store.indexToCType(data.return_type).updateHasher(hasher, store);
733 for (data.param_types) |param_ty| {
734 store.indexToCType(param_ty).updateHasher(hasher, store);
735 }
736 },
737 }
738 }
739
740 pub const Kind = enum { forward, forward_parameter, complete, global, parameter, payload };
741
742 const Convert = struct {
743 storage: union {
744 none: void,
745 child: Payload.Child,
746 seq: Payload.Sequence,
747 fwd: Payload.FwdDecl,
748 anon: struct {
749 fields: [2]Payload.Fields.Field,
750 pl: union {
751 forward: Payload.Fields,
752 complete: Payload.Aggregate,
753 },
754 },
755 },
756 value: union(enum) {
757 tag: Tag,
758 cty: CType,
759 },
760
761 pub fn init(self: *@This(), t: Tag) void {
762 self.* = if (t.hasPayload()) .{
763 .storage = .{ .none = {} },
764 .value = .{ .tag = t },
765 } else .{
766 .storage = .{ .none = {} },
767 .value = .{ .cty = initTag(t) },
768 };
769 }
770
771 pub fn tag(self: @This()) Tag {
772 return switch (self.value) {
773 .tag => |t| t,
774 .cty => |c| c.tag(),
775 };
776 }
777
778 fn tagFromIntInfo(signedness: std.builtin.Signedness, bits: u16) Tag {
779 return switch (bits) {
780 0 => .void,
781 1...8 => switch (signedness) {
782 .unsigned => .uint8_t,
783 .signed => .int8_t,
784 },
785 9...16 => switch (signedness) {
786 .unsigned => .uint16_t,
787 .signed => .int16_t,
788 },
789 17...32 => switch (signedness) {
790 .unsigned => .uint32_t,
791 .signed => .int32_t,
792 },
793 33...64 => switch (signedness) {
794 .unsigned => .uint64_t,
795 .signed => .int64_t,
796 },
797 65...128 => switch (signedness) {
798 .unsigned => .zig_u128,
799 .signed => .zig_i128,
800 },
801 else => .array,
802 };
803 }
804
805 pub const Lookup = union(enum) {
806 fail: Target,
807 imm: struct {
808 set: *const Store.Set,
809 target: Target,
810 },
811 mut: struct {
812 promoted: *Store.Promoted,
813 mod: *Module,
814 },
815
816 pub fn isMutable(self: @This()) bool {
817 return switch (self) {
818 .fail, .imm => false,
819 .mut => true,
820 };
821 }
822
823 pub fn getTarget(self: @This()) Target {
824 return switch (self) {
825 .fail => |target| target,
826 .imm => |imm| imm.target,
827 .mut => |mut| mut.mod.getTarget(),
828 };
829 }
830
831 pub fn getSet(self: @This()) ?*const Store.Set {
832 return switch (self) {
833 .fail => null,
834 .imm => |imm| imm.set,
835 .mut => |mut| &mut.promoted.set,
836 };
837 }
838
839 pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index {
840 return switch (self) {
841 .fail => null,
842 .imm => |imm| imm.set.typeToIndex(ty, imm.target, kind),
843 .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind),
844 };
845 }
846
847 pub fn indexToCType(self: @This(), index: Index) ?CType {
848 return if (self.getSet()) |set| set.indexToCType(index) else null;
849 }
850
851 pub fn freeze(self: @This()) @This() {
852 return switch (self) {
853 .fail, .imm => self,
854 .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .target = self.getTarget() } },
855 };
856 }
857 };
858
859 fn sortFields(self: *@This(), fields_len: usize) []Payload.Fields.Field {
860 const Field = Payload.Fields.Field;
861 const slice = self.storage.anon.fields[0..fields_len];
862 std.sort.sort(Field, slice, {}, struct {
863 fn before(_: void, lhs: Field, rhs: Field) bool {
864 return lhs.alignas.@"align" > rhs.alignas.@"align";
865 }
866 }.before);
867 return slice;
868 }
869
870 fn initAnon(self: *@This(), kind: Kind, fwd_idx: Index, fields_len: usize) void {
871 switch (kind) {
872 .forward, .forward_parameter => {
873 self.storage.anon.pl = .{ .forward = .{
874 .base = .{ .tag = .fwd_anon_struct },
875 .data = self.sortFields(fields_len),
876 } };
877 self.value = .{ .cty = initPayload(&self.storage.anon.pl.forward) };
878 },
879 .complete, .parameter, .global => {
880 self.storage.anon.pl = .{ .complete = .{
881 .base = .{ .tag = .anon_struct },
882 .data = .{
883 .fields = self.sortFields(fields_len),
884 .fwd_decl = fwd_idx,
885 },
886 } };
887 self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) };
888 },
889 .payload => unreachable,
890 }
891 }
892
893 fn initArrayParameter(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void {
894 if (switch (kind) {
895 .forward_parameter => @as(Index, undefined),
896 .parameter => try lookup.typeToIndex(ty, .forward_parameter),
897 .forward, .complete, .global, .payload => unreachable,
898 }) |fwd_idx| {
899 if (try lookup.typeToIndex(ty, switch (kind) {
900 .forward_parameter => .forward,
901 .parameter => .complete,
902 .forward, .complete, .global, .payload => unreachable,
903 })) |array_idx| {
904 self.storage = .{ .anon = undefined };
905 self.storage.anon.fields[0] = .{
906 .name = "array",
907 .type = array_idx,
908 .alignas = Payload.Fields.AlignAs.abiAlign(ty, lookup.getTarget()),
909 };
910 self.initAnon(kind, fwd_idx, 1);
911 } else self.init(switch (kind) {
912 .forward_parameter => .fwd_anon_struct,
913 .parameter => .anon_struct,
914 .forward, .complete, .global, .payload => unreachable,
915 });
916 } else self.init(.anon_struct);
917 }
918
919 pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void {
920 const target = lookup.getTarget();
921
922 self.* = undefined;
923 if (!ty.isFnOrHasRuntimeBitsIgnoreComptime())
924 self.init(.void)
925 else if (ty.isAbiInt()) switch (ty.tag()) {
926 .usize => self.init(.uintptr_t),
927 .isize => self.init(.intptr_t),
928 .c_short => self.init(.short),
929 .c_ushort => self.init(.@"unsigned short"),
930 .c_int => self.init(.int),
931 .c_uint => self.init(.@"unsigned int"),
932 .c_long => self.init(.long),
933 .c_ulong => self.init(.@"unsigned long"),
934 .c_longlong => self.init(.@"long long"),
935 .c_ulonglong => self.init(.@"unsigned long long"),
936 else => {
937 const info = ty.intInfo(target);
938 const t = tagFromIntInfo(info.signedness, info.bits);
939 switch (t) {
940 .void => unreachable,
941 else => self.init(t),
942 .array => switch (kind) {
943 .forward, .complete, .global => {
944 const abi_size = ty.abiSize(target);
945 const abi_align = ty.abiAlignment(target);
946 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
947 .len = @divExact(abi_size, abi_align),
948 .elem_type = tagFromIntInfo(
949 .unsigned,
950 @intCast(u16, abi_align * 8),
951 ).toIndex(),
952 } } };
953 self.value = .{ .cty = initPayload(&self.storage.seq) };
954 },
955 .forward_parameter,
956 .parameter,
957 => try self.initArrayParameter(ty, kind, lookup),
958 .payload => unreachable,
959 },
960 }
961 },
962 } else switch (ty.zigTypeTag()) {
963 .Frame => unreachable,
964 .AnyFrame => unreachable,
965
966 .Int,
967 .Enum,
968 .ErrorSet,
969 .Type,
970 .Void,
971 .NoReturn,
972 .ComptimeFloat,
973 .ComptimeInt,
974 .Undefined,
975 .Null,
976 .EnumLiteral,
977 => unreachable,
978
979 .Bool => self.init(.bool),
980
981 .Float => self.init(switch (ty.tag()) {
982 .f16 => .zig_f16,
983 .f32 => .zig_f32,
984 .f64 => .zig_f64,
985 .f80 => .zig_f80,
986 .f128 => .zig_f128,
987 .c_longdouble => .zig_c_longdouble,
988 else => unreachable,
989 }),
990
991 .Pointer => {
992 const info = ty.ptrInfo().data;
993 switch (info.size) {
994 .Slice => {
995 if (switch (kind) {
996 .forward, .forward_parameter => @as(Index, undefined),
997 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
998 .payload => unreachable,
999 }) |fwd_idx| {
1000 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1001 const ptr_ty = ty.slicePtrFieldType(&buf);
1002 if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| {
1003 self.storage = .{ .anon = undefined };
1004 self.storage.anon.fields[0] = .{
1005 .name = "ptr",
1006 .type = ptr_idx,
1007 .alignas = Payload.Fields.AlignAs.abiAlign(ptr_ty, target),
1008 };
1009 self.storage.anon.fields[1] = .{
1010 .name = "len",
1011 .type = Tag.uintptr_t.toIndex(),
1012 .alignas = Payload.Fields.AlignAs.abiAlign(Type.usize, target),
1013 };
1014 self.initAnon(kind, fwd_idx, 2);
1015 } else self.init(switch (kind) {
1016 .forward, .forward_parameter => .fwd_anon_struct,
1017 .complete, .parameter, .global => .anon_struct,
1018 .payload => unreachable,
1019 });
1020 } else self.init(.anon_struct);
1021 },
1022
1023 .One, .Many, .C => {
1024 const t: Tag = switch (info.@"volatile") {
1025 false => switch (info.mutable) {
1026 true => .pointer,
1027 false => .pointer_const,
1028 },
1029 true => switch (info.mutable) {
1030 true => .pointer_volatile,
1031 false => .pointer_const_volatile,
1032 },
1033 };
1034
1035 var host_int_pl = Type.Payload.Bits{
1036 .base = .{ .tag = .int_unsigned },
1037 .data = info.host_size * 8,
1038 };
1039 const pointee_ty = if (info.host_size > 0)
1040 Type.initPayload(&host_int_pl.base)
1041 else
1042 info.pointee_type;
1043
1044 if (if (info.size == .C and pointee_ty.tag() == .u8)
1045 Tag.char.toIndex()
1046 else
1047 try lookup.typeToIndex(pointee_ty, .forward)) |child_idx|
1048 {
1049 self.storage = .{ .child = .{
1050 .base = .{ .tag = t },
1051 .data = child_idx,
1052 } };
1053 self.value = .{ .cty = initPayload(&self.storage.child) };
1054 } else self.init(t);
1055 },
1056 }
1057 },
1058
1059 .Struct, .Union => |zig_tag| if (ty.containerLayout() == .Packed) {
1060 if (ty.castTag(.@"struct")) |struct_obj| {
1061 try self.initType(struct_obj.data.backing_int_ty, kind, lookup);
1062 } else {
1063 var buf: Type.Payload.Bits = .{
1064 .base = .{ .tag = .int_unsigned },
1065 .data = @intCast(u16, ty.bitSize(target)),
1066 };
1067 try self.initType(Type.initPayload(&buf.base), kind, lookup);
1068 }
1069 } else if (ty.isTupleOrAnonStruct()) {
1070 if (lookup.isMutable()) {
1071 for (0..ty.structFieldCount()) |field_i| {
1072 const field_ty = ty.structFieldType(field_i);
1073 if (ty.structFieldIsComptime(field_i) or
1074 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1075 _ = try lookup.typeToIndex(field_ty, switch (kind) {
1076 .forward, .forward_parameter => .forward,
1077 .complete, .parameter => .complete,
1078 .global => .global,
1079 .payload => unreachable,
1080 });
1081 }
1082 switch (kind) {
1083 .forward, .forward_parameter => {},
1084 .complete, .parameter, .global => _ = try lookup.typeToIndex(ty, .forward),
1085 .payload => unreachable,
1086 }
1087 }
1088 self.init(switch (kind) {
1089 .forward, .forward_parameter => .fwd_anon_struct,
1090 .complete, .parameter, .global => .anon_struct,
1091 .payload => unreachable,
1092 });
1093 } else {
1094 const tag_ty = ty.unionTagTypeSafety();
1095 const is_tagged_union_wrapper = kind != .payload and tag_ty != null;
1096 const is_struct = zig_tag == .Struct or is_tagged_union_wrapper;
1097 switch (kind) {
1098 .forward, .forward_parameter => {
1099 self.storage = .{ .fwd = .{
1100 .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union },
1101 .data = ty.getOwnerDecl(),
1102 } };
1103 self.value = .{ .cty = initPayload(&self.storage.fwd) };
1104 },
1105 .complete, .parameter, .global, .payload => if (is_tagged_union_wrapper) {
1106 const fwd_idx = try lookup.typeToIndex(ty, .forward);
1107 const payload_idx = try lookup.typeToIndex(ty, .payload);
1108 const tag_idx = try lookup.typeToIndex(tag_ty.?, kind);
1109 if (fwd_idx != null and payload_idx != null and tag_idx != null) {
1110 self.storage = .{ .anon = undefined };
1111 var field_count: usize = 0;
1112 if (payload_idx != Tag.void.toIndex()) {
1113 self.storage.anon.fields[field_count] = .{
1114 .name = "payload",
1115 .type = payload_idx.?,
1116 .alignas = Payload.Fields.AlignAs.unionPayloadAlign(ty, target),
1117 };
1118 field_count += 1;
1119 }
1120 if (tag_idx != Tag.void.toIndex()) {
1121 self.storage.anon.fields[field_count] = .{
1122 .name = "tag",
1123 .type = tag_idx.?,
1124 .alignas = Payload.Fields.AlignAs.abiAlign(tag_ty.?, target),
1125 };
1126 field_count += 1;
1127 }
1128 self.storage.anon.pl = .{ .complete = .{
1129 .base = .{ .tag = .@"struct" },
1130 .data = .{
1131 .fields = self.sortFields(field_count),
1132 .fwd_decl = fwd_idx.?,
1133 },
1134 } };
1135 self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) };
1136 } else self.init(.@"struct");
1137 } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes()) {
1138 self.init(.void);
1139 } else {
1140 var is_packed = false;
1141 for (0..switch (zig_tag) {
1142 .Struct => ty.structFieldCount(),
1143 .Union => ty.unionFields().count(),
1144 else => unreachable,
1145 }) |field_i| {
1146 const field_ty = ty.structFieldType(field_i);
1147 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1148
1149 const field_align = Payload.Fields.AlignAs.fieldAlign(
1150 ty,
1151 field_i,
1152 target,
1153 );
1154 if (field_align.@"align" < field_align.abi) {
1155 is_packed = true;
1156 if (!lookup.isMutable()) break;
1157 }
1158
1159 if (lookup.isMutable()) {
1160 _ = try lookup.typeToIndex(field_ty, switch (kind) {
1161 .forward, .forward_parameter => unreachable,
1162 .complete, .parameter, .payload => .complete,
1163 .global => .global,
1164 });
1165 }
1166 }
1167 switch (kind) {
1168 .forward, .forward_parameter => unreachable,
1169 .complete, .parameter, .global => {
1170 _ = try lookup.typeToIndex(ty, .forward);
1171 self.init(if (is_struct)
1172 if (is_packed) .packed_struct else .@"struct"
1173 else if (is_packed) .packed_union else .@"union");
1174 },
1175 .payload => self.init(if (is_packed)
1176 .packed_unnamed_union
1177 else
1178 .unnamed_union),
1179 }
1180 },
1181 }
1182 },
1183
1184 .Array, .Vector => |zig_tag| {
1185 switch (kind) {
1186 .forward, .complete, .global => {
1187 const t: Tag = switch (zig_tag) {
1188 .Array => .array,
1189 .Vector => .vector,
1190 else => unreachable,
1191 };
1192 if (try lookup.typeToIndex(ty.childType(), kind)) |child_idx| {
1193 self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{
1194 .len = ty.arrayLenIncludingSentinel(),
1195 .elem_type = child_idx,
1196 } } };
1197 self.value = .{ .cty = initPayload(&self.storage.seq) };
1198 } else self.init(t);
1199 },
1200 .forward_parameter, .parameter => try self.initArrayParameter(ty, kind, lookup),
1201 .payload => unreachable,
1202 }
1203 },
1204
1205 .Optional => {
1206 var buf: Type.Payload.ElemType = undefined;
1207 const payload_ty = ty.optionalChild(&buf);
1208 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {
1209 if (ty.optionalReprIsPayload()) {
1210 try self.initType(payload_ty, kind, lookup);
1211 } else if (switch (kind) {
1212 .forward, .forward_parameter => @as(Index, undefined),
1213 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
1214 .payload => unreachable,
1215 }) |fwd_idx| {
1216 if (try lookup.typeToIndex(payload_ty, switch (kind) {
1217 .forward, .forward_parameter => .forward,
1218 .complete, .parameter => .complete,
1219 .global => .global,
1220 .payload => unreachable,
1221 })) |payload_idx| {
1222 self.storage = .{ .anon = undefined };
1223 self.storage.anon.fields[0] = .{
1224 .name = "payload",
1225 .type = payload_idx,
1226 .alignas = Payload.Fields.AlignAs.abiAlign(payload_ty, target),
1227 };
1228 self.storage.anon.fields[1] = .{
1229 .name = "is_null",
1230 .type = Tag.bool.toIndex(),
1231 .alignas = Payload.Fields.AlignAs.abiAlign(Type.bool, target),
1232 };
1233 self.initAnon(kind, fwd_idx, 2);
1234 } else self.init(switch (kind) {
1235 .forward, .forward_parameter => .fwd_anon_struct,
1236 .complete, .parameter, .global => .anon_struct,
1237 .payload => unreachable,
1238 });
1239 } else self.init(.anon_struct);
1240 } else self.init(.bool);
1241 },
1242
1243 .ErrorUnion => {
1244 if (switch (kind) {
1245 .forward, .forward_parameter => @as(Index, undefined),
1246 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
1247 .payload => unreachable,
1248 }) |fwd_idx| {
1249 const payload_ty = ty.errorUnionPayload();
1250 if (try lookup.typeToIndex(payload_ty, switch (kind) {
1251 .forward, .forward_parameter => .forward,
1252 .complete, .parameter => .complete,
1253 .global => .global,
1254 .payload => unreachable,
1255 })) |payload_idx| {
1256 const error_ty = ty.errorUnionSet();
1257 if (payload_idx == Tag.void.toIndex()) {
1258 try self.initType(error_ty, kind, lookup);
1259 } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| {
1260 self.storage = .{ .anon = undefined };
1261 self.storage.anon.fields[0] = .{
1262 .name = "payload",
1263 .type = payload_idx,
1264 .alignas = Payload.Fields.AlignAs.abiAlign(payload_ty, target),
1265 };
1266 self.storage.anon.fields[1] = .{
1267 .name = "error",
1268 .type = error_idx,
1269 .alignas = Payload.Fields.AlignAs.abiAlign(error_ty, target),
1270 };
1271 self.initAnon(kind, fwd_idx, 2);
1272 } else self.init(switch (kind) {
1273 .forward, .forward_parameter => .fwd_anon_struct,
1274 .complete, .parameter, .global => .anon_struct,
1275 .payload => unreachable,
1276 });
1277 } else self.init(switch (kind) {
1278 .forward, .forward_parameter => .fwd_anon_struct,
1279 .complete, .parameter, .global => .anon_struct,
1280 .payload => unreachable,
1281 });
1282 } else self.init(.anon_struct);
1283 },
1284
1285 .Opaque => switch (ty.tag()) {
1286 .anyopaque => self.init(.void),
1287 .@"opaque" => {
1288 self.storage = .{ .fwd = .{
1289 .base = .{ .tag = .fwd_struct },
1290 .data = ty.getOwnerDecl(),
1291 } };
1292 self.value = .{ .cty = initPayload(&self.storage.fwd) };
1293 },
1294 else => unreachable,
1295 },
1296
1297 .Fn => {
1298 const info = ty.fnInfo();
1299 if (lookup.isMutable()) {
1300 const param_kind: Kind = switch (kind) {
1301 .forward, .forward_parameter => .forward_parameter,
1302 .complete, .parameter, .global => .parameter,
1303 .payload => unreachable,
1304 };
1305 _ = try lookup.typeToIndex(info.return_type, param_kind);
1306 for (info.param_types) |param_type| {
1307 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1308 _ = try lookup.typeToIndex(param_type, param_kind);
1309 }
1310 }
1311 self.init(if (info.is_var_args) .varargs_function else .function);
1312 },
1313 }
1314 }
1315 };
1316
1317 pub fn copy(self: CType, arena: Allocator) !CType {
1318 return self.copyContext(struct {
1319 arena: Allocator,
1320 pub fn copyIndex(_: @This(), idx: Index) Index {
1321 return idx;
1322 }
1323 }{ .arena = arena });
1324 }
1325
1326 fn copyFields(ctx: anytype, old_fields: Payload.Fields.Data) !Payload.Fields.Data {
1327 const new_fields = try ctx.arena.alloc(Payload.Fields.Field, old_fields.len);
1328 for (new_fields, old_fields) |*new_field, old_field| {
1329 new_field.name = try ctx.arena.dupeZ(u8, mem.span(old_field.name));
1330 new_field.type = ctx.copyIndex(old_field.type);
1331 new_field.alignas = old_field.alignas;
1332 }
1333 return new_fields;
1334 }
1335
1336 fn copyParams(ctx: anytype, old_param_types: []const Index) ![]const Index {
1337 const new_param_types = try ctx.arena.alloc(Index, old_param_types.len);
1338 for (new_param_types, old_param_types) |*new_param_type, old_param_type|
1339 new_param_type.* = ctx.copyIndex(old_param_type);
1340 return new_param_types;
1341 }
1342
1343 pub fn copyContext(self: CType, ctx: anytype) !CType {
1344 switch (self.tag()) {
1345 .void,
1346 .char,
1347 .@"signed char",
1348 .short,
1349 .int,
1350 .long,
1351 .@"long long",
1352 ._Bool,
1353 .@"unsigned char",
1354 .@"unsigned short",
1355 .@"unsigned int",
1356 .@"unsigned long",
1357 .@"unsigned long long",
1358 .float,
1359 .double,
1360 .@"long double",
1361 .bool,
1362 .size_t,
1363 .ptrdiff_t,
1364 .uint8_t,
1365 .int8_t,
1366 .uint16_t,
1367 .int16_t,
1368 .uint32_t,
1369 .int32_t,
1370 .uint64_t,
1371 .int64_t,
1372 .uintptr_t,
1373 .intptr_t,
1374 .zig_u128,
1375 .zig_i128,
1376 .zig_f16,
1377 .zig_f32,
1378 .zig_f64,
1379 .zig_f80,
1380 .zig_f128,
1381 .zig_c_longdouble,
1382 => return self,
1383
1384 .pointer,
1385 .pointer_const,
1386 .pointer_volatile,
1387 .pointer_const_volatile,
1388 => {
1389 const pl = self.cast(Payload.Child).?;
1390 const new_pl = try ctx.arena.create(Payload.Child);
1391 new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = ctx.copyIndex(pl.data) };
1392 return initPayload(new_pl);
1393 },
1394
1395 .array,
1396 .vector,
1397 => {
1398 const pl = self.cast(Payload.Sequence).?;
1399 const new_pl = try ctx.arena.create(Payload.Sequence);
1400 new_pl.* = .{
1401 .base = .{ .tag = pl.base.tag },
1402 .data = .{ .len = pl.data.len, .elem_type = ctx.copyIndex(pl.data.elem_type) },
1403 };
1404 return initPayload(new_pl);
1405 },
1406
1407 .fwd_anon_struct,
1408 .fwd_anon_union,
1409 => {
1410 const pl = self.cast(Payload.Fields).?;
1411 const new_pl = try ctx.arena.create(Payload.Fields);
1412 new_pl.* = .{
1413 .base = .{ .tag = pl.base.tag },
1414 .data = try copyFields(ctx, pl.data),
1415 };
1416 return initPayload(new_pl);
1417 },
1418
1419 .fwd_struct,
1420 .fwd_union,
1421 => {
1422 const pl = self.cast(Payload.FwdDecl).?;
1423 const new_pl = try ctx.arena.create(Payload.FwdDecl);
1424 new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = pl.data };
1425 return initPayload(new_pl);
1426 },
1427
1428 .unnamed_struct,
1429 .unnamed_union,
1430 .packed_unnamed_struct,
1431 .packed_unnamed_union,
1432 => {
1433 const pl = self.cast(Payload.Unnamed).?;
1434 const new_pl = try ctx.arena.create(Payload.Unnamed);
1435 new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{
1436 .fields = try copyFields(ctx, pl.data.fields),
1437 .owner_decl = pl.data.owner_decl,
1438 .id = pl.data.id,
1439 } };
1440 return initPayload(new_pl);
1441 },
1442
1443 .anon_struct,
1444 .anon_union,
1445 .@"struct",
1446 .@"union",
1447 .packed_struct,
1448 .packed_union,
1449 => {
1450 const pl = self.cast(Payload.Aggregate).?;
1451 const new_pl = try ctx.arena.create(Payload.Aggregate);
1452 new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{
1453 .fields = try copyFields(ctx, pl.data.fields),
1454 .fwd_decl = ctx.copyIndex(pl.data.fwd_decl),
1455 } };
1456 return initPayload(new_pl);
1457 },
1458
1459 .function,
1460 .varargs_function,
1461 => {
1462 const pl = self.cast(Payload.Function).?;
1463 const new_pl = try ctx.arena.create(Payload.Function);
1464 new_pl.* = .{ .base = .{ .tag = pl.base.tag }, .data = .{
1465 .return_type = ctx.copyIndex(pl.data.return_type),
1466 .param_types = try copyParams(ctx, pl.data.param_types),
1467 } };
1468 return initPayload(new_pl);
1469 },
1470 }
1471 }
1472
1473 fn createFromType(store: *Store.Promoted, ty: Type, target: Target, kind: Kind) !CType {
1474 var convert: Convert = undefined;
1475 try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .target = target } });
1476 return createFromConvert(store, ty, target, kind, &convert);
1477 }
1478
1479 fn createFromConvert(
1480 store: *Store.Promoted,
1481 ty: Type,
1482 target: Target,
1483 kind: Kind,
1484 convert: Convert,
1485 ) !CType {
1486 const arena = store.arena.allocator();
1487 switch (convert.value) {
1488 .cty => |c| return c.copy(arena),
1489 .tag => |t| switch (t) {
1490 .fwd_anon_struct,
1491 .fwd_anon_union,
1492 .unnamed_struct,
1493 .unnamed_union,
1494 .packed_unnamed_struct,
1495 .packed_unnamed_union,
1496 .anon_struct,
1497 .anon_union,
1498 .@"struct",
1499 .@"union",
1500 .packed_struct,
1501 .packed_union,
1502 => switch (ty.zigTypeTag()) {
1503 .Struct => {
1504 const fields_len = ty.structFieldCount();
1505
1506 var c_fields_len: usize = 0;
1507 for (0..fields_len) |field_i| {
1508 const field_ty = ty.structFieldType(field_i);
1509 if (ty.structFieldIsComptime(field_i) or
1510 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1511 c_fields_len += 1;
1512 }
1513
1514 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);
1515 var c_field_i: usize = 0;
1516 for (0..fields_len) |field_i| {
1517 const field_ty = ty.structFieldType(field_i);
1518 if (ty.structFieldIsComptime(field_i) or
1519 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1520
1521 fields_pl[c_field_i] = .{
1522 .name = try if (ty.isSimpleTuple())
1523 std.fmt.allocPrintZ(arena, "f{}", .{field_i})
1524 else
1525 arena.dupeZ(u8, ty.structFieldName(field_i)),
1526 .type = store.set.typeToIndex(field_ty, target, switch (kind) {
1527 .forward, .forward_parameter => .forward,
1528 .complete, .parameter => .complete,
1529 .global => .global,
1530 .payload => unreachable,
1531 }).?,
1532 .alignas = Payload.Fields.AlignAs.fieldAlign(ty, field_i, target),
1533 };
1534 c_field_i += 1;
1535 }
1536
1537 switch (t) {
1538 .fwd_anon_struct => {
1539 const anon_pl = try arena.create(Payload.Fields);
1540 anon_pl.* = .{ .base = .{ .tag = t }, .data = fields_pl };
1541 return initPayload(anon_pl);
1542 },
1543
1544 .anon_struct,
1545 .@"struct",
1546 .@"union",
1547 .packed_struct,
1548 .packed_union,
1549 => {
1550 const struct_pl = try arena.create(Payload.Aggregate);
1551 struct_pl.* = .{ .base = .{ .tag = t }, .data = .{
1552 .fields = fields_pl,
1553 .fwd_decl = store.set.typeToIndex(ty, target, .forward).?,
1554 } };
1555 return initPayload(struct_pl);
1556 },
1557
1558 else => unreachable,
1559 }
1560 },
1561
1562 .Union => {
1563 const union_fields = ty.unionFields();
1564 const fields_len = union_fields.count();
1565
1566 var c_fields_len: usize = 0;
1567 for (0..fields_len) |field_i| {
1568 const field_ty = ty.structFieldType(field_i);
1569 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1570 c_fields_len += 1;
1571 }
1572
1573 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);
1574 var field_i: usize = 0;
1575 var c_field_i: usize = 0;
1576 var field_it = union_fields.iterator();
1577 while (field_it.next()) |field| {
1578 defer field_i += 1;
1579 if (!field.value_ptr.ty.hasRuntimeBitsIgnoreComptime()) continue;
1580
1581 fields_pl[c_field_i] = .{
1582 .name = try arena.dupeZ(u8, field.key_ptr.*),
1583 .type = store.set.typeToIndex(field.value_ptr.ty, target, switch (kind) {
1584 .forward, .forward_parameter => unreachable,
1585 .complete, .parameter, .payload => .complete,
1586 .global => .global,
1587 }).?,
1588 .alignas = Payload.Fields.AlignAs.fieldAlign(ty, field_i, target),
1589 };
1590 c_field_i += 1;
1591 }
1592
1593 switch (kind) {
1594 .forward, .forward_parameter => unreachable,
1595 .complete, .parameter, .global => {
1596 const union_pl = try arena.create(Payload.Aggregate);
1597 union_pl.* = .{ .base = .{ .tag = t }, .data = .{
1598 .fields = fields_pl,
1599 .fwd_decl = store.set.typeToIndex(ty, target, .forward).?,
1600 } };
1601 return initPayload(union_pl);
1602 },
1603 .payload => if (ty.unionTagTypeSafety()) |_| {
1604 const union_pl = try arena.create(Payload.Unnamed);
1605 union_pl.* = .{ .base = .{ .tag = t }, .data = .{
1606 .fields = fields_pl,
1607 .owner_decl = ty.getOwnerDecl(),
1608 .id = 0,
1609 } };
1610 return initPayload(union_pl);
1611 } else unreachable,
1612 }
1613 },
1614
1615 else => unreachable,
1616 },
1617
1618 .function,
1619 .varargs_function,
1620 => {
1621 const info = ty.fnInfo();
1622 const param_kind: Kind = switch (kind) {
1623 .forward, .forward_parameter => .forward_parameter,
1624 .complete, .parameter, .global => .parameter,
1625 .payload => unreachable,
1626 };
1627
1628 var c_params_len: usize = 0;
1629 for (info.param_types) |param_type| {
1630 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1631 c_params_len += 1;
1632 }
1633
1634 const params_pl = try arena.alloc(Index, c_params_len);
1635 var c_param_i: usize = 0;
1636 for (info.param_types) |param_type| {
1637 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1638 params_pl[c_param_i] = store.set.typeToIndex(param_type, target, param_kind).?;
1639 c_param_i += 1;
1640 }
1641
1642 const fn_pl = try arena.create(Payload.Function);
1643 fn_pl.* = .{ .base = .{ .tag = t }, .data = .{
1644 .return_type = store.set.typeToIndex(info.return_type, target, param_kind).?,
1645 .param_types = params_pl,
1646 } };
1647 return initPayload(fn_pl);
1648 },
1649
1650 else => unreachable,
1651 },
1652 }
1653 }
1654
1655 pub const HashContext64 = struct {
1656 store: *const Store.Set,
1657
1658 pub fn hash(self: @This(), cty: CType) u64 {
1659 return cty.hash(self.store.*);
1660 }
1661 pub fn eql(_: @This(), lhs: CType, rhs: CType) bool {
1662 return lhs.eql(rhs);
1663 }
1664 };
1665
1666 pub const HashContext32 = struct {
1667 store: *const Store.Set,
1668
1669 pub fn hash(self: @This(), cty: CType) u32 {
1670 return @truncate(u32, cty.hash(self.store.*));
1671 }
1672 pub fn eql(_: @This(), lhs: CType, rhs: CType, _: usize) bool {
1673 return lhs.eql(rhs);
1674 }
1675 };
1676
1677 pub const TypeAdapter64 = struct {
1678 kind: Kind,
1679 lookup: Convert.Lookup,
1680 convert: *const Convert,
1681
1682 fn eqlRecurse(self: @This(), ty: Type, cty: Index, kind: Kind) bool {
1683 assert(!self.lookup.isMutable());
1684
1685 var convert: Convert = undefined;
1686 convert.initType(ty, kind, self.lookup) catch unreachable;
1687
1688 const self_recurse = @This(){ .kind = kind, .lookup = self.lookup, .convert = &convert };
1689 return self_recurse.eql(ty, self.lookup.indexToCType(cty).?);
1690 }
1691
1692 pub fn eql(self: @This(), ty: Type, cty: CType) bool {
1693 switch (self.convert.value) {
1694 .cty => |c| return c.eql(cty),
1695 .tag => |t| {
1696 if (t != cty.tag()) return false;
1697
1698 const target = self.lookup.getTarget();
1699 switch (t) {
1700 .fwd_anon_struct,
1701 .fwd_anon_union,
1702 => {
1703 if (!ty.isTupleOrAnonStruct()) return false;
1704
1705 var name_buf: [
1706 std.fmt.count("f{}", .{std.math.maxInt(usize)})
1707 ]u8 = undefined;
1708 const c_fields = cty.cast(Payload.Fields).?.data;
1709
1710 var c_field_i: usize = 0;
1711 for (0..ty.structFieldCount()) |field_i| {
1712 const field_ty = ty.structFieldType(field_i);
1713 if (ty.structFieldIsComptime(field_i) or
1714 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1715
1716 const c_field = &c_fields[c_field_i];
1717 c_field_i += 1;
1718
1719 if (!self.eqlRecurse(field_ty, c_field.type, switch (self.kind) {
1720 .forward, .forward_parameter => .forward,
1721 .complete, .parameter => .complete,
1722 .global => .global,
1723 .payload => unreachable,
1724 }) or !mem.eql(
1725 u8,
1726 if (ty.isSimpleTuple())
1727 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
1728 else
1729 ty.structFieldName(field_i),
1730 mem.span(c_field.name),
1731 ) or Payload.Fields.AlignAs.fieldAlign(ty, field_i, target).@"align" !=
1732 c_field.alignas.@"align") return false;
1733 }
1734 return true;
1735 },
1736
1737 .unnamed_struct,
1738 .unnamed_union,
1739 .packed_unnamed_struct,
1740 .packed_unnamed_union,
1741 => switch (self.kind) {
1742 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
1743 .payload => if (ty.unionTagTypeSafety()) |_| {
1744 const data = cty.cast(Payload.Unnamed).?.data;
1745 return ty.getOwnerDecl() == data.owner_decl and data.id == 0;
1746 } else unreachable,
1747 },
1748
1749 .anon_struct,
1750 .anon_union,
1751 .@"struct",
1752 .@"union",
1753 .packed_struct,
1754 .packed_union,
1755 => return self.eqlRecurse(
1756 ty,
1757 cty.cast(Payload.Aggregate).?.data.fwd_decl,
1758 .forward,
1759 ),
1760
1761 .function,
1762 .varargs_function,
1763 => {
1764 if (ty.zigTypeTag() != .Fn) return false;
1765
1766 const info = ty.fnInfo();
1767 const data = cty.cast(Payload.Function).?.data;
1768 const param_kind: Kind = switch (self.kind) {
1769 .forward, .forward_parameter => .forward_parameter,
1770 .complete, .parameter, .global => .parameter,
1771 .payload => unreachable,
1772 };
1773
1774 if (!self.eqlRecurse(info.return_type, data.return_type, param_kind))
1775 return false;
1776
1777 var c_param_i: usize = 0;
1778 for (info.param_types) |param_type| {
1779 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1780
1781 if (c_param_i >= data.param_types.len) return false;
1782 const param_cty = data.param_types[c_param_i];
1783 c_param_i += 1;
1784
1785 if (!self.eqlRecurse(param_type, param_cty, param_kind))
1786 return false;
1787 }
1788 return c_param_i == data.param_types.len;
1789 },
1790
1791 else => unreachable,
1792 }
1793 },
1794 }
1795 }
1796
1797 pub fn hash(self: @This(), ty: Type) u64 {
1798 var hasher = std.hash.Wyhash.init(0);
1799 self.updateHasher(&hasher, ty);
1800 return hasher.final();
1801 }
1802
1803 fn updateHasherRecurse(self: @This(), hasher: anytype, ty: Type, kind: Kind) void {
1804 assert(!self.lookup.isMutable());
1805
1806 var convert: Convert = undefined;
1807 convert.initType(ty, kind, self.lookup) catch unreachable;
1808
1809 const self_recurse = @This(){ .kind = kind, .lookup = self.lookup, .convert = &convert };
1810 self_recurse.updateHasher(hasher, ty);
1811 }
1812
1813 pub fn updateHasher(self: @This(), hasher: anytype, ty: Type) void {
1814 switch (self.convert.value) {
1815 .cty => |c| return c.updateHasher(hasher, self.lookup.getSet().?.*),
1816 .tag => |t| {
1817 autoHash(hasher, t);
1818
1819 const target = self.lookup.getTarget();
1820 switch (t) {
1821 .fwd_anon_struct,
1822 .fwd_anon_union,
1823 => {
1824 var name_buf: [
1825 std.fmt.count("f{}", .{std.math.maxInt(usize)})
1826 ]u8 = undefined;
1827 for (0..switch (ty.zigTypeTag()) {
1828 .Struct => ty.structFieldCount(),
1829 .Union => ty.unionFields().count(),
1830 else => unreachable,
1831 }) |field_i| {
1832 const field_ty = ty.structFieldType(field_i);
1833 if (ty.structFieldIsComptime(field_i) or
1834 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1835
1836 self.updateHasherRecurse(
1837 hasher,
1838 ty.structFieldType(field_i),
1839 switch (self.kind) {
1840 .forward, .forward_parameter => .forward,
1841 .complete, .parameter => .complete,
1842 .global => .global,
1843 .payload => unreachable,
1844 },
1845 );
1846 hasher.update(if (ty.isSimpleTuple())
1847 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
1848 else
1849 ty.structFieldName(field_i));
1850 autoHash(
1851 hasher,
1852 Payload.Fields.AlignAs.fieldAlign(ty, field_i, target).@"align",
1853 );
1854 }
1855 },
1856
1857 .unnamed_struct,
1858 .unnamed_union,
1859 .packed_unnamed_struct,
1860 .packed_unnamed_union,
1861 => switch (self.kind) {
1862 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
1863 .payload => if (ty.unionTagTypeSafety()) |_| {
1864 autoHash(hasher, ty.getOwnerDecl());
1865 autoHash(hasher, @as(u32, 0));
1866 } else unreachable,
1867 },
1868
1869 .anon_struct,
1870 .anon_union,
1871 .@"struct",
1872 .@"union",
1873 .packed_struct,
1874 .packed_union,
1875 => self.updateHasherRecurse(hasher, ty, .forward),
1876
1877 .function,
1878 .varargs_function,
1879 => {
1880 const info = ty.fnInfo();
1881 const param_kind: Kind = switch (self.kind) {
1882 .forward, .forward_parameter => .forward_parameter,
1883 .complete, .parameter, .global => .parameter,
1884 .payload => unreachable,
1885 };
1886
1887 self.updateHasherRecurse(hasher, info.return_type, param_kind);
1888 for (info.param_types) |param_type| {
1889 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1890 self.updateHasherRecurse(hasher, param_type, param_kind);
1891 }
1892 },
1893
1894 else => unreachable,
1895 }
1896 },
1897 }
1898 }
1899 };
1900
1901 pub const TypeAdapter32 = struct {
1902 kind: Kind,
1903 lookup: Convert.Lookup,
1904 convert: *const Convert,
1905
1906 fn to64(self: @This()) TypeAdapter64 {
1907 return .{ .kind = self.kind, .lookup = self.lookup, .convert = self.convert };
1908 }
1909
1910 pub fn eql(self: @This(), ty: Type, cty: CType, cty_index: usize) bool {
1911 _ = cty_index;
1912 return self.to64().eql(ty, cty);
1913 }
1914
1915 pub fn hash(self: @This(), ty: Type) u32 {
1916 return @truncate(u32, self.to64().hash(ty));
1917 }
1918 };
1919};
src/link/C.zig+250-128
......@@ -22,27 +22,22 @@ base: link.File,
2222/// Instead, it tracks all declarations in this table, and iterates over it
2323/// in the flush function, stitching pre-rendered pieces of C code together.
2424decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{},
25/// Stores Type/Value data for `typedefs` to reference.
26/// Accumulates allocations and then there is a periodic garbage collection after flush().
27arena: std.heap.ArenaAllocator,
2825
2926/// Per-declaration data.
3027const DeclBlock = struct {
3128 code: std.ArrayListUnmanaged(u8) = .{},
3229 fwd_decl: std.ArrayListUnmanaged(u8) = .{},
33 /// Each Decl stores a mapping of Zig Types to corresponding C types, for every
34 /// Zig Type used by the Decl. In flush(), we iterate over each Decl
35 /// and emit the typedef code for all types, making sure to not emit the same thing twice.
36 /// Any arena memory the Type points to lives in the `arena` field of `C`.
37 typedefs: codegen.TypedefMap.Unmanaged = .{},
30 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate
31 /// over each `Decl` and generate the definition for each used `CType` once.
32 ctypes: codegen.CType.Store = .{},
33 /// Key and Value storage use the ctype arena.
34 lazy_fns: codegen.LazyFnMap = .{},
3835
3936 fn deinit(db: *DeclBlock, gpa: Allocator) void {
40 db.code.deinit(gpa);
37 db.lazy_fns.deinit(gpa);
38 db.ctypes.deinit(gpa);
4139 db.fwd_decl.deinit(gpa);
42 for (db.typedefs.values()) |typedef| {
43 gpa.free(typedef.rendered);
44 }
45 db.typedefs.deinit(gpa);
40 db.code.deinit(gpa);
4641 db.* = undefined;
4742 }
4843};
......@@ -64,7 +59,6 @@ pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C
6459 errdefer gpa.destroy(c_file);
6560
6661 c_file.* = C{
67 .arena = std.heap.ArenaAllocator.init(gpa),
6862 .base = .{
6963 .tag = .c,
7064 .options = options,
......@@ -83,8 +77,6 @@ pub fn deinit(self: *C) void {
8377 db.deinit(gpa);
8478 }
8579 self.decl_table.deinit(gpa);
86
87 self.arena.deinit();
8880}
8981
9082pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
......@@ -99,124 +91,122 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
9991 const tracy = trace(@src());
10092 defer tracy.end();
10193
94 const gpa = self.base.allocator;
95
10296 const decl_index = func.owner_decl;
103 const gop = try self.decl_table.getOrPut(self.base.allocator, decl_index);
97 const gop = try self.decl_table.getOrPut(gpa, decl_index);
10498 if (!gop.found_existing) {
10599 gop.value_ptr.* = .{};
106100 }
101 const ctypes = &gop.value_ptr.ctypes;
102 const lazy_fns = &gop.value_ptr.lazy_fns;
107103 const fwd_decl = &gop.value_ptr.fwd_decl;
108 const typedefs = &gop.value_ptr.typedefs;
109104 const code = &gop.value_ptr.code;
105 ctypes.clearRetainingCapacity(gpa);
106 lazy_fns.clearRetainingCapacity();
110107 fwd_decl.shrinkRetainingCapacity(0);
111 for (typedefs.values()) |typedef| {
112 module.gpa.free(typedef.rendered);
113 }
114 typedefs.clearRetainingCapacity();
115108 code.shrinkRetainingCapacity(0);
116109
117110 var function: codegen.Function = .{
118 .value_map = codegen.CValueMap.init(module.gpa),
111 .value_map = codegen.CValueMap.init(gpa),
119112 .air = air,
120113 .liveness = liveness,
121114 .func = func,
122115 .object = .{
123116 .dg = .{
124 .gpa = module.gpa,
117 .gpa = gpa,
125118 .module = module,
126119 .error_msg = null,
127 .decl_index = decl_index,
120 .decl_index = decl_index.toOptional(),
128121 .decl = module.declPtr(decl_index),
129 .fwd_decl = fwd_decl.toManaged(module.gpa),
130 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),
131 .typedefs_arena = self.arena.allocator(),
122 .fwd_decl = fwd_decl.toManaged(gpa),
123 .ctypes = ctypes.*,
132124 },
133 .code = code.toManaged(module.gpa),
125 .code = code.toManaged(gpa),
134126 .indent_writer = undefined, // set later so we can get a pointer to object.code
135127 },
136 .arena = std.heap.ArenaAllocator.init(module.gpa),
128 .lazy_fns = lazy_fns.*,
129 .arena = std.heap.ArenaAllocator.init(gpa),
137130 };
138131
139132 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
140 defer function.deinit(module.gpa);
133 defer function.deinit();
141134
142135 codegen.genFunc(&function) catch |err| switch (err) {
143136 error.AnalysisFail => {
144 try module.failed_decls.put(module.gpa, decl_index, function.object.dg.error_msg.?);
137 try module.failed_decls.put(gpa, decl_index, function.object.dg.error_msg.?);
145138 return;
146139 },
147140 else => |e| return e,
148141 };
149142
143 ctypes.* = function.object.dg.ctypes.move();
144 lazy_fns.* = function.lazy_fns.move();
150145 fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();
151 typedefs.* = function.object.dg.typedefs.unmanaged;
152 function.object.dg.typedefs.unmanaged = .{};
153146 code.* = function.object.code.moveToUnmanaged();
154147
155148 // Free excess allocated memory for this Decl.
156 fwd_decl.shrinkAndFree(module.gpa, fwd_decl.items.len);
157 code.shrinkAndFree(module.gpa, code.items.len);
149 ctypes.shrinkAndFree(gpa, ctypes.count());
150 lazy_fns.shrinkAndFree(gpa, lazy_fns.count());
151 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);
152 code.shrinkAndFree(gpa, code.items.len);
158153}
159154
160155pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {
161156 const tracy = trace(@src());
162157 defer tracy.end();
163158
164 const gop = try self.decl_table.getOrPut(self.base.allocator, decl_index);
159 const gpa = self.base.allocator;
160
161 const gop = try self.decl_table.getOrPut(gpa, decl_index);
165162 if (!gop.found_existing) {
166163 gop.value_ptr.* = .{};
167164 }
165 const ctypes = &gop.value_ptr.ctypes;
168166 const fwd_decl = &gop.value_ptr.fwd_decl;
169 const typedefs = &gop.value_ptr.typedefs;
170167 const code = &gop.value_ptr.code;
168 ctypes.clearRetainingCapacity(gpa);
171169 fwd_decl.shrinkRetainingCapacity(0);
172 for (typedefs.values()) |value| {
173 module.gpa.free(value.rendered);
174 }
175 typedefs.clearRetainingCapacity();
176170 code.shrinkRetainingCapacity(0);
177171
178172 const decl = module.declPtr(decl_index);
179173
180174 var object: codegen.Object = .{
181175 .dg = .{
182 .gpa = module.gpa,
176 .gpa = gpa,
183177 .module = module,
184178 .error_msg = null,
185 .decl_index = decl_index,
179 .decl_index = decl_index.toOptional(),
186180 .decl = decl,
187 .fwd_decl = fwd_decl.toManaged(module.gpa),
188 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),
189 .typedefs_arena = self.arena.allocator(),
181 .fwd_decl = fwd_decl.toManaged(gpa),
182 .ctypes = ctypes.*,
190183 },
191 .code = code.toManaged(module.gpa),
184 .code = code.toManaged(gpa),
192185 .indent_writer = undefined, // set later so we can get a pointer to object.code
193186 };
194187 object.indent_writer = .{ .underlying_writer = object.code.writer() };
195188 defer {
196189 object.code.deinit();
197 for (object.dg.typedefs.values()) |typedef| {
198 module.gpa.free(typedef.rendered);
199 }
200 object.dg.typedefs.deinit();
190 object.dg.ctypes.deinit(object.dg.gpa);
201191 object.dg.fwd_decl.deinit();
202192 }
203193
204194 codegen.genDecl(&object) catch |err| switch (err) {
205195 error.AnalysisFail => {
206 try module.failed_decls.put(module.gpa, decl_index, object.dg.error_msg.?);
196 try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?);
207197 return;
208198 },
209199 else => |e| return e,
210200 };
211201
202 ctypes.* = object.dg.ctypes.move();
212203 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
213 typedefs.* = object.dg.typedefs.unmanaged;
214 object.dg.typedefs.unmanaged = .{};
215204 code.* = object.code.moveToUnmanaged();
216205
217206 // Free excess allocated memory for this Decl.
218 fwd_decl.shrinkAndFree(module.gpa, fwd_decl.items.len);
219 code.shrinkAndFree(module.gpa, code.items.len);
207 ctypes.shrinkAndFree(gpa, ctypes.count());
208 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);
209 code.shrinkAndFree(gpa, code.items.len);
220210}
221211
222212pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {
......@@ -246,7 +236,7 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
246236 sub_prog_node.activate();
247237 defer sub_prog_node.end();
248238
249 const gpa = comp.gpa;
239 const gpa = self.base.allocator;
250240 const module = self.base.options.module.?;
251241
252242 // This code path happens exclusively with -ofmt=c. The flush logic for
......@@ -257,30 +247,28 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
257247
258248 const abi_define = abiDefine(comp);
259249
260 // Covers defines, zig.h, typedef, and asm.
261 var buf_count: usize = 2;
262 if (abi_define != null) buf_count += 1;
263 try f.all_buffers.ensureUnusedCapacity(gpa, buf_count);
250 // Covers defines, zig.h, ctypes, asm, lazy fwd, lazy code.
251 try f.all_buffers.ensureUnusedCapacity(gpa, 6);
264252
265253 if (abi_define) |buf| f.appendBufAssumeCapacity(buf);
266254 f.appendBufAssumeCapacity(zig_h);
267255
268 const typedef_index = f.all_buffers.items.len;
256 const ctypes_index = f.all_buffers.items.len;
269257 f.all_buffers.items.len += 1;
270258
271259 {
272 var asm_buf = f.asm_buf.toManaged(module.gpa);
273 defer asm_buf.deinit();
274
275 try codegen.genGlobalAsm(module, &asm_buf);
276
277 f.asm_buf = asm_buf.moveToUnmanaged();
278 f.appendBufAssumeCapacity(f.asm_buf.items);
260 var asm_buf = f.asm_buf.toManaged(gpa);
261 defer f.asm_buf = asm_buf.moveToUnmanaged();
262 try codegen.genGlobalAsm(module, asm_buf.writer());
263 f.appendBufAssumeCapacity(asm_buf.items);
279264 }
280265
281 try self.flushErrDecls(&f);
266 const lazy_indices = f.all_buffers.items.len;
267 f.all_buffers.items.len += 2;
282268
283 // Typedefs, forward decls, and non-functions first.
269 try self.flushErrDecls(&f.lazy_db);
270
271 // `CType`s, forward decls, and non-functions first.
284272 // Unlike other backends, the .c code we are emitting is order-dependent. Therefore
285273 // we must traverse the set of Decls that we are emitting according to their dependencies.
286274 // Our strategy is to populate a set of remaining decls, pop Decls one by one,
......@@ -307,11 +295,35 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
307295 }
308296 }
309297
310 f.all_buffers.items[typedef_index] = .{
311 .iov_base = if (f.typedef_buf.items.len > 0) f.typedef_buf.items.ptr else "",
312 .iov_len = f.typedef_buf.items.len,
298 {
299 // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.
300 assert(f.ctypes.count() == 0);
301 try self.flushCTypes(&f, .none, f.lazy_db.ctypes);
302
303 var it = self.decl_table.iterator();
304 while (it.next()) |entry|
305 try self.flushCTypes(&f, entry.key_ptr.toOptional(), entry.value_ptr.ctypes);
306 }
307
308 {
309 f.all_buffers.items[lazy_indices + 0] = .{
310 .iov_base = if (f.lazy_db.fwd_decl.items.len > 0) f.lazy_db.fwd_decl.items.ptr else "",
311 .iov_len = f.lazy_db.fwd_decl.items.len,
312 };
313 f.file_size += f.lazy_db.fwd_decl.items.len;
314
315 f.all_buffers.items[lazy_indices + 1] = .{
316 .iov_base = if (f.lazy_db.code.items.len > 0) f.lazy_db.code.items.ptr else "",
317 .iov_len = f.lazy_db.code.items.len,
318 };
319 f.file_size += f.lazy_db.code.items.len;
320 }
321
322 f.all_buffers.items[ctypes_index] = .{
323 .iov_base = if (f.ctypes_buf.items.len > 0) f.ctypes_buf.items.ptr else "",
324 .iov_len = f.ctypes_buf.items.len,
313325 };
314 f.file_size += f.typedef_buf.items.len;
326 f.file_size += f.ctypes_buf.items.len;
315327
316328 // Now the code.
317329 try f.all_buffers.ensureUnusedCapacity(gpa, decl_values.len);
......@@ -324,22 +336,23 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
324336}
325337
326338const Flush = struct {
327 err_decls: DeclBlock = .{},
328339 remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{},
329 typedefs: Typedefs = .{},
330 typedef_buf: std.ArrayListUnmanaged(u8) = .{},
340
341 ctypes: codegen.CType.Store = .{},
342 ctypes_map: std.ArrayListUnmanaged(codegen.CType.Index) = .{},
343 ctypes_buf: std.ArrayListUnmanaged(u8) = .{},
344
345 lazy_db: DeclBlock = .{},
346 lazy_fns: LazyFns = .{},
347
331348 asm_buf: std.ArrayListUnmanaged(u8) = .{},
349
332350 /// We collect a list of buffers to write, and write them all at once with pwritev 😎
333351 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
334352 /// Keeps track of the total bytes of `all_buffers`.
335353 file_size: u64 = 0,
336354
337 const Typedefs = std.HashMapUnmanaged(
338 Type,
339 void,
340 Type.HashContext64,
341 std.hash_map.default_max_load_percentage,
342 );
355 const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void);
343356
344357 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {
345358 if (buf.len == 0) return;
......@@ -349,10 +362,13 @@ const Flush = struct {
349362
350363 fn deinit(f: *Flush, gpa: Allocator) void {
351364 f.all_buffers.deinit(gpa);
352 f.typedef_buf.deinit(gpa);
353 f.typedefs.deinit(gpa);
365 f.asm_buf.deinit(gpa);
366 f.lazy_fns.deinit(gpa);
367 f.lazy_db.deinit(gpa);
368 f.ctypes_buf.deinit(gpa);
369 f.ctypes_map.deinit(gpa);
370 f.ctypes.deinit(gpa);
354371 f.remaining_decls.deinit(gpa);
355 f.err_decls.deinit(gpa);
356372 }
357373};
358374
......@@ -360,53 +376,116 @@ const FlushDeclError = error{
360376 OutOfMemory,
361377};
362378
363fn flushTypedefs(self: *C, f: *Flush, typedefs: codegen.TypedefMap.Unmanaged) FlushDeclError!void {
364 if (typedefs.count() == 0) return;
379fn flushCTypes(
380 self: *C,
381 f: *Flush,
382 decl_index: Module.Decl.OptionalIndex,
383 decl_ctypes: codegen.CType.Store,
384) FlushDeclError!void {
365385 const gpa = self.base.allocator;
366 const module = self.base.options.module.?;
367
368 try f.typedefs.ensureUnusedCapacityContext(gpa, @intCast(u32, typedefs.count()), .{
369 .mod = module,
370 });
371 var it = typedefs.iterator();
372 while (it.next()) |new| {
373 const gop = f.typedefs.getOrPutAssumeCapacityContext(new.key_ptr.*, .{
374 .mod = module,
386 const mod = self.base.options.module.?;
387
388 const decl_ctypes_len = decl_ctypes.count();
389 f.ctypes_map.clearRetainingCapacity();
390 try f.ctypes_map.ensureTotalCapacity(gpa, decl_ctypes_len);
391
392 var global_ctypes = f.ctypes.promote(gpa);
393 defer f.ctypes.demote(global_ctypes);
394
395 var ctypes_buf = f.ctypes_buf.toManaged(gpa);
396 defer f.ctypes_buf = ctypes_buf.moveToUnmanaged();
397 const writer = ctypes_buf.writer();
398
399 const slice = decl_ctypes.set.map.entries.slice();
400 for (slice.items(.key), 0..) |decl_cty, decl_i| {
401 const Context = struct {
402 arena: Allocator,
403 ctypes_map: []codegen.CType.Index,
404 cached_hash: codegen.CType.Store.Set.Map.Hash,
405 idx: codegen.CType.Index,
406
407 pub fn hash(ctx: @This(), _: codegen.CType) codegen.CType.Store.Set.Map.Hash {
408 return ctx.cached_hash;
409 }
410 pub fn eql(ctx: @This(), lhs: codegen.CType, rhs: codegen.CType, _: usize) bool {
411 return lhs.eqlContext(rhs, ctx);
412 }
413 pub fn eqlIndex(
414 ctx: @This(),
415 lhs_idx: codegen.CType.Index,
416 rhs_idx: codegen.CType.Index,
417 ) bool {
418 if (lhs_idx < codegen.CType.Tag.no_payload_count or
419 rhs_idx < codegen.CType.Tag.no_payload_count) return lhs_idx == rhs_idx;
420 const lhs_i = lhs_idx - codegen.CType.Tag.no_payload_count;
421 if (lhs_i >= ctx.ctypes_map.len) return false;
422 return ctx.ctypes_map[lhs_i] == rhs_idx;
423 }
424 pub fn copyIndex(ctx: @This(), idx: codegen.CType.Index) codegen.CType.Index {
425 if (idx < codegen.CType.Tag.no_payload_count) return idx;
426 return ctx.ctypes_map[idx - codegen.CType.Tag.no_payload_count];
427 }
428 };
429 const decl_idx = @intCast(codegen.CType.Index, codegen.CType.Tag.no_payload_count + decl_i);
430 const ctx = Context{
431 .arena = global_ctypes.arena.allocator(),
432 .ctypes_map = f.ctypes_map.items,
433 .cached_hash = decl_ctypes.indexToHash(decl_idx),
434 .idx = decl_idx,
435 };
436 const gop = try global_ctypes.set.map.getOrPutContextAdapted(gpa, decl_cty, ctx, .{
437 .store = &global_ctypes.set,
375438 });
439 const global_idx =
440 @intCast(codegen.CType.Index, codegen.CType.Tag.no_payload_count + gop.index);
441 f.ctypes_map.appendAssumeCapacity(global_idx);
376442 if (!gop.found_existing) {
377 try f.typedef_buf.appendSlice(gpa, new.value_ptr.rendered);
443 errdefer _ = global_ctypes.set.map.pop();
444 gop.key_ptr.* = try decl_cty.copyContext(ctx);
445 }
446 if (std.debug.runtime_safety) {
447 const global_cty = &global_ctypes.set.map.entries.items(.key)[gop.index];
448 assert(global_cty == gop.key_ptr);
449 assert(decl_cty.eqlContext(global_cty.*, ctx));
450 assert(decl_cty.hash(decl_ctypes.set) == global_cty.hash(global_ctypes.set));
378451 }
452 try codegen.genTypeDecl(
453 mod,
454 writer,
455 global_ctypes.set,
456 global_idx,
457 decl_index,
458 decl_ctypes.set,
459 decl_idx,
460 gop.found_existing,
461 );
379462 }
380463}
381464
382fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
383 const module = self.base.options.module.?;
465fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void {
466 const gpa = self.base.allocator;
384467
385 const fwd_decl = &f.err_decls.fwd_decl;
386 const typedefs = &f.err_decls.typedefs;
387 const code = &f.err_decls.code;
468 const fwd_decl = &db.fwd_decl;
469 const ctypes = &db.ctypes;
470 const code = &db.code;
388471
389472 var object = codegen.Object{
390473 .dg = .{
391 .gpa = module.gpa,
392 .module = module,
474 .gpa = gpa,
475 .module = self.base.options.module.?,
393476 .error_msg = null,
394 .decl_index = undefined,
395 .decl = undefined,
396 .fwd_decl = fwd_decl.toManaged(module.gpa),
397 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),
398 .typedefs_arena = self.arena.allocator(),
477 .decl_index = .none,
478 .decl = null,
479 .fwd_decl = fwd_decl.toManaged(gpa),
480 .ctypes = ctypes.*,
399481 },
400 .code = code.toManaged(module.gpa),
482 .code = code.toManaged(gpa),
401483 .indent_writer = undefined, // set later so we can get a pointer to object.code
402484 };
403485 object.indent_writer = .{ .underlying_writer = object.code.writer() };
404486 defer {
405487 object.code.deinit();
406 for (object.dg.typedefs.values()) |typedef| {
407 module.gpa.free(typedef.rendered);
408 }
409 object.dg.typedefs.deinit();
488 object.dg.ctypes.deinit(gpa);
410489 object.dg.fwd_decl.deinit();
411490 }
412491
......@@ -416,14 +495,58 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
416495 };
417496
418497 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
419 typedefs.* = object.dg.typedefs.unmanaged;
420 object.dg.typedefs.unmanaged = .{};
498 ctypes.* = object.dg.ctypes.move();
499 code.* = object.code.moveToUnmanaged();
500}
501
502fn flushLazyFn(self: *C, db: *DeclBlock, lazy_fn: codegen.LazyFnMap.Entry) FlushDeclError!void {
503 const gpa = self.base.allocator;
504
505 const fwd_decl = &db.fwd_decl;
506 const ctypes = &db.ctypes;
507 const code = &db.code;
508
509 var object = codegen.Object{
510 .dg = .{
511 .gpa = gpa,
512 .module = self.base.options.module.?,
513 .error_msg = null,
514 .decl_index = .none,
515 .decl = null,
516 .fwd_decl = fwd_decl.toManaged(gpa),
517 .ctypes = ctypes.*,
518 },
519 .code = code.toManaged(gpa),
520 .indent_writer = undefined, // set later so we can get a pointer to object.code
521 };
522 object.indent_writer = .{ .underlying_writer = object.code.writer() };
523 defer {
524 object.code.deinit();
525 object.dg.ctypes.deinit(gpa);
526 object.dg.fwd_decl.deinit();
527 }
528
529 codegen.genLazyFn(&object, lazy_fn) catch |err| switch (err) {
530 error.AnalysisFail => unreachable,
531 else => |e| return e,
532 };
533
534 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
535 ctypes.* = object.dg.ctypes.move();
421536 code.* = object.code.moveToUnmanaged();
537}
422538
423 try self.flushTypedefs(f, typedefs.*);
424 try f.all_buffers.ensureUnusedCapacity(self.base.allocator, 1);
425 f.appendBufAssumeCapacity(fwd_decl.items);
426 f.appendBufAssumeCapacity(code.items);
539fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void {
540 const gpa = self.base.allocator;
541 try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(Flush.LazyFns.Size, lazy_fns.count()));
542
543 var it = lazy_fns.iterator();
544 while (it.next()) |entry| {
545 const gop = f.lazy_fns.getOrPutAssumeCapacity(entry.key_ptr.*);
546 if (gop.found_existing) continue;
547 gop.value_ptr.* = {};
548 try self.flushLazyFn(&f.lazy_db, entry);
549 }
427550}
428551
429552/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
......@@ -433,8 +556,8 @@ fn flushDecl(
433556 decl_index: Module.Decl.Index,
434557 export_names: std.StringHashMapUnmanaged(void),
435558) FlushDeclError!void {
436 const module = self.base.options.module.?;
437 const decl = module.declPtr(decl_index);
559 const gpa = self.base.allocator;
560 const decl = self.base.options.module.?.declPtr(decl_index);
438561 // Before flushing any particular Decl we must ensure its
439562 // dependencies are already flushed, so that the order in the .c
440563 // file comes out correctly.
......@@ -445,10 +568,9 @@ fn flushDecl(
445568 }
446569
447570 const decl_block = self.decl_table.getPtr(decl_index).?;
448 const gpa = self.base.allocator;
449571
450 try self.flushTypedefs(f, decl_block.typedefs);
451 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
572 try self.flushLazyFns(f, decl_block.lazy_fns);
573 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
452574 if (!(decl.isExtern() and export_names.contains(mem.span(decl.name))))
453575 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
454576}
stage1/zig.h created+2486
......@@ -0,0 +1,2486 @@
1#undef linux
2
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 _MSC_VER
10#include <intrin.h>
11#elif defined(__i386__) || defined(__x86_64__)
12#include <cpuid.h>
13#endif
14
15#if !defined(__cplusplus) && __STDC_VERSION__ <= 201710L
16#if __STDC_VERSION__ >= 199901L
17#include <stdbool.h>
18#else
19typedef char bool;
20#define false 0
21#define true 1
22#endif
23#endif
24
25#if defined(__has_builtin)
26#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)
27#else
28#define zig_has_builtin(builtin) 0
29#endif
30
31#if defined(__has_attribute)
32#define zig_has_attribute(attribute) __has_attribute(attribute)
33#else
34#define zig_has_attribute(attribute) 0
35#endif
36
37#if __STDC_VERSION__ >= 201112L
38#define zig_threadlocal _Thread_local
39#elif defined(__GNUC__)
40#define zig_threadlocal __thread
41#elif _MSC_VER
42#define zig_threadlocal __declspec(thread)
43#else
44#define zig_threadlocal zig_threadlocal_unavailable
45#endif
46
47#if defined(__clang__)
48#define zig_clang
49#elif defined(__GNUC__)
50#define zig_gnuc
51#endif
52
53#if _MSC_VER
54#define zig_const_arr
55#define zig_callconv(c) __##c
56#else
57#define zig_const_arr static const
58#define zig_callconv(c) __attribute__((c))
59#endif
60
61#if zig_has_attribute(naked) || defined(zig_gnuc)
62#define zig_naked_decl __attribute__((naked))
63#define zig_naked __attribute__((naked))
64#elif defined(_MSC_VER)
65#define zig_naked_decl
66#define zig_naked __declspec(naked)
67#else
68#define zig_naked_decl zig_naked_unavailable
69#define zig_naked zig_naked_unavailable
70#endif
71
72#if zig_has_attribute(cold)
73#define zig_cold __attribute__((cold))
74#else
75#define zig_cold
76#endif
77
78#if __STDC_VERSION__ >= 199901L
79#define zig_restrict restrict
80#elif defined(__GNUC__)
81#define zig_restrict __restrict
82#else
83#define zig_restrict
84#endif
85
86#if __STDC_VERSION__ >= 201112L
87#define zig_align(alignment) _Alignas(alignment)
88#elif zig_has_attribute(aligned)
89#define zig_align(alignment) __attribute__((aligned(alignment)))
90#elif _MSC_VER
91#define zig_align(alignment) __declspec(align(alignment))
92#else
93#define zig_align zig_align_unavailable
94#endif
95
96#if zig_has_attribute(aligned)
97#define zig_under_align(alignment) __attribute__((aligned(alignment)))
98#elif _MSC_VER
99#define zig_under_align(alignment) zig_align(alignment)
100#else
101#define zig_align zig_align_unavailable
102#endif
103
104#if zig_has_attribute(aligned)
105#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
106#elif _MSC_VER
107#define zig_align_fn(alignment)
108#else
109#define zig_align_fn zig_align_fn_unavailable
110#endif
111
112#if zig_has_attribute(packed)
113#define zig_packed(definition) __attribute__((packed)) definition
114#elif _MSC_VER
115#define zig_packed(definition) __pragma(pack(1)) definition __pragma(pack())
116#else
117#define zig_packed(definition) zig_packed_unavailable
118#endif
119
120#if zig_has_attribute(section)
121#define zig_linksection(name, def, ...) def __attribute__((section(name)))
122#elif _MSC_VER
123#define zig_linksection(name, def, ...) __pragma(section(name, __VA_ARGS__)) __declspec(allocate(name)) def
124#else
125#define zig_linksection(name, def, ...) zig_linksection_unavailable
126#endif
127
128#if zig_has_builtin(unreachable) || defined(zig_gnuc)
129#define zig_unreachable() __builtin_unreachable()
130#else
131#define zig_unreachable()
132#endif
133
134#if defined(__cplusplus)
135#define zig_extern extern "C"
136#else
137#define zig_extern extern
138#endif
139
140#if zig_has_attribute(alias)
141#define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(symbol)))
142#elif _MSC_VER
143#if _M_X64
144#define zig_export(sig, symbol, name) sig;\
145 __pragma(comment(linker, "/alternatename:" name "=" symbol ))
146#else /*_M_X64 */
147#define zig_export(sig, symbol, name) sig;\
148 __pragma(comment(linker, "/alternatename:_" name "=_" symbol ))
149#endif /*_M_X64 */
150#else
151#define zig_export(sig, symbol, name) __asm(name " = " symbol)
152#endif
153
154#if zig_has_builtin(debugtrap)
155#define zig_breakpoint() __builtin_debugtrap()
156#elif zig_has_builtin(trap) || defined(zig_gnuc)
157#define zig_breakpoint() __builtin_trap()
158#elif defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)
159#define zig_breakpoint() __debugbreak()
160#elif defined(__i386__) || defined(__x86_64__)
161#define zig_breakpoint() __asm__ volatile("int $0x03");
162#else
163#define zig_breakpoint() raise(SIGTRAP)
164#endif
165
166#if zig_has_builtin(return_address) || defined(zig_gnuc)
167#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))
168#elif defined(_MSC_VER)
169#define zig_return_address() _ReturnAddress()
170#else
171#define zig_return_address() 0
172#endif
173
174#if zig_has_builtin(frame_address) || defined(zig_gnuc)
175#define zig_frame_address() __builtin_frame_address(0)
176#else
177#define zig_frame_address() 0
178#endif
179
180#if zig_has_builtin(prefetch) || defined(zig_gnuc)
181#define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
182#else
183#define zig_prefetch(addr, rw, locality)
184#endif
185
186#if zig_has_builtin(memory_size) && zig_has_builtin(memory_grow)
187#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)
188#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)
189#else
190#define zig_wasm_memory_size(index) zig_unimplemented()
191#define zig_wasm_memory_grow(index, delta) zig_unimplemented()
192#endif
193
194#define zig_concat(lhs, rhs) lhs##rhs
195#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
196
197#if __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
198#include <stdatomic.h>
199#define zig_atomic(type) _Atomic(type)
200#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
201#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
202#define zig_atomicrmw_xchg(obj, arg, order, type) atomic_exchange_explicit (obj, arg, order)
203#define zig_atomicrmw_add(obj, arg, order, type) atomic_fetch_add_explicit (obj, arg, order)
204#define zig_atomicrmw_sub(obj, arg, order, type) atomic_fetch_sub_explicit (obj, arg, order)
205#define zig_atomicrmw_or(obj, arg, order, type) atomic_fetch_or_explicit (obj, arg, order)
206#define zig_atomicrmw_xor(obj, arg, order, type) atomic_fetch_xor_explicit (obj, arg, order)
207#define zig_atomicrmw_and(obj, arg, order, type) atomic_fetch_and_explicit (obj, arg, order)
208#define zig_atomicrmw_nand(obj, arg, order, type) __atomic_fetch_nand (obj, arg, order)
209#define zig_atomicrmw_min(obj, arg, order, type) __atomic_fetch_min (obj, arg, order)
210#define zig_atomicrmw_max(obj, arg, order, type) __atomic_fetch_max (obj, arg, order)
211#define zig_atomic_store(obj, arg, order, type) atomic_store_explicit (obj, arg, order)
212#define zig_atomic_load(obj, order, type) atomic_load_explicit (obj, order)
213#define zig_fence(order) atomic_thread_fence(order)
214#elif defined(__GNUC__)
215#define memory_order_relaxed __ATOMIC_RELAXED
216#define memory_order_consume __ATOMIC_CONSUME
217#define memory_order_acquire __ATOMIC_ACQUIRE
218#define memory_order_release __ATOMIC_RELEASE
219#define memory_order_acq_rel __ATOMIC_ACQ_REL
220#define memory_order_seq_cst __ATOMIC_SEQ_CST
221#define zig_atomic(type) type
222#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) __atomic_compare_exchange_n(obj, &(expected), desired, false, succ, fail)
223#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) __atomic_compare_exchange_n(obj, &(expected), desired, true , succ, fail)
224#define zig_atomicrmw_xchg(obj, arg, order, type) __atomic_exchange_n(obj, arg, order)
225#define zig_atomicrmw_add(obj, arg, order, type) __atomic_fetch_add (obj, arg, order)
226#define zig_atomicrmw_sub(obj, arg, order, type) __atomic_fetch_sub (obj, arg, order)
227#define zig_atomicrmw_or(obj, arg, order, type) __atomic_fetch_or (obj, arg, order)
228#define zig_atomicrmw_xor(obj, arg, order, type) __atomic_fetch_xor (obj, arg, order)
229#define zig_atomicrmw_and(obj, arg, order, type) __atomic_fetch_and (obj, arg, order)
230#define zig_atomicrmw_nand(obj, arg, order, type) __atomic_fetch_nand(obj, arg, order)
231#define zig_atomicrmw_min(obj, arg, order, type) __atomic_fetch_min (obj, arg, order)
232#define zig_atomicrmw_max(obj, arg, order, type) __atomic_fetch_max (obj, arg, order)
233#define zig_atomic_store(obj, arg, order, type) __atomic_store_n (obj, arg, order)
234#define zig_atomic_load(obj, order, type) __atomic_load_n (obj, order)
235#define zig_fence(order) __atomic_thread_fence(order)
236#elif _MSC_VER && (_M_IX86 || _M_X64)
237#define memory_order_relaxed 0
238#define memory_order_consume 1
239#define memory_order_acquire 2
240#define memory_order_release 3
241#define memory_order_acq_rel 4
242#define memory_order_seq_cst 5
243#define zig_atomic(type) type
244#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) zig_expand_concat(zig_msvc_cmpxchg_, type)(obj, &(expected), desired)
245#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) zig_cmpxchg_strong(obj, expected, desired, succ, fail, type)
246#define zig_atomicrmw_xchg(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_xchg_, type)(obj, arg)
247#define zig_atomicrmw_add(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_add_, type)(obj, arg)
248#define zig_atomicrmw_sub(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_sub_, type)(obj, arg)
249#define zig_atomicrmw_or(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_or_, type)(obj, arg)
250#define zig_atomicrmw_xor(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_xor_, type)(obj, arg)
251#define zig_atomicrmw_and(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_and_, type)(obj, arg)
252#define zig_atomicrmw_nand(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_nand_, type)(obj, arg)
253#define zig_atomicrmw_min(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_min_, type)(obj, arg)
254#define zig_atomicrmw_max(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_max_, type)(obj, arg)
255#define zig_atomic_store(obj, arg, order, type) zig_expand_concat(zig_msvc_atomic_store_, type)(obj, arg)
256#define zig_atomic_load(obj, order, type) zig_expand_concat(zig_msvc_atomic_load_, type)(obj)
257#if _M_X64
258#define zig_fence(order) __faststorefence()
259#else
260#define zig_fence(order) zig_msvc_atomic_barrier()
261#endif
262
263// TODO: _MSC_VER && (_M_ARM || _M_ARM64)
264#else
265#define memory_order_relaxed 0
266#define memory_order_consume 1
267#define memory_order_acquire 2
268#define memory_order_release 3
269#define memory_order_acq_rel 4
270#define memory_order_seq_cst 5
271#define zig_atomic(type) type
272#define zig_cmpxchg_strong(obj, expected, desired, succ, fail, type) zig_unimplemented()
273#define zig_cmpxchg_weak(obj, expected, desired, succ, fail, type) zig_unimplemented()
274#define zig_atomicrmw_xchg(obj, arg, order, type) zig_unimplemented()
275#define zig_atomicrmw_add(obj, arg, order, type) zig_unimplemented()
276#define zig_atomicrmw_sub(obj, arg, order, type) zig_unimplemented()
277#define zig_atomicrmw_or(obj, arg, order, type) zig_unimplemented()
278#define zig_atomicrmw_xor(obj, arg, order, type) zig_unimplemented()
279#define zig_atomicrmw_and(obj, arg, order, type) zig_unimplemented()
280#define zig_atomicrmw_nand(obj, arg, order, type) zig_unimplemented()
281#define zig_atomicrmw_min(obj, arg, order, type) zig_unimplemented()
282#define zig_atomicrmw_max(obj, arg, order, type) zig_unimplemented()
283#define zig_atomic_store(obj, arg, order, type) zig_unimplemented()
284#define zig_atomic_load(obj, order, type) zig_unimplemented()
285#define zig_fence(order) zig_unimplemented()
286#endif
287
288#if __STDC_VERSION__ >= 201112L
289#define zig_noreturn _Noreturn void
290#elif zig_has_attribute(noreturn) || defined(zig_gnuc)
291#define zig_noreturn __attribute__((noreturn)) void
292#elif _MSC_VER
293#define zig_noreturn __declspec(noreturn) void
294#else
295#define zig_noreturn void
296#endif
297
298#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
299
300typedef uintptr_t zig_usize;
301typedef intptr_t zig_isize;
302typedef signed short int zig_c_short;
303typedef unsigned short int zig_c_ushort;
304typedef signed int zig_c_int;
305typedef unsigned int zig_c_uint;
306typedef signed long int zig_c_long;
307typedef unsigned long int zig_c_ulong;
308typedef signed long long int zig_c_longlong;
309typedef unsigned long long int zig_c_ulonglong;
310
311typedef uint8_t zig_u8;
312typedef int8_t zig_i8;
313typedef uint16_t zig_u16;
314typedef int16_t zig_i16;
315typedef uint32_t zig_u32;
316typedef int32_t zig_i32;
317typedef uint64_t zig_u64;
318typedef int64_t zig_i64;
319
320#define zig_as_u8(val) UINT8_C(val)
321#define zig_as_i8(val) INT8_C(val)
322#define zig_as_u16(val) UINT16_C(val)
323#define zig_as_i16(val) INT16_C(val)
324#define zig_as_u32(val) UINT32_C(val)
325#define zig_as_i32(val) INT32_C(val)
326#define zig_as_u64(val) UINT64_C(val)
327#define zig_as_i64(val) INT64_C(val)
328
329#define zig_minInt_u8 zig_as_u8(0)
330#define zig_maxInt_u8 UINT8_MAX
331#define zig_minInt_i8 INT8_MIN
332#define zig_maxInt_i8 INT8_MAX
333#define zig_minInt_u16 zig_as_u16(0)
334#define zig_maxInt_u16 UINT16_MAX
335#define zig_minInt_i16 INT16_MIN
336#define zig_maxInt_i16 INT16_MAX
337#define zig_minInt_u32 zig_as_u32(0)
338#define zig_maxInt_u32 UINT32_MAX
339#define zig_minInt_i32 INT32_MIN
340#define zig_maxInt_i32 INT32_MAX
341#define zig_minInt_u64 zig_as_u64(0)
342#define zig_maxInt_u64 UINT64_MAX
343#define zig_minInt_i64 INT64_MIN
344#define zig_maxInt_i64 INT64_MAX
345
346#define zig_compiler_rt_abbrev_u32 si
347#define zig_compiler_rt_abbrev_i32 si
348#define zig_compiler_rt_abbrev_u64 di
349#define zig_compiler_rt_abbrev_i64 di
350#define zig_compiler_rt_abbrev_u128 ti
351#define zig_compiler_rt_abbrev_i128 ti
352#define zig_compiler_rt_abbrev_f16 hf
353#define zig_compiler_rt_abbrev_f32 sf
354#define zig_compiler_rt_abbrev_f64 df
355#define zig_compiler_rt_abbrev_f80 xf
356#define zig_compiler_rt_abbrev_f128 tf
357
358zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, zig_usize);
359zig_extern 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_expand_maxInt(Type, bits) zig_maxInt(Type, bits)
365#define zig_minInt(Type, bits) zig_not_##Type(zig_maxInt(Type, bits), bits)
366#define zig_expand_minInt(Type, bits) zig_minInt(Type, bits)
367
368#define zig_int_operator(Type, RhsType, operation, operator) \
369 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##RhsType rhs) { \
370 return lhs operator rhs; \
371 }
372#define zig_int_basic_operator(Type, operation, operator) \
373 zig_int_operator(Type, Type, operation, operator)
374#define zig_int_shift_operator(Type, operation, operator) \
375 zig_int_operator(Type, u8, operation, operator)
376#define zig_int_helpers(w) \
377 zig_int_basic_operator(u##w, and, &) \
378 zig_int_basic_operator(i##w, and, &) \
379 zig_int_basic_operator(u##w, or, |) \
380 zig_int_basic_operator(i##w, or, |) \
381 zig_int_basic_operator(u##w, xor, ^) \
382 zig_int_basic_operator(i##w, xor, ^) \
383 zig_int_shift_operator(u##w, shl, <<) \
384 zig_int_shift_operator(i##w, shl, <<) \
385 zig_int_shift_operator(u##w, shr, >>) \
386\
387 static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \
388 zig_i##w sign_mask = lhs < zig_as_i##w(0) ? -zig_as_i##w(1) : zig_as_i##w(0); \
389 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
390 } \
391\
392 static inline zig_u##w zig_not_u##w(zig_u##w val, zig_u8 bits) { \
393 return val ^ zig_maxInt(u##w, bits); \
394 } \
395\
396 static inline zig_i##w zig_not_i##w(zig_i##w val, zig_u8 bits) { \
397 (void)bits; \
398 return ~val; \
399 } \
400\
401 static inline zig_u##w zig_wrap_u##w(zig_u##w val, zig_u8 bits) { \
402 return val & zig_maxInt(u##w, bits); \
403 } \
404\
405 static inline zig_i##w zig_wrap_i##w(zig_i##w val, zig_u8 bits) { \
406 return (val & zig_as_u##w(1) << (bits - zig_as_u8(1))) != 0 \
407 ? val | zig_minInt(i##w, bits) : val & zig_maxInt(i##w, bits); \
408 } \
409\
410 zig_int_basic_operator(u##w, div_floor, /) \
411\
412 static inline zig_i##w zig_div_floor_i##w(zig_i##w lhs, zig_i##w rhs) { \
413 return lhs / rhs - (((lhs ^ rhs) & (lhs % rhs)) < zig_as_i##w(0)); \
414 } \
415\
416 zig_int_basic_operator(u##w, mod, %) \
417\
418 static inline zig_i##w zig_mod_i##w(zig_i##w lhs, zig_i##w rhs) { \
419 zig_i##w rem = lhs % rhs; \
420 return rem + (((lhs ^ rhs) & rem) < zig_as_i##w(0) ? rhs : zig_as_i##w(0)); \
421 } \
422\
423 static inline zig_u##w zig_shlw_u##w(zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
424 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
425 } \
426\
427 static inline zig_i##w zig_shlw_i##w(zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
428 return zig_wrap_i##w((zig_i##w)zig_shl_u##w((zig_u##w)lhs, (zig_u##w)rhs), bits); \
429 } \
430\
431 static inline zig_u##w zig_addw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
432 return zig_wrap_u##w(lhs + rhs, bits); \
433 } \
434\
435 static inline zig_i##w zig_addw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
436 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs + (zig_u##w)rhs), bits); \
437 } \
438\
439 static inline zig_u##w zig_subw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
440 return zig_wrap_u##w(lhs - rhs, bits); \
441 } \
442\
443 static inline zig_i##w zig_subw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
444 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs - (zig_u##w)rhs), bits); \
445 } \
446\
447 static inline zig_u##w zig_mulw_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
448 return zig_wrap_u##w(lhs * rhs, bits); \
449 } \
450\
451 static inline zig_i##w zig_mulw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
452 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs * (zig_u##w)rhs), bits); \
453 }
454zig_int_helpers(8)
455zig_int_helpers(16)
456zig_int_helpers(32)
457zig_int_helpers(64)
458
459static inline bool zig_addo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
460#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
461 zig_u32 full_res;
462 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
463 *res = zig_wrap_u32(full_res, bits);
464 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
465#else
466 *res = zig_addw_u32(lhs, rhs, bits);
467 return *res < lhs;
468#endif
469}
470
471static inline void zig_vaddo_u32(zig_u8 *ov, zig_u32 *res, int n,
472 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
473{
474 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits);
475}
476
477zig_extern zig_i32 __addosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
478static inline bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
479#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
480 zig_i32 full_res;
481 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
482#else
483 zig_c_int overflow_int;
484 zig_i32 full_res = __addosi4(lhs, rhs, &overflow_int);
485 bool overflow = overflow_int != 0;
486#endif
487 *res = zig_wrap_i32(full_res, bits);
488 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
489}
490
491static inline void zig_vaddo_i32(zig_u8 *ov, zig_i32 *res, int n,
492 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
493{
494 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits);
495}
496
497static inline bool zig_addo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
498#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
499 zig_u64 full_res;
500 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
501 *res = zig_wrap_u64(full_res, bits);
502 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
503#else
504 *res = zig_addw_u64(lhs, rhs, bits);
505 return *res < lhs;
506#endif
507}
508
509static inline void zig_vaddo_u64(zig_u8 *ov, zig_u64 *res, int n,
510 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
511{
512 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits);
513}
514
515zig_extern zig_i64 __addodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
516static inline bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
517#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
518 zig_i64 full_res;
519 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
520#else
521 zig_c_int overflow_int;
522 zig_i64 full_res = __addodi4(lhs, rhs, &overflow_int);
523 bool overflow = overflow_int != 0;
524#endif
525 *res = zig_wrap_i64(full_res, bits);
526 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
527}
528
529static inline void zig_vaddo_i64(zig_u8 *ov, zig_i64 *res, int n,
530 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
531{
532 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits);
533}
534
535static inline bool zig_addo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
536#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
537 zig_u8 full_res;
538 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
539 *res = zig_wrap_u8(full_res, bits);
540 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
541#else
542 zig_u32 full_res;
543 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
544 *res = (zig_u8)full_res;
545 return overflow;
546#endif
547}
548
549static inline void zig_vaddo_u8(zig_u8 *ov, zig_u8 *res, int n,
550 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
551{
552 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits);
553}
554
555static inline bool zig_addo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
556#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
557 zig_i8 full_res;
558 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
559 *res = zig_wrap_i8(full_res, bits);
560 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
561#else
562 zig_i32 full_res;
563 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
564 *res = (zig_i8)full_res;
565 return overflow;
566#endif
567}
568
569static inline void zig_vaddo_i8(zig_u8 *ov, zig_i8 *res, int n,
570 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
571{
572 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits);
573}
574
575static inline bool zig_addo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
576#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
577 zig_u16 full_res;
578 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
579 *res = zig_wrap_u16(full_res, bits);
580 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
581#else
582 zig_u32 full_res;
583 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
584 *res = (zig_u16)full_res;
585 return overflow;
586#endif
587}
588
589static inline void zig_vaddo_u16(zig_u8 *ov, zig_u16 *res, int n,
590 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
591{
592 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits);
593}
594
595static inline bool zig_addo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
596#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
597 zig_i16 full_res;
598 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
599 *res = zig_wrap_i16(full_res, bits);
600 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
601#else
602 zig_i32 full_res;
603 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
604 *res = (zig_i16)full_res;
605 return overflow;
606#endif
607}
608
609static inline void zig_vaddo_i16(zig_u8 *ov, zig_i16 *res, int n,
610 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
611{
612 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits);
613}
614
615static inline bool zig_subo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
616#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
617 zig_u32 full_res;
618 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
619 *res = zig_wrap_u32(full_res, bits);
620 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
621#else
622 *res = zig_subw_u32(lhs, rhs, bits);
623 return *res > lhs;
624#endif
625}
626
627static inline void zig_vsubo_u32(zig_u8 *ov, zig_u32 *res, int n,
628 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
629{
630 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits);
631}
632
633zig_extern zig_i32 __subosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
634static inline bool zig_subo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
635#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
636 zig_i32 full_res;
637 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
638#else
639 zig_c_int overflow_int;
640 zig_i32 full_res = __subosi4(lhs, rhs, &overflow_int);
641 bool overflow = overflow_int != 0;
642#endif
643 *res = zig_wrap_i32(full_res, bits);
644 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
645}
646
647static inline void zig_vsubo_i32(zig_u8 *ov, zig_i32 *res, int n,
648 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
649{
650 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits);
651}
652
653static inline bool zig_subo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
654#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
655 zig_u64 full_res;
656 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
657 *res = zig_wrap_u64(full_res, bits);
658 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
659#else
660 *res = zig_subw_u64(lhs, rhs, bits);
661 return *res > lhs;
662#endif
663}
664
665static inline void zig_vsubo_u64(zig_u8 *ov, zig_u64 *res, int n,
666 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
667{
668 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits);
669}
670
671zig_extern zig_i64 __subodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
672static inline bool zig_subo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
673#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
674 zig_i64 full_res;
675 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
676#else
677 zig_c_int overflow_int;
678 zig_i64 full_res = __subodi4(lhs, rhs, &overflow_int);
679 bool overflow = overflow_int != 0;
680#endif
681 *res = zig_wrap_i64(full_res, bits);
682 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
683}
684
685static inline void zig_vsubo_i64(zig_u8 *ov, zig_i64 *res, int n,
686 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
687{
688 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits);
689}
690
691static inline bool zig_subo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
692#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
693 zig_u8 full_res;
694 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
695 *res = zig_wrap_u8(full_res, bits);
696 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
697#else
698 zig_u32 full_res;
699 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
700 *res = (zig_u8)full_res;
701 return overflow;
702#endif
703}
704
705static inline void zig_vsubo_u8(zig_u8 *ov, zig_u8 *res, int n,
706 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
707{
708 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits);
709}
710
711static inline bool zig_subo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
712#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
713 zig_i8 full_res;
714 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
715 *res = zig_wrap_i8(full_res, bits);
716 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
717#else
718 zig_i32 full_res;
719 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
720 *res = (zig_i8)full_res;
721 return overflow;
722#endif
723}
724
725static inline void zig_vsubo_i8(zig_u8 *ov, zig_i8 *res, int n,
726 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
727{
728 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits);
729}
730
731
732static inline bool zig_subo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
733#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
734 zig_u16 full_res;
735 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
736 *res = zig_wrap_u16(full_res, bits);
737 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
738#else
739 zig_u32 full_res;
740 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
741 *res = (zig_u16)full_res;
742 return overflow;
743#endif
744}
745
746static inline void zig_vsubo_u16(zig_u8 *ov, zig_u16 *res, int n,
747 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
748{
749 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits);
750}
751
752
753static inline bool zig_subo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
754#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
755 zig_i16 full_res;
756 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
757 *res = zig_wrap_i16(full_res, bits);
758 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
759#else
760 zig_i32 full_res;
761 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
762 *res = (zig_i16)full_res;
763 return overflow;
764#endif
765}
766
767static inline void zig_vsubo_i16(zig_u8 *ov, zig_i16 *res, int n,
768 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
769{
770 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits);
771}
772
773static inline bool zig_mulo_u32(zig_u32 *res, zig_u32 lhs, zig_u32 rhs, zig_u8 bits) {
774#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
775 zig_u32 full_res;
776 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
777 *res = zig_wrap_u32(full_res, bits);
778 return overflow || full_res < zig_minInt(u32, bits) || full_res > zig_maxInt(u32, bits);
779#else
780 *res = zig_mulw_u32(lhs, rhs, bits);
781 return rhs != zig_as_u32(0) && lhs > zig_maxInt(u32, bits) / rhs;
782#endif
783}
784
785static inline void zig_vmulo_u32(zig_u8 *ov, zig_u32 *res, int n,
786 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)
787{
788 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits);
789}
790
791zig_extern zig_i32 __mulosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);
792static inline bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {
793#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
794 zig_i32 full_res;
795 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
796#else
797 zig_c_int overflow_int;
798 zig_i32 full_res = __mulosi4(lhs, rhs, &overflow_int);
799 bool overflow = overflow_int != 0;
800#endif
801 *res = zig_wrap_i32(full_res, bits);
802 return overflow || full_res < zig_minInt(i32, bits) || full_res > zig_maxInt(i32, bits);
803}
804
805static inline void zig_vmulo_i32(zig_u8 *ov, zig_i32 *res, int n,
806 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)
807{
808 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits);
809}
810
811static inline bool zig_mulo_u64(zig_u64 *res, zig_u64 lhs, zig_u64 rhs, zig_u8 bits) {
812#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
813 zig_u64 full_res;
814 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
815 *res = zig_wrap_u64(full_res, bits);
816 return overflow || full_res < zig_minInt(u64, bits) || full_res > zig_maxInt(u64, bits);
817#else
818 *res = zig_mulw_u64(lhs, rhs, bits);
819 return rhs != zig_as_u64(0) && lhs > zig_maxInt(u64, bits) / rhs;
820#endif
821}
822
823static inline void zig_vmulo_u64(zig_u8 *ov, zig_u64 *res, int n,
824 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)
825{
826 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits);
827}
828
829zig_extern zig_i64 __mulodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);
830static inline bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {
831#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
832 zig_i64 full_res;
833 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
834#else
835 zig_c_int overflow_int;
836 zig_i64 full_res = __mulodi4(lhs, rhs, &overflow_int);
837 bool overflow = overflow_int != 0;
838#endif
839 *res = zig_wrap_i64(full_res, bits);
840 return overflow || full_res < zig_minInt(i64, bits) || full_res > zig_maxInt(i64, bits);
841}
842
843static inline void zig_vmulo_i64(zig_u8 *ov, zig_i64 *res, int n,
844 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)
845{
846 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits);
847}
848
849static inline bool zig_mulo_u8(zig_u8 *res, zig_u8 lhs, zig_u8 rhs, zig_u8 bits) {
850#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
851 zig_u8 full_res;
852 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
853 *res = zig_wrap_u8(full_res, bits);
854 return overflow || full_res < zig_minInt(u8, bits) || full_res > zig_maxInt(u8, bits);
855#else
856 zig_u32 full_res;
857 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
858 *res = (zig_u8)full_res;
859 return overflow;
860#endif
861}
862
863static inline void zig_vmulo_u8(zig_u8 *ov, zig_u8 *res, int n,
864 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)
865{
866 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits);
867}
868
869static inline bool zig_mulo_i8(zig_i8 *res, zig_i8 lhs, zig_i8 rhs, zig_u8 bits) {
870#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
871 zig_i8 full_res;
872 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
873 *res = zig_wrap_i8(full_res, bits);
874 return overflow || full_res < zig_minInt(i8, bits) || full_res > zig_maxInt(i8, bits);
875#else
876 zig_i32 full_res;
877 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
878 *res = (zig_i8)full_res;
879 return overflow;
880#endif
881}
882
883static inline void zig_vmulo_i8(zig_u8 *ov, zig_i8 *res, int n,
884 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)
885{
886 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits);
887}
888
889static inline bool zig_mulo_u16(zig_u16 *res, zig_u16 lhs, zig_u16 rhs, zig_u8 bits) {
890#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
891 zig_u16 full_res;
892 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
893 *res = zig_wrap_u16(full_res, bits);
894 return overflow || full_res < zig_minInt(u16, bits) || full_res > zig_maxInt(u16, bits);
895#else
896 zig_u32 full_res;
897 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
898 *res = (zig_u16)full_res;
899 return overflow;
900#endif
901}
902
903static inline void zig_vmulo_u16(zig_u8 *ov, zig_u16 *res, int n,
904 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)
905{
906 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits);
907}
908
909static inline bool zig_mulo_i16(zig_i16 *res, zig_i16 lhs, zig_i16 rhs, zig_u8 bits) {
910#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
911 zig_i16 full_res;
912 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
913 *res = zig_wrap_i16(full_res, bits);
914 return overflow || full_res < zig_minInt(i16, bits) || full_res > zig_maxInt(i16, bits);
915#else
916 zig_i32 full_res;
917 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
918 *res = (zig_i16)full_res;
919 return overflow;
920#endif
921}
922
923static inline void zig_vmulo_i16(zig_u8 *ov, zig_i16 *res, int n,
924 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)
925{
926 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits);
927}
928
929#define zig_int_builtins(w) \
930 static inline bool zig_shlo_u##w(zig_u##w *res, zig_u##w lhs, zig_u8 rhs, zig_u8 bits) { \
931 *res = zig_shlw_u##w(lhs, rhs, bits); \
932 return lhs > zig_maxInt(u##w, bits) >> rhs; \
933 } \
934\
935 static inline bool zig_shlo_i##w(zig_i##w *res, zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \
936 *res = zig_shlw_i##w(lhs, rhs, bits); \
937 zig_i##w mask = (zig_i##w)(zig_maxInt_u##w << (bits - rhs - 1)); \
938 return (lhs & mask) != zig_as_i##w(0) && (lhs & mask) != mask; \
939 } \
940\
941 static inline zig_u##w zig_shls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
942 zig_u##w res; \
943 if (rhs >= bits) return lhs != zig_as_u##w(0) ? zig_maxInt(u##w, bits) : lhs; \
944 return zig_shlo_u##w(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u##w, bits) : res; \
945 } \
946\
947 static inline zig_i##w zig_shls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
948 zig_i##w res; \
949 if ((zig_u##w)rhs < (zig_u##w)bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \
950 return lhs < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
951 } \
952\
953 static inline zig_u##w zig_adds_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
954 zig_u##w res; \
955 return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
956 } \
957\
958 static inline zig_i##w zig_adds_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
959 zig_i##w res; \
960 if (!zig_addo_i##w(&res, lhs, rhs, bits)) return res; \
961 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
962 } \
963\
964 static inline zig_u##w zig_subs_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
965 zig_u##w res; \
966 return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt(u##w, bits) : res; \
967 } \
968\
969 static inline zig_i##w zig_subs_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
970 zig_i##w res; \
971 if (!zig_subo_i##w(&res, lhs, rhs, bits)) return res; \
972 return res >= zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
973 } \
974\
975 static inline zig_u##w zig_muls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \
976 zig_u##w res; \
977 return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \
978 } \
979\
980 static inline zig_i##w zig_muls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \
981 zig_i##w res; \
982 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
983 return (lhs ^ rhs) < zig_as_i##w(0) ? zig_minInt(i##w, bits) : zig_maxInt(i##w, bits); \
984 }
985zig_int_builtins(8)
986zig_int_builtins(16)
987zig_int_builtins(32)
988zig_int_builtins(64)
989
990#define zig_builtin8(name, val) __builtin_##name(val)
991typedef zig_c_uint zig_Builtin8;
992
993#define zig_builtin16(name, val) __builtin_##name(val)
994typedef zig_c_uint zig_Builtin16;
995
996#if INT_MIN <= INT32_MIN
997#define zig_builtin32(name, val) __builtin_##name(val)
998typedef zig_c_uint zig_Builtin32;
999#elif LONG_MIN <= INT32_MIN
1000#define zig_builtin32(name, val) __builtin_##name##l(val)
1001typedef zig_c_ulong zig_Builtin32;
1002#endif
1003
1004#if INT_MIN <= INT64_MIN
1005#define zig_builtin64(name, val) __builtin_##name(val)
1006typedef zig_c_uint zig_Builtin64;
1007#elif LONG_MIN <= INT64_MIN
1008#define zig_builtin64(name, val) __builtin_##name##l(val)
1009typedef zig_c_ulong zig_Builtin64;
1010#elif LLONG_MIN <= INT64_MIN
1011#define zig_builtin64(name, val) __builtin_##name##ll(val)
1012typedef zig_c_ulonglong zig_Builtin64;
1013#endif
1014
1015static inline zig_u8 zig_byte_swap_u8(zig_u8 val, zig_u8 bits) {
1016 return zig_wrap_u8(val >> (8 - bits), bits);
1017}
1018
1019static inline zig_i8 zig_byte_swap_i8(zig_i8 val, zig_u8 bits) {
1020 return zig_wrap_i8((zig_i8)zig_byte_swap_u8((zig_u8)val, bits), bits);
1021}
1022
1023static inline zig_u16 zig_byte_swap_u16(zig_u16 val, zig_u8 bits) {
1024 zig_u16 full_res;
1025#if zig_has_builtin(bswap16) || defined(zig_gnuc)
1026 full_res = __builtin_bswap16(val);
1027#else
1028 full_res = (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 0), 8) << 8 |
1029 (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 8), 8) >> 0;
1030#endif
1031 return zig_wrap_u16(full_res >> (16 - bits), bits);
1032}
1033
1034static inline zig_i16 zig_byte_swap_i16(zig_i16 val, zig_u8 bits) {
1035 return zig_wrap_i16((zig_i16)zig_byte_swap_u16((zig_u16)val, bits), bits);
1036}
1037
1038static inline zig_u32 zig_byte_swap_u32(zig_u32 val, zig_u8 bits) {
1039 zig_u32 full_res;
1040#if zig_has_builtin(bswap32) || defined(zig_gnuc)
1041 full_res = __builtin_bswap32(val);
1042#else
1043 full_res = (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 0), 16) << 16 |
1044 (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 16), 16) >> 0;
1045#endif
1046 return zig_wrap_u32(full_res >> (32 - bits), bits);
1047}
1048
1049static inline zig_i32 zig_byte_swap_i32(zig_i32 val, zig_u8 bits) {
1050 return zig_wrap_i32((zig_i32)zig_byte_swap_u32((zig_u32)val, bits), bits);
1051}
1052
1053static inline zig_u64 zig_byte_swap_u64(zig_u64 val, zig_u8 bits) {
1054 zig_u64 full_res;
1055#if zig_has_builtin(bswap64) || defined(zig_gnuc)
1056 full_res = __builtin_bswap64(val);
1057#else
1058 full_res = (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 0), 32) << 32 |
1059 (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 32), 32) >> 0;
1060#endif
1061 return zig_wrap_u64(full_res >> (64 - bits), bits);
1062}
1063
1064static inline zig_i64 zig_byte_swap_i64(zig_i64 val, zig_u8 bits) {
1065 return zig_wrap_i64((zig_i64)zig_byte_swap_u64((zig_u64)val, bits), bits);
1066}
1067
1068static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
1069 zig_u8 full_res;
1070#if zig_has_builtin(bitreverse8)
1071 full_res = __builtin_bitreverse8(val);
1072#else
1073 static zig_u8 const lut[0x10] = {
1074 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
1075 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
1076 };
1077 full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
1078#endif
1079 return zig_wrap_u8(full_res >> (8 - bits), bits);
1080}
1081
1082static inline zig_i8 zig_bit_reverse_i8(zig_i8 val, zig_u8 bits) {
1083 return zig_wrap_i8((zig_i8)zig_bit_reverse_u8((zig_u8)val, bits), bits);
1084}
1085
1086static inline zig_u16 zig_bit_reverse_u16(zig_u16 val, zig_u8 bits) {
1087 zig_u16 full_res;
1088#if zig_has_builtin(bitreverse16)
1089 full_res = __builtin_bitreverse16(val);
1090#else
1091 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0), 8) << 8 |
1092 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8), 8) >> 0;
1093#endif
1094 return zig_wrap_u16(full_res >> (16 - bits), bits);
1095}
1096
1097static inline zig_i16 zig_bit_reverse_i16(zig_i16 val, zig_u8 bits) {
1098 return zig_wrap_i16((zig_i16)zig_bit_reverse_u16((zig_u16)val, bits), bits);
1099}
1100
1101static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) {
1102 zig_u32 full_res;
1103#if zig_has_builtin(bitreverse32)
1104 full_res = __builtin_bitreverse32(val);
1105#else
1106 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0), 16) << 16 |
1107 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16), 16) >> 0;
1108#endif
1109 return zig_wrap_u32(full_res >> (32 - bits), bits);
1110}
1111
1112static inline zig_i32 zig_bit_reverse_i32(zig_i32 val, zig_u8 bits) {
1113 return zig_wrap_i32((zig_i32)zig_bit_reverse_u32((zig_u32)val, bits), bits);
1114}
1115
1116static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) {
1117 zig_u64 full_res;
1118#if zig_has_builtin(bitreverse64)
1119 full_res = __builtin_bitreverse64(val);
1120#else
1121 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0), 32) << 32 |
1122 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32), 32) >> 0;
1123#endif
1124 return zig_wrap_u64(full_res >> (64 - bits), bits);
1125}
1126
1127static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {
1128 return zig_wrap_i64((zig_i64)zig_bit_reverse_u64((zig_u64)val, bits), bits);
1129}
1130
1131#define zig_builtin_popcount_common(w) \
1132 static inline zig_u8 zig_popcount_i##w(zig_i##w val, zig_u8 bits) { \
1133 return zig_popcount_u##w((zig_u##w)val, bits); \
1134 }
1135#if zig_has_builtin(popcount) || defined(zig_gnuc)
1136#define zig_builtin_popcount(w) \
1137 static inline zig_u8 zig_popcount_u##w(zig_u##w val, zig_u8 bits) { \
1138 (void)bits; \
1139 return zig_builtin##w(popcount, val); \
1140 } \
1141\
1142 zig_builtin_popcount_common(w)
1143#else
1144#define zig_builtin_popcount(w) \
1145 static inline zig_u8 zig_popcount_u##w(zig_u##w val, zig_u8 bits) { \
1146 (void)bits; \
1147 zig_u##w temp = val - ((val >> 1) & (zig_maxInt_u##w / 3)); \
1148 temp = (temp & (zig_maxInt_u##w / 5)) + ((temp >> 2) & (zig_maxInt_u##w / 5)); \
1149 temp = (temp + (temp >> 4)) & (zig_maxInt_u##w / 17); \
1150 return temp * (zig_maxInt_u##w / 255) >> (w - 8); \
1151 } \
1152\
1153 zig_builtin_popcount_common(w)
1154#endif
1155zig_builtin_popcount(8)
1156zig_builtin_popcount(16)
1157zig_builtin_popcount(32)
1158zig_builtin_popcount(64)
1159
1160#define zig_builtin_ctz_common(w) \
1161 static inline zig_u8 zig_ctz_i##w(zig_i##w val, zig_u8 bits) { \
1162 return zig_ctz_u##w((zig_u##w)val, bits); \
1163 }
1164#if zig_has_builtin(ctz) || defined(zig_gnuc)
1165#define zig_builtin_ctz(w) \
1166 static inline zig_u8 zig_ctz_u##w(zig_u##w val, zig_u8 bits) { \
1167 if (val == 0) return bits; \
1168 return zig_builtin##w(ctz, val); \
1169 } \
1170\
1171 zig_builtin_ctz_common(w)
1172#else
1173#define zig_builtin_ctz(w) \
1174 static inline zig_u8 zig_ctz_u##w(zig_u##w val, zig_u8 bits) { \
1175 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
1176 } \
1177\
1178 zig_builtin_ctz_common(w)
1179#endif
1180zig_builtin_ctz(8)
1181zig_builtin_ctz(16)
1182zig_builtin_ctz(32)
1183zig_builtin_ctz(64)
1184
1185#define zig_builtin_clz_common(w) \
1186 static inline zig_u8 zig_clz_i##w(zig_i##w val, zig_u8 bits) { \
1187 return zig_clz_u##w((zig_u##w)val, bits); \
1188 }
1189#if zig_has_builtin(clz) || defined(zig_gnuc)
1190#define zig_builtin_clz(w) \
1191 static inline zig_u8 zig_clz_u##w(zig_u##w val, zig_u8 bits) { \
1192 if (val == 0) return bits; \
1193 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1194 } \
1195\
1196 zig_builtin_clz_common(w)
1197#else
1198#define zig_builtin_clz(w) \
1199 static inline zig_u8 zig_clz_u##w(zig_u##w val, zig_u8 bits) { \
1200 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
1201 } \
1202\
1203 zig_builtin_clz_common(w)
1204#endif
1205zig_builtin_clz(8)
1206zig_builtin_clz(16)
1207zig_builtin_clz(32)
1208zig_builtin_clz(64)
1209
1210/* ======================== 128-bit Integer Routines ======================== */
1211
1212#if !defined(zig_has_int128)
1213# if defined(__SIZEOF_INT128__)
1214# define zig_has_int128 1
1215# else
1216# define zig_has_int128 0
1217# endif
1218#endif
1219
1220#if zig_has_int128
1221
1222typedef unsigned __int128 zig_u128;
1223typedef signed __int128 zig_i128;
1224
1225#define zig_as_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1226#define zig_as_i128(hi, lo) ((zig_i128)zig_as_u128(hi, lo))
1227#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo)
1228#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo)
1229#define zig_hi_u128(val) ((zig_u64)((val) >> 64))
1230#define zig_lo_u128(val) ((zig_u64)((val) >> 0))
1231#define zig_hi_i128(val) ((zig_i64)((val) >> 64))
1232#define zig_lo_i128(val) ((zig_u64)((val) >> 0))
1233#define zig_bitcast_u128(val) ((zig_u128)(val))
1234#define zig_bitcast_i128(val) ((zig_i128)(val))
1235#define zig_cmp_int128(Type) \
1236 static inline zig_i32 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1237 return (lhs > rhs) - (lhs < rhs); \
1238 }
1239#define zig_bit_int128(Type, operation, operator) \
1240 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1241 return lhs operator rhs; \
1242 }
1243
1244#else /* zig_has_int128 */
1245
1246#if __LITTLE_ENDIAN__ || _MSC_VER
1247typedef struct { zig_align(16) zig_u64 lo; zig_u64 hi; } zig_u128;
1248typedef struct { zig_align(16) zig_u64 lo; zig_i64 hi; } zig_i128;
1249#else
1250typedef struct { zig_align(16) zig_u64 hi; zig_u64 lo; } zig_u128;
1251typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
1252#endif
1253
1254#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1255#define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
1256
1257#if _MSC_VER
1258#define zig_as_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1259#define zig_as_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1260#else
1261#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo)
1262#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo)
1263#endif
1264#define zig_hi_u128(val) ((val).hi)
1265#define zig_lo_u128(val) ((val).lo)
1266#define zig_hi_i128(val) ((val).hi)
1267#define zig_lo_i128(val) ((val).lo)
1268#define zig_bitcast_u128(val) zig_as_u128((zig_u64)(val).hi, (val).lo)
1269#define zig_bitcast_i128(val) zig_as_i128((zig_i64)(val).hi, (val).lo)
1270#define zig_cmp_int128(Type) \
1271 static inline zig_i32 zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
1272 return (lhs.hi == rhs.hi) \
1273 ? (lhs.lo > rhs.lo) - (lhs.lo < rhs.lo) \
1274 : (lhs.hi > rhs.hi) - (lhs.hi < rhs.hi); \
1275 }
1276#define zig_bit_int128(Type, operation, operator) \
1277 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
1278 return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
1279 }
1280
1281#endif /* zig_has_int128 */
1282
1283#define zig_minInt_u128 zig_as_u128(zig_minInt_u64, zig_minInt_u64)
1284#define zig_maxInt_u128 zig_as_u128(zig_maxInt_u64, zig_maxInt_u64)
1285#define zig_minInt_i128 zig_as_i128(zig_minInt_i64, zig_minInt_u64)
1286#define zig_maxInt_i128 zig_as_i128(zig_maxInt_i64, zig_maxInt_u64)
1287
1288zig_cmp_int128(u128)
1289zig_cmp_int128(i128)
1290
1291zig_bit_int128(u128, and, &)
1292zig_bit_int128(i128, and, &)
1293
1294zig_bit_int128(u128, or, |)
1295zig_bit_int128(i128, or, |)
1296
1297zig_bit_int128(u128, xor, ^)
1298zig_bit_int128(i128, xor, ^)
1299
1300static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs);
1301
1302#if zig_has_int128
1303
1304static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1305 return val ^ zig_maxInt(u128, bits);
1306}
1307
1308static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1309 (void)bits;
1310 return ~val;
1311}
1312
1313static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1314 return lhs >> rhs;
1315}
1316
1317static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1318 return lhs << rhs;
1319}
1320
1321static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1322 return lhs << rhs;
1323}
1324
1325static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
1326 return lhs + rhs;
1327}
1328
1329static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
1330 return lhs + rhs;
1331}
1332
1333static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
1334 return lhs - rhs;
1335}
1336
1337static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1338 return lhs - rhs;
1339}
1340
1341static inline zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1342 return lhs * rhs;
1343}
1344
1345static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1346 return lhs * rhs;
1347}
1348
1349static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
1350 return lhs / rhs;
1351}
1352
1353static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
1354 return lhs / rhs;
1355}
1356
1357static inline zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
1358 return lhs % rhs;
1359}
1360
1361static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
1362 return lhs % rhs;
1363}
1364
1365static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1366 return zig_div_trunc_i128(lhs, rhs) - (((lhs ^ rhs) & zig_rem_i128(lhs, rhs)) < zig_as_i128(0, 0));
1367}
1368
1369static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1370 zig_i128 rem = zig_rem_i128(lhs, rhs);
1371 return rem + (((lhs ^ rhs) & rem) < zig_as_i128(0, 0) ? rhs : zig_as_i128(0, 0));
1372}
1373
1374#else /* zig_has_int128 */
1375
1376static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {
1377 return (zig_u128){ .hi = zig_not_u64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
1378}
1379
1380static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {
1381 return (zig_i128){ .hi = zig_not_i64(val.hi, bits - zig_as_u8(64)), .lo = zig_not_u64(val.lo, zig_as_u8(64)) };
1382}
1383
1384static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {
1385 if (rhs == zig_as_u8(0)) return lhs;
1386 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - zig_as_u8(64)) };
1387 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (zig_as_u8(64) - rhs) | lhs.lo >> rhs };
1388}
1389
1390static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {
1391 if (rhs == zig_as_u8(0)) return lhs;
1392 if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.lo << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1393 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1394}
1395
1396static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {
1397 if (rhs == zig_as_u8(0)) return lhs;
1398 if (rhs >= zig_as_u8(64)) return (zig_i128){ .hi = lhs.lo << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 };
1399 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };
1400}
1401
1402static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
1403 zig_u128 res;
1404 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, 64);
1405 return res;
1406}
1407
1408static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
1409 zig_i128 res;
1410 res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, 64);
1411 return res;
1412}
1413
1414static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
1415 zig_u128 res;
1416 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, 64);
1417 return res;
1418}
1419
1420static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1421 zig_i128 res;
1422 res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, 64);
1423 return res;
1424}
1425
1426zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
1427static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1428 return zig_bitcast_u128(__multi3(zig_bitcast_i128(lhs), zig_bitcast_i128(rhs)));
1429}
1430
1431static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1432 return __multi3(lhs, rhs);
1433}
1434
1435zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
1436static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
1437 return __udivti3(lhs, rhs);
1438};
1439
1440zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
1441static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
1442 return __divti3(lhs, rhs);
1443};
1444
1445zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
1446static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
1447 return __umodti3(lhs, rhs);
1448}
1449
1450zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
1451static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
1452 return __modti3(lhs, rhs);
1453}
1454
1455static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1456 zig_i128 rem = zig_rem_i128(lhs, rhs);
1457 return zig_add_i128(rem, (((lhs.hi ^ rhs.hi) & rem.hi) < zig_as_i64(0) ? rhs : zig_as_i128(0, 0)));
1458}
1459
1460static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
1461 return zig_sub_i128(zig_div_trunc_i128(lhs, rhs), zig_as_i128(0, zig_cmp_i128(zig_and_i128(zig_xor_i128(lhs, rhs), zig_rem_i128(lhs, rhs)), zig_as_i128(0, 0)) < zig_as_i32(0)));
1462}
1463
1464#endif /* zig_has_int128 */
1465
1466#define zig_div_floor_u128 zig_div_trunc_u128
1467#define zig_mod_u128 zig_rem_u128
1468
1469static inline zig_u128 zig_nand_u128(zig_u128 lhs, zig_u128 rhs) {
1470 return zig_not_u128(zig_and_u128(lhs, rhs), 128);
1471}
1472
1473static inline zig_u128 zig_min_u128(zig_u128 lhs, zig_u128 rhs) {
1474 return zig_cmp_u128(lhs, rhs) < zig_as_i32(0) ? lhs : rhs;
1475}
1476
1477static inline zig_i128 zig_min_i128(zig_i128 lhs, zig_i128 rhs) {
1478 return zig_cmp_i128(lhs, rhs) < zig_as_i32(0) ? lhs : rhs;
1479}
1480
1481static inline zig_u128 zig_max_u128(zig_u128 lhs, zig_u128 rhs) {
1482 return zig_cmp_u128(lhs, rhs) > zig_as_i32(0) ? lhs : rhs;
1483}
1484
1485static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
1486 return zig_cmp_i128(lhs, rhs) > zig_as_i32(0) ? lhs : rhs;
1487}
1488
1489static inline zig_i128 zig_shr_i128(zig_i128 lhs, zig_u8 rhs) {
1490 zig_i128 sign_mask = zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_sub_i128(zig_as_i128(0, 0), zig_as_i128(0, 1)) : zig_as_i128(0, 0);
1491 return zig_xor_i128(zig_bitcast_i128(zig_shr_u128(zig_bitcast_u128(zig_xor_i128(lhs, sign_mask)), rhs)), sign_mask);
1492}
1493
1494static inline zig_u128 zig_wrap_u128(zig_u128 val, zig_u8 bits) {
1495 return zig_and_u128(val, zig_maxInt(u128, bits));
1496}
1497
1498static inline zig_i128 zig_wrap_i128(zig_i128 val, zig_u8 bits) {
1499 return zig_as_i128(zig_wrap_i64(zig_hi_i128(val), bits - zig_as_u8(64)), zig_lo_i128(val));
1500}
1501
1502static inline zig_u128 zig_shlw_u128(zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1503 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
1504}
1505
1506static inline zig_i128 zig_shlw_i128(zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1507 return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), rhs)), bits);
1508}
1509
1510static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1511 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
1512}
1513
1514static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1515 return zig_wrap_i128(zig_bitcast_i128(zig_add_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1516}
1517
1518static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1519 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
1520}
1521
1522static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1523 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1524}
1525
1526static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1527 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
1528}
1529
1530static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1531 return zig_wrap_i128(zig_bitcast_i128(zig_mul_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1532}
1533
1534#if zig_has_int128
1535
1536static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1537#if zig_has_builtin(add_overflow)
1538 zig_u128 full_res;
1539 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1540 *res = zig_wrap_u128(full_res, bits);
1541 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1542#else
1543 *res = zig_addw_u128(lhs, rhs, bits);
1544 return *res < lhs;
1545#endif
1546}
1547
1548zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1549static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1550#if zig_has_builtin(add_overflow)
1551 zig_i128 full_res;
1552 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1553#else
1554 zig_c_int overflow_int;
1555 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
1556 bool overflow = overflow_int != 0;
1557#endif
1558 *res = zig_wrap_i128(full_res, bits);
1559 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1560}
1561
1562static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1563#if zig_has_builtin(sub_overflow)
1564 zig_u128 full_res;
1565 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1566 *res = zig_wrap_u128(full_res, bits);
1567 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1568#else
1569 *res = zig_subw_u128(lhs, rhs, bits);
1570 return *res > lhs;
1571#endif
1572}
1573
1574zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1575static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1576#if zig_has_builtin(sub_overflow)
1577 zig_i128 full_res;
1578 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1579#else
1580 zig_c_int overflow_int;
1581 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
1582 bool overflow = overflow_int != 0;
1583#endif
1584 *res = zig_wrap_i128(full_res, bits);
1585 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1586}
1587
1588static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1589#if zig_has_builtin(mul_overflow)
1590 zig_u128 full_res;
1591 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1592 *res = zig_wrap_u128(full_res, bits);
1593 return overflow || full_res < zig_minInt(u128, bits) || full_res > zig_maxInt(u128, bits);
1594#else
1595 *res = zig_mulw_u128(lhs, rhs, bits);
1596 return rhs != zig_as_u128(0, 0) && lhs > zig_maxInt(u128, bits) / rhs;
1597#endif
1598}
1599
1600zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1601static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1602#if zig_has_builtin(mul_overflow)
1603 zig_i128 full_res;
1604 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1605#else
1606 zig_c_int overflow_int;
1607 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
1608 bool overflow = overflow_int != 0;
1609#endif
1610 *res = zig_wrap_i128(full_res, bits);
1611 return overflow || full_res < zig_minInt(i128, bits) || full_res > zig_maxInt(i128, bits);
1612}
1613
1614#else /* zig_has_int128 */
1615
1616static inline bool zig_overflow_u128(bool overflow, zig_u128 full_res, zig_u8 bits) {
1617 return overflow ||
1618 zig_cmp_u128(full_res, zig_minInt(u128, bits)) < zig_as_i32(0) ||
1619 zig_cmp_u128(full_res, zig_maxInt(u128, bits)) > zig_as_i32(0);
1620}
1621
1622static inline bool zig_overflow_i128(bool overflow, zig_i128 full_res, zig_u8 bits) {
1623 return overflow ||
1624 zig_cmp_i128(full_res, zig_minInt(i128, bits)) < zig_as_i32(0) ||
1625 zig_cmp_i128(full_res, zig_maxInt(i128, bits)) > zig_as_i32(0);
1626}
1627
1628static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1629 zig_u128 full_res;
1630 bool overflow =
1631 zig_addo_u64(&full_res.hi, lhs.hi, rhs.hi, 64) |
1632 zig_addo_u64(&full_res.hi, full_res.hi, zig_addo_u64(&full_res.lo, lhs.lo, rhs.lo, 64), 64);
1633 *res = zig_wrap_u128(full_res, bits);
1634 return zig_overflow_u128(overflow, full_res, bits);
1635}
1636
1637zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1638static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1639 zig_c_int overflow_int;
1640 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
1641 *res = zig_wrap_i128(full_res, bits);
1642 return zig_overflow_i128(overflow_int, full_res, bits);
1643}
1644
1645static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1646 zig_u128 full_res;
1647 bool overflow =
1648 zig_subo_u64(&full_res.hi, lhs.hi, rhs.hi, 64) |
1649 zig_subo_u64(&full_res.hi, full_res.hi, zig_subo_u64(&full_res.lo, lhs.lo, rhs.lo, 64), 64);
1650 *res = zig_wrap_u128(full_res, bits);
1651 return zig_overflow_u128(overflow, full_res, bits);
1652}
1653
1654zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1655static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1656 zig_c_int overflow_int;
1657 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
1658 *res = zig_wrap_i128(full_res, bits);
1659 return zig_overflow_i128(overflow_int, full_res, bits);
1660}
1661
1662static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1663 *res = zig_mulw_u128(lhs, rhs, bits);
1664 return zig_cmp_u128(*res, zig_as_u128(0, 0)) != zig_as_i32(0) &&
1665 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt(u128, bits), rhs)) > zig_as_i32(0);
1666}
1667
1668zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);
1669static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1670 zig_c_int overflow_int;
1671 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
1672 *res = zig_wrap_i128(full_res, bits);
1673 return zig_overflow_i128(overflow_int, full_res, bits);
1674}
1675
1676#endif /* zig_has_int128 */
1677
1678static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, zig_u8 rhs, zig_u8 bits) {
1679 *res = zig_shlw_u128(lhs, rhs, bits);
1680 return zig_cmp_u128(lhs, zig_shr_u128(zig_maxInt(u128, bits), rhs)) > zig_as_i32(0);
1681}
1682
1683static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, zig_u8 rhs, zig_u8 bits) {
1684 *res = zig_shlw_i128(lhs, rhs, bits);
1685 zig_i128 mask = zig_bitcast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - zig_as_u8(1)));
1686 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_as_i128(0, 0)) != zig_as_i32(0) &&
1687 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != zig_as_i32(0);
1688}
1689
1690static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1691 zig_u128 res;
1692 if (zig_cmp_u128(rhs, zig_as_u128(0, bits)) >= zig_as_i32(0))
1693 return zig_cmp_u128(lhs, zig_as_u128(0, 0)) != zig_as_i32(0) ? zig_maxInt(u128, bits) : lhs;
1694
1695#if zig_has_int128
1696 return zig_shlo_u128(&res, lhs, (zig_u8)rhs, bits) ? zig_maxInt(u128, bits) : res;
1697#else
1698 return zig_shlo_u128(&res, lhs, (zig_u8)rhs.lo, bits) ? zig_maxInt(u128, bits) : res;
1699#endif
1700}
1701
1702static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1703 zig_i128 res;
1704 if (zig_cmp_u128(zig_bitcast_u128(rhs), zig_as_u128(0, bits)) < zig_as_i32(0) && !zig_shlo_i128(&res, lhs, zig_lo_i128(rhs), bits)) return res;
1705 return zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1706}
1707
1708static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1709 zig_u128 res;
1710 return zig_addo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1711}
1712
1713static inline zig_i128 zig_adds_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1714 zig_i128 res;
1715 if (!zig_addo_i128(&res, lhs, rhs, bits)) return res;
1716 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1717}
1718
1719static inline zig_u128 zig_subs_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1720 zig_u128 res;
1721 return zig_subo_u128(&res, lhs, rhs, bits) ? zig_minInt(u128, bits) : res;
1722}
1723
1724static inline zig_i128 zig_subs_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1725 zig_i128 res;
1726 if (!zig_subo_i128(&res, lhs, rhs, bits)) return res;
1727 return zig_cmp_i128(res, zig_as_i128(0, 0)) >= zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1728}
1729
1730static inline zig_u128 zig_muls_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1731 zig_u128 res;
1732 return zig_mulo_u128(&res, lhs, rhs, bits) ? zig_maxInt(u128, bits) : res;
1733}
1734
1735static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1736 zig_i128 res;
1737 if (!zig_mulo_i128(&res, lhs, rhs, bits)) return res;
1738 return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);
1739}
1740
1741static inline zig_u8 zig_clz_u128(zig_u128 val, zig_u8 bits) {
1742 if (bits <= zig_as_u8(64)) return zig_clz_u64(zig_lo_u128(val), bits);
1743 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - zig_as_u8(64));
1744 return zig_clz_u64(zig_lo_u128(val), zig_as_u8(64)) + (bits - zig_as_u8(64));
1745}
1746
1747static inline zig_u8 zig_clz_i128(zig_i128 val, zig_u8 bits) {
1748 return zig_clz_u128(zig_bitcast_u128(val), bits);
1749}
1750
1751static inline zig_u8 zig_ctz_u128(zig_u128 val, zig_u8 bits) {
1752 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), zig_as_u8(64));
1753 return zig_ctz_u64(zig_hi_u128(val), bits - zig_as_u8(64)) + zig_as_u8(64);
1754}
1755
1756static inline zig_u8 zig_ctz_i128(zig_i128 val, zig_u8 bits) {
1757 return zig_ctz_u128(zig_bitcast_u128(val), bits);
1758}
1759
1760static inline zig_u8 zig_popcount_u128(zig_u128 val, zig_u8 bits) {
1761 return zig_popcount_u64(zig_hi_u128(val), bits - zig_as_u8(64)) +
1762 zig_popcount_u64(zig_lo_u128(val), zig_as_u8(64));
1763}
1764
1765static inline zig_u8 zig_popcount_i128(zig_i128 val, zig_u8 bits) {
1766 return zig_popcount_u128(zig_bitcast_u128(val), bits);
1767}
1768
1769static inline zig_u128 zig_byte_swap_u128(zig_u128 val, zig_u8 bits) {
1770 zig_u128 full_res;
1771#if zig_has_builtin(bswap128)
1772 full_res = __builtin_bswap128(val);
1773#else
1774 full_res = zig_as_u128(zig_byte_swap_u64(zig_lo_u128(val), zig_as_u8(64)),
1775 zig_byte_swap_u64(zig_hi_u128(val), zig_as_u8(64)));
1776#endif
1777 return zig_shr_u128(full_res, zig_as_u8(128) - bits);
1778}
1779
1780static inline zig_i128 zig_byte_swap_i128(zig_i128 val, zig_u8 bits) {
1781 return zig_bitcast_i128(zig_byte_swap_u128(zig_bitcast_u128(val), bits));
1782}
1783
1784static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {
1785 return zig_shr_u128(zig_as_u128(zig_bit_reverse_u64(zig_lo_u128(val), zig_as_u8(64)),
1786 zig_bit_reverse_u64(zig_hi_u128(val), zig_as_u8(64))),
1787 zig_as_u8(128) - bits);
1788}
1789
1790static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
1791 return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits));
1792}
1793
1794/* ========================= Floating Point Support ========================= */
1795
1796#if _MSC_VER
1797#define zig_msvc_flt_inf ((double)(1e+300 * 1e+300))
1798#define zig_msvc_flt_inff ((float)(1e+300 * 1e+300))
1799#define zig_msvc_flt_infl ((long double)(1e+300 * 1e+300))
1800#define zig_msvc_flt_nan ((double)(zig_msvc_flt_inf * 0.f))
1801#define zig_msvc_flt_nanf ((float)(zig_msvc_flt_inf * 0.f))
1802#define zig_msvc_flt_nanl ((long double)(zig_msvc_flt_inf * 0.f))
1803#define __builtin_nan(str) nan(str)
1804#define __builtin_nanf(str) nanf(str)
1805#define __builtin_nanl(str) nanl(str)
1806#define __builtin_inf() zig_msvc_flt_inf
1807#define __builtin_inff() zig_msvc_flt_inff
1808#define __builtin_infl() zig_msvc_flt_infl
1809#endif
1810
1811#if (zig_has_builtin(nan) && zig_has_builtin(nans) && zig_has_builtin(inf)) || defined(zig_gnuc)
1812#define zig_has_float_builtins 1
1813#define zig_as_special_f16(sign, name, arg, repr) sign zig_as_f16(__builtin_##name, )(arg)
1814#define zig_as_special_f32(sign, name, arg, repr) sign zig_as_f32(__builtin_##name, )(arg)
1815#define zig_as_special_f64(sign, name, arg, repr) sign zig_as_f64(__builtin_##name, )(arg)
1816#define zig_as_special_f80(sign, name, arg, repr) sign zig_as_f80(__builtin_##name, )(arg)
1817#define zig_as_special_f128(sign, name, arg, repr) sign zig_as_f128(__builtin_##name, )(arg)
1818#define zig_as_special_c_longdouble(sign, name, arg, repr) sign zig_as_c_longdouble(__builtin_##name, )(arg)
1819#else
1820#define zig_has_float_builtins 0
1821#define zig_as_special_f16(sign, name, arg, repr) zig_float_from_repr_f16(repr)
1822#define zig_as_special_f32(sign, name, arg, repr) zig_float_from_repr_f32(repr)
1823#define zig_as_special_f64(sign, name, arg, repr) zig_float_from_repr_f64(repr)
1824#define zig_as_special_f80(sign, name, arg, repr) zig_float_from_repr_f80(repr)
1825#define zig_as_special_f128(sign, name, arg, repr) zig_float_from_repr_f128(repr)
1826#define zig_as_special_c_longdouble(sign, name, arg, repr) zig_float_from_repr_c_longdouble(repr)
1827#endif
1828
1829#define zig_has_f16 1
1830#define zig_bitSizeOf_f16 16
1831#define zig_libc_name_f16(name) __##name##h
1832#define zig_as_special_constant_f16(sign, name, arg, repr) zig_as_special_f16(sign, name, arg, repr)
1833#if FLT_MANT_DIG == 11
1834typedef float zig_f16;
1835#define zig_as_f16(fp, repr) fp##f
1836#elif DBL_MANT_DIG == 11
1837typedef double zig_f16;
1838#define zig_as_f16(fp, repr) fp
1839#elif LDBL_MANT_DIG == 11
1840#define zig_bitSizeOf_c_longdouble 16
1841typedef long double zig_f16;
1842#define zig_as_f16(fp, repr) fp##l
1843#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc))
1844typedef _Float16 zig_f16;
1845#define zig_as_f16(fp, repr) fp##f16
1846#elif defined(__SIZEOF_FP16__)
1847typedef __fp16 zig_f16;
1848#define zig_as_f16(fp, repr) fp##f16
1849#else
1850#undef zig_has_f16
1851#define zig_has_f16 0
1852#define zig_repr_f16 i16
1853typedef zig_i16 zig_f16;
1854#define zig_as_f16(fp, repr) repr
1855#undef zig_as_special_f16
1856#define zig_as_special_f16(sign, name, arg, repr) repr
1857#undef zig_as_special_constant_f16
1858#define zig_as_special_constant_f16(sign, name, arg, repr) repr
1859#endif
1860
1861#define zig_has_f32 1
1862#define zig_bitSizeOf_f32 32
1863#define zig_libc_name_f32(name) name##f
1864#if _MSC_VER
1865#define zig_as_special_constant_f32(sign, name, arg, repr) sign zig_as_f32(zig_msvc_flt_##name, )
1866#else
1867#define zig_as_special_constant_f32(sign, name, arg, repr) zig_as_special_f32(sign, name, arg, repr)
1868#endif
1869#if FLT_MANT_DIG == 24
1870typedef float zig_f32;
1871#define zig_as_f32(fp, repr) fp##f
1872#elif DBL_MANT_DIG == 24
1873typedef double zig_f32;
1874#define zig_as_f32(fp, repr) fp
1875#elif LDBL_MANT_DIG == 24
1876#define zig_bitSizeOf_c_longdouble 32
1877typedef long double zig_f32;
1878#define zig_as_f32(fp, repr) fp##l
1879#elif FLT32_MANT_DIG == 24
1880typedef _Float32 zig_f32;
1881#define zig_as_f32(fp, repr) fp##f32
1882#else
1883#undef zig_has_f32
1884#define zig_has_f32 0
1885#define zig_repr_f32 i32
1886typedef zig_i32 zig_f32;
1887#define zig_as_f32(fp, repr) repr
1888#undef zig_as_special_f32
1889#define zig_as_special_f32(sign, name, arg, repr) repr
1890#undef zig_as_special_constant_f32
1891#define zig_as_special_constant_f32(sign, name, arg, repr) repr
1892#endif
1893
1894#define zig_has_f64 1
1895#define zig_bitSizeOf_f64 64
1896#define zig_libc_name_f64(name) name
1897#if _MSC_VER
1898#ifdef ZIG_TARGET_ABI_MSVC
1899#define zig_bitSizeOf_c_longdouble 64
1900#endif
1901#define zig_as_special_constant_f64(sign, name, arg, repr) sign zig_as_f64(zig_msvc_flt_##name, )
1902#else /* _MSC_VER */
1903#define zig_as_special_constant_f64(sign, name, arg, repr) zig_as_special_f64(sign, name, arg, repr)
1904#endif /* _MSC_VER */
1905#if FLT_MANT_DIG == 53
1906typedef float zig_f64;
1907#define zig_as_f64(fp, repr) fp##f
1908#elif DBL_MANT_DIG == 53
1909typedef double zig_f64;
1910#define zig_as_f64(fp, repr) fp
1911#elif LDBL_MANT_DIG == 53
1912#define zig_bitSizeOf_c_longdouble 64
1913typedef long double zig_f64;
1914#define zig_as_f64(fp, repr) fp##l
1915#elif FLT64_MANT_DIG == 53
1916typedef _Float64 zig_f64;
1917#define zig_as_f64(fp, repr) fp##f64
1918#elif FLT32X_MANT_DIG == 53
1919typedef _Float32x zig_f64;
1920#define zig_as_f64(fp, repr) fp##f32x
1921#else
1922#undef zig_has_f64
1923#define zig_has_f64 0
1924#define zig_repr_f64 i64
1925typedef zig_i64 zig_f64;
1926#define zig_as_f64(fp, repr) repr
1927#undef zig_as_special_f64
1928#define zig_as_special_f64(sign, name, arg, repr) repr
1929#undef zig_as_special_constant_f64
1930#define zig_as_special_constant_f64(sign, name, arg, repr) repr
1931#endif
1932
1933#define zig_has_f80 1
1934#define zig_bitSizeOf_f80 80
1935#define zig_libc_name_f80(name) __##name##x
1936#define zig_as_special_constant_f80(sign, name, arg, repr) zig_as_special_f80(sign, name, arg, repr)
1937#if FLT_MANT_DIG == 64
1938typedef float zig_f80;
1939#define zig_as_f80(fp, repr) fp##f
1940#elif DBL_MANT_DIG == 64
1941typedef double zig_f80;
1942#define zig_as_f80(fp, repr) fp
1943#elif LDBL_MANT_DIG == 64
1944#define zig_bitSizeOf_c_longdouble 80
1945typedef long double zig_f80;
1946#define zig_as_f80(fp, repr) fp##l
1947#elif FLT80_MANT_DIG == 64
1948typedef _Float80 zig_f80;
1949#define zig_as_f80(fp, repr) fp##f80
1950#elif FLT64X_MANT_DIG == 64
1951typedef _Float64x zig_f80;
1952#define zig_as_f80(fp, repr) fp##f64x
1953#elif defined(__SIZEOF_FLOAT80__)
1954typedef __float80 zig_f80;
1955#define zig_as_f80(fp, repr) fp##l
1956#else
1957#undef zig_has_f80
1958#define zig_has_f80 0
1959#define zig_repr_f80 i128
1960typedef zig_i128 zig_f80;
1961#define zig_as_f80(fp, repr) repr
1962#undef zig_as_special_f80
1963#define zig_as_special_f80(sign, name, arg, repr) repr
1964#undef zig_as_special_constant_f80
1965#define zig_as_special_constant_f80(sign, name, arg, repr) repr
1966#endif
1967
1968#define zig_has_f128 1
1969#define zig_bitSizeOf_f128 128
1970#define zig_libc_name_f128(name) name##q
1971#define zig_as_special_constant_f128(sign, name, arg, repr) zig_as_special_f128(sign, name, arg, repr)
1972#if FLT_MANT_DIG == 113
1973typedef float zig_f128;
1974#define zig_as_f128(fp, repr) fp##f
1975#elif DBL_MANT_DIG == 113
1976typedef double zig_f128;
1977#define zig_as_f128(fp, repr) fp
1978#elif LDBL_MANT_DIG == 113
1979#define zig_bitSizeOf_c_longdouble 128
1980typedef long double zig_f128;
1981#define zig_as_f128(fp, repr) fp##l
1982#elif FLT128_MANT_DIG == 113
1983typedef _Float128 zig_f128;
1984#define zig_as_f128(fp, repr) fp##f128
1985#elif FLT64X_MANT_DIG == 113
1986typedef _Float64x zig_f128;
1987#define zig_as_f128(fp, repr) fp##f64x
1988#elif defined(__SIZEOF_FLOAT128__)
1989typedef __float128 zig_f128;
1990#define zig_as_f128(fp, repr) fp##q
1991#undef zig_as_special_f128
1992#define zig_as_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
1993#else
1994#undef zig_has_f128
1995#define zig_has_f128 0
1996#define zig_repr_f128 i128
1997typedef zig_i128 zig_f128;
1998#define zig_as_f128(fp, repr) repr
1999#undef zig_as_special_f128
2000#define zig_as_special_f128(sign, name, arg, repr) repr
2001#undef zig_as_special_constant_f128
2002#define zig_as_special_constant_f128(sign, name, arg, repr) repr
2003#endif
2004
2005#define zig_has_c_longdouble 1
2006
2007#ifdef ZIG_TARGET_ABI_MSVC
2008#define zig_libc_name_c_longdouble(name) name
2009#else
2010#define zig_libc_name_c_longdouble(name) name##l
2011#endif
2012
2013#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) zig_as_special_c_longdouble(sign, name, arg, repr)
2014#ifdef zig_bitSizeOf_c_longdouble
2015
2016#ifdef ZIG_TARGET_ABI_MSVC
2017typedef double zig_c_longdouble;
2018#undef zig_bitSizeOf_c_longdouble
2019#define zig_bitSizeOf_c_longdouble 64
2020#define zig_as_c_longdouble(fp, repr) fp
2021#else
2022typedef long double zig_c_longdouble;
2023#define zig_as_c_longdouble(fp, repr) fp##l
2024#endif
2025
2026#else /* zig_bitSizeOf_c_longdouble */
2027
2028#undef zig_has_c_longdouble
2029#define zig_has_c_longdouble 0
2030#define zig_bitSizeOf_c_longdouble 80
2031#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80
2032#define zig_repr_c_longdouble i128
2033typedef zig_i128 zig_c_longdouble;
2034#define zig_as_c_longdouble(fp, repr) repr
2035#undef zig_as_special_c_longdouble
2036#define zig_as_special_c_longdouble(sign, name, arg, repr) repr
2037#undef zig_as_special_constant_c_longdouble
2038#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) repr
2039
2040#endif /* zig_bitSizeOf_c_longdouble */
2041
2042#if !zig_has_float_builtins
2043#define zig_float_from_repr(Type, ReprType) \
2044 static inline zig_##Type zig_float_from_repr_##Type(zig_##ReprType repr) { \
2045 return *((zig_##Type*)&repr); \
2046 }
2047
2048zig_float_from_repr(f16, u16)
2049zig_float_from_repr(f32, u32)
2050zig_float_from_repr(f64, u64)
2051zig_float_from_repr(f80, u128)
2052zig_float_from_repr(f128, u128)
2053#if zig_bitSizeOf_c_longdouble == 80
2054zig_float_from_repr(c_longdouble, u128)
2055#else
2056#define zig_expand_float_from_repr(Type, ReprType) zig_float_from_repr(Type, ReprType)
2057zig_expand_float_from_repr(c_longdouble, zig_expand_concat(u, zig_bitSizeOf_c_longdouble))
2058#endif
2059#endif
2060
2061#define zig_cast_f16 (zig_f16)
2062#define zig_cast_f32 (zig_f32)
2063#define zig_cast_f64 (zig_f64)
2064
2065#if _MSC_VER && !zig_has_f128
2066#define zig_cast_f80
2067#define zig_cast_c_longdouble
2068#define zig_cast_f128
2069#else
2070#define zig_cast_f80 (zig_f80)
2071#define zig_cast_c_longdouble (zig_c_longdouble)
2072#define zig_cast_f128 (zig_f128)
2073#endif
2074
2075#define zig_convert_builtin(ResType, operation, ArgType, version) \
2076 zig_extern zig_##ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
2077 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(zig_##ArgType);
2078zig_convert_builtin(f16, trunc, f32, 2)
2079zig_convert_builtin(f16, trunc, f64, 2)
2080zig_convert_builtin(f16, trunc, f80, 2)
2081zig_convert_builtin(f16, trunc, f128, 2)
2082zig_convert_builtin(f32, extend, f16, 2)
2083zig_convert_builtin(f32, trunc, f64, 2)
2084zig_convert_builtin(f32, trunc, f80, 2)
2085zig_convert_builtin(f32, trunc, f128, 2)
2086zig_convert_builtin(f64, extend, f16, 2)
2087zig_convert_builtin(f64, extend, f32, 2)
2088zig_convert_builtin(f64, trunc, f80, 2)
2089zig_convert_builtin(f64, trunc, f128, 2)
2090zig_convert_builtin(f80, extend, f16, 2)
2091zig_convert_builtin(f80, extend, f32, 2)
2092zig_convert_builtin(f80, extend, f64, 2)
2093zig_convert_builtin(f80, trunc, f128, 2)
2094zig_convert_builtin(f128, extend, f16, 2)
2095zig_convert_builtin(f128, extend, f32, 2)
2096zig_convert_builtin(f128, extend, f64, 2)
2097zig_convert_builtin(f128, extend, f80, 2)
2098
2099#define zig_float_negate_builtin_0(Type) \
2100 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \
2101 return zig_expand_concat(zig_xor_, zig_repr_##Type)(arg, zig_expand_minInt(zig_repr_##Type, zig_bitSizeOf_##Type)); \
2102 }
2103#define zig_float_negate_builtin_1(Type) \
2104 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \
2105 return -arg; \
2106 }
2107
2108#define zig_float_less_builtin_0(Type, operation) \
2109 zig_extern zig_i32 zig_expand_concat(zig_expand_concat(__##operation, \
2110 zig_compiler_rt_abbrev_##Type), 2)(zig_##Type, zig_##Type); \
2111 static inline zig_i32 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2112 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 2)(lhs, rhs); \
2113 }
2114#define zig_float_less_builtin_1(Type, operation) \
2115 static inline zig_i32 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2116 return (!(lhs <= rhs) - (lhs < rhs)); \
2117 }
2118
2119#define zig_float_greater_builtin_0(Type, operation) \
2120 zig_float_less_builtin_0(Type, operation)
2121#define zig_float_greater_builtin_1(Type, operation) \
2122 static inline zig_i32 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2123 return ((lhs > rhs) - !(lhs >= rhs)); \
2124 }
2125
2126#define zig_float_binary_builtin_0(Type, operation, operator) \
2127 zig_extern zig_##Type zig_expand_concat(zig_expand_concat(__##operation, \
2128 zig_compiler_rt_abbrev_##Type), 3)(zig_##Type, zig_##Type); \
2129 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2130 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_##Type), 3)(lhs, rhs); \
2131 }
2132#define zig_float_binary_builtin_1(Type, operation, operator) \
2133 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
2134 return lhs operator rhs; \
2135 }
2136
2137#define zig_float_builtins(Type) \
2138 zig_convert_builtin(i32, fix, Type, ) \
2139 zig_convert_builtin(u32, fixuns, Type, ) \
2140 zig_convert_builtin(i64, fix, Type, ) \
2141 zig_convert_builtin(u64, fixuns, Type, ) \
2142 zig_convert_builtin(i128, fix, Type, ) \
2143 zig_convert_builtin(u128, fixuns, Type, ) \
2144 zig_convert_builtin(Type, float, i32, ) \
2145 zig_convert_builtin(Type, floatun, u32, ) \
2146 zig_convert_builtin(Type, float, i64, ) \
2147 zig_convert_builtin(Type, floatun, u64, ) \
2148 zig_convert_builtin(Type, float, i128, ) \
2149 zig_convert_builtin(Type, floatun, u128, ) \
2150 zig_expand_concat(zig_float_negate_builtin_, zig_has_##Type)(Type) \
2151 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, cmp) \
2152 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, ne) \
2153 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, eq) \
2154 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, lt) \
2155 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, le) \
2156 zig_expand_concat(zig_float_greater_builtin_, zig_has_##Type)(Type, gt) \
2157 zig_expand_concat(zig_float_greater_builtin_, zig_has_##Type)(Type, ge) \
2158 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, add, +) \
2159 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, sub, -) \
2160 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, mul, *) \
2161 zig_expand_concat(zig_float_binary_builtin_, zig_has_##Type)(Type, div, /) \
2162 zig_extern zig_##Type zig_libc_name_##Type(sqrt)(zig_##Type); \
2163 zig_extern zig_##Type zig_libc_name_##Type(sin)(zig_##Type); \
2164 zig_extern zig_##Type zig_libc_name_##Type(cos)(zig_##Type); \
2165 zig_extern zig_##Type zig_libc_name_##Type(tan)(zig_##Type); \
2166 zig_extern zig_##Type zig_libc_name_##Type(exp)(zig_##Type); \
2167 zig_extern zig_##Type zig_libc_name_##Type(exp2)(zig_##Type); \
2168 zig_extern zig_##Type zig_libc_name_##Type(log)(zig_##Type); \
2169 zig_extern zig_##Type zig_libc_name_##Type(log2)(zig_##Type); \
2170 zig_extern zig_##Type zig_libc_name_##Type(log10)(zig_##Type); \
2171 zig_extern zig_##Type zig_libc_name_##Type(fabs)(zig_##Type); \
2172 zig_extern zig_##Type zig_libc_name_##Type(floor)(zig_##Type); \
2173 zig_extern zig_##Type zig_libc_name_##Type(ceil)(zig_##Type); \
2174 zig_extern zig_##Type zig_libc_name_##Type(round)(zig_##Type); \
2175 zig_extern zig_##Type zig_libc_name_##Type(trunc)(zig_##Type); \
2176 zig_extern zig_##Type zig_libc_name_##Type(fmod)(zig_##Type, zig_##Type); \
2177 zig_extern zig_##Type zig_libc_name_##Type(fmin)(zig_##Type, zig_##Type); \
2178 zig_extern zig_##Type zig_libc_name_##Type(fmax)(zig_##Type, zig_##Type); \
2179 zig_extern zig_##Type zig_libc_name_##Type(fma)(zig_##Type, zig_##Type, zig_##Type); \
2180\
2181 static inline zig_##Type zig_div_trunc_##Type(zig_##Type lhs, zig_##Type rhs) { \
2182 return zig_libc_name_##Type(trunc)(zig_div_##Type(lhs, rhs)); \
2183 } \
2184\
2185 static inline zig_##Type zig_div_floor_##Type(zig_##Type lhs, zig_##Type rhs) { \
2186 return zig_libc_name_##Type(floor)(zig_div_##Type(lhs, rhs)); \
2187 } \
2188\
2189 static inline zig_##Type zig_mod_##Type(zig_##Type lhs, zig_##Type rhs) { \
2190 return zig_sub_##Type(lhs, zig_mul_##Type(zig_div_floor_##Type(lhs, rhs), rhs)); \
2191 }
2192zig_float_builtins(f16)
2193zig_float_builtins(f32)
2194zig_float_builtins(f64)
2195zig_float_builtins(f80)
2196zig_float_builtins(f128)
2197zig_float_builtins(c_longdouble)
2198
2199#if _MSC_VER && (_M_IX86 || _M_X64)
2200
2201// TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, and load 64 bit without interlocked on x64
2202
2203#define zig_msvc_atomics(Type, suffix) \
2204 static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
2205 zig_##Type comparand = *expected; \
2206 zig_##Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \
2207 bool exchanged = initial == comparand; \
2208 if (!exchanged) { \
2209 *expected = initial; \
2210 } \
2211 return exchanged; \
2212 } \
2213 static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2214 return _InterlockedExchange##suffix(obj, value); \
2215 } \
2216 static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2217 return _InterlockedExchangeAdd##suffix(obj, value); \
2218 } \
2219 static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2220 bool success = false; \
2221 zig_##Type new; \
2222 zig_##Type prev; \
2223 while (!success) { \
2224 prev = *obj; \
2225 new = prev - value; \
2226 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2227 } \
2228 return prev; \
2229 } \
2230 static inline zig_##Type zig_msvc_atomicrmw_or_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2231 return _InterlockedOr##suffix(obj, value); \
2232 } \
2233 static inline zig_##Type zig_msvc_atomicrmw_xor_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2234 return _InterlockedXor##suffix(obj, value); \
2235 } \
2236 static inline zig_##Type zig_msvc_atomicrmw_and_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2237 return _InterlockedAnd##suffix(obj, value); \
2238 } \
2239 static inline zig_##Type zig_msvc_atomicrmw_nand_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2240 bool success = false; \
2241 zig_##Type new; \
2242 zig_##Type prev; \
2243 while (!success) { \
2244 prev = *obj; \
2245 new = ~(prev & value); \
2246 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2247 } \
2248 return prev; \
2249 } \
2250 static inline zig_##Type zig_msvc_atomicrmw_min_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2251 bool success = false; \
2252 zig_##Type new; \
2253 zig_##Type prev; \
2254 while (!success) { \
2255 prev = *obj; \
2256 new = value < prev ? value : prev; \
2257 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2258 } \
2259 return prev; \
2260 } \
2261 static inline zig_##Type zig_msvc_atomicrmw_max_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2262 bool success = false; \
2263 zig_##Type new; \
2264 zig_##Type prev; \
2265 while (!success) { \
2266 prev = *obj; \
2267 new = value > prev ? value : prev; \
2268 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2269 } \
2270 return prev; \
2271 } \
2272 static inline void zig_msvc_atomic_store_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2273 _InterlockedExchange##suffix(obj, value); \
2274 } \
2275 static inline zig_##Type zig_msvc_atomic_load_##Type(zig_##Type volatile* obj) { \
2276 return _InterlockedOr##suffix(obj, 0); \
2277 }
2278
2279zig_msvc_atomics(u8, 8)
2280zig_msvc_atomics(i8, 8)
2281zig_msvc_atomics(u16, 16)
2282zig_msvc_atomics(i16, 16)
2283zig_msvc_atomics(u32, )
2284zig_msvc_atomics(i32, )
2285
2286#if _M_X64
2287zig_msvc_atomics(u64, 64)
2288zig_msvc_atomics(i64, 64)
2289#endif
2290
2291#define zig_msvc_flt_atomics(Type, ReprType, suffix) \
2292 static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
2293 zig_##ReprType comparand = *((zig_##ReprType*)expected); \
2294 zig_##ReprType initial = _InterlockedCompareExchange##suffix((zig_##ReprType volatile*)obj, *((zig_##ReprType*)&desired), comparand); \
2295 bool exchanged = initial == comparand; \
2296 if (!exchanged) { \
2297 *expected = *((zig_##Type*)&initial); \
2298 } \
2299 return exchanged; \
2300 } \
2301 static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2302 zig_##ReprType initial = _InterlockedExchange##suffix((zig_##ReprType volatile*)obj, *((zig_##ReprType*)&value)); \
2303 return *((zig_##Type*)&initial); \
2304 } \
2305 static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2306 bool success = false; \
2307 zig_##ReprType new; \
2308 zig_##Type prev; \
2309 while (!success) { \
2310 prev = *obj; \
2311 new = prev + value; \
2312 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \
2313 } \
2314 return prev; \
2315 } \
2316 static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2317 bool success = false; \
2318 zig_##ReprType new; \
2319 zig_##Type prev; \
2320 while (!success) { \
2321 prev = *obj; \
2322 new = prev - value; \
2323 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \
2324 } \
2325 return prev; \
2326 }
2327
2328zig_msvc_flt_atomics(f32, u32, )
2329#if _M_X64
2330zig_msvc_flt_atomics(f64, u64, 64)
2331#endif
2332
2333#if _M_IX86
2334static inline void zig_msvc_atomic_barrier() {
2335 zig_i32 barrier;
2336 __asm {
2337 xchg barrier, eax
2338 }
2339}
2340
2341static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, zig_u32* arg) {
2342 return _InterlockedExchangePointer(obj, arg);
2343}
2344
2345static inline void zig_msvc_atomic_store_p32(void** obj, zig_u32* arg) {
2346 _InterlockedExchangePointer(obj, arg);
2347}
2348
2349static inline void* zig_msvc_atomic_load_p32(void** obj) {
2350 return (void*)_InterlockedOr((void*)obj, 0);
2351}
2352
2353static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desired) {
2354 void* comparand = *expected;
2355 void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand);
2356 bool exchanged = initial == comparand;
2357 if (!exchanged) {
2358 *expected = initial;
2359 }
2360 return exchanged;
2361}
2362#else /* _M_IX86 */
2363static inline void* zig_msvc_atomicrmw_xchg_p64(void** obj, zig_u64* arg) {
2364 return _InterlockedExchangePointer(obj, arg);
2365}
2366
2367static inline void zig_msvc_atomic_store_p64(void** obj, zig_u64* arg) {
2368 _InterlockedExchangePointer(obj, arg);
2369}
2370
2371static inline void* zig_msvc_atomic_load_p64(void** obj) {
2372 return (void*)_InterlockedOr64((void*)obj, 0);
2373}
2374
2375static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desired) {
2376 void* comparand = *expected;
2377 void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand);
2378 bool exchanged = initial == comparand;
2379 if (!exchanged) {
2380 *expected = initial;
2381 }
2382 return exchanged;
2383}
2384
2385static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expected, zig_u128 desired) {
2386 return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_i64*)expected);
2387}
2388
2389static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {
2390 return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_u64*)expected);
2391}
2392
2393#define zig_msvc_atomics_128xchg(Type) \
2394 static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2395 bool success = false; \
2396 zig_##Type prev; \
2397 while (!success) { \
2398 prev = *obj; \
2399 success = zig_msvc_cmpxchg_##Type(obj, &prev, value); \
2400 } \
2401 return prev; \
2402 }
2403
2404zig_msvc_atomics_128xchg(u128)
2405zig_msvc_atomics_128xchg(i128)
2406
2407#define zig_msvc_atomics_128op(Type, operation) \
2408 static inline zig_##Type zig_msvc_atomicrmw_##operation##_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2409 bool success = false; \
2410 zig_##Type new; \
2411 zig_##Type prev; \
2412 while (!success) { \
2413 prev = *obj; \
2414 new = zig_##operation##_##Type(prev, value); \
2415 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
2416 } \
2417 return prev; \
2418 }
2419
2420zig_msvc_atomics_128op(u128, add)
2421zig_msvc_atomics_128op(u128, sub)
2422zig_msvc_atomics_128op(u128, or)
2423zig_msvc_atomics_128op(u128, xor)
2424zig_msvc_atomics_128op(u128, and)
2425zig_msvc_atomics_128op(u128, nand)
2426zig_msvc_atomics_128op(u128, min)
2427zig_msvc_atomics_128op(u128, max)
2428#endif /* _M_IX86 */
2429
2430#endif /* _MSC_VER && (_M_IX86 || _M_X64) */
2431
2432/* ========================= Special Case Intrinsics ========================= */
2433
2434#if (_MSC_VER && _M_X64) || defined(__x86_64__)
2435
2436static inline void* zig_x86_64_windows_teb(void) {
2437#if _MSC_VER
2438 return (void*)__readgsqword(0x30);
2439#else
2440 void* teb;
2441 __asm volatile(" movq %%gs:0x30, %[ptr]": [ptr]"=r"(teb)::);
2442 return teb;
2443#endif
2444}
2445
2446#elif (_MSC_VER && _M_IX86) || defined(__i386__) || defined(__X86__)
2447
2448static inline void* zig_x86_windows_teb(void) {
2449#if _MSC_VER
2450 return (void*)__readfsdword(0x18);
2451#else
2452 void* teb;
2453 __asm volatile(" movl %%fs:0x18, %[ptr]": [ptr]"=r"(teb)::);
2454 return teb;
2455#endif
2456}
2457
2458#endif
2459
2460#if (_MSC_VER && (_M_IX86 || _M_X64)) || defined(__i386__) || defined(__x86_64__)
2461
2462static inline void zig_x86_cpuid(zig_u32 leaf_id, zig_u32 subid, zig_u32* eax, zig_u32* ebx, zig_u32* ecx, zig_u32* edx) {
2463 zig_u32 cpu_info[4];
2464#if _MSC_VER
2465 __cpuidex(cpu_info, leaf_id, subid);
2466#else
2467 __cpuid_count(leaf_id, subid, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
2468#endif
2469 *eax = cpu_info[0];
2470 *ebx = cpu_info[1];
2471 *ecx = cpu_info[2];
2472 *edx = cpu_info[3];
2473}
2474
2475static inline zig_u32 zig_x86_get_xcr0(void) {
2476#if _MSC_VER
2477 return (zig_u32)_xgetbv(0);
2478#else
2479 zig_u32 eax;
2480 zig_u32 edx;
2481 __asm__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
2482 return eax;
2483#endif
2484}
2485
2486#endif
test/behavior/align.zig+5-1
......@@ -551,7 +551,11 @@ test "align(N) on functions" {
551551 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
552552 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
553553 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
554 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO this is not supported on MSVC
554
555 // This is not supported on MSVC
556 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) {
557 return error.SkipZigTest;
558 }
555559
556560 // function alignment is a compile error on wasm32/wasm64
557561 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;
test/behavior/asm.zig+13-5
......@@ -7,6 +7,7 @@ const is_x86_64_linux = builtin.cpu.arch == .x86_64 and builtin.os.tag == .linux
77comptime {
88 if (builtin.zig_backend != .stage2_arm and
99 builtin.zig_backend != .stage2_aarch64 and
10 !(builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) and // MSVC doesn't support inline assembly
1011 is_x86_64_linux)
1112 {
1213 asm (
......@@ -23,7 +24,8 @@ test "module level assembly" {
2324 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
2425 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
2526 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
27
28 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
2729
2830 if (is_x86_64_linux) {
2931 try expect(this_is_my_alias() == 1234);
......@@ -36,7 +38,8 @@ test "output constraint modifiers" {
3638 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
3739 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
3840 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
39 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
41
42 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
4043
4144 // This is only testing compilation.
4245 var a: u32 = 3;
......@@ -58,7 +61,8 @@ test "alternative constraints" {
5861 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5962 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
6063 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
64
65 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
6266
6367 // Make sure we allow commas as a separator for alternative constraints.
6468 var a: u32 = 3;
......@@ -75,7 +79,8 @@ test "sized integer/float in asm input" {
7579 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
7680 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7781 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
82
83 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
7984
8085 asm volatile (""
8186 :
......@@ -125,7 +130,8 @@ test "struct/array/union types as input values" {
125130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
126131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
127132 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
128 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
133
134 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
129135
130136 asm volatile (""
131137 :
......@@ -151,6 +157,8 @@ test "asm modifiers (AArch64)" {
151157 if (builtin.target.cpu.arch != .aarch64) return error.SkipZigTest;
152158 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
153159
160 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
161
154162 var x: u32 = 15;
155163 const double = asm ("add %[ret:w], %[in:w], %[in:w]"
156164 : [ret] "=r" (-> u32),
test/behavior/int_comparison_elision.zig-1
......@@ -13,7 +13,6 @@ test "int comparison elision" {
1313
1414 // TODO: support int types > 128 bits wide in other backends
1515 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1716 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1817 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1918 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/lower_strlit_to_vector.zig-1
......@@ -7,7 +7,6 @@ test "strlit to vector" {
77 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
88 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
99 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1110
1211 const strlit = "0123456789abcdef0123456789ABCDEF";
1312 const vec_from_strlit: @Vector(32, u8) = strlit.*;
test/behavior/math.zig-1
......@@ -1463,7 +1463,6 @@ test "vector integer addition" {
14631463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
14641464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
14651465 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1466 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
14671466 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14681467
14691468 const S = struct {
test/behavior/struct.zig-1
......@@ -1330,7 +1330,6 @@ test "struct field init value is size of the struct" {
13301330}
13311331
13321332test "under-aligned struct field" {
1333 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
13341333 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
13351334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
13361335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/vector.zig-5
......@@ -75,7 +75,6 @@ test "vector int operators" {
7575 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
7676 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7777 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
7978 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8079
8180 const S = struct {
......@@ -178,7 +177,6 @@ test "tuple to vector" {
178177 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
179178 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
180179 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
181 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
182180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
183181
184182 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
......@@ -943,7 +941,6 @@ test "multiplication-assignment operator with an array operand" {
943941 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
944942 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
945943 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
946 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
947944 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
948945
949946 const S = struct {
......@@ -1247,7 +1244,6 @@ test "array operands to shuffle are coerced to vectors" {
12471244test "load packed vector element" {
12481245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12491246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12511247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12521248 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
12531249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
......@@ -1260,7 +1256,6 @@ test "load packed vector element" {
12601256test "store packed vector element" {
12611257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
12621258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1263 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12641259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
12651260 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
12661261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/stage2/cbe.zig+6-6
......@@ -959,7 +959,7 @@ pub fn addCases(ctx: *TestContext) !void {
959959 \\ _ = a;
960960 \\}
961961 ,
962 \\zig_extern void start(zig_u8 const a0);
962 \\zig_extern void start(uint8_t const a0);
963963 \\
964964 );
965965 ctx.h("header with multiple param function", linux_x64,
......@@ -967,19 +967,19 @@ pub fn addCases(ctx: *TestContext) !void {
967967 \\ _ = a; _ = b; _ = c;
968968 \\}
969969 ,
970 \\zig_extern void start(zig_u8 const a0, zig_u8 const a1, zig_u8 const a2);
970 \\zig_extern void start(uint8_t const a0, uint8_t const a1, uint8_t 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 void start(zig_u32 const a0);
976 \\zig_extern void start(uint32_t 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 void start(zig_usize const a0);
982 \\zig_extern void start(uintptr_t const a0);
983983 \\
984984 );
985985 ctx.h("header with bool param function", linux_x64,
......@@ -993,7 +993,7 @@ pub fn addCases(ctx: *TestContext) !void {
993993 \\ unreachable;
994994 \\}
995995 ,
996 \\zig_extern zig_noreturn start(void);
996 \\zig_extern zig_noreturn void start(void);
997997 \\
998998 );
999999 ctx.h("header with multiple functions", linux_x64,
......@@ -1009,7 +1009,7 @@ pub fn addCases(ctx: *TestContext) !void {
10091009 ctx.h("header with multiple includes", linux_x64,
10101010 \\export fn start(a: u32, b: usize) void{ _ = a; _ = b; }
10111011 ,
1012 \\zig_extern void start(zig_u32 const a0, zig_usize const a1);
1012 \\zig_extern void start(uint32_t const a0, uintptr_t const a1);
10131013 \\
10141014 );
10151015}