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...@@ -569,6 +569,7 @@ set(ZIG_STAGE2_SOURCES
569 "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig"569 "${CMAKE_SOURCE_DIR}/src/clang_options_data.zig"
570 "${CMAKE_SOURCE_DIR}/src/codegen.zig"570 "${CMAKE_SOURCE_DIR}/src/codegen.zig"
571 "${CMAKE_SOURCE_DIR}/src/codegen/c.zig"571 "${CMAKE_SOURCE_DIR}/src/codegen/c.zig"
572 "${CMAKE_SOURCE_DIR}/src/codegen/c/type.zig"
572 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"573 "${CMAKE_SOURCE_DIR}/src/codegen/llvm.zig"
573 "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig"574 "${CMAKE_SOURCE_DIR}/src/codegen/llvm/bindings.zig"
574 "${CMAKE_SOURCE_DIR}/src/glibc.zig"575 "${CMAKE_SOURCE_DIR}/src/glibc.zig"
...@@ -784,7 +785,7 @@ set_target_properties(zig2 PROPERTIES...@@ -784,7 +785,7 @@ set_target_properties(zig2 PROPERTIES
784 COMPILE_FLAGS ${ZIG2_COMPILE_FLAGS}785 COMPILE_FLAGS ${ZIG2_COMPILE_FLAGS}
785 LINK_FLAGS ${ZIG2_LINK_FLAGS}786 LINK_FLAGS ${ZIG2_LINK_FLAGS}
786)787)
787target_include_directories(zig2 PUBLIC "${CMAKE_SOURCE_DIR}/lib")788target_include_directories(zig2 PUBLIC "${CMAKE_SOURCE_DIR}/stage1")
788target_link_libraries(zig2 LINK_PUBLIC zigcpp)789target_link_libraries(zig2 LINK_PUBLIC zigcpp)
789790
790if(MSVC)791if(MSVC)
build.zig+31
...@@ -509,8 +509,39 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {...@@ -509,8 +509,39 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void {
509 run_opt.addArg("-o");509 run_opt.addArg("-o");
510 run_opt.addFileSourceArg(.{ .path = "stage1/zig1.wasm" });510 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
512 const update_zig1_step = b.step("update-zig1", "Update stage1/zig1.wasm");542 const update_zig1_step = b.step("update-zig1", "Update stage1/zig1.wasm");
513 update_zig1_step.dependOn(&run_opt.step);543 update_zig1_step.dependOn(&run_opt.step);
544 update_zig1_step.dependOn(&copy_zig_h.step);
514}545}
515546
516fn addCompilerStep(547fn addCompilerStep(
lib/std/hash_map.zig+2-2
...@@ -508,7 +508,7 @@ pub fn HashMap(...@@ -508,7 +508,7 @@ pub fn HashMap(
508 /// If a new entry needs to be stored, this function asserts there508 /// If a new entry needs to be stored, this function asserts there
509 /// is enough capacity to store it.509 /// is enough capacity to store it.
510 pub fn getOrPutAssumeCapacityAdapted(self: *Self, key: anytype, ctx: anytype) GetOrPutResult {510 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);
512 }512 }
513513
514 pub fn getOrPutValue(self: *Self, key: K, value: V) Allocator.Error!Entry {514 pub fn getOrPutValue(self: *Self, key: K, value: V) Allocator.Error!Entry {
...@@ -2130,7 +2130,7 @@ test "std.hash_map getOrPutAdapted" {...@@ -2130,7 +2130,7 @@ test "std.hash_map getOrPutAdapted" {
2130 try testing.expectEqual(map.count(), keys.len);2130 try testing.expectEqual(map.count(), keys.len);
21312131
2132 inline for (keys, 0..) |key_str, i| {2132 inline for (keys, 0..) |key_str, i| {
2133 const result = try map.getOrPutAdapted(key_str, AdaptedContext{});2133 const result = map.getOrPutAssumeCapacityAdapted(key_str, AdaptedContext{});
2134 try testing.expect(result.found_existing);2134 try testing.expect(result.found_existing);
2135 try testing.expectEqual(real_keys[i], result.key_ptr.*);2135 try testing.expectEqual(real_keys[i], result.key_ptr.*);
2136 try testing.expectEqual(@as(u64, i) * 2, result.value_ptr.*);2136 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 {...@@ -433,15 +433,9 @@ pub fn MultiArrayList(comptime S: type) type {
433 }433 }
434434
435 fn capacityInBytes(capacity: usize) usize {435 fn capacityInBytes(capacity: usize) usize {
436 if (builtin.zig_backend == .stage2_c) {436 comptime var elem_bytes: usize = 0;
437 var bytes: usize = 0;437 inline for (sizes.bytes) |size| elem_bytes += size;
438 for (sizes.bytes) |size| bytes += size * capacity;438 return elem_bytes * 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 }
445 }439 }
446440
447 fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {441 fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {
lib/zig.h+860-767
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1#undef linux1#undef linux
22
3#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
3#define __STDC_WANT_IEC_60559_TYPES_EXT__4#define __STDC_WANT_IEC_60559_TYPES_EXT__
5#endif
4#include <float.h>6#include <float.h>
5#include <limits.h>7#include <limits.h>
6#include <stddef.h>8#include <stddef.h>
...@@ -286,701 +288,802 @@ typedef char bool;...@@ -286,701 +288,802 @@ typedef char bool;
286#endif288#endif
287289
288#if __STDC_VERSION__ >= 201112L290#if __STDC_VERSION__ >= 201112L
289#define zig_noreturn _Noreturn void291#define zig_noreturn _Noreturn
290#elif zig_has_attribute(noreturn) || defined(zig_gnuc)292#elif zig_has_attribute(noreturn) || defined(zig_gnuc)
291#define zig_noreturn __attribute__((noreturn)) void293#define zig_noreturn __attribute__((noreturn))
292#elif _MSC_VER294#elif _MSC_VER
293#define zig_noreturn __declspec(noreturn) void295#define zig_noreturn __declspec(noreturn)
294#else296#else
295#define zig_noreturn void297#define zig_noreturn
296#endif298#endif
297299
298#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))300#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
299301
300typedef uintptr_t zig_usize;302#define zig_compiler_rt_abbrev_uint32_t si
301typedef intptr_t zig_isize;303#define zig_compiler_rt_abbrev_int32_t si
302typedef signed short int zig_c_short;304#define zig_compiler_rt_abbrev_uint64_t di
303typedef unsigned short int zig_c_ushort;305#define zig_compiler_rt_abbrev_int64_t di
304typedef signed int zig_c_int;306#define zig_compiler_rt_abbrev_zig_u128 ti
305typedef unsigned int zig_c_uint;307#define zig_compiler_rt_abbrev_zig_i128 ti
306typedef signed long int zig_c_long;308#define zig_compiler_rt_abbrev_zig_f16 hf
307typedef unsigned long int zig_c_ulong;309#define zig_compiler_rt_abbrev_zig_f32 sf
308typedef signed long long int zig_c_longlong;310#define zig_compiler_rt_abbrev_zig_f64 df
309typedef unsigned long long int zig_c_ulonglong;311#define zig_compiler_rt_abbrev_zig_f80 xf
310312#define zig_compiler_rt_abbrev_zig_f128 tf
311typedef uint8_t zig_u8;313
312typedef int8_t zig_i8;314zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
313typedef uint16_t zig_u16;315zig_extern void *memset (void *, int, size_t);
314typedef int16_t zig_i16;316
315typedef uint32_t zig_u32;317/* ===================== 8/16/32/64-bit Integer Support ===================== */
316typedef int32_t zig_i32;318
317typedef uint64_t zig_u64;319#if __STDC_VERSION__ >= 199901L || _MSC_VER
318typedef int64_t zig_i64;320#include <stdint.h>
319321#else
320#define zig_as_u8(val) UINT8_C(val)322
321#define zig_as_i8(val) INT8_C(val)323#if SCHAR_MIN == ~0x7F && SCHAR_MAX == 0x7F && UCHAR_MAX == 0xFF
322#define zig_as_u16(val) UINT16_C(val)324typedef unsigned char uint8_t;
323#define zig_as_i16(val) INT16_C(val)325typedef signed char int8_t;
324#define zig_as_u32(val) UINT32_C(val)326#define INT8_C(c) c
325#define zig_as_i32(val) INT32_C(val)327#define UINT8_C(c) c##U
326#define zig_as_u64(val) UINT64_C(val)328#elif SHRT_MIN == ~0x7F && SHRT_MAX == 0x7F && USHRT_MAX == 0xFF
327#define zig_as_i64(val) INT64_C(val)329typedef unsigned short uint8_t;
328330typedef signed short int8_t;
329#define zig_minInt_u8 zig_as_u8(0)331#define INT8_C(c) c
330#define zig_maxInt_u8 UINT8_MAX332#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
331#define zig_minInt_i8 INT8_MIN448#define zig_minInt_i8 INT8_MIN
332#define zig_maxInt_i8 INT8_MAX449#define zig_maxInt_i8 INT8_MAX
333#define zig_minInt_u16 zig_as_u16(0)450#define zig_minInt_u8 UINT8_C(0)
334#define zig_maxInt_u16 UINT16_MAX451#define zig_maxInt_u8 UINT8_MAX
335#define zig_minInt_i16 INT16_MIN452#define zig_minInt_i16 INT16_MIN
336#define zig_maxInt_i16 INT16_MAX453#define zig_maxInt_i16 INT16_MAX
337#define zig_minInt_u32 zig_as_u32(0)454#define zig_minInt_u16 UINT16_C(0)
338#define zig_maxInt_u32 UINT32_MAX455#define zig_maxInt_u16 UINT16_MAX
339#define zig_minInt_i32 INT32_MIN456#define zig_minInt_i32 INT32_MIN
340#define zig_maxInt_i32 INT32_MAX457#define zig_maxInt_i32 INT32_MAX
341#define zig_minInt_u64 zig_as_u64(0)458#define zig_minInt_u32 UINT32_C(0)
342#define zig_maxInt_u64 UINT64_MAX459#define zig_maxInt_u32 UINT32_MAX
343#define zig_minInt_i64 INT64_MIN460#define zig_minInt_i64 INT64_MIN
344#define zig_maxInt_i64 INT64_MAX461#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 si465#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
347#define zig_compiler_rt_abbrev_i32 si466#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
348#define zig_compiler_rt_abbrev_u64 di467#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
349#define zig_compiler_rt_abbrev_i64 di468#define zig_minInt_u(w, bits) zig_intLimit(u, w, min, bits)
350#define zig_compiler_rt_abbrev_u128 ti469#define zig_maxInt_u(w, bits) zig_intLimit(u, w, max, bits)
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)
367470
368#define zig_int_operator(Type, RhsType, operation, operator) \471#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) { \
370 return lhs operator rhs; \473 return lhs operator rhs; \
371 }474 }
372#define zig_int_basic_operator(Type, operation, operator) \475#define zig_int_basic_operator(Type, operation, operator) \
373 zig_int_operator(Type, Type, operation, operator)476 zig_int_operator(Type, Type, operation, operator)
374#define zig_int_shift_operator(Type, operation, operator) \477#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)
376#define zig_int_helpers(w) \479#define zig_int_helpers(w) \
377 zig_int_basic_operator(u##w, and, &) \480 zig_int_basic_operator(uint##w##_t, and_u##w, &) \
378 zig_int_basic_operator(i##w, and, &) \481 zig_int_basic_operator( int##w##_t, and_i##w, &) \
379 zig_int_basic_operator(u##w, or, |) \482 zig_int_basic_operator(uint##w##_t, or_u##w, |) \
380 zig_int_basic_operator(i##w, or, |) \483 zig_int_basic_operator( int##w##_t, or_i##w, |) \
381 zig_int_basic_operator(u##w, xor, ^) \484 zig_int_basic_operator(uint##w##_t, xor_u##w, ^) \
382 zig_int_basic_operator(i##w, xor, ^) \485 zig_int_basic_operator( int##w##_t, xor_i##w, ^) \
383 zig_int_shift_operator(u##w, shl, <<) \486 zig_int_shift_operator(uint##w##_t, shl_u##w, <<) \
384 zig_int_shift_operator(i##w, shl, <<) \487 zig_int_shift_operator( int##w##_t, shl_i##w, <<) \
385 zig_int_shift_operator(u##w, shr, >>) \488 zig_int_shift_operator(uint##w##_t, shr_u##w, >>) \
386\489\
387 static inline zig_i##w zig_shr_i##w(zig_i##w lhs, zig_u8 rhs) { \490 static inline int##w##_t zig_shr_i##w(int##w##_t lhs, uint8_t rhs) { \
388 zig_i##w sign_mask = lhs < zig_as_i##w(0) ? -zig_as_i##w(1) : zig_as_i##w(0); \491 int##w##_t sign_mask = lhs < INT##w##_C(0) ? -INT##w##_C(1) : INT##w##_C(0); \
389 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \492 return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
390 } \493 } \
391\494\
392 static inline zig_u##w zig_not_u##w(zig_u##w val, zig_u8 bits) { \495 static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \
393 return val ^ zig_maxInt(u##w, bits); \496 return val ^ zig_maxInt_u(w, bits); \
394 } \497 } \
395\498\
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) { \
397 (void)bits; \500 (void)bits; \
398 return ~val; \501 return ~val; \
399 } \502 } \
400\503\
401 static inline zig_u##w zig_wrap_u##w(zig_u##w val, zig_u8 bits) { \504 static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \
402 return val & zig_maxInt(u##w, bits); \505 return val & zig_maxInt_u(w, bits); \
403 } \506 } \
404\507\
405 static inline zig_i##w zig_wrap_i##w(zig_i##w val, zig_u8 bits) { \508 static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \
406 return (val & zig_as_u##w(1) << (bits - zig_as_u8(1))) != 0 \509 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
407 ? val | zig_minInt(i##w, bits) : val & zig_maxInt(i##w, bits); \510 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
408 } \511 } \
409\512\
410 zig_int_basic_operator(u##w, div_floor, /) \513 zig_int_basic_operator(uint##w##_t, div_floor_u##w, /) \
411\514\
412 static inline zig_i##w zig_div_floor_i##w(zig_i##w lhs, zig_i##w rhs) { \515 static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \
413 return lhs / rhs - (((lhs ^ rhs) & (lhs % rhs)) < zig_as_i##w(0)); \516 return lhs / rhs - (((lhs ^ rhs) & (lhs % rhs)) < INT##w##_C(0)); \
414 } \517 } \
415\518\
416 zig_int_basic_operator(u##w, mod, %) \519 zig_int_basic_operator(uint##w##_t, mod_u##w, %) \
417\520\
418 static inline zig_i##w zig_mod_i##w(zig_i##w lhs, zig_i##w rhs) { \521 static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
419 zig_i##w rem = lhs % rhs; \522 int##w##_t rem = lhs % rhs; \
420 return rem + (((lhs ^ rhs) & rem) < zig_as_i##w(0) ? rhs : zig_as_i##w(0)); \523 return rem + (((lhs ^ rhs) & rem) < INT##w##_C(0) ? rhs : INT##w##_C(0)); \
421 } \524 } \
422\525\
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) { \
424 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \527 return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
425 } \528 } \
426\529\
427 static inline zig_i##w zig_shlw_i##w(zig_i##w lhs, zig_u8 rhs, zig_u8 bits) { \530 static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
428 return zig_wrap_i##w((zig_i##w)zig_shl_u##w((zig_u##w)lhs, (zig_u##w)rhs), bits); \531 return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, (uint##w##_t)rhs), bits); \
429 } \532 } \
430\533\
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) { \
432 return zig_wrap_u##w(lhs + rhs, bits); \535 return zig_wrap_u##w(lhs + rhs, bits); \
433 } \536 } \
434\537\
435 static inline zig_i##w zig_addw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \538 static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
436 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs + (zig_u##w)rhs), bits); \539 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \
437 } \540 } \
438\541\
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) { \
440 return zig_wrap_u##w(lhs - rhs, bits); \543 return zig_wrap_u##w(lhs - rhs, bits); \
441 } \544 } \
442\545\
443 static inline zig_i##w zig_subw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \546 static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
444 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs - (zig_u##w)rhs), bits); \547 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \
445 } \548 } \
446\549\
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) { \
448 return zig_wrap_u##w(lhs * rhs, bits); \551 return zig_wrap_u##w(lhs * rhs, bits); \
449 } \552 } \
450\553\
451 static inline zig_i##w zig_mulw_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \554 static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
452 return zig_wrap_i##w((zig_i##w)((zig_u##w)lhs * (zig_u##w)rhs), bits); \555 return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \
453 }556 }
454zig_int_helpers(8)557zig_int_helpers(8)
455zig_int_helpers(16)558zig_int_helpers(16)
456zig_int_helpers(32)559zig_int_helpers(32)
457zig_int_helpers(64)560zig_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) {
460#if zig_has_builtin(add_overflow) || defined(zig_gnuc)563#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
461 zig_u32 full_res;564 uint32_t full_res;
462 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);565 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
463 *res = zig_wrap_u32(full_res, bits);566 *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);
465#else568#else
466 *res = zig_addw_u32(lhs, rhs, bits);569 *res = zig_addw_u32(lhs, rhs, bits);
467 return *res < lhs;570 return *res < lhs;
468#endif571#endif
469}572}
470573
471static inline void zig_vaddo_u32(zig_u8 *ov, zig_u32 *res, int n,574static inline void zig_vaddo_u32(uint8_t *ov, uint32_t *res, int n,
472 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)575 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
473{576{
474 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits);577 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u32(&res[i], lhs[i], rhs[i], bits);
475}578}
476579
477zig_extern zig_i32 __addosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);580zig_extern int32_t __addosi4(int32_t lhs, int32_t rhs, int *overflow);
478static inline bool zig_addo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {581static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
479#if zig_has_builtin(add_overflow) || defined(zig_gnuc)582#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
480 zig_i32 full_res;583 int32_t full_res;
481 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);584 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
482#else585#else
483 zig_c_int overflow_int;586 int overflow_int;
484 zig_i32 full_res = __addosi4(lhs, rhs, &overflow_int);587 int32_t full_res = __addosi4(lhs, rhs, &overflow_int);
485 bool overflow = overflow_int != 0;588 bool overflow = overflow_int != 0;
486#endif589#endif
487 *res = zig_wrap_i32(full_res, bits);590 *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);
489}592}
490593
491static inline void zig_vaddo_i32(zig_u8 *ov, zig_i32 *res, int n,594static inline void zig_vaddo_i32(uint8_t *ov, int32_t *res, int n,
492 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)595 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
493{596{
494 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits);597 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i32(&res[i], lhs[i], rhs[i], bits);
495}598}
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) {
498#if zig_has_builtin(add_overflow) || defined(zig_gnuc)601#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
499 zig_u64 full_res;602 uint64_t full_res;
500 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);603 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
501 *res = zig_wrap_u64(full_res, bits);604 *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);
503#else606#else
504 *res = zig_addw_u64(lhs, rhs, bits);607 *res = zig_addw_u64(lhs, rhs, bits);
505 return *res < lhs;608 return *res < lhs;
506#endif609#endif
507}610}
508611
509static inline void zig_vaddo_u64(zig_u8 *ov, zig_u64 *res, int n,612static inline void zig_vaddo_u64(uint8_t *ov, uint64_t *res, int n,
510 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)613 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
511{614{
512 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits);615 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u64(&res[i], lhs[i], rhs[i], bits);
513}616}
514617
515zig_extern zig_i64 __addodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);618zig_extern int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
516static inline bool zig_addo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {619static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
517#if zig_has_builtin(add_overflow) || defined(zig_gnuc)620#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
518 zig_i64 full_res;621 int64_t full_res;
519 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);622 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
520#else623#else
521 zig_c_int overflow_int;624 int overflow_int;
522 zig_i64 full_res = __addodi4(lhs, rhs, &overflow_int);625 int64_t full_res = __addodi4(lhs, rhs, &overflow_int);
523 bool overflow = overflow_int != 0;626 bool overflow = overflow_int != 0;
524#endif627#endif
525 *res = zig_wrap_i64(full_res, bits);628 *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);
527}630}
528631
529static inline void zig_vaddo_i64(zig_u8 *ov, zig_i64 *res, int n,632static inline void zig_vaddo_i64(uint8_t *ov, int64_t *res, int n,
530 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)633 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
531{634{
532 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits);635 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i64(&res[i], lhs[i], rhs[i], bits);
533}636}
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) {
536#if zig_has_builtin(add_overflow) || defined(zig_gnuc)639#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
537 zig_u8 full_res;640 uint8_t full_res;
538 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);641 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
539 *res = zig_wrap_u8(full_res, bits);642 *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);
541#else644#else
542 zig_u32 full_res;645 uint32_t full_res;
543 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);646 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
544 *res = (zig_u8)full_res;647 *res = (uint8_t)full_res;
545 return overflow;648 return overflow;
546#endif649#endif
547}650}
548651
549static inline void zig_vaddo_u8(zig_u8 *ov, zig_u8 *res, int n,652static inline void zig_vaddo_u8(uint8_t *ov, uint8_t *res, int n,
550 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)653 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
551{654{
552 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits);655 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u8(&res[i], lhs[i], rhs[i], bits);
553}656}
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) {
556#if zig_has_builtin(add_overflow) || defined(zig_gnuc)659#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
557 zig_i8 full_res;660 int8_t full_res;
558 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);661 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
559 *res = zig_wrap_i8(full_res, bits);662 *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);
561#else664#else
562 zig_i32 full_res;665 int32_t full_res;
563 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);666 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
564 *res = (zig_i8)full_res;667 *res = (int8_t)full_res;
565 return overflow;668 return overflow;
566#endif669#endif
567}670}
568671
569static inline void zig_vaddo_i8(zig_u8 *ov, zig_i8 *res, int n,672static inline void zig_vaddo_i8(uint8_t *ov, int8_t *res, int n,
570 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)673 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
571{674{
572 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits);675 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i8(&res[i], lhs[i], rhs[i], bits);
573}676}
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) {
576#if zig_has_builtin(add_overflow) || defined(zig_gnuc)679#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
577 zig_u16 full_res;680 uint16_t full_res;
578 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);681 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
579 *res = zig_wrap_u16(full_res, bits);682 *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);
581#else684#else
582 zig_u32 full_res;685 uint32_t full_res;
583 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);686 bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
584 *res = (zig_u16)full_res;687 *res = (uint16_t)full_res;
585 return overflow;688 return overflow;
586#endif689#endif
587}690}
588691
589static inline void zig_vaddo_u16(zig_u8 *ov, zig_u16 *res, int n,692static inline void zig_vaddo_u16(uint8_t *ov, uint16_t *res, int n,
590 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)693 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
591{694{
592 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits);695 for (int i = 0; i < n; ++i) ov[i] = zig_addo_u16(&res[i], lhs[i], rhs[i], bits);
593}696}
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) {
596#if zig_has_builtin(add_overflow) || defined(zig_gnuc)699#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
597 zig_i16 full_res;700 int16_t full_res;
598 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);701 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
599 *res = zig_wrap_i16(full_res, bits);702 *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);
601#else704#else
602 zig_i32 full_res;705 int32_t full_res;
603 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);706 bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
604 *res = (zig_i16)full_res;707 *res = (int16_t)full_res;
605 return overflow;708 return overflow;
606#endif709#endif
607}710}
608711
609static inline void zig_vaddo_i16(zig_u8 *ov, zig_i16 *res, int n,712static inline void zig_vaddo_i16(uint8_t *ov, int16_t *res, int n,
610 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)713 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
611{714{
612 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits);715 for (int i = 0; i < n; ++i) ov[i] = zig_addo_i16(&res[i], lhs[i], rhs[i], bits);
613}716}
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) {
616#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)719#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
617 zig_u32 full_res;720 uint32_t full_res;
618 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);721 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
619 *res = zig_wrap_u32(full_res, bits);722 *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);
621#else724#else
622 *res = zig_subw_u32(lhs, rhs, bits);725 *res = zig_subw_u32(lhs, rhs, bits);
623 return *res > lhs;726 return *res > lhs;
624#endif727#endif
625}728}
626729
627static inline void zig_vsubo_u32(zig_u8 *ov, zig_u32 *res, int n,730static inline void zig_vsubo_u32(uint8_t *ov, uint32_t *res, int n,
628 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)731 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
629{732{
630 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits);733 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u32(&res[i], lhs[i], rhs[i], bits);
631}734}
632735
633zig_extern zig_i32 __subosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);736zig_extern int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);
634static inline bool zig_subo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {737static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
635#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)738#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
636 zig_i32 full_res;739 int32_t full_res;
637 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);740 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
638#else741#else
639 zig_c_int overflow_int;742 int overflow_int;
640 zig_i32 full_res = __subosi4(lhs, rhs, &overflow_int);743 int32_t full_res = __subosi4(lhs, rhs, &overflow_int);
641 bool overflow = overflow_int != 0;744 bool overflow = overflow_int != 0;
642#endif745#endif
643 *res = zig_wrap_i32(full_res, bits);746 *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);
645}748}
646749
647static inline void zig_vsubo_i32(zig_u8 *ov, zig_i32 *res, int n,750static inline void zig_vsubo_i32(uint8_t *ov, int32_t *res, int n,
648 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)751 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
649{752{
650 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits);753 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i32(&res[i], lhs[i], rhs[i], bits);
651}754}
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) {
654#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)757#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
655 zig_u64 full_res;758 uint64_t full_res;
656 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);759 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
657 *res = zig_wrap_u64(full_res, bits);760 *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);
659#else762#else
660 *res = zig_subw_u64(lhs, rhs, bits);763 *res = zig_subw_u64(lhs, rhs, bits);
661 return *res > lhs;764 return *res > lhs;
662#endif765#endif
663}766}
664767
665static inline void zig_vsubo_u64(zig_u8 *ov, zig_u64 *res, int n,768static inline void zig_vsubo_u64(uint8_t *ov, uint64_t *res, int n,
666 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)769 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
667{770{
668 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits);771 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u64(&res[i], lhs[i], rhs[i], bits);
669}772}
670773
671zig_extern zig_i64 __subodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);774zig_extern int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);
672static inline bool zig_subo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {775static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
673#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)776#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
674 zig_i64 full_res;777 int64_t full_res;
675 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);778 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
676#else779#else
677 zig_c_int overflow_int;780 int overflow_int;
678 zig_i64 full_res = __subodi4(lhs, rhs, &overflow_int);781 int64_t full_res = __subodi4(lhs, rhs, &overflow_int);
679 bool overflow = overflow_int != 0;782 bool overflow = overflow_int != 0;
680#endif783#endif
681 *res = zig_wrap_i64(full_res, bits);784 *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);
683}786}
684787
685static inline void zig_vsubo_i64(zig_u8 *ov, zig_i64 *res, int n,788static inline void zig_vsubo_i64(uint8_t *ov, int64_t *res, int n,
686 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)789 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
687{790{
688 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits);791 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i64(&res[i], lhs[i], rhs[i], bits);
689}792}
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) {
692#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)795#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
693 zig_u8 full_res;796 uint8_t full_res;
694 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);797 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
695 *res = zig_wrap_u8(full_res, bits);798 *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);
697#else800#else
698 zig_u32 full_res;801 uint32_t full_res;
699 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);802 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
700 *res = (zig_u8)full_res;803 *res = (uint8_t)full_res;
701 return overflow;804 return overflow;
702#endif805#endif
703}806}
704807
705static inline void zig_vsubo_u8(zig_u8 *ov, zig_u8 *res, int n,808static inline void zig_vsubo_u8(uint8_t *ov, uint8_t *res, int n,
706 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)809 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
707{810{
708 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits);811 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u8(&res[i], lhs[i], rhs[i], bits);
709}812}
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) {
712#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)815#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
713 zig_i8 full_res;816 int8_t full_res;
714 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);817 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
715 *res = zig_wrap_i8(full_res, bits);818 *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);
717#else820#else
718 zig_i32 full_res;821 int32_t full_res;
719 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);822 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
720 *res = (zig_i8)full_res;823 *res = (int8_t)full_res;
721 return overflow;824 return overflow;
722#endif825#endif
723}826}
724827
725static inline void zig_vsubo_i8(zig_u8 *ov, zig_i8 *res, int n,828static inline void zig_vsubo_i8(uint8_t *ov, int8_t *res, int n,
726 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)829 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
727{830{
728 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits);831 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i8(&res[i], lhs[i], rhs[i], bits);
729}832}
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) {
733#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)836#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
734 zig_u16 full_res;837 uint16_t full_res;
735 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);838 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
736 *res = zig_wrap_u16(full_res, bits);839 *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);
738#else841#else
739 zig_u32 full_res;842 uint32_t full_res;
740 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);843 bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
741 *res = (zig_u16)full_res;844 *res = (uint16_t)full_res;
742 return overflow;845 return overflow;
743#endif846#endif
744}847}
745848
746static inline void zig_vsubo_u16(zig_u8 *ov, zig_u16 *res, int n,849static inline void zig_vsubo_u16(uint8_t *ov, uint16_t *res, int n,
747 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)850 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
748{851{
749 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits);852 for (int i = 0; i < n; ++i) ov[i] = zig_subo_u16(&res[i], lhs[i], rhs[i], bits);
750}853}
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) {
754#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)857#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
755 zig_i16 full_res;858 int16_t full_res;
756 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);859 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
757 *res = zig_wrap_i16(full_res, bits);860 *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);
759#else862#else
760 zig_i32 full_res;863 int32_t full_res;
761 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);864 bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
762 *res = (zig_i16)full_res;865 *res = (int16_t)full_res;
763 return overflow;866 return overflow;
764#endif867#endif
765}868}
766869
767static inline void zig_vsubo_i16(zig_u8 *ov, zig_i16 *res, int n,870static inline void zig_vsubo_i16(uint8_t *ov, int16_t *res, int n,
768 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)871 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
769{872{
770 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits);873 for (int i = 0; i < n; ++i) ov[i] = zig_subo_i16(&res[i], lhs[i], rhs[i], bits);
771}874}
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) {
774#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)877#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
775 zig_u32 full_res;878 uint32_t full_res;
776 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);879 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
777 *res = zig_wrap_u32(full_res, bits);880 *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);
779#else882#else
780 *res = zig_mulw_u32(lhs, rhs, bits);883 *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;
782#endif885#endif
783}886}
784887
785static inline void zig_vmulo_u32(zig_u8 *ov, zig_u32 *res, int n,888static inline void zig_vmulo_u32(uint8_t *ov, uint32_t *res, int n,
786 const zig_u32 *lhs, const zig_u32 *rhs, zig_u8 bits)889 const uint32_t *lhs, const uint32_t *rhs, uint8_t bits)
787{890{
788 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits);891 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u32(&res[i], lhs[i], rhs[i], bits);
789}892}
790893
791zig_extern zig_i32 __mulosi4(zig_i32 lhs, zig_i32 rhs, zig_c_int *overflow);894zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
792static inline bool zig_mulo_i32(zig_i32 *res, zig_i32 lhs, zig_i32 rhs, zig_u8 bits) {895static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
793#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)896#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
794 zig_i32 full_res;897 int32_t full_res;
795 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);898 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
796#else899#else
797 zig_c_int overflow_int;900 int overflow_int;
798 zig_i32 full_res = __mulosi4(lhs, rhs, &overflow_int);901 int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
799 bool overflow = overflow_int != 0;902 bool overflow = overflow_int != 0;
800#endif903#endif
801 *res = zig_wrap_i32(full_res, bits);904 *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);
803}906}
804907
805static inline void zig_vmulo_i32(zig_u8 *ov, zig_i32 *res, int n,908static inline void zig_vmulo_i32(uint8_t *ov, int32_t *res, int n,
806 const zig_i32 *lhs, const zig_i32 *rhs, zig_u8 bits)909 const int32_t *lhs, const int32_t *rhs, uint8_t bits)
807{910{
808 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits);911 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i32(&res[i], lhs[i], rhs[i], bits);
809}912}
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) {
812#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)915#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
813 zig_u64 full_res;916 uint64_t full_res;
814 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);917 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
815 *res = zig_wrap_u64(full_res, bits);918 *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);
817#else920#else
818 *res = zig_mulw_u64(lhs, rhs, bits);921 *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;
820#endif923#endif
821}924}
822925
823static inline void zig_vmulo_u64(zig_u8 *ov, zig_u64 *res, int n,926static inline void zig_vmulo_u64(uint8_t *ov, uint64_t *res, int n,
824 const zig_u64 *lhs, const zig_u64 *rhs, zig_u8 bits)927 const uint64_t *lhs, const uint64_t *rhs, uint8_t bits)
825{928{
826 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits);929 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u64(&res[i], lhs[i], rhs[i], bits);
827}930}
828931
829zig_extern zig_i64 __mulodi4(zig_i64 lhs, zig_i64 rhs, zig_c_int *overflow);932zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
830static inline bool zig_mulo_i64(zig_i64 *res, zig_i64 lhs, zig_i64 rhs, zig_u8 bits) {933static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
831#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)934#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
832 zig_i64 full_res;935 int64_t full_res;
833 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);936 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
834#else937#else
835 zig_c_int overflow_int;938 int overflow_int;
836 zig_i64 full_res = __mulodi4(lhs, rhs, &overflow_int);939 int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
837 bool overflow = overflow_int != 0;940 bool overflow = overflow_int != 0;
838#endif941#endif
839 *res = zig_wrap_i64(full_res, bits);942 *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);
841}944}
842945
843static inline void zig_vmulo_i64(zig_u8 *ov, zig_i64 *res, int n,946static inline void zig_vmulo_i64(uint8_t *ov, int64_t *res, int n,
844 const zig_i64 *lhs, const zig_i64 *rhs, zig_u8 bits)947 const int64_t *lhs, const int64_t *rhs, uint8_t bits)
845{948{
846 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits);949 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i64(&res[i], lhs[i], rhs[i], bits);
847}950}
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) {
850#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)953#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
851 zig_u8 full_res;954 uint8_t full_res;
852 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);955 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
853 *res = zig_wrap_u8(full_res, bits);956 *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);
855#else958#else
856 zig_u32 full_res;959 uint32_t full_res;
857 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);960 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
858 *res = (zig_u8)full_res;961 *res = (uint8_t)full_res;
859 return overflow;962 return overflow;
860#endif963#endif
861}964}
862965
863static inline void zig_vmulo_u8(zig_u8 *ov, zig_u8 *res, int n,966static inline void zig_vmulo_u8(uint8_t *ov, uint8_t *res, int n,
864 const zig_u8 *lhs, const zig_u8 *rhs, zig_u8 bits)967 const uint8_t *lhs, const uint8_t *rhs, uint8_t bits)
865{968{
866 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits);969 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u8(&res[i], lhs[i], rhs[i], bits);
867}970}
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) {
870#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)973#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
871 zig_i8 full_res;974 int8_t full_res;
872 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);975 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
873 *res = zig_wrap_i8(full_res, bits);976 *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);
875#else978#else
876 zig_i32 full_res;979 int32_t full_res;
877 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);980 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
878 *res = (zig_i8)full_res;981 *res = (int8_t)full_res;
879 return overflow;982 return overflow;
880#endif983#endif
881}984}
882985
883static inline void zig_vmulo_i8(zig_u8 *ov, zig_i8 *res, int n,986static inline void zig_vmulo_i8(uint8_t *ov, int8_t *res, int n,
884 const zig_i8 *lhs, const zig_i8 *rhs, zig_u8 bits)987 const int8_t *lhs, const int8_t *rhs, uint8_t bits)
885{988{
886 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits);989 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i8(&res[i], lhs[i], rhs[i], bits);
887}990}
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) {
890#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)993#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
891 zig_u16 full_res;994 uint16_t full_res;
892 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);995 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
893 *res = zig_wrap_u16(full_res, bits);996 *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);
895#else998#else
896 zig_u32 full_res;999 uint32_t full_res;
897 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);1000 bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
898 *res = (zig_u16)full_res;1001 *res = (uint16_t)full_res;
899 return overflow;1002 return overflow;
900#endif1003#endif
901}1004}
9021005
903static inline void zig_vmulo_u16(zig_u8 *ov, zig_u16 *res, int n,1006static inline void zig_vmulo_u16(uint8_t *ov, uint16_t *res, int n,
904 const zig_u16 *lhs, const zig_u16 *rhs, zig_u8 bits)1007 const uint16_t *lhs, const uint16_t *rhs, uint8_t bits)
905{1008{
906 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits);1009 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_u16(&res[i], lhs[i], rhs[i], bits);
907}1010}
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) {
910#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)1013#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
911 zig_i16 full_res;1014 int16_t full_res;
912 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1015 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
913 *res = zig_wrap_i16(full_res, bits);1016 *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);
915#else1018#else
916 zig_i32 full_res;1019 int32_t full_res;
917 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);1020 bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
918 *res = (zig_i16)full_res;1021 *res = (int16_t)full_res;
919 return overflow;1022 return overflow;
920#endif1023#endif
921}1024}
9221025
923static inline void zig_vmulo_i16(zig_u8 *ov, zig_i16 *res, int n,1026static inline void zig_vmulo_i16(uint8_t *ov, int16_t *res, int n,
924 const zig_i16 *lhs, const zig_i16 *rhs, zig_u8 bits)1027 const int16_t *lhs, const int16_t *rhs, uint8_t bits)
925{1028{
926 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits);1029 for (int i = 0; i < n; ++i) ov[i] = zig_mulo_i16(&res[i], lhs[i], rhs[i], bits);
927}1030}
9281031
929#define zig_int_builtins(w) \1032#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) { \
931 *res = zig_shlw_u##w(lhs, rhs, bits); \1034 *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; \
933 } \1036 } \
934\1037\
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) { \
936 *res = zig_shlw_i##w(lhs, rhs, bits); \1039 *res = zig_shlw_i##w(lhs, rhs, bits); \
937 zig_i##w mask = (zig_i##w)(zig_maxInt_u##w << (bits - rhs - 1)); \1040 int##w##_t mask = (int##w##_t)(UINT##w##_MAX << (bits - rhs - 1)); \
938 return (lhs & mask) != zig_as_i##w(0) && (lhs & mask) != mask; \1041 return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
939 } \1042 } \
940\1043\
941 static inline zig_u##w zig_shls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \1044 static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
942 zig_u##w res; \1045 uint##w##_t res; \
943 if (rhs >= bits) return lhs != zig_as_u##w(0) ? zig_maxInt(u##w, bits) : lhs; \1046 if (rhs >= bits) return lhs != UINT##w##_C(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; \1047 return zig_shlo_u##w(&res, lhs, (uint8_t)rhs, bits) ? zig_maxInt_u(w, bits) : res; \
945 } \1048 } \
946\1049\
947 static inline zig_i##w zig_shls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \1050 static inline int##w##_t zig_shls_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
948 zig_i##w res; \1051 int##w##_t res; \
949 if ((zig_u##w)rhs < (zig_u##w)bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \1052 if ((uint##w##_t)rhs < (uint##w##_t)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); \1053 return lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
951 } \1054 } \
952\1055\
953 static inline zig_u##w zig_adds_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \1056 static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
954 zig_u##w res; \1057 uint##w##_t res; \
955 return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \1058 return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt_u(w, bits) : res; \
956 } \1059 } \
957\1060\
958 static inline zig_i##w zig_adds_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \1061 static inline int##w##_t zig_adds_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
959 zig_i##w res; \1062 int##w##_t res; \
960 if (!zig_addo_i##w(&res, lhs, rhs, bits)) return res; \1063 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); \
962 } \1065 } \
963\1066\
964 static inline zig_u##w zig_subs_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \1067 static inline uint##w##_t zig_subs_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
965 zig_u##w res; \1068 uint##w##_t res; \
966 return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt(u##w, bits) : res; \1069 return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt_u(w, bits) : res; \
967 } \1070 } \
968\1071\
969 static inline zig_i##w zig_subs_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \1072 static inline int##w##_t zig_subs_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
970 zig_i##w res; \1073 int##w##_t res; \
971 if (!zig_subo_i##w(&res, lhs, rhs, bits)) return res; \1074 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); \
973 } \1076 } \
974\1077\
975 static inline zig_u##w zig_muls_u##w(zig_u##w lhs, zig_u##w rhs, zig_u8 bits) { \1078 static inline uint##w##_t zig_muls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
976 zig_u##w res; \1079 uint##w##_t res; \
977 return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt(u##w, bits) : res; \1080 return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt_u(w, bits) : res; \
978 } \1081 } \
979\1082\
980 static inline zig_i##w zig_muls_i##w(zig_i##w lhs, zig_i##w rhs, zig_u8 bits) { \1083 static inline int##w##_t zig_muls_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
981 zig_i##w res; \1084 int##w##_t res; \
982 if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \1085 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); \
984 }1087 }
985zig_int_builtins(8)1088zig_int_builtins(8)
986zig_int_builtins(16)1089zig_int_builtins(16)
...@@ -988,89 +1091,89 @@ zig_int_builtins(32)...@@ -988,89 +1091,89 @@ zig_int_builtins(32)
988zig_int_builtins(64)1091zig_int_builtins(64)
9891092
990#define zig_builtin8(name, val) __builtin_##name(val)1093#define zig_builtin8(name, val) __builtin_##name(val)
991typedef zig_c_uint zig_Builtin8;1094typedef unsigned int zig_Builtin8;
9921095
993#define zig_builtin16(name, val) __builtin_##name(val)1096#define zig_builtin16(name, val) __builtin_##name(val)
994typedef zig_c_uint zig_Builtin16;1097typedef unsigned int zig_Builtin16;
9951098
996#if INT_MIN <= INT32_MIN1099#if INT_MIN <= INT32_MIN
997#define zig_builtin32(name, val) __builtin_##name(val)1100#define zig_builtin32(name, val) __builtin_##name(val)
998typedef zig_c_uint zig_Builtin32;1101typedef unsigned int zig_Builtin32;
999#elif LONG_MIN <= INT32_MIN1102#elif LONG_MIN <= INT32_MIN
1000#define zig_builtin32(name, val) __builtin_##name##l(val)1103#define zig_builtin32(name, val) __builtin_##name##l(val)
1001typedef zig_c_ulong zig_Builtin32;1104typedef unsigned long zig_Builtin32;
1002#endif1105#endif
10031106
1004#if INT_MIN <= INT64_MIN1107#if INT_MIN <= INT64_MIN
1005#define zig_builtin64(name, val) __builtin_##name(val)1108#define zig_builtin64(name, val) __builtin_##name(val)
1006typedef zig_c_uint zig_Builtin64;1109typedef unsigned int zig_Builtin64;
1007#elif LONG_MIN <= INT64_MIN1110#elif LONG_MIN <= INT64_MIN
1008#define zig_builtin64(name, val) __builtin_##name##l(val)1111#define zig_builtin64(name, val) __builtin_##name##l(val)
1009typedef zig_c_ulong zig_Builtin64;1112typedef unsigned long zig_Builtin64;
1010#elif LLONG_MIN <= INT64_MIN1113#elif LLONG_MIN <= INT64_MIN
1011#define zig_builtin64(name, val) __builtin_##name##ll(val)1114#define zig_builtin64(name, val) __builtin_##name##ll(val)
1012typedef zig_c_ulonglong zig_Builtin64;1115typedef unsigned long long zig_Builtin64;
1013#endif1116#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) {
1016 return zig_wrap_u8(val >> (8 - bits), bits);1119 return zig_wrap_u8(val >> (8 - bits), bits);
1017}1120}
10181121
1019static inline zig_i8 zig_byte_swap_i8(zig_i8 val, zig_u8 bits) {1122static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {
1020 return zig_wrap_i8((zig_i8)zig_byte_swap_u8((zig_u8)val, bits), bits);1123 return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);
1021}1124}
10221125
1023static inline zig_u16 zig_byte_swap_u16(zig_u16 val, zig_u8 bits) {1126static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) {
1024 zig_u16 full_res;1127 uint16_t full_res;
1025#if zig_has_builtin(bswap16) || defined(zig_gnuc)1128#if zig_has_builtin(bswap16) || defined(zig_gnuc)
1026 full_res = __builtin_bswap16(val);1129 full_res = __builtin_bswap16(val);
1027#else1130#else
1028 full_res = (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 0), 8) << 8 |1131 full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |
1029 (zig_u16)zig_byte_swap_u8((zig_u8)(val >> 8), 8) >> 0;1132 (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;
1030#endif1133#endif
1031 return zig_wrap_u16(full_res >> (16 - bits), bits);1134 return zig_wrap_u16(full_res >> (16 - bits), bits);
1032}1135}
10331136
1034static inline zig_i16 zig_byte_swap_i16(zig_i16 val, zig_u8 bits) {1137static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {
1035 return zig_wrap_i16((zig_i16)zig_byte_swap_u16((zig_u16)val, bits), bits);1138 return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);
1036}1139}
10371140
1038static inline zig_u32 zig_byte_swap_u32(zig_u32 val, zig_u8 bits) {1141static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) {
1039 zig_u32 full_res;1142 uint32_t full_res;
1040#if zig_has_builtin(bswap32) || defined(zig_gnuc)1143#if zig_has_builtin(bswap32) || defined(zig_gnuc)
1041 full_res = __builtin_bswap32(val);1144 full_res = __builtin_bswap32(val);
1042#else1145#else
1043 full_res = (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 0), 16) << 16 |1146 full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |
1044 (zig_u32)zig_byte_swap_u16((zig_u16)(val >> 16), 16) >> 0;1147 (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;
1045#endif1148#endif
1046 return zig_wrap_u32(full_res >> (32 - bits), bits);1149 return zig_wrap_u32(full_res >> (32 - bits), bits);
1047}1150}
10481151
1049static inline zig_i32 zig_byte_swap_i32(zig_i32 val, zig_u8 bits) {1152static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {
1050 return zig_wrap_i32((zig_i32)zig_byte_swap_u32((zig_u32)val, bits), bits);1153 return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);
1051}1154}
10521155
1053static inline zig_u64 zig_byte_swap_u64(zig_u64 val, zig_u8 bits) {1156static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) {
1054 zig_u64 full_res;1157 uint64_t full_res;
1055#if zig_has_builtin(bswap64) || defined(zig_gnuc)1158#if zig_has_builtin(bswap64) || defined(zig_gnuc)
1056 full_res = __builtin_bswap64(val);1159 full_res = __builtin_bswap64(val);
1057#else1160#else
1058 full_res = (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 0), 32) << 32 |1161 full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |
1059 (zig_u64)zig_byte_swap_u32((zig_u32)(val >> 32), 32) >> 0;1162 (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;
1060#endif1163#endif
1061 return zig_wrap_u64(full_res >> (64 - bits), bits);1164 return zig_wrap_u64(full_res >> (64 - bits), bits);
1062}1165}
10631166
1064static inline zig_i64 zig_byte_swap_i64(zig_i64 val, zig_u8 bits) {1167static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {
1065 return zig_wrap_i64((zig_i64)zig_byte_swap_u64((zig_u64)val, bits), bits);1168 return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);
1066}1169}
10671170
1068static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {1171static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) {
1069 zig_u8 full_res;1172 uint8_t full_res;
1070#if zig_has_builtin(bitreverse8)1173#if zig_has_builtin(bitreverse8)
1071 full_res = __builtin_bitreverse8(val);1174 full_res = __builtin_bitreverse8(val);
1072#else1175#else
1073 static zig_u8 const lut[0x10] = {1176 static uint8_t const lut[0x10] = {
1074 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,1177 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
1075 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf1178 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
1076 };1179 };
...@@ -1079,62 +1182,62 @@ static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {...@@ -1079,62 +1182,62 @@ static inline zig_u8 zig_bit_reverse_u8(zig_u8 val, zig_u8 bits) {
1079 return zig_wrap_u8(full_res >> (8 - bits), bits);1182 return zig_wrap_u8(full_res >> (8 - bits), bits);
1080}1183}
10811184
1082static inline zig_i8 zig_bit_reverse_i8(zig_i8 val, zig_u8 bits) {1185static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {
1083 return zig_wrap_i8((zig_i8)zig_bit_reverse_u8((zig_u8)val, bits), bits);1186 return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);
1084}1187}
10851188
1086static inline zig_u16 zig_bit_reverse_u16(zig_u16 val, zig_u8 bits) {1189static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) {
1087 zig_u16 full_res;1190 uint16_t full_res;
1088#if zig_has_builtin(bitreverse16)1191#if zig_has_builtin(bitreverse16)
1089 full_res = __builtin_bitreverse16(val);1192 full_res = __builtin_bitreverse16(val);
1090#else1193#else
1091 full_res = (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 0), 8) << 8 |1194 full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |
1092 (zig_u16)zig_bit_reverse_u8((zig_u8)(val >> 8), 8) >> 0;1195 (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;
1093#endif1196#endif
1094 return zig_wrap_u16(full_res >> (16 - bits), bits);1197 return zig_wrap_u16(full_res >> (16 - bits), bits);
1095}1198}
10961199
1097static inline zig_i16 zig_bit_reverse_i16(zig_i16 val, zig_u8 bits) {1200static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {
1098 return zig_wrap_i16((zig_i16)zig_bit_reverse_u16((zig_u16)val, bits), bits);1201 return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);
1099}1202}
11001203
1101static inline zig_u32 zig_bit_reverse_u32(zig_u32 val, zig_u8 bits) {1204static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) {
1102 zig_u32 full_res;1205 uint32_t full_res;
1103#if zig_has_builtin(bitreverse32)1206#if zig_has_builtin(bitreverse32)
1104 full_res = __builtin_bitreverse32(val);1207 full_res = __builtin_bitreverse32(val);
1105#else1208#else
1106 full_res = (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 0), 16) << 16 |1209 full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |
1107 (zig_u32)zig_bit_reverse_u16((zig_u16)(val >> 16), 16) >> 0;1210 (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;
1108#endif1211#endif
1109 return zig_wrap_u32(full_res >> (32 - bits), bits);1212 return zig_wrap_u32(full_res >> (32 - bits), bits);
1110}1213}
11111214
1112static inline zig_i32 zig_bit_reverse_i32(zig_i32 val, zig_u8 bits) {1215static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {
1113 return zig_wrap_i32((zig_i32)zig_bit_reverse_u32((zig_u32)val, bits), bits);1216 return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);
1114}1217}
11151218
1116static inline zig_u64 zig_bit_reverse_u64(zig_u64 val, zig_u8 bits) {1219static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) {
1117 zig_u64 full_res;1220 uint64_t full_res;
1118#if zig_has_builtin(bitreverse64)1221#if zig_has_builtin(bitreverse64)
1119 full_res = __builtin_bitreverse64(val);1222 full_res = __builtin_bitreverse64(val);
1120#else1223#else
1121 full_res = (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 0), 32) << 32 |1224 full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |
1122 (zig_u64)zig_bit_reverse_u32((zig_u32)(val >> 32), 32) >> 0;1225 (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;
1123#endif1226#endif
1124 return zig_wrap_u64(full_res >> (64 - bits), bits);1227 return zig_wrap_u64(full_res >> (64 - bits), bits);
1125}1228}
11261229
1127static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {1230static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {
1128 return zig_wrap_i64((zig_i64)zig_bit_reverse_u64((zig_u64)val, bits), bits);1231 return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);
1129}1232}
11301233
1131#define zig_builtin_popcount_common(w) \1234#define zig_builtin_popcount_common(w) \
1132 static inline zig_u8 zig_popcount_i##w(zig_i##w val, zig_u8 bits) { \1235 static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \
1133 return zig_popcount_u##w((zig_u##w)val, bits); \1236 return zig_popcount_u##w((uint##w##_t)val, bits); \
1134 }1237 }
1135#if zig_has_builtin(popcount) || defined(zig_gnuc)1238#if zig_has_builtin(popcount) || defined(zig_gnuc)
1136#define zig_builtin_popcount(w) \1239#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) { \
1138 (void)bits; \1241 (void)bits; \
1139 return zig_builtin##w(popcount, val); \1242 return zig_builtin##w(popcount, val); \
1140 } \1243 } \
...@@ -1142,12 +1245,12 @@ static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {...@@ -1142,12 +1245,12 @@ static inline zig_i64 zig_bit_reverse_i64(zig_i64 val, zig_u8 bits) {
1142 zig_builtin_popcount_common(w)1245 zig_builtin_popcount_common(w)
1143#else1246#else
1144#define zig_builtin_popcount(w) \1247#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) { \
1146 (void)bits; \1249 (void)bits; \
1147 zig_u##w temp = val - ((val >> 1) & (zig_maxInt_u##w / 3)); \1250 uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \
1148 temp = (temp & (zig_maxInt_u##w / 5)) + ((temp >> 2) & (zig_maxInt_u##w / 5)); \1251 temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
1149 temp = (temp + (temp >> 4)) & (zig_maxInt_u##w / 17); \1252 temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
1150 return temp * (zig_maxInt_u##w / 255) >> (w - 8); \1253 return temp * (UINT##w##_MAX / 255) >> (w - 8); \
1151 } \1254 } \
1152\1255\
1153 zig_builtin_popcount_common(w)1256 zig_builtin_popcount_common(w)
...@@ -1158,12 +1261,12 @@ zig_builtin_popcount(32)...@@ -1158,12 +1261,12 @@ zig_builtin_popcount(32)
1158zig_builtin_popcount(64)1261zig_builtin_popcount(64)
11591262
1160#define zig_builtin_ctz_common(w) \1263#define zig_builtin_ctz_common(w) \
1161 static inline zig_u8 zig_ctz_i##w(zig_i##w val, zig_u8 bits) { \1264 static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \
1162 return zig_ctz_u##w((zig_u##w)val, bits); \1265 return zig_ctz_u##w((uint##w##_t)val, bits); \
1163 }1266 }
1164#if zig_has_builtin(ctz) || defined(zig_gnuc)1267#if zig_has_builtin(ctz) || defined(zig_gnuc)
1165#define zig_builtin_ctz(w) \1268#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) { \
1167 if (val == 0) return bits; \1270 if (val == 0) return bits; \
1168 return zig_builtin##w(ctz, val); \1271 return zig_builtin##w(ctz, val); \
1169 } \1272 } \
...@@ -1171,7 +1274,7 @@ zig_builtin_popcount(64)...@@ -1171,7 +1274,7 @@ zig_builtin_popcount(64)
1171 zig_builtin_ctz_common(w)1274 zig_builtin_ctz_common(w)
1172#else1275#else
1173#define zig_builtin_ctz(w) \1276#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) { \
1175 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \1278 return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
1176 } \1279 } \
1177\1280\
...@@ -1183,12 +1286,12 @@ zig_builtin_ctz(32)...@@ -1183,12 +1286,12 @@ zig_builtin_ctz(32)
1183zig_builtin_ctz(64)1286zig_builtin_ctz(64)
11841287
1185#define zig_builtin_clz_common(w) \1288#define zig_builtin_clz_common(w) \
1186 static inline zig_u8 zig_clz_i##w(zig_i##w val, zig_u8 bits) { \1289 static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \
1187 return zig_clz_u##w((zig_u##w)val, bits); \1290 return zig_clz_u##w((uint##w##_t)val, bits); \
1188 }1291 }
1189#if zig_has_builtin(clz) || defined(zig_gnuc)1292#if zig_has_builtin(clz) || defined(zig_gnuc)
1190#define zig_builtin_clz(w) \1293#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) { \
1192 if (val == 0) return bits; \1295 if (val == 0) return bits; \
1193 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \1296 return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
1194 } \1297 } \
...@@ -1196,7 +1299,7 @@ zig_builtin_ctz(64)...@@ -1196,7 +1299,7 @@ zig_builtin_ctz(64)
1196 zig_builtin_clz_common(w)1299 zig_builtin_clz_common(w)
1197#else1300#else
1198#define zig_builtin_clz(w) \1301#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) { \
1200 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \1303 return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
1201 } \1304 } \
1202\1305\
...@@ -1207,7 +1310,7 @@ zig_builtin_clz(16)...@@ -1207,7 +1310,7 @@ zig_builtin_clz(16)
1207zig_builtin_clz(32)1310zig_builtin_clz(32)
1208zig_builtin_clz(64)1311zig_builtin_clz(64)
12091312
1210/* ======================== 128-bit Integer Routines ======================== */1313/* ======================== 128-bit Integer Support ========================= */
12111314
1212#if !defined(zig_has_int128)1315#if !defined(zig_has_int128)
1213# if defined(__SIZEOF_INT128__)1316# if defined(__SIZEOF_INT128__)
...@@ -1222,18 +1325,18 @@ zig_builtin_clz(64)...@@ -1222,18 +1325,18 @@ zig_builtin_clz(64)
1222typedef unsigned __int128 zig_u128;1325typedef unsigned __int128 zig_u128;
1223typedef signed __int128 zig_i128;1326typedef signed __int128 zig_i128;
12241327
1225#define zig_as_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))1328#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1226#define zig_as_i128(hi, lo) ((zig_i128)zig_as_u128(hi, lo))1329#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1227#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo)1330#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
1228#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo)1331#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
1229#define zig_hi_u128(val) ((zig_u64)((val) >> 64))1332#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
1230#define zig_lo_u128(val) ((zig_u64)((val) >> 0))1333#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
1231#define zig_hi_i128(val) ((zig_i64)((val) >> 64))1334#define zig_hi_i128(val) (( int64_t)((val) >> 64))
1232#define zig_lo_i128(val) ((zig_u64)((val) >> 0))1335#define zig_lo_i128(val) ((uint64_t)((val) >> 0))
1233#define zig_bitcast_u128(val) ((zig_u128)(val))1336#define zig_bitcast_u128(val) ((zig_u128)(val))
1234#define zig_bitcast_i128(val) ((zig_i128)(val))1337#define zig_bitcast_i128(val) ((zig_i128)(val))
1235#define zig_cmp_int128(Type) \1338#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) { \
1237 return (lhs > rhs) - (lhs < rhs); \1340 return (lhs > rhs) - (lhs < rhs); \
1238 }1341 }
1239#define zig_bit_int128(Type, operation, operator) \1342#define zig_bit_int128(Type, operation, operator) \
...@@ -1244,31 +1347,31 @@ typedef signed __int128 zig_i128;...@@ -1244,31 +1347,31 @@ typedef signed __int128 zig_i128;
1244#else /* zig_has_int128 */1347#else /* zig_has_int128 */
12451348
1246#if __LITTLE_ENDIAN__ || _MSC_VER1349#if __LITTLE_ENDIAN__ || _MSC_VER
1247typedef struct { zig_align(16) zig_u64 lo; zig_u64 hi; } zig_u128;1350typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
1248typedef struct { zig_align(16) zig_u64 lo; zig_i64 hi; } zig_i128;1351typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
1249#else1352#else
1250typedef struct { zig_align(16) zig_u64 hi; zig_u64 lo; } zig_u128;1353typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
1251typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;1354typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
1252#endif1355#endif
12531356
1254#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })1357#define zig_make_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) })1358#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
12561359
1257#if _MSC_VER1360#if _MSC_VER /* MSVC doesn't allow struct literals in constant expressions */
1258#define zig_as_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }1361#define zig_make_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1259#define zig_as_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }1362#define zig_make_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1260#else1363#else /* But non-MSVC doesn't like the unprotected commas */
1261#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo)1364#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)
1262#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo)1365#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)
1263#endif1366#endif
1264#define zig_hi_u128(val) ((val).hi)1367#define zig_hi_u128(val) ((val).hi)
1265#define zig_lo_u128(val) ((val).lo)1368#define zig_lo_u128(val) ((val).lo)
1266#define zig_hi_i128(val) ((val).hi)1369#define zig_hi_i128(val) ((val).hi)
1267#define zig_lo_i128(val) ((val).lo)1370#define zig_lo_i128(val) ((val).lo)
1268#define zig_bitcast_u128(val) zig_as_u128((zig_u64)(val).hi, (val).lo)1371#define zig_bitcast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)
1269#define zig_bitcast_i128(val) zig_as_i128((zig_i64)(val).hi, (val).lo)1372#define zig_bitcast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo)
1270#define zig_cmp_int128(Type) \1373#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) { \
1272 return (lhs.hi == rhs.hi) \1375 return (lhs.hi == rhs.hi) \
1273 ? (lhs.lo > rhs.lo) - (lhs.lo < rhs.lo) \1376 ? (lhs.lo > rhs.lo) - (lhs.lo < rhs.lo) \
1274 : (lhs.hi > rhs.hi) - (lhs.hi < rhs.hi); \1377 : (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;...@@ -1280,10 +1383,10 @@ typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
12801383
1281#endif /* zig_has_int128 */1384#endif /* zig_has_int128 */
12821385
1283#define zig_minInt_u128 zig_as_u128(zig_minInt_u64, zig_minInt_u64)1386#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
1284#define zig_maxInt_u128 zig_as_u128(zig_maxInt_u64, zig_maxInt_u64)1387#define zig_maxInt_u128 zig_make_u128(zig_maxInt_u64, zig_maxInt_u64)
1285#define zig_minInt_i128 zig_as_i128(zig_minInt_i64, zig_minInt_u64)1388#define zig_minInt_i128 zig_make_i128(zig_minInt_i64, zig_minInt_u64)
1286#define zig_maxInt_i128 zig_as_i128(zig_maxInt_i64, zig_maxInt_u64)1389#define zig_maxInt_i128 zig_make_i128(zig_maxInt_i64, zig_maxInt_u64)
12871390
1288zig_cmp_int128(u128)1391zig_cmp_int128(u128)
1289zig_cmp_int128(i128)1392zig_cmp_int128(i128)
...@@ -1297,28 +1400,33 @@ zig_bit_int128(i128, or, |)...@@ -1297,28 +1400,33 @@ zig_bit_int128(i128, or, |)
1297zig_bit_int128(u128, xor, ^)1400zig_bit_int128(u128, xor, ^)
1298zig_bit_int128(i128, xor, ^)1401zig_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
1302#if zig_has_int1281405#if zig_has_int128
13031406
1304static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {1407static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
1305 return val ^ zig_maxInt(u128, bits);1408 return val ^ zig_maxInt_u(128, bits);
1306}1409}
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) {
1309 (void)bits;1412 (void)bits;
1310 return ~val;1413 return ~val;
1311}1414}
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) {
1314 return lhs >> rhs;1417 return lhs >> rhs;
1315}1418}
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) {
1318 return lhs << rhs;1421 return lhs << rhs;
1319}1422}
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) {
1322 return lhs << rhs;1430 return lhs << rhs;
1323}1431}
13241432
...@@ -1363,40 +1471,46 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {...@@ -1363,40 +1471,46 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
1363}1471}
13641472
1365static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {1473static 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));
1367}1475}
13681476
1369static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {1477static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1370 zig_i128 rem = zig_rem_i128(lhs, rhs);1478 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));
1372}1480}
13731481
1374#else /* zig_has_int128 */1482#else /* zig_has_int128 */
13751483
1376static inline zig_u128 zig_not_u128(zig_u128 val, zig_u8 bits) {1484static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t 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)) };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)) };
1378}1490}
13791491
1380static inline zig_i128 zig_not_i128(zig_i128 val, zig_u8 bits) {1492static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
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)) };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 };
1382}1496}
13831497
1384static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) {1498static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
1385 if (rhs == zig_as_u8(0)) return lhs;1499 if (rhs == UINT8_C(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)) };1500 if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1387 return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (zig_as_u8(64) - rhs) | lhs.lo >> rhs };1501 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
1388}1502}
13891503
1390static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) {1504static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
1391 if (rhs == zig_as_u8(0)) return lhs;1505 if (rhs == UINT8_C(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 };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))) };
1393 return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };1507 return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
1394}1508}
13951509
1396static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) {1510static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
1397 if (rhs == zig_as_u8(0)) return lhs;1511 if (rhs == UINT8_C(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 };1512 if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
1399 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs };1513 return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
1400}1514}
14011515
1402static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {1516static 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) {...@@ -1424,14 +1538,14 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1424}1538}
14251539
1426zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);1540zig_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) {1541static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
1432 return __multi3(lhs, rhs);1542 return __multi3(lhs, rhs);
1433}1543}
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
1435zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);1549zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
1436static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {1550static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
1437 return __udivti3(lhs, rhs);1551 return __udivti3(lhs, rhs);
...@@ -1454,11 +1568,11 @@ static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {...@@ -1454,11 +1568,11 @@ static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
14541568
1455static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {1569static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1456 zig_i128 rem = zig_rem_i128(lhs, rhs);1570 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));
1458}1572}
14591573
1460static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {1574static 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)));
1462}1576}
14631577
1464#endif /* zig_has_int128 */1578#endif /* zig_has_int128 */
...@@ -1471,323 +1585,294 @@ static inline zig_u128 zig_nand_u128(zig_u128 lhs, zig_u128 rhs) {...@@ -1471,323 +1585,294 @@ static inline zig_u128 zig_nand_u128(zig_u128 lhs, zig_u128 rhs) {
1471}1585}
14721586
1473static inline zig_u128 zig_min_u128(zig_u128 lhs, zig_u128 rhs) {1587static 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;
1475}1589}
14761590
1477static inline zig_i128 zig_min_i128(zig_i128 lhs, zig_i128 rhs) {1591static 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;
1479}1593}
14801594
1481static inline zig_u128 zig_max_u128(zig_u128 lhs, zig_u128 rhs) {1595static 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;
1483}1597}
14841598
1485static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {1599static 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;1600 return zig_cmp_i128(lhs, rhs) > INT32_C(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}1601}
14931602
1494static inline zig_u128 zig_wrap_u128(zig_u128 val, zig_u8 bits) {1603static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
1495 return zig_and_u128(val, zig_maxInt(u128, bits));1604 return zig_and_u128(val, zig_maxInt_u(128, bits));
1496}1605}
14971606
1498static inline zig_i128 zig_wrap_i128(zig_i128 val, zig_u8 bits) {1607static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
1499 return zig_as_i128(zig_wrap_i64(zig_hi_i128(val), bits - zig_as_u8(64)), zig_lo_i128(val));1608 return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
1500}1609}
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) {
1503 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);1612 return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
1504}1613}
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) {
1507 return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), rhs)), bits);1616 return zig_wrap_i128(zig_bitcast_i128(zig_shl_u128(zig_bitcast_u128(lhs), rhs)), bits);
1508}1617}
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) {
1511 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);1620 return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
1512}1621}
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) {
1515 return zig_wrap_i128(zig_bitcast_i128(zig_add_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);1624 return zig_wrap_i128(zig_bitcast_i128(zig_add_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1516}1625}
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) {
1519 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);1628 return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
1520}1629}
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) {
1523 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);1632 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1524}1633}
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) {
1527 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);1636 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
1528}1637}
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) {
1531 return zig_wrap_i128(zig_bitcast_i128(zig_mul_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);1640 return zig_wrap_i128(zig_bitcast_i128(zig_mul_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1532}1641}
15331642
1534#if zig_has_int1281643#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) {
1537#if zig_has_builtin(add_overflow)1646#if zig_has_builtin(add_overflow)
1538 zig_u128 full_res;1647 zig_u128 full_res;
1539 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1648 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1540 *res = zig_wrap_u128(full_res, bits);1649 *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);
1542#else1651#else
1543 *res = zig_addw_u128(lhs, rhs, bits);1652 *res = zig_addw_u128(lhs, rhs, bits);
1544 return *res < lhs;1653 return *res < lhs;
1545#endif1654#endif
1546}1655}
15471656
1548zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);1657zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1549static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {1658static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1550#if zig_has_builtin(add_overflow)1659#if zig_has_builtin(add_overflow)
1551 zig_i128 full_res;1660 zig_i128 full_res;
1552 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);1661 bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
1553#else1662#else
1554 zig_c_int overflow_int;1663 int overflow_int;
1555 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);1664 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
1556 bool overflow = overflow_int != 0;1665 bool overflow = overflow_int != 0;
1557#endif1666#endif
1558 *res = zig_wrap_i128(full_res, bits);1667 *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);
1560}1669}
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) {
1563#if zig_has_builtin(sub_overflow)1672#if zig_has_builtin(sub_overflow)
1564 zig_u128 full_res;1673 zig_u128 full_res;
1565 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1674 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1566 *res = zig_wrap_u128(full_res, bits);1675 *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);
1568#else1677#else
1569 *res = zig_subw_u128(lhs, rhs, bits);1678 *res = zig_subw_u128(lhs, rhs, bits);
1570 return *res > lhs;1679 return *res > lhs;
1571#endif1680#endif
1572}1681}
15731682
1574zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);1683zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1575static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {1684static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1576#if zig_has_builtin(sub_overflow)1685#if zig_has_builtin(sub_overflow)
1577 zig_i128 full_res;1686 zig_i128 full_res;
1578 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);1687 bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
1579#else1688#else
1580 zig_c_int overflow_int;1689 int overflow_int;
1581 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);1690 zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
1582 bool overflow = overflow_int != 0;1691 bool overflow = overflow_int != 0;
1583#endif1692#endif
1584 *res = zig_wrap_i128(full_res, bits);1693 *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);
1586}1695}
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) {
1589#if zig_has_builtin(mul_overflow)1698#if zig_has_builtin(mul_overflow)
1590 zig_u128 full_res;1699 zig_u128 full_res;
1591 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1700 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1592 *res = zig_wrap_u128(full_res, bits);1701 *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);
1594#else1703#else
1595 *res = zig_mulw_u128(lhs, rhs, bits);1704 *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;
1597#endif1706#endif
1598}1707}
15991708
1600zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);1709zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1601static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {1710static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1602#if zig_has_builtin(mul_overflow)1711#if zig_has_builtin(mul_overflow)
1603 zig_i128 full_res;1712 zig_i128 full_res;
1604 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);1713 bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
1605#else1714#else
1606 zig_c_int overflow_int;1715 int overflow_int;
1607 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);1716 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
1608 bool overflow = overflow_int != 0;1717 bool overflow = overflow_int != 0;
1609#endif1718#endif
1610 *res = zig_wrap_i128(full_res, bits);1719 *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);
1612}1721}
16131722
1614#else /* zig_has_int128 */1723#else /* zig_has_int128 */
16151724
1616static inline bool zig_overflow_u128(bool overflow, zig_u128 full_res, zig_u8 bits) {1725static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
1617 return overflow ||1726 uint64_t hi;
1618 zig_cmp_u128(full_res, zig_minInt(u128, bits)) < zig_as_i32(0) ||1727 bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
1619 zig_cmp_u128(full_res, zig_maxInt(u128, bits)) > zig_as_i32(0);1728 return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
1620}1729}
16211730
1622static inline bool zig_overflow_i128(bool overflow, zig_i128 full_res, zig_u8 bits) {1731static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1623 return overflow ||1732 int64_t hi;
1624 zig_cmp_i128(full_res, zig_minInt(i128, bits)) < zig_as_i32(0) ||1733 bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
1625 zig_cmp_i128(full_res, zig_maxInt(i128, bits)) > zig_as_i32(0);1734 return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
1626}1735}
16271736
1628static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {1737static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
1629 zig_u128 full_res;1738 uint64_t hi;
1630 bool overflow =1739 bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
1631 zig_addo_u64(&full_res.hi, lhs.hi, rhs.hi, 64) |1740 return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 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}1741}
16361742
1637zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);1743static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1638static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {1744 int64_t hi;
1639 zig_c_int overflow_int;1745 bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
1640 zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);1746 return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
1641 *res = zig_wrap_i128(full_res, bits);
1642 return zig_overflow_i128(overflow_int, full_res, bits);
1643}1747}
16441748
1645static inline bool zig_subo_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) {
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);1750 *res = zig_mulw_u128(lhs, rhs, bits);
1664 return zig_cmp_u128(*res, zig_as_u128(0, 0)) != zig_as_i32(0) &&1751 return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&
1665 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt(u128, bits), rhs)) > zig_as_i32(0);1752 zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
1666}1753}
16671754
1668zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, zig_c_int *overflow);1755zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
1669static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {1756static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
1670 zig_c_int overflow_int;1757 int overflow_int;
1671 zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);1758 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);
1672 *res = zig_wrap_i128(full_res, bits);1762 *res = zig_wrap_i128(full_res, bits);
1673 return zig_overflow_i128(overflow_int, full_res, bits);1763 return overflow;
1674}1764}
16751765
1676#endif /* zig_has_int128 */1766#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) {
1679 *res = zig_shlw_u128(lhs, rhs, bits);1769 *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);
1681}1771}
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) {
1684 *res = zig_shlw_i128(lhs, rhs, bits);1774 *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)));1775 zig_i128 mask = zig_bitcast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)));
1686 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_as_i128(0, 0)) != zig_as_i32(0) &&1776 return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
1687 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != zig_as_i32(0);1777 zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
1688}1778}
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) {
1691 zig_u128 res;1781 zig_u128 res;
1692 if (zig_cmp_u128(rhs, zig_as_u128(0, bits)) >= zig_as_i32(0))1782 if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) >= INT32_C(0))
1693 return zig_cmp_u128(lhs, zig_as_u128(0, 0)) != zig_as_i32(0) ? zig_maxInt(u128, bits) : lhs;1783 return zig_cmp_u128(lhs, zig_make_u128(0, 0)) != INT32_C(0) ? zig_maxInt_u(128, bits) : lhs;
16941784 return zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits) ? zig_maxInt_u(128, bits) : res;
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}1785}
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) {
1703 zig_i128 res;1788 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;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;
1705 return zig_cmp_i128(lhs, zig_as_i128(0, 0)) < zig_as_i32(0) ? zig_minInt(i128, bits) : zig_maxInt(i128, bits);1790 return zig_cmp_i128(lhs, zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
1706}1791}
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) {
1709 zig_u128 res;1794 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;
1711}1796}
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) {
1714 zig_i128 res;1799 zig_i128 res;
1715 if (!zig_addo_i128(&res, lhs, rhs, bits)) return res;1800 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);
1717}1802}
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) {
1720 zig_u128 res;1805 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;
1722}1807}
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) {
1725 zig_i128 res;1810 zig_i128 res;
1726 if (!zig_subo_i128(&res, lhs, rhs, bits)) return res;1811 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);
1728}1813}
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) {
1731 zig_u128 res;1816 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;
1733}1818}
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) {
1736 zig_i128 res;1821 zig_i128 res;
1737 if (!zig_mulo_i128(&res, lhs, rhs, bits)) return res;1822 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);
1739}1824}
17401825
1741static inline zig_u8 zig_clz_u128(zig_u128 val, zig_u8 bits) {1826static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {
1742 if (bits <= zig_as_u8(64)) return zig_clz_u64(zig_lo_u128(val), bits);1827 if (bits <= UINT8_C(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));1828 if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));
1744 return zig_clz_u64(zig_lo_u128(val), zig_as_u8(64)) + (bits - zig_as_u8(64));1829 return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));
1745}1830}
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) {
1748 return zig_clz_u128(zig_bitcast_u128(val), bits);1833 return zig_clz_u128(zig_bitcast_u128(val), bits);
1749}1834}
17501835
1751static inline zig_u8 zig_ctz_u128(zig_u128 val, zig_u8 bits) {1836static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {
1752 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), zig_as_u8(64));1837 if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));
1753 return zig_ctz_u64(zig_hi_u128(val), bits - zig_as_u8(64)) + zig_as_u8(64);1838 return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);
1754}1839}
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) {
1757 return zig_ctz_u128(zig_bitcast_u128(val), bits);1842 return zig_ctz_u128(zig_bitcast_u128(val), bits);
1758}1843}
17591844
1760static inline zig_u8 zig_popcount_u128(zig_u128 val, zig_u8 bits) {1845static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {
1761 return zig_popcount_u64(zig_hi_u128(val), bits - zig_as_u8(64)) +1846 return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +
1762 zig_popcount_u64(zig_lo_u128(val), zig_as_u8(64));1847 zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));
1763}1848}
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) {
1766 return zig_popcount_u128(zig_bitcast_u128(val), bits);1851 return zig_popcount_u128(zig_bitcast_u128(val), bits);
1767}1852}
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) {
1770 zig_u128 full_res;1855 zig_u128 full_res;
1771#if zig_has_builtin(bswap128)1856#if zig_has_builtin(bswap128)
1772 full_res = __builtin_bswap128(val);1857 full_res = __builtin_bswap128(val);
1773#else1858#else
1774 full_res = zig_as_u128(zig_byte_swap_u64(zig_lo_u128(val), zig_as_u8(64)),1859 full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),
1775 zig_byte_swap_u64(zig_hi_u128(val), zig_as_u8(64)));1860 zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));
1776#endif1861#endif
1777 return zig_shr_u128(full_res, zig_as_u8(128) - bits);1862 return zig_shr_u128(full_res, UINT8_C(128) - bits);
1778}1863}
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) {
1781 return zig_bitcast_i128(zig_byte_swap_u128(zig_bitcast_u128(val), bits));1866 return zig_bitcast_i128(zig_byte_swap_u128(zig_bitcast_u128(val), bits));
1782}1867}
17831868
1784static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, zig_u8 bits) {1869static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {
1785 return zig_shr_u128(zig_as_u128(zig_bit_reverse_u64(zig_lo_u128(val), zig_as_u8(64)),1870 return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),
1786 zig_bit_reverse_u64(zig_hi_u128(val), zig_as_u8(64))),1871 zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),
1787 zig_as_u8(128) - bits);1872 UINT8_C(128) - bits);
1788}1873}
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) {
1791 return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits));1876 return zig_bitcast_i128(zig_bit_reverse_u128(zig_bitcast_u128(val), bits));
1792}1877}
17931878
...@@ -1810,85 +1895,87 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {...@@ -1810,85 +1895,87 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
18101895
1811#if (zig_has_builtin(nan) && zig_has_builtin(nans) && zig_has_builtin(inf)) || defined(zig_gnuc)1896#if (zig_has_builtin(nan) && zig_has_builtin(nans) && zig_has_builtin(inf)) || defined(zig_gnuc)
1812#define zig_has_float_builtins 11897#define zig_has_float_builtins 1
1813#define zig_as_special_f16(sign, name, arg, repr) sign zig_as_f16(__builtin_##name, )(arg)1898#define zig_make_special_f16(sign, name, arg, repr) sign zig_make_f16(__builtin_##name, )(arg)
1814#define zig_as_special_f32(sign, name, arg, repr) sign zig_as_f32(__builtin_##name, )(arg)1899#define zig_make_special_f32(sign, name, arg, repr) sign zig_make_f32(__builtin_##name, )(arg)
1815#define zig_as_special_f64(sign, name, arg, repr) sign zig_as_f64(__builtin_##name, )(arg)1900#define zig_make_special_f64(sign, name, arg, repr) sign zig_make_f64(__builtin_##name, )(arg)
1816#define zig_as_special_f80(sign, name, arg, repr) sign zig_as_f80(__builtin_##name, )(arg)1901#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80(__builtin_##name, )(arg)
1817#define zig_as_special_f128(sign, name, arg, repr) sign zig_as_f128(__builtin_##name, )(arg)1902#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
1818#define zig_as_special_c_longdouble(sign, name, arg, repr) sign zig_as_c_longdouble(__builtin_##name, )(arg)1903#define zig_make_special_c_longdouble(sign, name, arg, repr) sign zig_make_c_longdouble(__builtin_##name, )(arg)
1819#else1904#else
1820#define zig_has_float_builtins 01905#define zig_has_float_builtins 0
1821#define zig_as_special_f16(sign, name, arg, repr) zig_float_from_repr_f16(repr)1906#define zig_make_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)1907#define zig_make_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)1908#define zig_make_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)1909#define zig_make_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)1910#define zig_make_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)1911#define zig_make_special_c_longdouble(sign, name, arg, repr) zig_float_from_repr_c_longdouble(repr)
1827#endif1912#endif
18281913
1829#define zig_has_f16 11914#define zig_has_f16 1
1830#define zig_bitSizeOf_f16 161915#define zig_bitSizeOf_f16 16
1831#define zig_libc_name_f16(name) __##name##h1916#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)
1833#if FLT_MANT_DIG == 111918#if FLT_MANT_DIG == 11
1834typedef float zig_f16;1919typedef float zig_f16;
1835#define zig_as_f16(fp, repr) fp##f1920#define zig_make_f16(fp, repr) fp##f
1836#elif DBL_MANT_DIG == 111921#elif DBL_MANT_DIG == 11
1837typedef double zig_f16;1922typedef double zig_f16;
1838#define zig_as_f16(fp, repr) fp1923#define zig_make_f16(fp, repr) fp
1839#elif LDBL_MANT_DIG == 111924#elif LDBL_MANT_DIG == 11
1840#define zig_bitSizeOf_c_longdouble 161925#define zig_bitSizeOf_c_longdouble 16
1926typedef uint16_t zig_repr_c_longdouble;
1841typedef long double zig_f16;1927typedef long double zig_f16;
1842#define zig_as_f16(fp, repr) fp##l1928#define zig_make_f16(fp, repr) fp##l
1843#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc))1929#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc))
1844typedef _Float16 zig_f16;1930typedef _Float16 zig_f16;
1845#define zig_as_f16(fp, repr) fp##f161931#define zig_make_f16(fp, repr) fp##f16
1846#elif defined(__SIZEOF_FP16__)1932#elif defined(__SIZEOF_FP16__)
1847typedef __fp16 zig_f16;1933typedef __fp16 zig_f16;
1848#define zig_as_f16(fp, repr) fp##f161934#define zig_make_f16(fp, repr) fp##f16
1849#else1935#else
1850#undef zig_has_f161936#undef zig_has_f16
1851#define zig_has_f16 01937#define zig_has_f16 0
1852#define zig_repr_f16 i161938#define zig_bitSizeOf_repr_f16 16
1853typedef zig_i16 zig_f16;1939typedef int16_t zig_f16;
1854#define zig_as_f16(fp, repr) repr1940#define zig_make_f16(fp, repr) repr
1855#undef zig_as_special_f161941#undef zig_make_special_f16
1856#define zig_as_special_f16(sign, name, arg, repr) repr1942#define zig_make_special_f16(sign, name, arg, repr) repr
1857#undef zig_as_special_constant_f161943#undef zig_make_special_constant_f16
1858#define zig_as_special_constant_f16(sign, name, arg, repr) repr1944#define zig_make_special_constant_f16(sign, name, arg, repr) repr
1859#endif1945#endif
18601946
1861#define zig_has_f32 11947#define zig_has_f32 1
1862#define zig_bitSizeOf_f32 321948#define zig_bitSizeOf_f32 32
1863#define zig_libc_name_f32(name) name##f1949#define zig_libc_name_f32(name) name##f
1864#if _MSC_VER1950#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, )
1866#else1952#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)
1868#endif1954#endif
1869#if FLT_MANT_DIG == 241955#if FLT_MANT_DIG == 24
1870typedef float zig_f32;1956typedef float zig_f32;
1871#define zig_as_f32(fp, repr) fp##f1957#define zig_make_f32(fp, repr) fp##f
1872#elif DBL_MANT_DIG == 241958#elif DBL_MANT_DIG == 24
1873typedef double zig_f32;1959typedef double zig_f32;
1874#define zig_as_f32(fp, repr) fp1960#define zig_make_f32(fp, repr) fp
1875#elif LDBL_MANT_DIG == 241961#elif LDBL_MANT_DIG == 24
1876#define zig_bitSizeOf_c_longdouble 321962#define zig_bitSizeOf_c_longdouble 32
1963typedef uint32_t zig_repr_c_longdouble;
1877typedef long double zig_f32;1964typedef long double zig_f32;
1878#define zig_as_f32(fp, repr) fp##l1965#define zig_make_f32(fp, repr) fp##l
1879#elif FLT32_MANT_DIG == 241966#elif FLT32_MANT_DIG == 24
1880typedef _Float32 zig_f32;1967typedef _Float32 zig_f32;
1881#define zig_as_f32(fp, repr) fp##f321968#define zig_make_f32(fp, repr) fp##f32
1882#else1969#else
1883#undef zig_has_f321970#undef zig_has_f32
1884#define zig_has_f32 01971#define zig_has_f32 0
1885#define zig_repr_f32 i321972#define zig_bitSizeOf_repr_f32 32
1886typedef zig_i32 zig_f32;1973typedef int32_t zig_f32;
1887#define zig_as_f32(fp, repr) repr1974#define zig_make_f32(fp, repr) repr
1888#undef zig_as_special_f321975#undef zig_make_special_f32
1889#define zig_as_special_f32(sign, name, arg, repr) repr1976#define zig_make_special_f32(sign, name, arg, repr) repr
1890#undef zig_as_special_constant_f321977#undef zig_make_special_constant_f32
1891#define zig_as_special_constant_f32(sign, name, arg, repr) repr1978#define zig_make_special_constant_f32(sign, name, arg, repr) repr
1892#endif1979#endif
18931980
1894#define zig_has_f64 11981#define zig_has_f64 1
...@@ -1897,109 +1984,113 @@ typedef zig_i32 zig_f32;...@@ -1897,109 +1984,113 @@ typedef zig_i32 zig_f32;
1897#if _MSC_VER1984#if _MSC_VER
1898#ifdef ZIG_TARGET_ABI_MSVC1985#ifdef ZIG_TARGET_ABI_MSVC
1899#define zig_bitSizeOf_c_longdouble 641986#define zig_bitSizeOf_c_longdouble 64
1987typedef uint64_t zig_repr_c_longdouble;
1900#endif1988#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, )
1902#else /* _MSC_VER */1990#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)
1904#endif /* _MSC_VER */1992#endif /* _MSC_VER */
1905#if FLT_MANT_DIG == 531993#if FLT_MANT_DIG == 53
1906typedef float zig_f64;1994typedef float zig_f64;
1907#define zig_as_f64(fp, repr) fp##f1995#define zig_make_f64(fp, repr) fp##f
1908#elif DBL_MANT_DIG == 531996#elif DBL_MANT_DIG == 53
1909typedef double zig_f64;1997typedef double zig_f64;
1910#define zig_as_f64(fp, repr) fp1998#define zig_make_f64(fp, repr) fp
1911#elif LDBL_MANT_DIG == 531999#elif LDBL_MANT_DIG == 53
1912#define zig_bitSizeOf_c_longdouble 642000#define zig_bitSizeOf_c_longdouble 64
2001typedef uint64_t zig_repr_c_longdouble;
1913typedef long double zig_f64;2002typedef long double zig_f64;
1914#define zig_as_f64(fp, repr) fp##l2003#define zig_make_f64(fp, repr) fp##l
1915#elif FLT64_MANT_DIG == 532004#elif FLT64_MANT_DIG == 53
1916typedef _Float64 zig_f64;2005typedef _Float64 zig_f64;
1917#define zig_as_f64(fp, repr) fp##f642006#define zig_make_f64(fp, repr) fp##f64
1918#elif FLT32X_MANT_DIG == 532007#elif FLT32X_MANT_DIG == 53
1919typedef _Float32x zig_f64;2008typedef _Float32x zig_f64;
1920#define zig_as_f64(fp, repr) fp##f32x2009#define zig_make_f64(fp, repr) fp##f32x
1921#else2010#else
1922#undef zig_has_f642011#undef zig_has_f64
1923#define zig_has_f64 02012#define zig_has_f64 0
1924#define zig_repr_f64 i642013#define zig_bitSizeOf_repr_f64 64
1925typedef zig_i64 zig_f64;2014typedef int64_t zig_f64;
1926#define zig_as_f64(fp, repr) repr2015#define zig_make_f64(fp, repr) repr
1927#undef zig_as_special_f642016#undef zig_make_special_f64
1928#define zig_as_special_f64(sign, name, arg, repr) repr2017#define zig_make_special_f64(sign, name, arg, repr) repr
1929#undef zig_as_special_constant_f642018#undef zig_make_special_constant_f64
1930#define zig_as_special_constant_f64(sign, name, arg, repr) repr2019#define zig_make_special_constant_f64(sign, name, arg, repr) repr
1931#endif2020#endif
19322021
1933#define zig_has_f80 12022#define zig_has_f80 1
1934#define zig_bitSizeOf_f80 802023#define zig_bitSizeOf_f80 80
1935#define zig_libc_name_f80(name) __##name##x2024#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)
1937#if FLT_MANT_DIG == 642026#if FLT_MANT_DIG == 64
1938typedef float zig_f80;2027typedef float zig_f80;
1939#define zig_as_f80(fp, repr) fp##f2028#define zig_make_f80(fp, repr) fp##f
1940#elif DBL_MANT_DIG == 642029#elif DBL_MANT_DIG == 64
1941typedef double zig_f80;2030typedef double zig_f80;
1942#define zig_as_f80(fp, repr) fp2031#define zig_make_f80(fp, repr) fp
1943#elif LDBL_MANT_DIG == 642032#elif LDBL_MANT_DIG == 64
1944#define zig_bitSizeOf_c_longdouble 802033#define zig_bitSizeOf_c_longdouble 80
2034typedef zig_u128 zig_repr_c_longdouble;
1945typedef long double zig_f80;2035typedef long double zig_f80;
1946#define zig_as_f80(fp, repr) fp##l2036#define zig_make_f80(fp, repr) fp##l
1947#elif FLT80_MANT_DIG == 642037#elif FLT80_MANT_DIG == 64
1948typedef _Float80 zig_f80;2038typedef _Float80 zig_f80;
1949#define zig_as_f80(fp, repr) fp##f802039#define zig_make_f80(fp, repr) fp##f80
1950#elif FLT64X_MANT_DIG == 642040#elif FLT64X_MANT_DIG == 64
1951typedef _Float64x zig_f80;2041typedef _Float64x zig_f80;
1952#define zig_as_f80(fp, repr) fp##f64x2042#define zig_make_f80(fp, repr) fp##f64x
1953#elif defined(__SIZEOF_FLOAT80__)2043#elif defined(__SIZEOF_FLOAT80__)
1954typedef __float80 zig_f80;2044typedef __float80 zig_f80;
1955#define zig_as_f80(fp, repr) fp##l2045#define zig_make_f80(fp, repr) fp##l
1956#else2046#else
1957#undef zig_has_f802047#undef zig_has_f80
1958#define zig_has_f80 02048#define zig_has_f80 0
1959#define zig_repr_f80 i1282049#define zig_bitSizeOf_repr_f80 128
1960typedef zig_i128 zig_f80;2050typedef zig_i128 zig_f80;
1961#define zig_as_f80(fp, repr) repr2051#define zig_make_f80(fp, repr) repr
1962#undef zig_as_special_f802052#undef zig_make_special_f80
1963#define zig_as_special_f80(sign, name, arg, repr) repr2053#define zig_make_special_f80(sign, name, arg, repr) repr
1964#undef zig_as_special_constant_f802054#undef zig_make_special_constant_f80
1965#define zig_as_special_constant_f80(sign, name, arg, repr) repr2055#define zig_make_special_constant_f80(sign, name, arg, repr) repr
1966#endif2056#endif
19672057
1968#define zig_has_f128 12058#define zig_has_f128 1
1969#define zig_bitSizeOf_f128 1282059#define zig_bitSizeOf_f128 128
1970#define zig_libc_name_f128(name) name##q2060#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)
1972#if FLT_MANT_DIG == 1132062#if FLT_MANT_DIG == 113
1973typedef float zig_f128;2063typedef float zig_f128;
1974#define zig_as_f128(fp, repr) fp##f2064#define zig_make_f128(fp, repr) fp##f
1975#elif DBL_MANT_DIG == 1132065#elif DBL_MANT_DIG == 113
1976typedef double zig_f128;2066typedef double zig_f128;
1977#define zig_as_f128(fp, repr) fp2067#define zig_make_f128(fp, repr) fp
1978#elif LDBL_MANT_DIG == 1132068#elif LDBL_MANT_DIG == 113
1979#define zig_bitSizeOf_c_longdouble 1282069#define zig_bitSizeOf_c_longdouble 128
2070typedef zig_u128 zig_repr_c_longdouble;
1980typedef long double zig_f128;2071typedef long double zig_f128;
1981#define zig_as_f128(fp, repr) fp##l2072#define zig_make_f128(fp, repr) fp##l
1982#elif FLT128_MANT_DIG == 1132073#elif FLT128_MANT_DIG == 113
1983typedef _Float128 zig_f128;2074typedef _Float128 zig_f128;
1984#define zig_as_f128(fp, repr) fp##f1282075#define zig_make_f128(fp, repr) fp##f128
1985#elif FLT64X_MANT_DIG == 1132076#elif FLT64X_MANT_DIG == 113
1986typedef _Float64x zig_f128;2077typedef _Float64x zig_f128;
1987#define zig_as_f128(fp, repr) fp##f64x2078#define zig_make_f128(fp, repr) fp##f64x
1988#elif defined(__SIZEOF_FLOAT128__)2079#elif defined(__SIZEOF_FLOAT128__)
1989typedef __float128 zig_f128;2080typedef __float128 zig_f128;
1990#define zig_as_f128(fp, repr) fp##q2081#define zig_make_f128(fp, repr) fp##q
1991#undef zig_as_special_f1282082#undef zig_make_special_f128
1992#define zig_as_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)2083#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
1993#else2084#else
1994#undef zig_has_f1282085#undef zig_has_f128
1995#define zig_has_f128 02086#define zig_has_f128 0
1996#define zig_repr_f128 i1282087#define zig_bitSizeOf_repr_f128 128
1997typedef zig_i128 zig_f128;2088typedef zig_i128 zig_f128;
1998#define zig_as_f128(fp, repr) repr2089#define zig_make_f128(fp, repr) repr
1999#undef zig_as_special_f1282090#undef zig_make_special_f128
2000#define zig_as_special_f128(sign, name, arg, repr) repr2091#define zig_make_special_f128(sign, name, arg, repr) repr
2001#undef zig_as_special_constant_f1282092#undef zig_make_special_constant_f128
2002#define zig_as_special_constant_f128(sign, name, arg, repr) repr2093#define zig_make_special_constant_f128(sign, name, arg, repr) repr
2003#endif2094#endif
20042095
2005#define zig_has_c_longdouble 12096#define zig_has_c_longdouble 1
...@@ -2010,17 +2101,18 @@ typedef zig_i128 zig_f128;...@@ -2010,17 +2101,18 @@ typedef zig_i128 zig_f128;
2010#define zig_libc_name_c_longdouble(name) name##l2101#define zig_libc_name_c_longdouble(name) name##l
2011#endif2102#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)
2014#ifdef zig_bitSizeOf_c_longdouble2105#ifdef zig_bitSizeOf_c_longdouble
20152106
2016#ifdef ZIG_TARGET_ABI_MSVC2107#ifdef ZIG_TARGET_ABI_MSVC
2017typedef double zig_c_longdouble;
2018#undef zig_bitSizeOf_c_longdouble2108#undef zig_bitSizeOf_c_longdouble
2019#define zig_bitSizeOf_c_longdouble 642109#define zig_bitSizeOf_c_longdouble 64
2020#define zig_as_c_longdouble(fp, repr) fp2110typedef uint64_t zig_repr_c_longdouble;
2111typedef zig_f64 zig_c_longdouble;
2112#define zig_make_c_longdouble(fp, repr) fp
2021#else2113#else
2022typedef long double zig_c_longdouble;2114typedef long double zig_c_longdouble;
2023#define zig_as_c_longdouble(fp, repr) fp##l2115#define zig_make_c_longdouble(fp, repr) fp##l
2024#endif2116#endif
20252117
2026#else /* zig_bitSizeOf_c_longdouble */2118#else /* zig_bitSizeOf_c_longdouble */
...@@ -2028,34 +2120,32 @@ typedef long double zig_c_longdouble;...@@ -2028,34 +2120,32 @@ typedef long double zig_c_longdouble;
2028#undef zig_has_c_longdouble2120#undef zig_has_c_longdouble
2029#define zig_has_c_longdouble 02121#define zig_has_c_longdouble 0
2030#define zig_bitSizeOf_c_longdouble 802122#define zig_bitSizeOf_c_longdouble 80
2123typedef zig_u128 zig_repr_c_longdouble;
2031#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f802124#define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80
2032#define zig_repr_c_longdouble i1282125#define zig_bitSizeOf_repr_c_longdouble 128
2033typedef zig_i128 zig_c_longdouble;2126typedef zig_i128 zig_c_longdouble;
2034#define zig_as_c_longdouble(fp, repr) repr2127#define zig_make_c_longdouble(fp, repr) repr
2035#undef zig_as_special_c_longdouble2128#undef zig_make_special_c_longdouble
2036#define zig_as_special_c_longdouble(sign, name, arg, repr) repr2129#define zig_make_special_c_longdouble(sign, name, arg, repr) repr
2037#undef zig_as_special_constant_c_longdouble2130#undef zig_make_special_constant_c_longdouble
2038#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) repr2131#define zig_make_special_constant_c_longdouble(sign, name, arg, repr) repr
20392132
2040#endif /* zig_bitSizeOf_c_longdouble */2133#endif /* zig_bitSizeOf_c_longdouble */
20412134
2042#if !zig_has_float_builtins2135#if !zig_has_float_builtins
2043#define zig_float_from_repr(Type, ReprType) \2136#define zig_float_from_repr(Type, ReprType) \
2044 static inline zig_##Type zig_float_from_repr_##Type(zig_##ReprType repr) { \2137 static inline zig_##Type zig_float_from_repr_##Type(ReprType repr) { \
2045 return *((zig_##Type*)&repr); \2138 zig_##Type result; \
2139 memcpy(&result, &repr, sizeof(result)); \
2140 return result; \
2046 }2141 }
20472142
2048zig_float_from_repr(f16, u16)2143zig_float_from_repr(f16, uint16_t)
2049zig_float_from_repr(f32, u32)2144zig_float_from_repr(f32, uint32_t)
2050zig_float_from_repr(f64, u64)2145zig_float_from_repr(f64, uint64_t)
2051zig_float_from_repr(f80, u128)2146zig_float_from_repr(f80, zig_u128)
2052zig_float_from_repr(f128, u128)2147zig_float_from_repr(f128, zig_u128)
2053#if zig_bitSizeOf_c_longdouble == 802148zig_float_from_repr(c_longdouble, zig_repr_c_longdouble)
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#endif2149#endif
20602150
2061#define zig_cast_f16 (zig_f16)2151#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...@@ -2073,32 +2163,35 @@ zig_expand_float_from_repr(c_longdouble, zig_expand_concat(u, zig_bitSizeOf_c_lo
2073#endif2163#endif
20742164
2075#define zig_convert_builtin(ResType, operation, ArgType, version) \2165#define zig_convert_builtin(ResType, operation, ArgType, version) \
2076 zig_extern zig_##ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \2166 zig_extern 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);2167 zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType);
2078zig_convert_builtin(f16, trunc, f32, 2)2168zig_convert_builtin(zig_f16, trunc, zig_f32, 2)
2079zig_convert_builtin(f16, trunc, f64, 2)2169zig_convert_builtin(zig_f16, trunc, zig_f64, 2)
2080zig_convert_builtin(f16, trunc, f80, 2)2170zig_convert_builtin(zig_f16, trunc, zig_f80, 2)
2081zig_convert_builtin(f16, trunc, f128, 2)2171zig_convert_builtin(zig_f16, trunc, zig_f128, 2)
2082zig_convert_builtin(f32, extend, f16, 2)2172zig_convert_builtin(zig_f32, extend, zig_f16, 2)
2083zig_convert_builtin(f32, trunc, f64, 2)2173zig_convert_builtin(zig_f32, trunc, zig_f64, 2)
2084zig_convert_builtin(f32, trunc, f80, 2)2174zig_convert_builtin(zig_f32, trunc, zig_f80, 2)
2085zig_convert_builtin(f32, trunc, f128, 2)2175zig_convert_builtin(zig_f32, trunc, zig_f128, 2)
2086zig_convert_builtin(f64, extend, f16, 2)2176zig_convert_builtin(zig_f64, extend, zig_f16, 2)
2087zig_convert_builtin(f64, extend, f32, 2)2177zig_convert_builtin(zig_f64, extend, zig_f32, 2)
2088zig_convert_builtin(f64, trunc, f80, 2)2178zig_convert_builtin(zig_f64, trunc, zig_f80, 2)
2089zig_convert_builtin(f64, trunc, f128, 2)2179zig_convert_builtin(zig_f64, trunc, zig_f128, 2)
2090zig_convert_builtin(f80, extend, f16, 2)2180zig_convert_builtin(zig_f80, extend, zig_f16, 2)
2091zig_convert_builtin(f80, extend, f32, 2)2181zig_convert_builtin(zig_f80, extend, zig_f32, 2)
2092zig_convert_builtin(f80, extend, f64, 2)2182zig_convert_builtin(zig_f80, extend, zig_f64, 2)
2093zig_convert_builtin(f80, trunc, f128, 2)2183zig_convert_builtin(zig_f80, trunc, zig_f128, 2)
2094zig_convert_builtin(f128, extend, f16, 2)2184zig_convert_builtin(zig_f128, extend, zig_f16, 2)
2095zig_convert_builtin(f128, extend, f32, 2)2185zig_convert_builtin(zig_f128, extend, zig_f32, 2)
2096zig_convert_builtin(f128, extend, f64, 2)2186zig_convert_builtin(zig_f128, extend, zig_f64, 2)
2097zig_convert_builtin(f128, extend, f80, 2)2187zig_convert_builtin(zig_f128, extend, zig_f80, 2)
20982188
2099#define zig_float_negate_builtin_0(Type) \2189#define zig_float_negate_builtin_0(Type) \
2100 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \2190 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 ); \
2102 }2195 }
2103#define zig_float_negate_builtin_1(Type) \2196#define zig_float_negate_builtin_1(Type) \
2104 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \2197 static inline zig_##Type zig_neg_##Type(zig_##Type arg) { \
...@@ -2106,28 +2199,28 @@ zig_convert_builtin(f128, extend, f80, 2)...@@ -2106,28 +2199,28 @@ zig_convert_builtin(f128, extend, f80, 2)
2106 }2199 }
21072200
2108#define zig_float_less_builtin_0(Type, operation) \2201#define zig_float_less_builtin_0(Type, operation) \
2109 zig_extern zig_i32 zig_expand_concat(zig_expand_concat(__##operation, \2202 zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \
2110 zig_compiler_rt_abbrev_##Type), 2)(zig_##Type, zig_##Type); \2203 zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
2111 static inline zig_i32 zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \2204 static inline int32_t 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); \2205 return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
2113 }2206 }
2114#define zig_float_less_builtin_1(Type, operation) \2207#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) { \
2116 return (!(lhs <= rhs) - (lhs < rhs)); \2209 return (!(lhs <= rhs) - (lhs < rhs)); \
2117 }2210 }
21182211
2119#define zig_float_greater_builtin_0(Type, operation) \2212#define zig_float_greater_builtin_0(Type, operation) \
2120 zig_float_less_builtin_0(Type, operation)2213 zig_float_less_builtin_0(Type, operation)
2121#define zig_float_greater_builtin_1(Type, operation) \2214#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) { \
2123 return ((lhs > rhs) - !(lhs >= rhs)); \2216 return ((lhs > rhs) - !(lhs >= rhs)); \
2124 }2217 }
21252218
2126#define zig_float_binary_builtin_0(Type, operation, operator) \2219#define zig_float_binary_builtin_0(Type, operation, operator) \
2127 zig_extern zig_##Type zig_expand_concat(zig_expand_concat(__##operation, \2220 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); \
2129 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \2222 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); \
2131 }2224 }
2132#define zig_float_binary_builtin_1(Type, operation, operator) \2225#define zig_float_binary_builtin_1(Type, operation, operator) \
2133 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \2226 static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
...@@ -2135,18 +2228,18 @@ zig_convert_builtin(f128, extend, f80, 2)...@@ -2135,18 +2228,18 @@ zig_convert_builtin(f128, extend, f80, 2)
2135 }2228 }
21362229
2137#define zig_float_builtins(Type) \2230#define zig_float_builtins(Type) \
2138 zig_convert_builtin(i32, fix, Type, ) \2231 zig_convert_builtin( int32_t, fix, zig_##Type, ) \
2139 zig_convert_builtin(u32, fixuns, Type, ) \2232 zig_convert_builtin(uint32_t, fixuns, zig_##Type, ) \
2140 zig_convert_builtin(i64, fix, Type, ) \2233 zig_convert_builtin( int64_t, fix, zig_##Type, ) \
2141 zig_convert_builtin(u64, fixuns, Type, ) \2234 zig_convert_builtin(uint64_t, fixuns, zig_##Type, ) \
2142 zig_convert_builtin(i128, fix, Type, ) \2235 zig_convert_builtin(zig_i128, fix, zig_##Type, ) \
2143 zig_convert_builtin(u128, fixuns, Type, ) \2236 zig_convert_builtin(zig_u128, fixuns, zig_##Type, ) \
2144 zig_convert_builtin(Type, float, i32, ) \2237 zig_convert_builtin(zig_##Type, float, int32_t, ) \
2145 zig_convert_builtin(Type, floatun, u32, ) \2238 zig_convert_builtin(zig_##Type, floatun, uint32_t, ) \
2146 zig_convert_builtin(Type, float, i64, ) \2239 zig_convert_builtin(zig_##Type, float, int64_t, ) \
2147 zig_convert_builtin(Type, floatun, u64, ) \2240 zig_convert_builtin(zig_##Type, floatun, uint64_t, ) \
2148 zig_convert_builtin(Type, float, i128, ) \2241 zig_convert_builtin(zig_##Type, float, zig_i128, ) \
2149 zig_convert_builtin(Type, floatun, u128, ) \2242 zig_convert_builtin(zig_##Type, floatun, zig_u128, ) \
2150 zig_expand_concat(zig_float_negate_builtin_, zig_has_##Type)(Type) \2243 zig_expand_concat(zig_float_negate_builtin_, zig_has_##Type)(Type) \
2151 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, cmp) \2244 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) \2245 zig_expand_concat(zig_float_less_builtin_, zig_has_##Type)(Type, ne) \
...@@ -2200,98 +2293,98 @@ zig_float_builtins(c_longdouble)...@@ -2200,98 +2293,98 @@ zig_float_builtins(c_longdouble)
22002293
2201// TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, and load 64 bit without interlocked on x642294// 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) \2296#define zig_msvc_atomics(ZigType, Type, suffix) \
2204 static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \2297 static inline bool zig_msvc_cmpxchg_##ZigType(Type volatile* obj, Type* expected, Type desired) { \
2205 zig_##Type comparand = *expected; \2298 Type comparand = *expected; \
2206 zig_##Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \2299 Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \
2207 bool exchanged = initial == comparand; \2300 bool exchanged = initial == comparand; \
2208 if (!exchanged) { \2301 if (!exchanged) { \
2209 *expected = initial; \2302 *expected = initial; \
2210 } \2303 } \
2211 return exchanged; \2304 return exchanged; \
2212 } \2305 } \
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) { \
2214 return _InterlockedExchange##suffix(obj, value); \2307 return _InterlockedExchange##suffix(obj, value); \
2215 } \2308 } \
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) { \
2217 return _InterlockedExchangeAdd##suffix(obj, value); \2310 return _InterlockedExchangeAdd##suffix(obj, value); \
2218 } \2311 } \
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) { \
2220 bool success = false; \2313 bool success = false; \
2221 zig_##Type new; \2314 Type new; \
2222 zig_##Type prev; \2315 Type prev; \
2223 while (!success) { \2316 while (!success) { \
2224 prev = *obj; \2317 prev = *obj; \
2225 new = prev - value; \2318 new = prev - value; \
2226 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \2319 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
2227 } \2320 } \
2228 return prev; \2321 return prev; \
2229 } \2322 } \
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) { \
2231 return _InterlockedOr##suffix(obj, value); \2324 return _InterlockedOr##suffix(obj, value); \
2232 } \2325 } \
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) { \
2234 return _InterlockedXor##suffix(obj, value); \2327 return _InterlockedXor##suffix(obj, value); \
2235 } \2328 } \
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) { \
2237 return _InterlockedAnd##suffix(obj, value); \2330 return _InterlockedAnd##suffix(obj, value); \
2238 } \2331 } \
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) { \
2240 bool success = false; \2333 bool success = false; \
2241 zig_##Type new; \2334 Type new; \
2242 zig_##Type prev; \2335 Type prev; \
2243 while (!success) { \2336 while (!success) { \
2244 prev = *obj; \2337 prev = *obj; \
2245 new = ~(prev & value); \2338 new = ~(prev & value); \
2246 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \2339 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
2247 } \2340 } \
2248 return prev; \2341 return prev; \
2249 } \2342 } \
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) { \
2251 bool success = false; \2344 bool success = false; \
2252 zig_##Type new; \2345 Type new; \
2253 zig_##Type prev; \2346 Type prev; \
2254 while (!success) { \2347 while (!success) { \
2255 prev = *obj; \2348 prev = *obj; \
2256 new = value < prev ? value : prev; \2349 new = value < prev ? value : prev; \
2257 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \2350 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
2258 } \2351 } \
2259 return prev; \2352 return prev; \
2260 } \2353 } \
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) { \
2262 bool success = false; \2355 bool success = false; \
2263 zig_##Type new; \2356 Type new; \
2264 zig_##Type prev; \2357 Type prev; \
2265 while (!success) { \2358 while (!success) { \
2266 prev = *obj; \2359 prev = *obj; \
2267 new = value > prev ? value : prev; \2360 new = value > prev ? value : prev; \
2268 success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \2361 success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
2269 } \2362 } \
2270 return prev; \2363 return prev; \
2271 } \2364 } \
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) { \
2273 _InterlockedExchange##suffix(obj, value); \2366 _InterlockedExchange##suffix(obj, value); \
2274 } \2367 } \
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) { \
2276 return _InterlockedOr##suffix(obj, 0); \2369 return _InterlockedOr##suffix(obj, 0); \
2277 }2370 }
22782371
2279zig_msvc_atomics(u8, 8)2372zig_msvc_atomics( u8, uint8_t, 8)
2280zig_msvc_atomics(i8, 8)2373zig_msvc_atomics( i8, int8_t, 8)
2281zig_msvc_atomics(u16, 16)2374zig_msvc_atomics(u16, uint16_t, 16)
2282zig_msvc_atomics(i16, 16)2375zig_msvc_atomics(i16, int16_t, 16)
2283zig_msvc_atomics(u32, )2376zig_msvc_atomics(u32, uint32_t, )
2284zig_msvc_atomics(i32, )2377zig_msvc_atomics(i32, int32_t, )
22852378
2286#if _M_X642379#if _M_X64
2287zig_msvc_atomics(u64, 64)2380zig_msvc_atomics(u64, uint64_t, 64)
2288zig_msvc_atomics(i64, 64)2381zig_msvc_atomics(i64, int64_t, 64)
2289#endif2382#endif
22902383
2291#define zig_msvc_flt_atomics(Type, ReprType, suffix) \2384#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) { \2385 static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
2293 zig_##ReprType comparand = *((zig_##ReprType*)expected); \2386 ReprType comparand = *((ReprType*)expected); \
2294 zig_##ReprType initial = _InterlockedCompareExchange##suffix((zig_##ReprType volatile*)obj, *((zig_##ReprType*)&desired), comparand); \2387 ReprType initial = _InterlockedCompareExchange##suffix((ReprType volatile*)obj, *((ReprType*)&desired), comparand); \
2295 bool exchanged = initial == comparand; \2388 bool exchanged = initial == comparand; \
2296 if (!exchanged) { \2389 if (!exchanged) { \
2297 *expected = *((zig_##Type*)&initial); \2390 *expected = *((zig_##Type*)&initial); \
...@@ -2299,50 +2392,50 @@ zig_msvc_atomics(i64, 64)...@@ -2299,50 +2392,50 @@ zig_msvc_atomics(i64, 64)
2299 return exchanged; \2392 return exchanged; \
2300 } \2393 } \
2301 static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \2394 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)); \
2303 return *((zig_##Type*)&initial); \2396 return *((zig_##Type*)&initial); \
2304 } \2397 } \
2305 static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \2398 static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2306 bool success = false; \2399 bool success = false; \
2307 zig_##ReprType new; \2400 ReprType new; \
2308 zig_##Type prev; \2401 zig_##Type prev; \
2309 while (!success) { \2402 while (!success) { \
2310 prev = *obj; \2403 prev = *obj; \
2311 new = prev + value; \2404 new = prev + value; \
2312 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \2405 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((ReprType*)&new)); \
2313 } \2406 } \
2314 return prev; \2407 return prev; \
2315 } \2408 } \
2316 static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \2409 static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \
2317 bool success = false; \2410 bool success = false; \
2318 zig_##ReprType new; \2411 ReprType new; \
2319 zig_##Type prev; \2412 zig_##Type prev; \
2320 while (!success) { \2413 while (!success) { \
2321 prev = *obj; \2414 prev = *obj; \
2322 new = prev - value; \2415 new = prev - value; \
2323 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \2416 success = zig_msvc_cmpxchg_##Type(obj, &prev, *((ReprType*)&new)); \
2324 } \2417 } \
2325 return prev; \2418 return prev; \
2326 }2419 }
23272420
2328zig_msvc_flt_atomics(f32, u32, )2421zig_msvc_flt_atomics(f32, uint32_t, )
2329#if _M_X642422#if _M_X64
2330zig_msvc_flt_atomics(f64, u64, 64)2423zig_msvc_flt_atomics(f64, uint64_t, 64)
2331#endif2424#endif
23322425
2333#if _M_IX862426#if _M_IX86
2334static inline void zig_msvc_atomic_barrier() {2427static inline void zig_msvc_atomic_barrier() {
2335 zig_i32 barrier;2428 int32_t barrier;
2336 __asm {2429 __asm {
2337 xchg barrier, eax2430 xchg barrier, eax
2338 }2431 }
2339}2432}
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) {
2342 return _InterlockedExchangePointer(obj, arg);2435 return _InterlockedExchangePointer(obj, arg);
2343}2436}
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) {
2346 _InterlockedExchangePointer(obj, arg);2439 _InterlockedExchangePointer(obj, arg);
2347}2440}
23482441
...@@ -2360,11 +2453,11 @@ static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desir...@@ -2360,11 +2453,11 @@ static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desir
2360 return exchanged;2453 return exchanged;
2361}2454}
2362#else /* _M_IX86 */2455#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) {
2364 return _InterlockedExchangePointer(obj, arg);2457 return _InterlockedExchangePointer(obj, arg);
2365}2458}
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) {
2368 _InterlockedExchangePointer(obj, arg);2461 _InterlockedExchangePointer(obj, arg);
2369}2462}
23702463
...@@ -2383,11 +2476,11 @@ static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desir...@@ -2383,11 +2476,11 @@ static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desir
2383}2476}
23842477
2385static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expected, zig_u128 desired) {2478static 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);
2387}2480}
23882481
2389static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {2482static 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);
2391}2484}
23922485
2393#define zig_msvc_atomics_128xchg(Type) \2486#define zig_msvc_atomics_128xchg(Type) \
...@@ -2429,7 +2522,7 @@ zig_msvc_atomics_128op(u128, max)...@@ -2429,7 +2522,7 @@ zig_msvc_atomics_128op(u128, max)
24292522
2430#endif /* _MSC_VER && (_M_IX86 || _M_X64) */2523#endif /* _MSC_VER && (_M_IX86 || _M_X64) */
24312524
2432/* ========================= Special Case Intrinsics ========================= */2525/* ======================== Special Case Intrinsics ========================= */
24332526
2434#if (_MSC_VER && _M_X64) || defined(__x86_64__)2527#if (_MSC_VER && _M_X64) || defined(__x86_64__)
24352528
...@@ -2459,8 +2552,8 @@ static inline void* zig_x86_windows_teb(void) {...@@ -2459,8 +2552,8 @@ static inline void* zig_x86_windows_teb(void) {
24592552
2460#if (_MSC_VER && (_M_IX86 || _M_X64)) || defined(__i386__) || defined(__x86_64__)2553#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) {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) {
2463 zig_u32 cpu_info[4];2556 uint32_t cpu_info[4];
2464#if _MSC_VER2557#if _MSC_VER
2465 __cpuidex(cpu_info, leaf_id, subid);2558 __cpuidex(cpu_info, leaf_id, subid);
2466#else2559#else
...@@ -2472,12 +2565,12 @@ static inline void zig_x86_cpuid(zig_u32 leaf_id, zig_u32 subid, zig_u32* eax, z...@@ -2472,12 +2565,12 @@ static inline void zig_x86_cpuid(zig_u32 leaf_id, zig_u32 subid, zig_u32* eax, z
2472 *edx = cpu_info[3];2565 *edx = cpu_info[3];
2473}2566}
24742567
2475static inline zig_u32 zig_x86_get_xcr0(void) {2568static inline uint32_t zig_x86_get_xcr0(void) {
2476#if _MSC_VER2569#if _MSC_VER
2477 return (zig_u32)_xgetbv(0);2570 return (uint32_t)_xgetbv(0);
2478#else2571#else
2479 zig_u32 eax;2572 uint32_t eax;
2480 zig_u32 edx;2573 uint32_t edx;
2481 __asm__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));2574 __asm__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
2482 return eax;2575 return eax;
2483#endif2576#endif
src/Compilation.zig+5-9
...@@ -3325,24 +3325,20 @@ fn processOneJob(comp: *Compilation, job: Job) !void {...@@ -3325,24 +3325,20 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
3325 const decl_emit_h = emit_h.declPtr(decl_index);3325 const decl_emit_h = emit_h.declPtr(decl_index);
3326 const fwd_decl = &decl_emit_h.fwd_decl;3326 const fwd_decl = &decl_emit_h.fwd_decl;
3327 fwd_decl.shrinkRetainingCapacity(0);3327 fwd_decl.shrinkRetainingCapacity(0);
3328 var typedefs_arena = std.heap.ArenaAllocator.init(gpa);3328 var ctypes_arena = std.heap.ArenaAllocator.init(gpa);
3329 defer typedefs_arena.deinit();3329 defer ctypes_arena.deinit();
33303330
3331 var dg: c_codegen.DeclGen = .{3331 var dg: c_codegen.DeclGen = .{
3332 .gpa = gpa,3332 .gpa = gpa,
3333 .module = module,3333 .module = module,
3334 .error_msg = null,3334 .error_msg = null,
3335 .decl_index = decl_index,3335 .decl_index = decl_index.toOptional(),
3336 .decl = decl,3336 .decl = decl,
3337 .fwd_decl = fwd_decl.toManaged(gpa),3337 .fwd_decl = fwd_decl.toManaged(gpa),
3338 .typedefs = c_codegen.TypedefMap.initContext(gpa, .{ .mod = module }),3338 .ctypes = .{},
3339 .typedefs_arena = typedefs_arena.allocator(),
3340 };3339 };
3341 defer {3340 defer {
3342 for (dg.typedefs.values()) |typedef| {3341 dg.ctypes.deinit(gpa);
3343 module.gpa.free(typedef.rendered);
3344 }
3345 dg.typedefs.deinit();
3346 dg.fwd_decl.deinit();3342 dg.fwd_decl.deinit();
3347 }3343 }
33483344
src/codegen/c.zig+890-1103
...@@ -23,12 +23,15 @@ const libcFloatSuffix = target_util.libcFloatSuffix;...@@ -23,12 +23,15 @@ const libcFloatSuffix = target_util.libcFloatSuffix;
23const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;23const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev;
24const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;24const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev;
2525
26const Mutability = enum { Const, ConstArgument, Mut };26const Mutability = enum { @"const", mut };
27const BigIntLimb = std.math.big.Limb;27const BigIntLimb = std.math.big.Limb;
28const BigInt = std.math.big.int;28const BigInt = std.math.big.int;
2929
30pub const CType = @import("c/type.zig").CType;
31
30pub const CValue = union(enum) {32pub const CValue = union(enum) {
31 none: void,33 none: void,
34 new_local: LocalIndex,
32 local: LocalIndex,35 local: LocalIndex,
33 /// Address of a local.36 /// Address of a local.
34 local_ref: LocalIndex,37 local_ref: LocalIndex,
...@@ -36,6 +39,8 @@ pub const CValue = union(enum) {...@@ -36,6 +39,8 @@ pub const CValue = union(enum) {
36 constant: Air.Inst.Ref,39 constant: Air.Inst.Ref,
37 /// Index into the parameters40 /// Index into the parameters
38 arg: usize,41 arg: usize,
42 /// The payload field of a parameter
43 arg_array: usize,
39 /// Index into a tuple's fields44 /// Index into a tuple's fields
40 field: usize,45 field: usize,
41 /// By-value46 /// By-value
...@@ -61,12 +66,17 @@ const TypedefKind = enum {...@@ -61,12 +66,17 @@ const TypedefKind = enum {
61};66};
6267
63pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);68pub const CValueMap = std.AutoHashMap(Air.Inst.Ref, CValue);
64pub const TypedefMap = std.ArrayHashMap(69
65 Type,70pub const LazyFnKey = union(enum) {
66 struct { name: []const u8, rendered: []u8 },71 tag_name: Decl.Index,
67 Type.HashContext32,72};
68 true,73pub const LazyFnValue = struct {
69);74 fn_name: []const u8,
75 data: union {
76 tag_name: Type,
77 },
78};
79pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);
7080
71const LoopDepth = u16;81const LoopDepth = u16;
72const Local = struct {82const Local = struct {
...@@ -81,11 +91,6 @@ const LocalsList = std.ArrayListUnmanaged(LocalIndex);...@@ -81,11 +91,6 @@ const LocalsList = std.ArrayListUnmanaged(LocalIndex);
81const LocalsMap = std.ArrayHashMapUnmanaged(Type, LocalsList, Type.HashContext32, true);91const LocalsMap = std.ArrayHashMapUnmanaged(Type, LocalsList, Type.HashContext32, true);
82const LocalsStack = std.ArrayListUnmanaged(LocalsMap);92const LocalsStack = std.ArrayListUnmanaged(LocalsMap);
8393
84const FormatTypeAsCIdentContext = struct {
85 ty: Type,
86 mod: *Module,
87};
88
89const ValueRenderLocation = enum {94const ValueRenderLocation = enum {
90 FunctionArgument,95 FunctionArgument,
91 Initializer,96 Initializer,
...@@ -106,26 +111,6 @@ const BuiltinInfo = enum {...@@ -106,26 +111,6 @@ const BuiltinInfo = enum {
106 Bits,111 Bits,
107};112};
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
129const reserved_idents = std.ComptimeStringMap(void, .{114const reserved_idents = std.ComptimeStringMap(void, .{
130 // C language115 // C language
131 .{ "alignas", {116 .{ "alignas", {
...@@ -281,6 +266,7 @@ pub const Function = struct {...@@ -281,6 +266,7 @@ pub const Function = struct {
281 next_arg_index: usize = 0,266 next_arg_index: usize = 0,
282 next_block_index: usize = 0,267 next_block_index: usize = 0,
283 object: Object,268 object: Object,
269 lazy_fns: LazyFnMap,
284 func: *Module.Fn,270 func: *Module.Fn,
285 /// All the locals, to be emitted at the top of the function.271 /// All the locals, to be emitted at the top of the function.
286 locals: std.ArrayListUnmanaged(Local) = .{},272 locals: std.ArrayListUnmanaged(Local) = .{},
...@@ -315,9 +301,9 @@ pub const Function = struct {...@@ -315,9 +301,9 @@ pub const Function = struct {
315 const alignment = 0;301 const alignment = 0;
316 const decl_c_value = try f.allocLocalValue(ty, alignment);302 const decl_c_value = try f.allocLocalValue(ty, alignment);
317 const gpa = f.object.dg.gpa;303 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);
319 try writer.writeAll("static ");305 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);
321 try writer.writeAll(" = ");307 try writer.writeAll(" = ");
322 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);308 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
323 try writer.writeAll(";\n ");309 try writer.writeAll(";\n ");
...@@ -347,12 +333,12 @@ pub const Function = struct {...@@ -347,12 +333,12 @@ pub const Function = struct {
347 .alignment = alignment,333 .alignment = alignment,
348 .loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1),334 .loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1),
349 });335 });
350 return CValue{ .local = @intCast(LocalIndex, f.locals.items.len - 1) };336 return CValue{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) };
351 }337 }
352338
353 fn allocLocal(f: *Function, inst: Air.Inst.Index, ty: Type) !CValue {339 fn allocLocal(f: *Function, inst: Air.Inst.Index, ty: Type) !CValue {
354 const result = try f.allocAlignedLocal(ty, .Mut, 0);340 const result = try f.allocAlignedLocal(ty, .mut, 0);
355 log.debug("%{d}: allocating t{d}", .{ inst, result.local });341 log.debug("%{d}: allocating t{d}", .{ inst, result.new_local });
356 return result;342 return result;
357 }343 }
358344
...@@ -366,7 +352,7 @@ pub const Function = struct {...@@ -366,7 +352,7 @@ pub const Function = struct {
366 if (local.alignment >= alignment) {352 if (local.alignment >= alignment) {
367 local.loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1);353 local.loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1);
368 _ = locals_list.swapRemove(i);354 _ = locals_list.swapRemove(i);
369 return CValue{ .local = local_index };355 return CValue{ .new_local = local_index };
370 }356 }
371 }357 }
372 }358 }
...@@ -446,7 +432,31 @@ pub const Function = struct {...@@ -446,7 +432,31 @@ pub const Function = struct {
446 return f.object.dg.fmtIntLiteral(ty, val);432 return f.object.dg.fmtIntLiteral(ty, val);
447 }433 }
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;
450 f.allocs.deinit(gpa);460 f.allocs.deinit(gpa);
451 f.locals.deinit(gpa);461 f.locals.deinit(gpa);
452 for (f.free_locals_stack.items) |*free_locals| {462 for (f.free_locals_stack.items) |*free_locals| {
...@@ -455,11 +465,9 @@ pub const Function = struct {...@@ -455,11 +465,9 @@ pub const Function = struct {
455 f.free_locals_stack.deinit(gpa);465 f.free_locals_stack.deinit(gpa);
456 f.blocks.deinit(gpa);466 f.blocks.deinit(gpa);
457 f.value_map.deinit();467 f.value_map.deinit();
468 f.lazy_fns.deinit(gpa);
458 f.object.code.deinit();469 f.object.code.deinit();
459 for (f.object.dg.typedefs.values()) |typedef| {470 f.object.dg.ctypes.deinit(gpa);
460 gpa.free(typedef.rendered);
461 }
462 f.object.dg.typedefs.deinit();
463 f.object.dg.fwd_decl.deinit();471 f.object.dg.fwd_decl.deinit();
464 f.arena.deinit();472 f.arena.deinit();
465 }473 }
...@@ -483,30 +491,20 @@ pub const Object = struct {...@@ -483,30 +491,20 @@ pub const Object = struct {
483pub const DeclGen = struct {491pub const DeclGen = struct {
484 gpa: std.mem.Allocator,492 gpa: std.mem.Allocator,
485 module: *Module,493 module: *Module,
486 decl: *Decl,494 decl: ?*Decl,
487 decl_index: Decl.Index,495 decl_index: Decl.OptionalIndex,
488 fwd_decl: std.ArrayList(u8),496 fwd_decl: std.ArrayList(u8),
489 error_msg: ?*Module.ErrorMsg,497 error_msg: ?*Module.ErrorMsg,
490 /// The key of this map is Type which has references to typedefs_arena.498 ctypes: CType.Store,
491 typedefs: TypedefMap,
492 typedefs_arena: std.mem.Allocator,
493499
494 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {500 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
495 @setCold(true);501 @setCold(true);
496 const src = LazySrcLoc.nodeOffset(0);502 const src = LazySrcLoc.nodeOffset(0);
497 const src_loc = src.toSrcLoc(dg.decl);503 const src_loc = src.toSrcLoc(dg.decl.?);
498 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);504 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
499 return error.AnalysisFail;505 return error.AnalysisFail;
500 }506 }
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
510 fn renderDeclValue(508 fn renderDeclValue(
511 dg: *DeclGen,509 dg: *DeclGen,
512 writer: anytype,510 writer: anytype,
...@@ -747,7 +745,7 @@ pub const DeclGen = struct {...@@ -747,7 +745,7 @@ pub const DeclGen = struct {
747745
748 try writer.writeAll("zig_cast_");746 try writer.writeAll("zig_cast_");
749 try dg.renderTypeForBuiltinFnName(writer, ty);747 try dg.renderTypeForBuiltinFnName(writer, ty);
750 try writer.writeAll(" zig_as_");748 try writer.writeAll(" zig_make_");
751 try dg.renderTypeForBuiltinFnName(writer, ty);749 try dg.renderTypeForBuiltinFnName(writer, ty);
752 try writer.writeByte('(');750 try writer.writeByte('(');
753 switch (bits) {751 switch (bits) {
...@@ -821,7 +819,7 @@ pub const DeclGen = struct {...@@ -821,7 +819,7 @@ pub const DeclGen = struct {
821819
822 empty = false;820 empty = false;
823 }821 }
824 if (empty) try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)});822
825 return writer.writeByte('}');823 return writer.writeByte('}');
826 },824 },
827 .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}),825 .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}),
...@@ -957,7 +955,7 @@ pub const DeclGen = struct {...@@ -957,7 +955,7 @@ pub const DeclGen = struct {
957 try writer.writeByte(' ');955 try writer.writeByte(' ');
958 var empty = true;956 var empty = true;
959 if (std.math.isFinite(f128_val)) {957 if (std.math.isFinite(f128_val)) {
960 try writer.writeAll("zig_as_");958 try writer.writeAll("zig_make_");
961 try dg.renderTypeForBuiltinFnName(writer, ty);959 try dg.renderTypeForBuiltinFnName(writer, ty);
962 try writer.writeByte('(');960 try writer.writeByte('(');
963 switch (bits) {961 switch (bits) {
...@@ -992,7 +990,7 @@ pub const DeclGen = struct {...@@ -992,7 +990,7 @@ pub const DeclGen = struct {
992 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});990 // return dg.fail("Only quiet nans are supported in global variable initializers", .{});
993 }991 }
994992
995 try writer.writeAll("zig_as_special_");993 try writer.writeAll("zig_make_special_");
996 if (location == .StaticInitializer) try writer.writeAll("constant_");994 if (location == .StaticInitializer) try writer.writeAll("constant_");
997 try dg.renderTypeForBuiltinFnName(writer, ty);995 try dg.renderTypeForBuiltinFnName(writer, ty);
998 try writer.writeByte('(');996 try writer.writeByte('(');
...@@ -1292,7 +1290,6 @@ pub const DeclGen = struct {...@@ -1292,7 +1290,6 @@ pub const DeclGen = struct {
12921290
1293 empty = false;1291 empty = false;
1294 }1292 }
1295 if (empty) try writer.print("{}", .{try dg.fmtIntLiteral(Type.u8, Value.zero)});
1296 try writer.writeByte('}');1293 try writer.writeByte('}');
1297 },1294 },
1298 .Packed => {1295 .Packed => {
...@@ -1309,7 +1306,7 @@ pub const DeclGen = struct {...@@ -1309,7 +1306,7 @@ pub const DeclGen = struct {
1309 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);1306 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
13101307
1311 var eff_num_fields: usize = 0;1308 var eff_num_fields: usize = 0;
1312 for (field_vals, 0..) |_, index| {1309 for (0..field_vals.len) |index| {
1313 const field_ty = ty.structFieldType(index);1310 const field_ty = ty.structFieldType(index);
1314 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;1311 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
13151312
...@@ -1413,6 +1410,7 @@ pub const DeclGen = struct {...@@ -1413,6 +1410,7 @@ pub const DeclGen = struct {
1413 return;1410 return;
1414 }1411 }
14151412
1413 var has_payload_init = false;
1416 try writer.writeByte('{');1414 try writer.writeByte('{');
1417 if (ty.unionTagTypeSafety()) |tag_ty| {1415 if (ty.unionTagTypeSafety()) |tag_ty| {
1418 const layout = ty.unionGetLayout(target);1416 const layout = ty.unionGetLayout(target);
...@@ -1421,7 +1419,10 @@ pub const DeclGen = struct {...@@ -1421,7 +1419,10 @@ pub const DeclGen = struct {
1421 try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type);1419 try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type);
1422 try writer.writeAll(", ");1420 try writer.writeAll(", ");
1423 }1421 }
1424 try writer.writeAll(".payload = {");1422 if (!ty.unionHasAllZeroBitFieldTypes()) {
1423 try writer.writeAll(".payload = {");
1424 has_payload_init = true;
1425 }
1425 }1426 }
14261427
1427 var it = ty.unionFields().iterator();1428 var it = ty.unionFields().iterator();
...@@ -1433,8 +1434,8 @@ pub const DeclGen = struct {...@@ -1433,8 +1434,8 @@ pub const DeclGen = struct {
1433 try writer.print(".{ } = ", .{fmtIdent(field.key_ptr.*)});1434 try writer.print(".{ } = ", .{fmtIdent(field.key_ptr.*)});
1434 try dg.renderValue(writer, field.value_ptr.ty, Value.undef, initializer_type);1435 try dg.renderValue(writer, field.value_ptr.ty, Value.undef, initializer_type);
1435 break;1436 break;
1436 } else try writer.writeAll(".empty_union = 0");1437 }
1437 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');1438 if (has_payload_init) try writer.writeByte('}');
1438 try writer.writeByte('}');1439 try writer.writeByte('}');
1439 },1440 },
14401441
...@@ -1457,496 +1458,62 @@ pub const DeclGen = struct {...@@ -1457,496 +1458,62 @@ pub const DeclGen = struct {
1457 }1458 }
14581459
1459 fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind, export_index: u32) !void {1460 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();
1461 if (fn_info.cc == .Naked) {1471 if (fn_info.cc == .Naked) {
1462 switch (kind) {1472 switch (kind) {
1463 .Forward => try w.writeAll("zig_naked_decl "),1473 .Forward => try w.writeAll("zig_naked_decl "),
1464 .Complete => try w.writeAll("zig_naked "),1474 .Complete => try w.writeAll("zig_naked "),
1465 }1475 }
1466 }1476 }
1467 if (dg.decl.val.castTag(.function)) |func_payload|1477 if (dg.decl.?.val.castTag(.function)) |func_payload|
1468 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");1478 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
14691479 if (fn_info.return_type.tag() == .noreturn) try w.writeAll("zig_noreturn ");
1470 const target = dg.module.getTarget();1480
1471 var ret_buf: LowerFnRetTyBuffer = undefined;1481 const trailing = try renderTypePrefix(
1472 const ret_ty = lowerFnRetTy(fn_info.return_type, &ret_buf, target);1482 dg.decl_index,
14731483 store.*,
1474 try dg.renderType(w, ret_ty, kind);1484 module,
1475 try w.writeByte(' ');1485 w,
1486 fn_cty_idx,
1487 .suffix,
1488 CQualifiers.init(.{}),
1489 );
1490 try w.print("{}", .{trailing});
14761491
1477 if (toCallingConvention(fn_info.cc)) |call_conv| {1492 if (toCallingConvention(fn_info.cc)) |call_conv| {
1478 try w.print("zig_callconv({s}) ", .{call_conv});1493 try w.print("zig_callconv({s}) ", .{call_conv});
1479 }1494 }
14801495
1481 if (fn_info.alignment > 0 and kind == .Complete) try w.print(" zig_align_fn({})", .{fn_info.alignment});1496 if (fn_info.alignment > 0 and kind == .Complete) {
14821497 try w.print(" zig_align_fn({})", .{fn_info.alignment});
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;
1493 }1498 }
14941499
1495 if (fn_info.is_var_args) {1500 try dg.renderDeclName(w, dg.decl_index.unwrap().?, export_index);
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();
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();1504 if (fn_info.alignment > 0 and kind == .Forward) {
1513 var ret_buf: LowerFnRetTyBuffer = undefined;1505 try w.print(" zig_align_fn({})", .{fn_info.alignment});
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;
1536 }1506 }
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;
1557 }1507 }
15581508
1559 fn renderSliceTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1509 fn indexToCType(dg: *DeclGen, idx: CType.Index) CType {
1560 std.debug.assert(t.sentinel() == null); // expected canonical type1510 return dg.ctypes.indexToCType(idx);
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;
1597 }1511 }
15981512 fn typeToIndex(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType.Index {
1599 fn renderFwdTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1513 return dg.ctypes.typeToIndex(dg.gpa, ty, dg.module, kind);
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;
1653 }1514 }
16541515 fn typeToCType(dg: *DeclGen, ty: Type, kind: CType.Kind) !CType {
1655 fn renderStructTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1516 return dg.ctypes.typeToCType(dg.gpa, ty, dg.module, kind);
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;
1950 }1517 }
19511518
1952 /// Renders a type as a single identifier, generating intermediate typedefs1519 /// Renders a type as a single identifier, generating intermediate typedefs
...@@ -1959,275 +1526,27 @@ pub const DeclGen = struct {...@@ -1959,275 +1526,27 @@ pub const DeclGen = struct {
1959 /// |---------------------|-----------------|---------------------|1526 /// |---------------------|-----------------|---------------------|
1960 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |1527 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
1961 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |1528 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
1962 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |1529 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
1963 ///1530 ///
1964 fn renderType(1531 fn renderType(
1965 dg: *DeclGen,1532 dg: *DeclGen,
1966 w: anytype,1533 w: anytype,
1967 t: Type,1534 t: Type,
1968 kind: TypedefKind,1535 _: 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,
2214 ) error{ OutOfMemory, AnalysisFail }!void {1536 ) error{ OutOfMemory, AnalysisFail }!void {
2215 const target = dg.module.getTarget();1537 const store = &dg.ctypes.set;
2216 const int_info = t.intInfo(target);1538 const module = dg.module;
2217 if (toCIntBits(int_info.bits)) |c_bits|1539 const idx = try dg.typeToIndex(t, .complete);
2218 return w.print("zig_{c}{d}", .{ signAbbrev(int_info.signedness), c_bits })1540 _ = try renderTypePrefix(
2219 else if (loweredArrayInfo(t, target)) |array_info| {1541 dg.decl_index,
2220 assert(array_info.sentinel == null);1542 store.*,
2221 var array_pl = Type.Payload.Array{1543 module,
2222 .base = .{ .tag = .array },1544 w,
2223 .data = .{ .len = array_info.len, .elem_type = array_info.elem_type },1545 idx,
2224 };1546 .suffix,
2225 const array_ty = Type.initPayload(&array_pl.base);1547 CQualifiers.init(.{}),
22261548 );
2227 return dg.renderType(w, array_ty, kind);1549 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix);
2228 } else return dg.fail("C backend: Unable to lower unnamed integer type {}", .{
2229 t.fmt(dg.module),
2230 });
2231 }1550 }
22321551
2233 const IntCastContext = union(enum) {1552 const IntCastContext = union(enum) {
...@@ -2254,16 +1573,16 @@ pub const DeclGen = struct {...@@ -2254,16 +1573,16 @@ pub const DeclGen = struct {
2254 /// Renders a cast to an int type, from either an int or a pointer.1573 /// Renders a cast to an int type, from either an int or a pointer.
2255 ///1574 ///
2256 /// Some platforms don't have 128 bit integers, so we need to use1575 /// 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.
2258 ///1577 ///
2259 /// | Dest type bits | Src type | Result1578 /// | Dest type bits | Src type | Result
2260 /// |------------------|------------------|---------------------------|1579 /// |------------------|------------------|---------------------------|
2261 /// | < 64 bit integer | pointer | (zig_<dest_ty>)(zig_<u|i>size)src1580 /// | < 64 bit integer | pointer | (zig_<dest_ty>)(zig_<u|i>size)src
2262 /// | < 64 bit integer | < 64 bit integer | (zig_<dest_ty>)src1581 /// | < 64 bit integer | < 64 bit integer | (zig_<dest_ty>)src
2263 /// | < 64 bit integer | > 64 bit integer | zig_lo(src)1582 /// | < 64 bit integer | > 64 bit integer | zig_lo(src)
2264 /// | > 64 bit integer | pointer | zig_as_<dest_ty>(0, (zig_<u|i>size)src)1583 /// | > 64 bit integer | pointer | zig_make_<dest_ty>(0, (zig_<u|i>size)src)
2265 /// | > 64 bit integer | < 64 bit integer | zig_as_<dest_ty>(0, src)1584 /// | > 64 bit integer | < 64 bit integer | zig_make_<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))1585 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
2267 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {1586 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {
2268 const target = dg.module.getTarget();1587 const target = dg.module.getTarget();
2269 const dest_bits = dest_ty.bitSize(target);1588 const dest_bits = dest_ty.bitSize(target);
...@@ -2301,7 +1620,7 @@ pub const DeclGen = struct {...@@ -2301,7 +1620,7 @@ pub const DeclGen = struct {
2301 try context.writeValue(dg, w, src_ty, .FunctionArgument);1620 try context.writeValue(dg, w, src_ty, .FunctionArgument);
2302 try w.writeByte(')');1621 try w.writeByte(')');
2303 } else if (dest_bits > 64 and src_bits <= 64) {1622 } else if (dest_bits > 64 and src_bits <= 64) {
2304 try w.writeAll("zig_as_");1623 try w.writeAll("zig_make_");
2305 try dg.renderTypeForBuiltinFnName(w, dest_ty);1624 try dg.renderTypeForBuiltinFnName(w, dest_ty);
2306 try w.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral?1625 try w.writeAll("(0, "); // TODO: Should the 0 go through fmtIntLiteral?
2307 if (src_is_ptr) {1626 if (src_is_ptr) {
...@@ -2313,7 +1632,7 @@ pub const DeclGen = struct {...@@ -2313,7 +1632,7 @@ pub const DeclGen = struct {
2313 try w.writeByte(')');1632 try w.writeByte(')');
2314 } else {1633 } else {
2315 assert(!src_is_ptr);1634 assert(!src_is_ptr);
2316 try w.writeAll("zig_as_");1635 try w.writeAll("zig_make_");
2317 try dg.renderTypeForBuiltinFnName(w, dest_ty);1636 try dg.renderTypeForBuiltinFnName(w, dest_ty);
2318 try w.writeAll("(zig_hi_");1637 try w.writeAll("(zig_hi_");
2319 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);1638 try dg.renderTypeForBuiltinFnName(w, src_eff_ty);
...@@ -2337,10 +1656,10 @@ pub const DeclGen = struct {...@@ -2337,10 +1656,10 @@ pub const DeclGen = struct {
2337 /// |---------------------|-----------------|---------------------|1656 /// |---------------------|-----------------|---------------------|
2338 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |1657 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
2339 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |1658 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2340 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |1659 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2341 ///1660 ///
2342 fn renderTypecast(dg: *DeclGen, w: anytype, ty: Type) error{ OutOfMemory, AnalysisFail }!void {1661 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);
2344 }1663 }
23451664
2346 /// Renders a type and name in field declaration/definition format.1665 /// Renders a type and name in field declaration/definition format.
...@@ -2350,7 +1669,7 @@ pub const DeclGen = struct {...@@ -2350,7 +1669,7 @@ pub const DeclGen = struct {
2350 /// |---------------------|-----------------|---------------------|1669 /// |---------------------|-----------------|---------------------|
2351 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |1670 /// | `renderTypecast` | "uint8_t *" | "uint8_t *[10]" |
2352 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |1671 /// | `renderTypeAndName` | "uint8_t *name" | "uint8_t *name[10]" |
2353 /// | `renderType` | "uint8_t *" | "zig_A_uint8_t_10" |1672 /// | `renderType` | "uint8_t *" | "uint8_t *[10]" |
2354 ///1673 ///
2355 fn renderTypeAndName(1674 fn renderTypeAndName(
2356 dg: *DeclGen,1675 dg: *DeclGen,
...@@ -2359,65 +1678,45 @@ pub const DeclGen = struct {...@@ -2359,65 +1678,45 @@ pub const DeclGen = struct {
2359 name: CValue,1678 name: CValue,
2360 mutability: Mutability,1679 mutability: Mutability,
2361 alignment: u32,1680 alignment: u32,
2362 kind: TypedefKind,1681 _: TypedefKind,
2363 ) error{ OutOfMemory, AnalysisFail }!void {1682 ) error{ OutOfMemory, AnalysisFail }!void {
2364 var suffix = std.ArrayList(u8).init(dg.gpa);1683 const store = &dg.ctypes.set;
2365 defer suffix.deinit();1684 const module = dg.module;
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);
23941685
2395 const const_prefix = switch (mutability) {1686 if (alignment != 0) switch (std.math.order(alignment, ty.abiAlignment(dg.module.getTarget()))) {
2396 .Const, .ConstArgument => "const ",1687 .lt => try w.print("zig_under_align({}) ", .{alignment}),
2397 .Mut => "",1688 .eq => {},
1689 .gt => try w.print("zig_align({}) ", .{alignment}),
2398 };1690 };
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});
2400 try dg.writeCValue(w, name);1703 try dg.writeCValue(w, name);
2401 try w.writeAll(suffix.items);1704 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix);
2402 }1705 }
24031706
2404 fn renderTagNameFn(dg: *DeclGen, enum_ty: Type) error{ OutOfMemory, AnalysisFail }![]const u8 {1707 fn renderTagNameFn(dg: *DeclGen, w: anytype, fn_name: []const u8, enum_ty: Type) !void {
2405 var buffer = std.ArrayList(u8).init(dg.typedefs.allocator);
2406 defer buffer.deinit();
2407 const bw = buffer.writer();
2408
2409 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);1708 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
24101709
2411 try buffer.appendSlice("static ");1710 try w.writeAll("static ");
2412 try dg.renderType(bw, name_slice_ty, .Complete);1711 try dg.renderType(w, name_slice_ty, .Complete);
2413 const name_begin = buffer.items.len + " ".len;1712 try w.writeByte(' ');
2414 try bw.print(" zig_tagName_{}_{d}(", .{ typeToCIdentifier(enum_ty, dg.module), @enumToInt(enum_ty.getOwnerDecl()) });1713 try w.writeAll(fn_name);
2415 const name_end = buffer.items.len - "(".len;1714 try w.writeByte('(');
2416 try dg.renderTypeAndName(bw, enum_ty, .{ .identifier = "tag" }, .Const, 0, .Complete);1715 try dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, .@"const", 0, .Complete);
2417 try buffer.appendSlice(") {\n switch (tag) {\n");1716 try w.writeAll(") {\n switch (tag) {\n");
2418 for (enum_ty.enumFields().keys(), 0..) |name, index| {1717 for (enum_ty.enumFields().keys(), 0..) |name, index| {
2419 const name_z = try dg.typedefs.allocator.dupeZ(u8, name);1718 const name_z = try dg.gpa.dupeZ(u8, name);
2420 defer dg.typedefs.allocator.free(name_z);1719 defer dg.gpa.free(name_z);
2421 const name_bytes = name_z[0 .. name_z.len + 1];1720 const name_bytes = name_z[0 .. name_z.len + 1];
24221721
2423 var tag_pl: Value.Payload.U32 = .{1722 var tag_pl: Value.Payload.U32 = .{
...@@ -2438,40 +1737,23 @@ pub const DeclGen = struct {...@@ -2438,40 +1737,23 @@ pub const DeclGen = struct {
2438 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };1737 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
2439 const len_val = Value.initPayload(&len_pl.base);1738 const len_val = Value.initPayload(&len_pl.base);
24401739
2441 try bw.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});1740 try w.print(" case {}: {{\n static ", .{try dg.fmtIntLiteral(enum_ty, int_val)});
2442 try dg.renderTypeAndName(bw, name_ty, .{ .identifier = "name" }, .Const, 0, .Complete);1741 try dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, .@"const", 0, .Complete);
2443 try buffer.appendSlice(" = ");1742 try w.writeAll(" = ");
2444 try dg.renderValue(bw, name_ty, name_val, .Initializer);1743 try dg.renderValue(w, name_ty, name_val, .Initializer);
2445 try buffer.appendSlice(";\n return (");1744 try w.writeAll(";\n return (");
2446 try dg.renderTypecast(bw, name_slice_ty);1745 try dg.renderTypecast(w, name_slice_ty);
2447 try bw.print("){{{}, {}}};\n", .{1746 try w.print("){{{}, {}}};\n", .{
2448 fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val),1747 fmtIdent("name"), try dg.fmtIntLiteral(Type.usize, len_val),
2449 });1748 });
24501749
2451 try buffer.appendSlice(" }\n");1750 try w.writeAll(" }\n");
2452 }1751 }
2453 try buffer.appendSlice(" }\n while (");1752 try w.writeAll(" }\n while (");
2454 try dg.renderValue(bw, Type.bool, Value.true, .Other);1753 try dg.renderValue(w, Type.bool, Value.true, .Other);
2455 try buffer.appendSlice(") ");1754 try w.writeAll(") ");
2456 _ = try airBreakpoint(bw);1755 _ = try airBreakpoint(w);
2457 try buffer.appendSlice("}\n");1756 try w.writeAll("}\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);
2475 }1757 }
24761758
2477 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {1759 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
...@@ -2492,10 +1774,11 @@ pub const DeclGen = struct {...@@ -2492,10 +1774,11 @@ pub const DeclGen = struct {
2492 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {1774 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2493 switch (c_value) {1775 switch (c_value) {
2494 .none => unreachable,1776 .none => unreachable,
2495 .local => |i| return w.print("t{d}", .{i}),1777 .local, .new_local => |i| return w.print("t{d}", .{i}),
2496 .local_ref => |i| return w.print("&t{d}", .{i}),1778 .local_ref => |i| return w.print("&t{d}", .{i}),
2497 .constant => unreachable,1779 .constant => unreachable,
2498 .arg => |i| return w.print("a{d}", .{i}),1780 .arg => |i| return w.print("a{d}", .{i}),
1781 .arg_array => |i| return dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }),
2499 .field => |i| return w.print("f{d}", .{i}),1782 .field => |i| return w.print("f{d}", .{i}),
2500 .decl => |decl| return dg.renderDeclName(w, decl, 0),1783 .decl => |decl| return dg.renderDeclName(w, decl, 0),
2501 .decl_ref => |decl| {1784 .decl_ref => |decl| {
...@@ -2511,10 +1794,15 @@ pub const DeclGen = struct {...@@ -2511,10 +1794,15 @@ pub const DeclGen = struct {
2511 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {1794 fn writeCValueDeref(dg: *DeclGen, w: anytype, c_value: CValue) !void {
2512 switch (c_value) {1795 switch (c_value) {
2513 .none => unreachable,1796 .none => unreachable,
2514 .local => |i| return w.print("(*t{d})", .{i}),1797 .local, .new_local => |i| return w.print("(*t{d})", .{i}),
2515 .local_ref => |i| return w.print("t{d}", .{i}),1798 .local_ref => |i| return w.print("t{d}", .{i}),
2516 .constant => unreachable,1799 .constant => unreachable,
2517 .arg => |i| return w.print("(*a{d})", .{i}),1800 .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 },
2518 .field => |i| return w.print("f{d}", .{i}),1806 .field => |i| return w.print("f{d}", .{i}),
2519 .decl => |decl| {1807 .decl => |decl| {
2520 try w.writeAll("(*");1808 try w.writeAll("(*");
...@@ -2541,7 +1829,7 @@ pub const DeclGen = struct {...@@ -2541,7 +1829,7 @@ pub const DeclGen = struct {
2541 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {1829 fn writeCValueDerefMember(dg: *DeclGen, writer: anytype, c_value: CValue, member: CValue) !void {
2542 switch (c_value) {1830 switch (c_value) {
2543 .none, .constant, .field, .undef => unreachable,1831 .none, .constant, .field, .undef => unreachable,
2544 .local, .arg, .decl, .identifier, .bytes => {1832 .new_local, .local, .arg, .arg_array, .decl, .identifier, .bytes => {
2545 try dg.writeCValue(writer, c_value);1833 try dg.writeCValue(writer, c_value);
2546 try writer.writeAll("->");1834 try writer.writeAll("->");
2547 },1835 },
...@@ -2668,10 +1956,493 @@ pub const DeclGen = struct {...@@ -2668,10 +1956,493 @@ pub const DeclGen = struct {
2668 }1956 }
2669};1957};
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 {
2672 var it = mod.global_assembly.valueIterator();2443 var it = mod.global_assembly.valueIterator();
2673 while (it.next()) |asm_source| {2444 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.*)});
2675 }2446 }
2676}2447}
26772448
...@@ -2709,7 +2480,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2709,7 +2480,7 @@ pub fn genErrDecls(o: *Object) !void {
2709 const name_val = Value.initPayload(&name_pl.base);2480 const name_val = Value.initPayload(&name_pl.base);
27102481
2711 try writer.writeAll("static ");2482 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);
2713 try writer.writeAll(" = ");2484 try writer.writeAll(" = ");
2714 try o.dg.renderValue(writer, name_ty, name_val, .StaticInitializer);2485 try o.dg.renderValue(writer, name_ty, name_val, .StaticInitializer);
2715 try writer.writeAll(";\n");2486 try writer.writeAll(";\n");
...@@ -2722,7 +2493,7 @@ pub fn genErrDecls(o: *Object) !void {...@@ -2722,7 +2493,7 @@ pub fn genErrDecls(o: *Object) !void {
2722 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);2493 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
27232494
2724 try writer.writeAll("static ");2495 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);
2726 try writer.writeAll(" = {");2497 try writer.writeAll(" = {");
2727 for (o.dg.module.error_name_list.items, 0..) |name, value| {2498 for (o.dg.module.error_name_list.items, 0..) |name, value| {
2728 if (value != 0) try writer.writeByte(',');2499 if (value != 0) try writer.writeByte(',');
...@@ -2742,14 +2513,27 @@ fn genExports(o: *Object) !void {...@@ -2742,14 +2513,27 @@ fn genExports(o: *Object) !void {
2742 defer tracy.end();2513 defer tracy.end();
27432514
2744 const fwd_decl_writer = o.dg.fwd_decl.writer();2515 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| {2516 if (o.dg.module.decl_exports.get(o.dg.decl_index.unwrap().?)) |exports| {
2746 try fwd_decl_writer.writeAll("zig_export(");2517 for (exports.items[1..], 1..) |@"export", i| {
2747 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, 1 + i));2518 try fwd_decl_writer.writeAll("zig_export(");
2748 try fwd_decl_writer.print(", {s}, {s});\n", .{2519 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward, @intCast(u32, i));
2749 fmtStringLiteral(exports.items[0].options.name),2520 try fwd_decl_writer.print(", {s}, {s});\n", .{
2750 fmtStringLiteral(@"export".options.name),2521 fmtStringLiteral(exports.items[0].options.name),
2751 });2522 fmtStringLiteral(@"export".options.name),
2752 };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 }
2753}2537}
27542538
2755pub fn genFunc(f: *Function) !void {2539pub fn genFunc(f: *Function) !void {
...@@ -2759,8 +2543,8 @@ pub fn genFunc(f: *Function) !void {...@@ -2759,8 +2543,8 @@ pub fn genFunc(f: *Function) !void {
2759 const o = &f.object;2543 const o = &f.object;
2760 const gpa = o.dg.gpa;2544 const gpa = o.dg.gpa;
2761 const tv: TypedValue = .{2545 const tv: TypedValue = .{
2762 .ty = o.dg.decl.ty,2546 .ty = o.dg.decl.?.ty,
2763 .val = o.dg.decl.val,2547 .val = o.dg.decl.?.val,
2764 };2548 };
27652549
2766 o.code_header = std.ArrayList(u8).init(gpa);2550 o.code_header = std.ArrayList(u8).init(gpa);
...@@ -2799,9 +2583,8 @@ pub fn genFunc(f: *Function) !void {...@@ -2799,9 +2583,8 @@ pub fn genFunc(f: *Function) !void {
2799 // missing. These are added now to complete the map. Then we can sort by2583 // missing. These are added now to complete the map. Then we can sort by
2800 // alignment, descending.2584 // alignment, descending.
2801 const free_locals = f.getFreeLocals();2585 const free_locals = f.getFreeLocals();
2802 const values = f.allocs.values();2586 for (f.allocs.keys(), f.allocs.values()) |local_index, value| {
2803 for (f.allocs.keys(), 0..) |local_index, i| {2587 if (value) continue; // static
2804 if (values[i]) continue; // static
2805 const local = f.locals.items[local_index];2588 const local = f.locals.items[local_index];
2806 log.debug("inserting local {d} into free_locals", .{local_index});2589 log.debug("inserting local {d} into free_locals", .{local_index});
2807 const gop = try free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());2590 const gop = try free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());
...@@ -2830,7 +2613,7 @@ pub fn genFunc(f: *Function) !void {...@@ -2830,7 +2613,7 @@ pub fn genFunc(f: *Function) !void {
2830 w,2613 w,
2831 local.ty,2614 local.ty,
2832 .{ .local = local_index },2615 .{ .local = local_index },
2833 .Mut,2616 .mut,
2834 local.alignment,2617 local.alignment,
2835 .Complete,2618 .Complete,
2836 );2619 );
...@@ -2850,10 +2633,10 @@ pub fn genDecl(o: *Object) !void {...@@ -2850,10 +2633,10 @@ pub fn genDecl(o: *Object) !void {
2850 const tracy = trace(@src());2633 const tracy = trace(@src());
2851 defer tracy.end();2634 defer tracy.end();
28522635
2853 const tv: TypedValue = .{2636 const decl = o.dg.decl.?;
2854 .ty = o.dg.decl.ty,2637 const decl_c_value: CValue = .{ .decl = o.dg.decl_index.unwrap().? };
2855 .val = o.dg.decl.val,2638 const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val };
2856 };2639
2857 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime()) return;2640 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime()) return;
2858 if (tv.val.tag() == .extern_fn) {2641 if (tv.val.tag() == .extern_fn) {
2859 const fwd_decl_writer = o.dg.fwd_decl.writer();2642 const fwd_decl_writer = o.dg.fwd_decl.writer();
...@@ -2867,11 +2650,9 @@ pub fn genDecl(o: *Object) !void {...@@ -2867,11 +2650,9 @@ pub fn genDecl(o: *Object) !void {
2867 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;2650 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
2868 const fwd_decl_writer = o.dg.fwd_decl.writer();2651 const fwd_decl_writer = o.dg.fwd_decl.writer();
28692652
2870 const decl_c_value = CValue{ .decl = o.dg.decl_index };
2871
2872 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2653 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");
2873 if (variable.is_threadlocal) try fwd_decl_writer.writeAll("zig_threadlocal ");2654 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);
2875 try fwd_decl_writer.writeAll(";\n");2656 try fwd_decl_writer.writeAll(";\n");
2876 try genExports(o);2657 try genExports(o);
28772658
...@@ -2880,27 +2661,26 @@ pub fn genDecl(o: *Object) !void {...@@ -2880,27 +2661,26 @@ pub fn genDecl(o: *Object) !void {
2880 const w = o.writer();2661 const w = o.writer();
2881 if (!is_global) try w.writeAll("static ");2662 if (!is_global) try w.writeAll("static ");
2882 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");2663 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
2883 if (o.dg.decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});2664 if (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);2665 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .mut, decl.@"align", .Complete);
2885 if (o.dg.decl.@"linksection" != null) try w.writeAll(", read, write)");2666 if (decl.@"linksection" != null) try w.writeAll(", read, write)");
2886 try w.writeAll(" = ");2667 try w.writeAll(" = ");
2887 try o.dg.renderValue(w, tv.ty, variable.init, .StaticInitializer);2668 try o.dg.renderValue(w, tv.ty, variable.init, .StaticInitializer);
2888 try w.writeByte(';');2669 try w.writeByte(';');
2889 try o.indent_writer.insertNewline();2670 try o.indent_writer.insertNewline();
2890 } else {2671 } 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);
2892 const fwd_decl_writer = o.dg.fwd_decl.writer();2673 const fwd_decl_writer = o.dg.fwd_decl.writer();
2893 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
28942674
2895 try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static ");2675 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);
2897 try fwd_decl_writer.writeAll(";\n");2677 try fwd_decl_writer.writeAll(";\n");
28982678
2899 const w = o.writer();2679 const w = o.writer();
2900 if (!is_global) try w.writeAll("static ");2680 if (!is_global) try w.writeAll("static ");
2901 if (o.dg.decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});2681 if (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);2682 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .@"const", decl.@"align", .Complete);
2903 if (o.dg.decl.@"linksection" != null) try w.writeAll(", read)");2683 if (decl.@"linksection" != null) try w.writeAll(", read)");
2904 try w.writeAll(" = ");2684 try w.writeAll(" = ");
2905 try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer);2685 try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer);
2906 try w.writeAll(";\n");2686 try w.writeAll(";\n");
...@@ -2912,8 +2692,8 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {...@@ -2912,8 +2692,8 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
2912 defer tracy.end();2692 defer tracy.end();
29132693
2914 const tv: TypedValue = .{2694 const tv: TypedValue = .{
2915 .ty = dg.decl.ty,2695 .ty = dg.decl.?.ty,
2916 .val = dg.decl.val,2696 .val = dg.decl.?.val,
2917 };2697 };
2918 const writer = dg.fwd_decl.writer();2698 const writer = dg.fwd_decl.writer();
29192699
...@@ -2951,7 +2731,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -2951,7 +2731,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
2951 // zig fmt: off2731 // zig fmt: off
2952 .constant => unreachable, // excluded from function bodies2732 .constant => unreachable, // excluded from function bodies
2953 .const_ty => unreachable, // excluded from function bodies2733 .const_ty => unreachable, // excluded from function bodies
2954 .arg => airArg(f),2734 .arg => try airArg(f, inst),
29552735
2956 .breakpoint => try airBreakpoint(f.object.writer()),2736 .breakpoint => try airBreakpoint(f.object.writer()),
2957 .ret_addr => try airRetAddr(f, inst),2737 .ret_addr => try airRetAddr(f, inst),
...@@ -3200,13 +2980,14 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3200,13 +2980,14 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3200 .c_va_start => return f.fail("TODO implement c_va_start", .{}),2980 .c_va_start => return f.fail("TODO implement c_va_start", .{}),
3201 // zig fmt: on2981 // zig fmt: on
3202 };2982 };
3203 if (result_value == .local) {2983 if (result_value == .new_local) {
3204 log.debug("map %{d} to t{d}", .{ inst, result_value.local });2984 log.debug("map %{d} to t{d}", .{ inst, result_value.new_local });
3205 }
3206 switch (result_value) {
3207 .none => {},
3208 else => try f.value_map.putNoClobber(Air.indexToRef(inst), result_value),
3209 }2985 }
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 });
3210 }2991 }
3211}2992}
32122993
...@@ -3283,6 +3064,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3283,6 +3064,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3283 return CValue.none;3064 return CValue.none;
3284 }3065 }
32853066
3067 const inst_ty = f.air.typeOfIndex(inst);
3286 const ptr_ty = f.air.typeOf(bin_op.lhs);3068 const ptr_ty = f.air.typeOf(bin_op.lhs);
3287 const child_ty = ptr_ty.childType();3069 const child_ty = ptr_ty.childType();
32883070
...@@ -3297,7 +3079,9 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3297,7 +3079,9 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3297 const writer = f.object.writer();3079 const writer = f.object.writer();
3298 const local = try f.allocLocal(inst, f.air.typeOfIndex(inst));3080 const local = try f.allocLocal(inst, f.air.typeOfIndex(inst));
3299 try f.writeCValue(writer, local, .Other);3081 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(")&(");
3301 if (ptr_ty.ptrSize() == .One) {3085 if (ptr_ty.ptrSize() == .One) {
3302 // It's a pointer to an array, so we need to de-reference.3086 // It's a pointer to an array, so we need to de-reference.
3303 try f.writeCValueDeref(writer, ptr);3087 try f.writeCValueDeref(writer, ptr);
...@@ -3428,13 +3212,13 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3428,13 +3212,13 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
3428 return CValue{ .undef = inst_ty };3212 return CValue{ .undef = inst_ty };
3429 }3213 }
34303214
3431 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;3215 const mutability: Mutability = if (inst_ty.isConstPtr()) .@"const" else .mut;
3432 const target = f.object.dg.module.getTarget();3216 const target = f.object.dg.module.getTarget();
3433 const local = try f.allocAlignedLocal(elem_type, mutability, inst_ty.ptrAlignment(target));3217 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 });
3435 const gpa = f.object.dg.module.gpa;3219 const gpa = f.object.dg.module.gpa;
3436 try f.allocs.put(gpa, local.local, false);3220 try f.allocs.put(gpa, local.new_local, false);
3437 return CValue{ .local_ref = local.local };3221 return CValue{ .local_ref = local.new_local };
3438}3222}
34393223
3440fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {3224fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -3445,19 +3229,25 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3445,19 +3229,25 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3445 return CValue{ .undef = inst_ty };3229 return CValue{ .undef = inst_ty };
3446 }3230 }
34473231
3448 const mutability: Mutability = if (inst_ty.isConstPtr()) .Const else .Mut;3232 const mutability: Mutability = if (inst_ty.isConstPtr()) .@"const" else .mut;
3449 const target = f.object.dg.module.getTarget();3233 const target = f.object.dg.module.getTarget();
3450 const local = try f.allocAlignedLocal(elem_ty, mutability, inst_ty.ptrAlignment(target));3234 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 });
3452 const gpa = f.object.dg.module.gpa;3236 const gpa = f.object.dg.module.gpa;
3453 try f.allocs.put(gpa, local.local, false);3237 try f.allocs.put(gpa, local.new_local, false);
3454 return CValue{ .local_ref = local.local };3238 return CValue{ .local_ref = local.new_local };
3455}3239}
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
3458 const i = f.next_arg_index;3245 const i = f.next_arg_index;
3459 f.next_arg_index += 1;3246 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 };
3461}3251}
34623252
3463fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {3253fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
...@@ -3567,7 +3357,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -3567,7 +3357,7 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3567 const ret_val = if (is_array) ret_val: {3357 const ret_val = if (is_array) ret_val: {
3568 const array_local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator()));3358 const array_local = try f.allocLocal(inst, try lowered_ret_ty.copy(f.arena.allocator()));
3569 try writer.writeAll("memcpy(");3359 try writer.writeAll("memcpy(");
3570 try f.writeCValueMember(writer, array_local, .{ .field = 0 });3360 try f.writeCValueMember(writer, array_local, .{ .identifier = "array" });
3571 try writer.writeAll(", ");3361 try writer.writeAll(", ");
3572 if (deref)3362 if (deref)
3573 try f.writeCValueDeref(writer, operand)3363 try f.writeCValueDeref(writer, operand)
...@@ -3587,14 +3377,13 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {...@@ -3587,14 +3377,13 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3587 try f.writeCValue(writer, ret_val, .Other);3377 try f.writeCValue(writer, ret_val, .Other);
3588 try writer.writeAll(";\n");3378 try writer.writeAll(";\n");
3589 if (is_array) {3379 if (is_array) {
3590 try freeLocal(f, inst, ret_val.local, 0);3380 try freeLocal(f, inst, ret_val.new_local, 0);
3591 }3381 }
3592 } else {3382 } else {
3593 try reap(f, inst, &.{un_op});3383 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)
3595 // Not even allowed to return void in a naked function.3385 // Not even allowed to return void in a naked function.
3596 try writer.writeAll("return;\n");3386 try writer.writeAll("return;\n");
3597 }
3598 }3387 }
3599 return CValue.none;3388 return CValue.none;
3600}3389}
...@@ -3796,7 +3585,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3796,7 +3585,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
3796 try f.renderTypecast(writer, src_ty);3585 try f.renderTypecast(writer, src_ty);
3797 try writer.writeAll("))");3586 try writer.writeAll("))");
3798 if (src_val == .constant) {3587 if (src_val == .constant) {
3799 try freeLocal(f, inst, array_src.local, 0);3588 try freeLocal(f, inst, array_src.new_local, 0);
3800 }3589 }
3801 } else if (ptr_info.host_size != 0) {3590 } else if (ptr_info.host_size != 0) {
3802 const host_bits = ptr_info.host_size * 8;3591 const host_bits = ptr_info.host_size * 8;
...@@ -3847,7 +3636,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3847,7 +3636,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index) !CValue {
3847 const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64;3636 const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64;
3848 if (cant_cast) {3637 if (cant_cast) {
3849 if (src_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});3638 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_");
3851 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);3640 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
3852 try writer.writeAll("(0, ");3641 try writer.writeAll("(0, ");
3853 } else {3642 } else {
...@@ -4118,32 +3907,31 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {...@@ -4118,32 +3907,31 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
4118 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });3907 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
41193908
4120 const inst_ty = f.air.typeOfIndex(inst);3909 const inst_ty = f.air.typeOfIndex(inst);
4121 const elem_ty = switch (inst_ty.ptrSize()) {3910 const elem_ty = inst_ty.elemType2();
4122 .One => blk: {
4123 const array_ty = inst_ty.childType();
4124 break :blk array_ty.childType();
4125 },
4126 else => inst_ty.childType(),
4127 };
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.
4132 const local = try f.allocLocal(inst, inst_ty);3912 const local = try f.allocLocal(inst, inst_ty);
4133 const writer = f.object.writer();3913 const writer = f.object.writer();
4134 try f.writeCValue(writer, local, .Other);3914 try f.writeCValue(writer, local, .Other);
4135 try writer.writeAll(" = (");3915 try writer.writeAll(" = ");
4136 try f.renderTypecast(writer, inst_ty);3916
4137 try writer.writeAll(")(((uintptr_t)");3917 if (elem_ty.hasRuntimeBitsIgnoreComptime()) {
4138 try f.writeCValue(writer, lhs, .Other);3918 // We must convert to and from integer types to prevent UB if the operation
4139 try writer.writeAll(") ");3919 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
4140 try writer.writeByte(operator);3920 // if the result is NULL and then dereferenced.
4141 try writer.writeAll(" (");3921 try writer.writeByte('(');
4142 try f.writeCValue(writer, rhs, .Other);3922 try f.renderTypecast(writer, inst_ty);
4143 try writer.writeAll("*sizeof(");3923 try writer.writeAll(")(((uintptr_t)");
4144 try f.renderTypecast(writer, elem_ty);3924 try f.writeCValue(writer, lhs, .Other);
4145 try writer.writeAll(")));\n");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");
4147 return local;3935 return local;
4148}3936}
41493937
...@@ -4222,8 +4010,12 @@ fn airCall(...@@ -4222,8 +4010,12 @@ fn airCall(
4222 modifier: std.builtin.CallModifier,4010 modifier: std.builtin.CallModifier,
4223) !CValue {4011) !CValue {
4224 // Not even allowed to call panic in a naked function.4012 // 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
4226 const gpa = f.object.dg.gpa;4015 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
4228 switch (modifier) {4020 switch (modifier) {
4229 .auto => {},4021 .auto => {},
...@@ -4238,8 +4030,28 @@ fn airCall(...@@ -4238,8 +4030,28 @@ fn airCall(
42384030
4239 const resolved_args = try gpa.alloc(CValue, args.len);4031 const resolved_args = try gpa.alloc(CValue, args.len);
4240 defer gpa.free(resolved_args);4032 defer gpa.free(resolved_args);
4241 for (args, 0..) |arg, i| {4033 for (resolved_args, args) |*resolved_arg, arg| {
4242 resolved_args[i] = try f.resolveInst(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 }
4243 }4055 }
42444056
4245 const callee = try f.resolveInst(pl_op.operand);4057 const callee = try f.resolveInst(pl_op.operand);
...@@ -4256,9 +4068,7 @@ fn airCall(...@@ -4256,9 +4068,7 @@ fn airCall(
4256 .Pointer => callee_ty.childType(),4068 .Pointer => callee_ty.childType(),
4257 else => unreachable,4069 else => unreachable,
4258 };4070 };
4259 const writer = f.object.writer();
42604071
4261 const target = f.object.dg.module.getTarget();
4262 const ret_ty = fn_ty.fnReturnType();4072 const ret_ty = fn_ty.fnReturnType();
4263 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;4073 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
4264 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);4074 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
...@@ -4293,7 +4103,7 @@ fn airCall(...@@ -4293,7 +4103,7 @@ fn airCall(
4293 else => break :known,4103 else => break :known,
4294 };4104 };
4295 };4105 };
4296 name = f.object.dg.module.declPtr(fn_decl).name;4106 name = module.declPtr(fn_decl).name;
4297 try f.object.dg.renderDeclName(writer, fn_decl, 0);4107 try f.object.dg.renderDeclName(writer, fn_decl, 0);
4298 break :callee;4108 break :callee;
4299 }4109 }
...@@ -4303,22 +4113,11 @@ fn airCall(...@@ -4303,22 +4113,11 @@ fn airCall(
43034113
4304 try writer.writeByte('(');4114 try writer.writeByte('(');
4305 var args_written: usize = 0;4115 var args_written: usize = 0;
4306 for (args, 0..) |arg, arg_i| {4116 for (resolved_args) |resolved_arg| {
4307 const ty = f.air.typeOf(arg);4117 if (resolved_arg == .none) continue;
4308 if (!ty.hasRuntimeBitsIgnoreComptime()) continue;4118 if (args_written != 0) try writer.writeAll(", ");
4309 if (args_written != 0) {4119 try f.writeCValue(writer, resolved_arg, .FunctionArgument);
4310 try writer.writeAll(", ");4120 if (resolved_arg == .new_local) try freeLocal(f, inst, resolved_arg.new_local, 0);
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);
4322 args_written += 1;4121 args_written += 1;
4323 }4122 }
4324 try writer.writeAll(");\n");4123 try writer.writeAll(");\n");
...@@ -4331,11 +4130,11 @@ fn airCall(...@@ -4331,11 +4130,11 @@ fn airCall(
4331 try writer.writeAll("memcpy(");4130 try writer.writeAll("memcpy(");
4332 try f.writeCValue(writer, array_local, .FunctionArgument);4131 try f.writeCValue(writer, array_local, .FunctionArgument);
4333 try writer.writeAll(", ");4132 try writer.writeAll(", ");
4334 try f.writeCValueMember(writer, result_local, .{ .field = 0 });4133 try f.writeCValueMember(writer, result_local, .{ .identifier = "array" });
4335 try writer.writeAll(", sizeof(");4134 try writer.writeAll(", sizeof(");
4336 try f.renderTypecast(writer, ret_ty);4135 try f.renderTypecast(writer, ret_ty);
4337 try writer.writeAll("));\n");4136 try writer.writeAll("));\n");
4338 try freeLocal(f, inst, result_local.local, 0);4137 try freeLocal(f, inst, result_local.new_local, 0);
4339 break :r array_local;4138 break :r array_local;
4340 };4139 };
43414140
...@@ -4599,7 +4398,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4599,7 +4398,7 @@ fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
4599 }4398 }
46004399
4601 if (operand == .constant) {4400 if (operand == .constant) {
4602 try freeLocal(f, inst, operand_lval.local, 0);4401 try freeLocal(f, inst, operand_lval.new_local, 0);
4603 }4402 }
46044403
4605 return local;4404 return local;
...@@ -4645,7 +4444,7 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4645,7 +4444,7 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
46454444
4646fn airUnreach(f: *Function) !CValue {4445fn airUnreach(f: *Function) !CValue {
4647 // Not even allowed to call unreachable in a naked function.4446 // 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
4650 try f.object.writer().writeAll("zig_unreachable();\n");4449 try f.object.writer().writeAll("zig_unreachable();\n");
4651 return CValue.none;4450 return CValue.none;
...@@ -4922,7 +4721,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4922,7 +4721,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4922 writer,4721 writer,
4923 output_ty,4722 output_ty,
4924 local_value,4723 local_value,
4925 .Mut,4724 .mut,
4926 alignment,4725 alignment,
4927 .Complete,4726 .Complete,
4928 );4727 );
...@@ -4961,7 +4760,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4961,7 +4760,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4961 writer,4760 writer,
4962 input_ty,4761 input_ty,
4963 local_value,4762 local_value,
4964 .Const,4763 .@"const",
4965 alignment,4764 alignment,
4966 .Complete,4765 .Complete,
4967 );4766 );
...@@ -5119,7 +4918,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5119,7 +4918,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
5119 const is_reg = constraint[1] == '{';4918 const is_reg = constraint[1] == '{';
5120 if (is_reg) {4919 if (is_reg) {
5121 try f.writeCValueDeref(writer, if (output == .none)4920 try f.writeCValueDeref(writer, if (output == .none)
5122 CValue{ .local_ref = local.local }4921 CValue{ .local_ref = local.new_local }
5123 else4922 else
5124 try f.resolveInst(output));4923 try f.resolveInst(output));
5125 try writer.writeAll(" = ");4924 try writer.writeAll(" = ");
...@@ -5425,18 +5224,20 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc...@@ -5425,18 +5224,20 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
5425 else => .none,5224 else => .none,
5426 };5225 };
54275226
5428 const FieldLoc = union(enum) {5227 const field_loc: union(enum) {
5429 begin: void,5228 begin: void,
5430 field: CValue,5229 field: CValue,
5431 end: void,5230 end: void,
5432 };5231 } = switch (struct_ty.tag()) {
5433 const field_loc = switch (struct_ty.tag()) {5232 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {
5434 .@"struct" => switch (struct_ty.containerLayout()) {5233 .Auto, .Extern => for (index..struct_ty.structFieldCount()) |field_i| {
5435 .Auto, .Extern => for (struct_ty.structFields().values()[index..], 0..) |field, offset| {5234 if (!struct_ty.structFieldIsComptime(field_i) and
5436 if (field.ty.hasRuntimeBitsIgnoreComptime()) break FieldLoc{ .field = .{5235 struct_ty.structFieldType(field_i).hasRuntimeBitsIgnoreComptime())
5437 .identifier = struct_ty.structFieldName(index + offset),5236 break .{ .field = if (struct_ty.isSimpleTuple())
5438 } };5237 .{ .field = field_i }
5439 } else @as(FieldLoc, .end),5238 else
5239 .{ .identifier = struct_ty.structFieldName(field_i) } };
5240 } else .end,
5440 .Packed => if (field_ptr_info.data.host_size == 0) {5241 .Packed => if (field_ptr_info.data.host_size == 0) {
5441 const target = f.object.dg.module.getTarget();5242 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...@@ -5461,45 +5262,33 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
5461 try f.writeCValue(writer, struct_ptr, .Other);5262 try f.writeCValue(writer, struct_ptr, .Other);
5462 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});5263 try writer.print(")[{}];\n", .{try f.fmtIntLiteral(Type.usize, byte_offset_val)});
5463 return local;5264 return local;
5464 } else @as(FieldLoc, .begin),5265 } else .begin,
5465 },5266 },
5466 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {5267 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
5467 try f.writeCValue(writer, struct_ptr, .Other);5268 try f.writeCValue(writer, struct_ptr, .Other);
5468 try writer.writeAll(";\n");5269 try writer.writeAll(";\n");
5469 return local;5270 return local;
5470 } else if (field_ty.hasRuntimeBitsIgnoreComptime()) FieldLoc{ .field = .{5271 } else if (field_ty.hasRuntimeBitsIgnoreComptime()) .{ .field = .{
5471 .identifier = struct_ty.unionFields().keys()[index],5272 .identifier = struct_ty.unionFields().keys()[index],
5472 } } else @as(FieldLoc, .end),5273 } } else .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 },
5485 else => unreachable,5274 else => unreachable,
5486 };5275 };
54875276
5488 try writer.writeByte('&');5277 if (struct_ty.hasRuntimeBitsIgnoreComptime()) {
5489 switch (field_loc) {5278 try writer.writeByte('&');
5490 .begin, .end => {5279 switch (field_loc) {
5491 try writer.writeByte('(');5280 .begin, .end => {
5492 try f.writeCValue(writer, struct_ptr, .Other);5281 try writer.writeByte('(');
5493 try writer.print(")[{}]", .{5282 try f.writeCValue(writer, struct_ptr, .Other);
5494 @boolToInt(field_loc == .end and struct_ty.hasRuntimeBitsIgnoreComptime()),5283 try writer.print(")[{}]", .{@boolToInt(field_loc == .end)});
5495 });5284 },
5496 },5285 .field => |field| if (extra_name != .none) {
5497 .field => |field| if (extra_name != .none) {5286 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
5498 try f.writeCValueDerefMember(writer, struct_ptr, extra_name);5287 try writer.writeByte('.');
5499 try writer.writeByte('.');5288 try f.writeCValue(writer, field, .Other);
5500 try f.writeCValue(writer, field, .Other);5289 } else try f.writeCValueDerefMember(writer, struct_ptr, field),
5501 } else try f.writeCValueDerefMember(writer, struct_ptr, field),5290 }
5502 }5291 } else try f.writeCValue(writer, struct_ptr, .Other);
5503 try writer.writeAll(";\n");5292 try writer.writeAll(";\n");
5504 return local;5293 return local;
5505}5294}
...@@ -5534,8 +5323,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5534,8 +5323,11 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5534 };5323 };
55355324
5536 const field_name: CValue = switch (struct_ty.tag()) {5325 const field_name: CValue = switch (struct_ty.tag()) {
5537 .@"struct" => switch (struct_ty.containerLayout()) {5326 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {
5538 .Auto, .Extern => .{ .identifier = struct_ty.structFieldName(extra.field_index) },5327 .Auto, .Extern => if (struct_ty.isSimpleTuple())
5328 .{ .field = extra.field_index }
5329 else
5330 .{ .identifier = struct_ty.structFieldName(extra.field_index) },
5539 .Packed => {5331 .Packed => {
5540 const struct_obj = struct_ty.castTag(.@"struct").?.data;5332 const struct_obj = struct_ty.castTag(.@"struct").?.data;
5541 const int_info = struct_ty.intInfo(target);5333 const int_info = struct_ty.intInfo(target);
...@@ -5593,13 +5385,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5593,13 +5385,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
55935385
5594 const local = try f.allocLocal(inst, inst_ty);5386 const local = try f.allocLocal(inst, inst_ty);
5595 try writer.writeAll("memcpy(");5387 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);
5597 try writer.writeAll(", ");5389 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);
5599 try writer.writeAll(", sizeof(");5391 try writer.writeAll(", sizeof(");
5600 try f.renderTypecast(writer, inst_ty);5392 try f.renderTypecast(writer, inst_ty);
5601 try writer.writeAll("));\n");5393 try writer.writeAll("));\n");
5602 try freeLocal(f, inst, temp_local.local, 0);5394 try freeLocal(f, inst, temp_local.new_local, 0);
5603 return local;5395 return local;
5604 },5396 },
5605 },5397 },
...@@ -5623,22 +5415,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5623,22 +5415,13 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5623 try writer.writeAll("));\n");5415 try writer.writeAll("));\n");
56245416
5625 if (struct_byval == .constant) {5417 if (struct_byval == .constant) {
5626 try freeLocal(f, inst, operand_lval.local, 0);5418 try freeLocal(f, inst, operand_lval.new_local, 0);
5627 }5419 }
56285420
5629 return local;5421 return local;
5630 } else .{5422 } else .{
5631 .identifier = struct_ty.unionFields().keys()[extra.field_index],5423 .identifier = struct_ty.unionFields().keys()[extra.field_index],
5632 },5424 },
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 },
5642 else => unreachable,5425 else => unreachable,
5643 };5426 };
56445427
...@@ -5965,26 +5748,28 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -5965,26 +5748,28 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
5965 const inst_ty = f.air.typeOfIndex(inst);5748 const inst_ty = f.air.typeOfIndex(inst);
5966 const writer = f.object.writer();5749 const writer = f.object.writer();
5967 const local = try f.allocLocal(inst, inst_ty);5750 const local = try f.allocLocal(inst, inst_ty);
5968 try f.writeCValue(writer, local, .Other);5751 const array_ty = f.air.typeOf(ty_op.operand).childType();
5969 const array_len = f.air.typeOf(ty_op.operand).elemType().arrayLen();
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
5972 if (operand == .undef) {5757 if (operand == .undef) {
5973 // Unfortunately, C does not support any equivalent to
5974 // &(*(void *)p)[0], although LLVM does via GetElementPtr
5975 var buf: Type.SlicePtrFieldTypeBuffer = undefined;5758 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
5976 try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer);5759 try f.writeCValue(writer, CValue{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer);
5977 } else {5760 } else if (array_ty.hasRuntimeBitsIgnoreComptime()) {
5978 try writer.writeAll("&(");5761 try writer.writeAll("&(");
5979 try f.writeCValueDeref(writer, operand);5762 try f.writeCValueDeref(writer, operand);
5980 try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, Value.zero)});5763 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();
5983 var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len };5768 var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len };
5984 const len_val = Value.initPayload(&len_pl.base);5769 const len_val = Value.initPayload(&len_pl.base);
5985 try writer.writeAll("; ");5770 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
5986 try f.writeCValue(writer, local, .Other);5771 try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
5987 try writer.print(".len = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});5772
5988 return local;5773 return local;
5989}5774}
59905775
...@@ -6223,7 +6008,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue...@@ -6223,7 +6008,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
6223 }6008 }
62246009
6225 if (f.liveness.isUnused(inst)) {6010 if (f.liveness.isUnused(inst)) {
6226 try freeLocal(f, inst, local.local, 0);6011 try freeLocal(f, inst, local.new_local, 0);
6227 return CValue.none;6012 return CValue.none;
6228 }6013 }
62296014
...@@ -6266,7 +6051,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6266,7 +6051,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6266 try writer.writeAll(");\n");6051 try writer.writeAll(");\n");
62676052
6268 if (f.liveness.isUnused(inst)) {6053 if (f.liveness.isUnused(inst)) {
6269 try freeLocal(f, inst, local.local, 0);6054 try freeLocal(f, inst, local.new_local, 0);
6270 return CValue.none;6055 return CValue.none;
6271 }6056 }
62726057
...@@ -6363,7 +6148,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6363,7 +6148,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index) !CValue {
6363 try writer.writeAll(";\n");6148 try writer.writeAll(";\n");
63646149
6365 try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs });6150 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
6368 return CValue.none;6153 return CValue.none;
6369 }6154 }
...@@ -6465,7 +6250,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6465,7 +6250,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
6465 const writer = f.object.writer();6250 const writer = f.object.writer();
6466 const local = try f.allocLocal(inst, inst_ty);6251 const local = try f.allocLocal(inst, inst_ty);
6467 try f.writeCValue(writer, local, .Other);6252 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)});
6469 try f.writeCValue(writer, operand, .Other);6254 try f.writeCValue(writer, operand, .Other);
6470 try writer.writeAll(");\n");6255 try writer.writeAll(");\n");
64716256
...@@ -6680,7 +6465,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6680,7 +6465,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66806465
6681 try writer.writeAll(";\n");6466 try writer.writeAll(";\n");
66826467
6683 try freeLocal(f, inst, it.local, 0);6468 try freeLocal(f, inst, it.new_local, 0);
66846469
6685 return accum;6470 return accum;
6686}6471}
...@@ -6693,8 +6478,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6693,8 +6478,8 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6693 const gpa = f.object.dg.gpa;6478 const gpa = f.object.dg.gpa;
6694 const resolved_elements = try gpa.alloc(CValue, elements.len);6479 const resolved_elements = try gpa.alloc(CValue, elements.len);
6695 defer gpa.free(resolved_elements);6480 defer gpa.free(resolved_elements);
6696 for (elements, 0..) |element, i| {6481 for (resolved_elements, elements) |*resolved_element, element| {
6697 resolved_elements[i] = try f.resolveInst(element);6482 resolved_element.* = try f.resolveInst(element);
6698 }6483 }
6699 {6484 {
6700 var bt = iterateBigTomb(f, inst);6485 var bt = iterateBigTomb(f, inst);
...@@ -6733,46 +6518,47 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6733,46 +6518,47 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6733 try writer.writeAll(")");6518 try writer.writeAll(")");
6734 try writer.writeByte('{');6519 try writer.writeByte('{');
6735 var empty = true;6520 var empty = true;
6736 for (elements, 0..) |element, index| {6521 for (elements, resolved_elements, 0..) |element, resolved_element, field_i| {
6737 if (inst_ty.structFieldValueComptime(index)) |_| continue;6522 if (inst_ty.structFieldValueComptime(field_i)) |_| continue;
67386523
6739 if (!empty) try writer.writeAll(", ");6524 if (!empty) try writer.writeAll(", ");
6740 if (!inst_ty.isTupleOrAnonStruct()) {6525
6741 try writer.print(".{ } = ", .{fmtIdent(inst_ty.structFieldName(index))});6526 const field_name: CValue = if (inst_ty.isSimpleTuple())
6742 }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
6744 const element_ty = f.air.typeOf(element);6534 const element_ty = f.air.typeOf(element);
6745 try f.writeCValue(writer, switch (element_ty.zigTypeTag()) {6535 try f.writeCValue(writer, switch (element_ty.zigTypeTag()) {
6746 .Array => CValue{ .undef = element_ty },6536 .Array => CValue{ .undef = element_ty },
6747 else => resolved_elements[index],6537 else => resolved_element,
6748 }, .Initializer);6538 }, .Initializer);
6749 empty = false;6539 empty = false;
6750 }6540 }
6751 if (empty) try writer.print("{}", .{try f.fmtIntLiteral(Type.u8, Value.zero)});
6752 try writer.writeAll("};\n");6541 try writer.writeAll("};\n");
67536542
6754 var field_id: usize = 0;6543 for (elements, resolved_elements, 0..) |element, resolved_element, field_i| {
6755 for (elements, 0..) |element, index| {6544 if (inst_ty.structFieldValueComptime(field_i)) |_| continue;
6756 if (inst_ty.structFieldValueComptime(index)) |_| continue;
67576545
6758 const element_ty = f.air.typeOf(element);6546 const element_ty = f.air.typeOf(element);
6759 if (element_ty.zigTypeTag() != .Array) continue;6547 if (element_ty.zigTypeTag() != .Array) continue;
67606548
6761 const field_name = if (inst_ty.isTupleOrAnonStruct())6549 const field_name: CValue = if (inst_ty.isSimpleTuple())
6762 CValue{ .field = field_id }6550 .{ .field = field_i }
6763 else6551 else
6764 CValue{ .identifier = inst_ty.structFieldName(index) };6552 .{ .identifier = inst_ty.structFieldName(field_i) };
67656553
6766 try writer.writeAll(";\n");6554 try writer.writeAll(";\n");
6767 try writer.writeAll("memcpy(");6555 try writer.writeAll("memcpy(");
6768 try f.writeCValueMember(writer, local, field_name);6556 try f.writeCValueMember(writer, local, field_name);
6769 try writer.writeAll(", ");6557 try writer.writeAll(", ");
6770 try f.writeCValue(writer, resolved_elements[index], .FunctionArgument);6558 try f.writeCValue(writer, resolved_element, .FunctionArgument);
6771 try writer.writeAll(", sizeof(");6559 try writer.writeAll(", sizeof(");
6772 try f.renderTypecast(writer, element_ty);6560 try f.renderTypecast(writer, element_ty);
6773 try writer.writeAll("));\n");6561 try writer.writeAll("));\n");
6774
6775 field_id += 1;
6776 }6562 }
6777 },6563 },
6778 .Packed => {6564 .Packed => {
...@@ -6790,7 +6576,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6790,7 +6576,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6790 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);6576 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
67916577
6792 var empty = true;6578 var empty = true;
6793 for (elements, 0..) |_, index| {6579 for (0..elements.len) |index| {
6794 const field_ty = inst_ty.structFieldType(index);6580 const field_ty = inst_ty.structFieldType(index);
6795 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;6581 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
67966582
...@@ -6839,13 +6625,6 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6839,13 +6625,6 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6839 empty = false;6625 empty = false;
6840 }6626 }
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
6849 try writer.writeAll(";\n");6628 try writer.writeAll(";\n");
6850 },6629 },
6851 },6630 },
...@@ -7350,7 +7129,7 @@ fn formatIntLiteral(...@@ -7350,7 +7129,7 @@ fn formatIntLiteral(
7350 use_twos_comp = true;7129 use_twos_comp = true;
7351 } else {7130 } else {
7352 // TODO: Use fmtIntLiteral for 0?7131 // 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 });
7354 }7133 }
7355 } else {7134 } else {
7356 try writer.writeByte('-');7135 try writer.writeByte('-');
...@@ -7360,11 +7139,16 @@ fn formatIntLiteral(...@@ -7360,11 +7139,16 @@ fn formatIntLiteral(
7360 switch (data.ty.tag()) {7139 switch (data.ty.tag()) {
7361 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},7140 .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {},
7362 else => {7141 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) {
7364 // MSVC treats casting the struct initializer as not constant (C2099), so an alternate form is used in global initializers7148 // 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 });
7366 } else {7150 } 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 });
7368 }7152 }
7369 },7153 },
7370 }7154 }
...@@ -7473,17 +7257,20 @@ fn isByRef(ty: Type) bool {...@@ -7473,17 +7257,20 @@ fn isByRef(ty: Type) bool {
7473}7257}
74747258
7475const LowerFnRetTyBuffer = struct {7259const LowerFnRetTyBuffer = struct {
7260 names: [1][]const u8,
7476 types: [1]Type,7261 types: [1]Type,
7477 values: [1]Value,7262 values: [1]Value,
7478 payload: Type.Payload.Tuple,7263 payload: Type.Payload.AnonStruct,
7479};7264};
7480fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {7265fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {
7481 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);7266 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);
74827267
7483 if (lowersToArray(ret_ty, target)) {7268 if (lowersToArray(ret_ty, target)) {
7269 buffer.names = [1][]const u8{"array"};
7484 buffer.types = [1]Type{ret_ty};7270 buffer.types = [1]Type{ret_ty};
7485 buffer.values = [1]Value{Value.initTag(.unreachable_value)};7271 buffer.values = [1]Value{Value.initTag(.unreachable_value)};
7486 buffer.payload = .{ .data = .{7272 buffer.payload = .{ .data = .{
7273 .names = &buffer.names,
7487 .types = &buffer.types,7274 .types = &buffer.types,
7488 .values = &buffer.values,7275 .values = &buffer.values,
7489 } };7276 } };
...@@ -7539,7 +7326,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {...@@ -7539,7 +7326,7 @@ fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
7539 if (f.air.instructions.items(.tag)[ref_inst] == .constant) return;7326 if (f.air.instructions.items(.tag)[ref_inst] == .constant) return;
7540 const c_value = (f.value_map.fetchRemove(ref) orelse return).value;7327 const c_value = (f.value_map.fetchRemove(ref) orelse return).value;
7541 const local_index = switch (c_value) {7328 const local_index = switch (c_value) {
7542 .local => |l| l,7329 .local, .new_local => |l| l,
7543 else => return,7330 else => return,
7544 };7331 };
7545 try freeLocal(f, inst, local_index, ref_inst);7332 try freeLocal(f, inst, local_index, ref_inst);
...@@ -7614,8 +7401,8 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {...@@ -7614,8 +7401,8 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {
7614}7401}
76157402
7616fn noticeBranchFrees(f: *Function, pre_locals_len: LocalIndex, inst: Air.Inst.Index) !void {7403fn noticeBranchFrees(f: *Function, pre_locals_len: LocalIndex, inst: Air.Inst.Index) !void {
7617 for (f.locals.items[pre_locals_len..], 0..) |*local, local_offset| {7404 for (f.locals.items[pre_locals_len..], pre_locals_len..) |*local, local_i| {
7618 const local_index = pre_locals_len + @intCast(LocalIndex, local_offset);7405 const local_index = @intCast(LocalIndex, local_i);
7619 if (f.allocs.contains(local_index)) continue; // allocs are not freeable7406 if (f.allocs.contains(local_index)) continue; // allocs are not freeable
76207407
7621 // free more deeply nested locals from other branches at current depth7408 // 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,...@@ -22,27 +22,22 @@ base: link.File,
22/// Instead, it tracks all declarations in this table, and iterates over it22/// Instead, it tracks all declarations in this table, and iterates over it
23/// in the flush function, stitching pre-rendered pieces of C code together.23/// in the flush function, stitching pre-rendered pieces of C code together.
24decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclBlock) = .{},24decl_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
29/// Per-declaration data.26/// Per-declaration data.
30const DeclBlock = struct {27const DeclBlock = struct {
31 code: std.ArrayListUnmanaged(u8) = .{},28 code: std.ArrayListUnmanaged(u8) = .{},
32 fwd_decl: std.ArrayListUnmanaged(u8) = .{},29 fwd_decl: std.ArrayListUnmanaged(u8) = .{},
33 /// Each Decl stores a mapping of Zig Types to corresponding C types, for every30 /// Each `Decl` stores a set of used `CType`s. In `flush()`, we iterate
34 /// Zig Type used by the Decl. In flush(), we iterate over each Decl31 /// over each `Decl` and generate the definition for each used `CType` once.
35 /// and emit the typedef code for all types, making sure to not emit the same thing twice.32 ctypes: codegen.CType.Store = .{},
36 /// Any arena memory the Type points to lives in the `arena` field of `C`.33 /// Key and Value storage use the ctype arena.
37 typedefs: codegen.TypedefMap.Unmanaged = .{},34 lazy_fns: codegen.LazyFnMap = .{},
3835
39 fn deinit(db: *DeclBlock, gpa: Allocator) void {36 fn deinit(db: *DeclBlock, gpa: Allocator) void {
40 db.code.deinit(gpa);37 db.lazy_fns.deinit(gpa);
38 db.ctypes.deinit(gpa);
41 db.fwd_decl.deinit(gpa);39 db.fwd_decl.deinit(gpa);
42 for (db.typedefs.values()) |typedef| {40 db.code.deinit(gpa);
43 gpa.free(typedef.rendered);
44 }
45 db.typedefs.deinit(gpa);
46 db.* = undefined;41 db.* = undefined;
47 }42 }
48};43};
...@@ -64,7 +59,6 @@ pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C...@@ -64,7 +59,6 @@ pub fn openPath(gpa: Allocator, sub_path: []const u8, options: link.Options) !*C
64 errdefer gpa.destroy(c_file);59 errdefer gpa.destroy(c_file);
6560
66 c_file.* = C{61 c_file.* = C{
67 .arena = std.heap.ArenaAllocator.init(gpa),
68 .base = .{62 .base = .{
69 .tag = .c,63 .tag = .c,
70 .options = options,64 .options = options,
...@@ -83,8 +77,6 @@ pub fn deinit(self: *C) void {...@@ -83,8 +77,6 @@ pub fn deinit(self: *C) void {
83 db.deinit(gpa);77 db.deinit(gpa);
84 }78 }
85 self.decl_table.deinit(gpa);79 self.decl_table.deinit(gpa);
86
87 self.arena.deinit();
88}80}
8981
90pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {82pub 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...@@ -99,124 +91,122 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
99 const tracy = trace(@src());91 const tracy = trace(@src());
100 defer tracy.end();92 defer tracy.end();
10193
94 const gpa = self.base.allocator;
95
102 const decl_index = func.owner_decl;96 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);
104 if (!gop.found_existing) {98 if (!gop.found_existing) {
105 gop.value_ptr.* = .{};99 gop.value_ptr.* = .{};
106 }100 }
101 const ctypes = &gop.value_ptr.ctypes;
102 const lazy_fns = &gop.value_ptr.lazy_fns;
107 const fwd_decl = &gop.value_ptr.fwd_decl;103 const fwd_decl = &gop.value_ptr.fwd_decl;
108 const typedefs = &gop.value_ptr.typedefs;
109 const code = &gop.value_ptr.code;104 const code = &gop.value_ptr.code;
105 ctypes.clearRetainingCapacity(gpa);
106 lazy_fns.clearRetainingCapacity();
110 fwd_decl.shrinkRetainingCapacity(0);107 fwd_decl.shrinkRetainingCapacity(0);
111 for (typedefs.values()) |typedef| {
112 module.gpa.free(typedef.rendered);
113 }
114 typedefs.clearRetainingCapacity();
115 code.shrinkRetainingCapacity(0);108 code.shrinkRetainingCapacity(0);
116109
117 var function: codegen.Function = .{110 var function: codegen.Function = .{
118 .value_map = codegen.CValueMap.init(module.gpa),111 .value_map = codegen.CValueMap.init(gpa),
119 .air = air,112 .air = air,
120 .liveness = liveness,113 .liveness = liveness,
121 .func = func,114 .func = func,
122 .object = .{115 .object = .{
123 .dg = .{116 .dg = .{
124 .gpa = module.gpa,117 .gpa = gpa,
125 .module = module,118 .module = module,
126 .error_msg = null,119 .error_msg = null,
127 .decl_index = decl_index,120 .decl_index = decl_index.toOptional(),
128 .decl = module.declPtr(decl_index),121 .decl = module.declPtr(decl_index),
129 .fwd_decl = fwd_decl.toManaged(module.gpa),122 .fwd_decl = fwd_decl.toManaged(gpa),
130 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),123 .ctypes = ctypes.*,
131 .typedefs_arena = self.arena.allocator(),
132 },124 },
133 .code = code.toManaged(module.gpa),125 .code = code.toManaged(gpa),
134 .indent_writer = undefined, // set later so we can get a pointer to object.code126 .indent_writer = undefined, // set later so we can get a pointer to object.code
135 },127 },
136 .arena = std.heap.ArenaAllocator.init(module.gpa),128 .lazy_fns = lazy_fns.*,
129 .arena = std.heap.ArenaAllocator.init(gpa),
137 };130 };
138131
139 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };132 function.object.indent_writer = .{ .underlying_writer = function.object.code.writer() };
140 defer function.deinit(module.gpa);133 defer function.deinit();
141134
142 codegen.genFunc(&function) catch |err| switch (err) {135 codegen.genFunc(&function) catch |err| switch (err) {
143 error.AnalysisFail => {136 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.?);
145 return;138 return;
146 },139 },
147 else => |e| return e,140 else => |e| return e,
148 };141 };
149142
143 ctypes.* = function.object.dg.ctypes.move();
144 lazy_fns.* = function.lazy_fns.move();
150 fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();145 fwd_decl.* = function.object.dg.fwd_decl.moveToUnmanaged();
151 typedefs.* = function.object.dg.typedefs.unmanaged;
152 function.object.dg.typedefs.unmanaged = .{};
153 code.* = function.object.code.moveToUnmanaged();146 code.* = function.object.code.moveToUnmanaged();
154147
155 // Free excess allocated memory for this Decl.148 // Free excess allocated memory for this Decl.
156 fwd_decl.shrinkAndFree(module.gpa, fwd_decl.items.len);149 ctypes.shrinkAndFree(gpa, ctypes.count());
157 code.shrinkAndFree(module.gpa, code.items.len);150 lazy_fns.shrinkAndFree(gpa, lazy_fns.count());
151 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);
152 code.shrinkAndFree(gpa, code.items.len);
158}153}
159154
160pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {155pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {
161 const tracy = trace(@src());156 const tracy = trace(@src());
162 defer tracy.end();157 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);
165 if (!gop.found_existing) {162 if (!gop.found_existing) {
166 gop.value_ptr.* = .{};163 gop.value_ptr.* = .{};
167 }164 }
165 const ctypes = &gop.value_ptr.ctypes;
168 const fwd_decl = &gop.value_ptr.fwd_decl;166 const fwd_decl = &gop.value_ptr.fwd_decl;
169 const typedefs = &gop.value_ptr.typedefs;
170 const code = &gop.value_ptr.code;167 const code = &gop.value_ptr.code;
168 ctypes.clearRetainingCapacity(gpa);
171 fwd_decl.shrinkRetainingCapacity(0);169 fwd_decl.shrinkRetainingCapacity(0);
172 for (typedefs.values()) |value| {
173 module.gpa.free(value.rendered);
174 }
175 typedefs.clearRetainingCapacity();
176 code.shrinkRetainingCapacity(0);170 code.shrinkRetainingCapacity(0);
177171
178 const decl = module.declPtr(decl_index);172 const decl = module.declPtr(decl_index);
179173
180 var object: codegen.Object = .{174 var object: codegen.Object = .{
181 .dg = .{175 .dg = .{
182 .gpa = module.gpa,176 .gpa = gpa,
183 .module = module,177 .module = module,
184 .error_msg = null,178 .error_msg = null,
185 .decl_index = decl_index,179 .decl_index = decl_index.toOptional(),
186 .decl = decl,180 .decl = decl,
187 .fwd_decl = fwd_decl.toManaged(module.gpa),181 .fwd_decl = fwd_decl.toManaged(gpa),
188 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),182 .ctypes = ctypes.*,
189 .typedefs_arena = self.arena.allocator(),
190 },183 },
191 .code = code.toManaged(module.gpa),184 .code = code.toManaged(gpa),
192 .indent_writer = undefined, // set later so we can get a pointer to object.code185 .indent_writer = undefined, // set later so we can get a pointer to object.code
193 };186 };
194 object.indent_writer = .{ .underlying_writer = object.code.writer() };187 object.indent_writer = .{ .underlying_writer = object.code.writer() };
195 defer {188 defer {
196 object.code.deinit();189 object.code.deinit();
197 for (object.dg.typedefs.values()) |typedef| {190 object.dg.ctypes.deinit(object.dg.gpa);
198 module.gpa.free(typedef.rendered);
199 }
200 object.dg.typedefs.deinit();
201 object.dg.fwd_decl.deinit();191 object.dg.fwd_decl.deinit();
202 }192 }
203193
204 codegen.genDecl(&object) catch |err| switch (err) {194 codegen.genDecl(&object) catch |err| switch (err) {
205 error.AnalysisFail => {195 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.?);
207 return;197 return;
208 },198 },
209 else => |e| return e,199 else => |e| return e,
210 };200 };
211201
202 ctypes.* = object.dg.ctypes.move();
212 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();203 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
213 typedefs.* = object.dg.typedefs.unmanaged;
214 object.dg.typedefs.unmanaged = .{};
215 code.* = object.code.moveToUnmanaged();204 code.* = object.code.moveToUnmanaged();
216205
217 // Free excess allocated memory for this Decl.206 // Free excess allocated memory for this Decl.
218 fwd_decl.shrinkAndFree(module.gpa, fwd_decl.items.len);207 ctypes.shrinkAndFree(gpa, ctypes.count());
219 code.shrinkAndFree(module.gpa, code.items.len);208 fwd_decl.shrinkAndFree(gpa, fwd_decl.items.len);
209 code.shrinkAndFree(gpa, code.items.len);
220}210}
221211
222pub fn updateDeclLineNumber(self: *C, module: *Module, decl_index: Module.Decl.Index) !void {212pub 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)...@@ -246,7 +236,7 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
246 sub_prog_node.activate();236 sub_prog_node.activate();
247 defer sub_prog_node.end();237 defer sub_prog_node.end();
248238
249 const gpa = comp.gpa;239 const gpa = self.base.allocator;
250 const module = self.base.options.module.?;240 const module = self.base.options.module.?;
251241
252 // This code path happens exclusively with -ofmt=c. The flush logic for242 // 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)...@@ -257,30 +247,28 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
257247
258 const abi_define = abiDefine(comp);248 const abi_define = abiDefine(comp);
259249
260 // Covers defines, zig.h, typedef, and asm.250 // Covers defines, zig.h, ctypes, asm, lazy fwd, lazy code.
261 var buf_count: usize = 2;251 try f.all_buffers.ensureUnusedCapacity(gpa, 6);
262 if (abi_define != null) buf_count += 1;
263 try f.all_buffers.ensureUnusedCapacity(gpa, buf_count);
264252
265 if (abi_define) |buf| f.appendBufAssumeCapacity(buf);253 if (abi_define) |buf| f.appendBufAssumeCapacity(buf);
266 f.appendBufAssumeCapacity(zig_h);254 f.appendBufAssumeCapacity(zig_h);
267255
268 const typedef_index = f.all_buffers.items.len;256 const ctypes_index = f.all_buffers.items.len;
269 f.all_buffers.items.len += 1;257 f.all_buffers.items.len += 1;
270258
271 {259 {
272 var asm_buf = f.asm_buf.toManaged(module.gpa);260 var asm_buf = f.asm_buf.toManaged(gpa);
273 defer asm_buf.deinit();261 defer f.asm_buf = asm_buf.moveToUnmanaged();
274262 try codegen.genGlobalAsm(module, asm_buf.writer());
275 try codegen.genGlobalAsm(module, &asm_buf);263 f.appendBufAssumeCapacity(asm_buf.items);
276
277 f.asm_buf = asm_buf.moveToUnmanaged();
278 f.appendBufAssumeCapacity(f.asm_buf.items);
279 }264 }
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.
284 // Unlike other backends, the .c code we are emitting is order-dependent. Therefore272 // Unlike other backends, the .c code we are emitting is order-dependent. Therefore
285 // we must traverse the set of Decls that we are emitting according to their dependencies.273 // we must traverse the set of Decls that we are emitting according to their dependencies.
286 // Our strategy is to populate a set of remaining decls, pop Decls one by one,274 // 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)...@@ -307,11 +295,35 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
307 }295 }
308 }296 }
309297
310 f.all_buffers.items[typedef_index] = .{298 {
311 .iov_base = if (f.typedef_buf.items.len > 0) f.typedef_buf.items.ptr else "",299 // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.
312 .iov_len = f.typedef_buf.items.len,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,
313 };325 };
314 f.file_size += f.typedef_buf.items.len;326 f.file_size += f.ctypes_buf.items.len;
315327
316 // Now the code.328 // Now the code.
317 try f.all_buffers.ensureUnusedCapacity(gpa, decl_values.len);329 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)...@@ -324,22 +336,23 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
324}336}
325337
326const Flush = struct {338const Flush = struct {
327 err_decls: DeclBlock = .{},
328 remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{},339 remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{},
329 typedefs: Typedefs = .{},340
330 typedef_buf: std.ArrayListUnmanaged(u8) = .{},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
331 asm_buf: std.ArrayListUnmanaged(u8) = .{},348 asm_buf: std.ArrayListUnmanaged(u8) = .{},
349
332 /// We collect a list of buffers to write, and write them all at once with pwritev 😎350 /// We collect a list of buffers to write, and write them all at once with pwritev 😎
333 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},351 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
334 /// Keeps track of the total bytes of `all_buffers`.352 /// Keeps track of the total bytes of `all_buffers`.
335 file_size: u64 = 0,353 file_size: u64 = 0,
336354
337 const Typedefs = std.HashMapUnmanaged(355 const LazyFns = std.AutoHashMapUnmanaged(codegen.LazyFnKey, void);
338 Type,
339 void,
340 Type.HashContext64,
341 std.hash_map.default_max_load_percentage,
342 );
343356
344 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {357 fn appendBufAssumeCapacity(f: *Flush, buf: []const u8) void {
345 if (buf.len == 0) return;358 if (buf.len == 0) return;
...@@ -349,10 +362,13 @@ const Flush = struct {...@@ -349,10 +362,13 @@ const Flush = struct {
349362
350 fn deinit(f: *Flush, gpa: Allocator) void {363 fn deinit(f: *Flush, gpa: Allocator) void {
351 f.all_buffers.deinit(gpa);364 f.all_buffers.deinit(gpa);
352 f.typedef_buf.deinit(gpa);365 f.asm_buf.deinit(gpa);
353 f.typedefs.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);
354 f.remaining_decls.deinit(gpa);371 f.remaining_decls.deinit(gpa);
355 f.err_decls.deinit(gpa);
356 }372 }
357};373};
358374
...@@ -360,53 +376,116 @@ const FlushDeclError = error{...@@ -360,53 +376,116 @@ const FlushDeclError = error{
360 OutOfMemory,376 OutOfMemory,
361};377};
362378
363fn flushTypedefs(self: *C, f: *Flush, typedefs: codegen.TypedefMap.Unmanaged) FlushDeclError!void {379fn flushCTypes(
364 if (typedefs.count() == 0) return;380 self: *C,
381 f: *Flush,
382 decl_index: Module.Decl.OptionalIndex,
383 decl_ctypes: codegen.CType.Store,
384) FlushDeclError!void {
365 const gpa = self.base.allocator;385 const gpa = self.base.allocator;
366 const module = self.base.options.module.?;386 const mod = self.base.options.module.?;
367387
368 try f.typedefs.ensureUnusedCapacityContext(gpa, @intCast(u32, typedefs.count()), .{388 const decl_ctypes_len = decl_ctypes.count();
369 .mod = module,389 f.ctypes_map.clearRetainingCapacity();
370 });390 try f.ctypes_map.ensureTotalCapacity(gpa, decl_ctypes_len);
371 var it = typedefs.iterator();391
372 while (it.next()) |new| {392 var global_ctypes = f.ctypes.promote(gpa);
373 const gop = f.typedefs.getOrPutAssumeCapacityContext(new.key_ptr.*, .{393 defer f.ctypes.demote(global_ctypes);
374 .mod = module,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,
375 });438 });
439 const global_idx =
440 @intCast(codegen.CType.Index, codegen.CType.Tag.no_payload_count + gop.index);
441 f.ctypes_map.appendAssumeCapacity(global_idx);
376 if (!gop.found_existing) {442 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));
378 }451 }
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 );
379 }462 }
380}463}
381464
382fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {465fn flushErrDecls(self: *C, db: *DeclBlock) FlushDeclError!void {
383 const module = self.base.options.module.?;466 const gpa = self.base.allocator;
384467
385 const fwd_decl = &f.err_decls.fwd_decl;468 const fwd_decl = &db.fwd_decl;
386 const typedefs = &f.err_decls.typedefs;469 const ctypes = &db.ctypes;
387 const code = &f.err_decls.code;470 const code = &db.code;
388471
389 var object = codegen.Object{472 var object = codegen.Object{
390 .dg = .{473 .dg = .{
391 .gpa = module.gpa,474 .gpa = gpa,
392 .module = module,475 .module = self.base.options.module.?,
393 .error_msg = null,476 .error_msg = null,
394 .decl_index = undefined,477 .decl_index = .none,
395 .decl = undefined,478 .decl = null,
396 .fwd_decl = fwd_decl.toManaged(module.gpa),479 .fwd_decl = fwd_decl.toManaged(gpa),
397 .typedefs = typedefs.promoteContext(module.gpa, .{ .mod = module }),480 .ctypes = ctypes.*,
398 .typedefs_arena = self.arena.allocator(),
399 },481 },
400 .code = code.toManaged(module.gpa),482 .code = code.toManaged(gpa),
401 .indent_writer = undefined, // set later so we can get a pointer to object.code483 .indent_writer = undefined, // set later so we can get a pointer to object.code
402 };484 };
403 object.indent_writer = .{ .underlying_writer = object.code.writer() };485 object.indent_writer = .{ .underlying_writer = object.code.writer() };
404 defer {486 defer {
405 object.code.deinit();487 object.code.deinit();
406 for (object.dg.typedefs.values()) |typedef| {488 object.dg.ctypes.deinit(gpa);
407 module.gpa.free(typedef.rendered);
408 }
409 object.dg.typedefs.deinit();
410 object.dg.fwd_decl.deinit();489 object.dg.fwd_decl.deinit();
411 }490 }
412491
...@@ -416,14 +495,58 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {...@@ -416,14 +495,58 @@ fn flushErrDecls(self: *C, f: *Flush) FlushDeclError!void {
416 };495 };
417496
418 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();497 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
419 typedefs.* = object.dg.typedefs.unmanaged;498 ctypes.* = object.dg.ctypes.move();
420 object.dg.typedefs.unmanaged = .{};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();
421 code.* = object.code.moveToUnmanaged();536 code.* = object.code.moveToUnmanaged();
537}
422538
423 try self.flushTypedefs(f, typedefs.*);539fn flushLazyFns(self: *C, f: *Flush, lazy_fns: codegen.LazyFnMap) FlushDeclError!void {
424 try f.all_buffers.ensureUnusedCapacity(self.base.allocator, 1);540 const gpa = self.base.allocator;
425 f.appendBufAssumeCapacity(fwd_decl.items);541 try f.lazy_fns.ensureUnusedCapacity(gpa, @intCast(Flush.LazyFns.Size, lazy_fns.count()));
426 f.appendBufAssumeCapacity(code.items);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 }
427}550}
428551
429/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.552/// Assumes `decl` was in the `remaining_decls` set, and has already been removed.
...@@ -433,8 +556,8 @@ fn flushDecl(...@@ -433,8 +556,8 @@ fn flushDecl(
433 decl_index: Module.Decl.Index,556 decl_index: Module.Decl.Index,
434 export_names: std.StringHashMapUnmanaged(void),557 export_names: std.StringHashMapUnmanaged(void),
435) FlushDeclError!void {558) FlushDeclError!void {
436 const module = self.base.options.module.?;559 const gpa = self.base.allocator;
437 const decl = module.declPtr(decl_index);560 const decl = self.base.options.module.?.declPtr(decl_index);
438 // Before flushing any particular Decl we must ensure its561 // Before flushing any particular Decl we must ensure its
439 // dependencies are already flushed, so that the order in the .c562 // dependencies are already flushed, so that the order in the .c
440 // file comes out correctly.563 // file comes out correctly.
...@@ -445,10 +568,9 @@ fn flushDecl(...@@ -445,10 +568,9 @@ fn flushDecl(
445 }568 }
446569
447 const decl_block = self.decl_table.getPtr(decl_index).?;570 const decl_block = self.decl_table.getPtr(decl_index).?;
448 const gpa = self.base.allocator;
449571
450 try self.flushTypedefs(f, decl_block.typedefs);572 try self.flushLazyFns(f, decl_block.lazy_fns);
451 try f.all_buffers.ensureUnusedCapacity(gpa, 2);573 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
452 if (!(decl.isExtern() and export_names.contains(mem.span(decl.name))))574 if (!(decl.isExtern() and export_names.contains(mem.span(decl.name))))
453 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);575 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
454}576}
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" {...@@ -551,7 +551,11 @@ test "align(N) on functions" {
551 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO551 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
552 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO552 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
553 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO553 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 MSVC554
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
556 // function alignment is a compile error on wasm32/wasm64560 // function alignment is a compile error on wasm32/wasm64
557 if (native_arch == .wasm32 or native_arch == .wasm64) return error.SkipZigTest;561 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...@@ -7,6 +7,7 @@ const is_x86_64_linux = builtin.cpu.arch == .x86_64 and builtin.os.tag == .linux
7comptime {7comptime {
8 if (builtin.zig_backend != .stage2_arm and8 if (builtin.zig_backend != .stage2_arm and
9 builtin.zig_backend != .stage2_aarch64 and9 builtin.zig_backend != .stage2_aarch64 and
10 !(builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) and // MSVC doesn't support inline assembly
10 is_x86_64_linux)11 is_x86_64_linux)
11 {12 {
12 asm (13 asm (
...@@ -23,7 +24,8 @@ test "module level assembly" {...@@ -23,7 +24,8 @@ test "module level assembly" {
23 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO25 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
25 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
26 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO27
28 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
2729
28 if (is_x86_64_linux) {30 if (is_x86_64_linux) {
29 try expect(this_is_my_alias() == 1234);31 try expect(this_is_my_alias() == 1234);
...@@ -36,7 +38,8 @@ test "output constraint modifiers" {...@@ -36,7 +38,8 @@ test "output constraint modifiers" {
36 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO38 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
37 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO39 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
38 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO40 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
39 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO41
42 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
4043
41 // This is only testing compilation.44 // This is only testing compilation.
42 var a: u32 = 3;45 var a: u32 = 3;
...@@ -58,7 +61,8 @@ test "alternative constraints" {...@@ -58,7 +61,8 @@ test "alternative constraints" {
58 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO61 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
59 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO62 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
60 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO63 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
61 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO64
65 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
6266
63 // Make sure we allow commas as a separator for alternative constraints.67 // Make sure we allow commas as a separator for alternative constraints.
64 var a: u32 = 3;68 var a: u32 = 3;
...@@ -75,7 +79,8 @@ test "sized integer/float in asm input" {...@@ -75,7 +79,8 @@ test "sized integer/float in asm input" {
75 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO80 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO81 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO82
83 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
7984
80 asm volatile (""85 asm volatile (""
81 :86 :
...@@ -125,7 +130,8 @@ test "struct/array/union types as input values" {...@@ -125,7 +130,8 @@ test "struct/array/union types as input values" {
125 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO130 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
126 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO131 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
127 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO132 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
128 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO133
134 if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
129135
130 asm volatile (""136 asm volatile (""
131 :137 :
...@@ -151,6 +157,8 @@ test "asm modifiers (AArch64)" {...@@ -151,6 +157,8 @@ test "asm modifiers (AArch64)" {
151 if (builtin.target.cpu.arch != .aarch64) return error.SkipZigTest;157 if (builtin.target.cpu.arch != .aarch64) return error.SkipZigTest;
152 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO158 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
154 var x: u32 = 15;162 var x: u32 = 15;
155 const double = asm ("add %[ret:w], %[in:w], %[in:w]"163 const double = asm ("add %[ret:w], %[in:w], %[in:w]"
156 : [ret] "=r" (-> u32),164 : [ret] "=r" (-> u32),
test/behavior/int_comparison_elision.zig-1
...@@ -13,7 +13,6 @@ test "int comparison elision" {...@@ -13,7 +13,6 @@ test "int comparison elision" {
1313
14 // TODO: support int types > 128 bits wide in other backends14 // TODO: support int types > 128 bits wide in other backends
15 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO15 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
16 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
17 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO16 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
18 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO17 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
19 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO18 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" {...@@ -7,7 +7,6 @@ test "strlit to vector" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1110
12 const strlit = "0123456789abcdef0123456789ABCDEF";11 const strlit = "0123456789abcdef0123456789ABCDEF";
13 const vec_from_strlit: @Vector(32, u8) = strlit.*;12 const vec_from_strlit: @Vector(32, u8) = strlit.*;
test/behavior/math.zig-1
...@@ -1463,7 +1463,6 @@ test "vector integer addition" {...@@ -1463,7 +1463,6 @@ test "vector integer addition" {
1463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1463 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1464 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1465 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1465 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1466 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1467 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1466 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14681467
1469 const S = struct {1468 const S = struct {
test/behavior/struct.zig-1
...@@ -1330,7 +1330,6 @@ test "struct field init value is size of the struct" {...@@ -1330,7 +1330,6 @@ test "struct field init value is size of the struct" {
1330}1330}
13311331
1332test "under-aligned struct field" {1332test "under-aligned struct field" {
1333 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1334 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1333 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1335 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1334 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1336 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1335 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
test/behavior/vector.zig-5
...@@ -75,7 +75,6 @@ test "vector int operators" {...@@ -75,7 +75,6 @@ test "vector int operators" {
75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
79 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
8079
81 const S = struct {80 const S = struct {
...@@ -178,7 +177,6 @@ test "tuple to vector" {...@@ -178,7 +177,6 @@ test "tuple to vector" {
178 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO177 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO178 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
180 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO179 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
181 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
182 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
183181
184 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {182 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) {
...@@ -943,7 +941,6 @@ test "multiplication-assignment operator with an array operand" {...@@ -943,7 +941,6 @@ test "multiplication-assignment operator with an array operand" {
943 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO941 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
944 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO942 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
945 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO943 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
946 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
947 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO944 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
948945
949 const S = struct {946 const S = struct {
...@@ -1247,7 +1244,6 @@ test "array operands to shuffle are coerced to vectors" {...@@ -1247,7 +1244,6 @@ test "array operands to shuffle are coerced to vectors" {
1247test "load packed vector element" {1244test "load packed vector element" {
1248 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1245 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1249 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1246 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1251 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1252 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1248 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1253 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
...@@ -1260,7 +1256,6 @@ test "load packed vector element" {...@@ -1260,7 +1256,6 @@ test "load packed vector element" {
1260test "store packed vector element" {1256test "store packed vector element" {
1261 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1257 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1262 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1258 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1263 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1264 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1265 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1260 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1266 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1261 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 {...@@ -959,7 +959,7 @@ pub fn addCases(ctx: *TestContext) !void {
959 \\ _ = a;959 \\ _ = a;
960 \\}960 \\}
961 ,961 ,
962 \\zig_extern void start(zig_u8 const a0);962 \\zig_extern void start(uint8_t const a0);
963 \\963 \\
964 );964 );
965 ctx.h("header with multiple param function", linux_x64,965 ctx.h("header with multiple param function", linux_x64,
...@@ -967,19 +967,19 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -967,19 +967,19 @@ pub fn addCases(ctx: *TestContext) !void {
967 \\ _ = a; _ = b; _ = c;967 \\ _ = a; _ = b; _ = c;
968 \\}968 \\}
969 ,969 ,
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);
971 \\971 \\
972 );972 );
973 ctx.h("header with u32 param function", linux_x64,973 ctx.h("header with u32 param function", linux_x64,
974 \\export fn start(a: u32) void{ _ = a; }974 \\export fn start(a: u32) void{ _ = a; }
975 ,975 ,
976 \\zig_extern void start(zig_u32 const a0);976 \\zig_extern void start(uint32_t const a0);
977 \\977 \\
978 );978 );
979 ctx.h("header with usize param function", linux_x64,979 ctx.h("header with usize param function", linux_x64,
980 \\export fn start(a: usize) void{ _ = a; }980 \\export fn start(a: usize) void{ _ = a; }
981 ,981 ,
982 \\zig_extern void start(zig_usize const a0);982 \\zig_extern void start(uintptr_t const a0);
983 \\983 \\
984 );984 );
985 ctx.h("header with bool param function", linux_x64,985 ctx.h("header with bool param function", linux_x64,
...@@ -993,7 +993,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -993,7 +993,7 @@ pub fn addCases(ctx: *TestContext) !void {
993 \\ unreachable;993 \\ unreachable;
994 \\}994 \\}
995 ,995 ,
996 \\zig_extern zig_noreturn start(void);996 \\zig_extern zig_noreturn void start(void);
997 \\997 \\
998 );998 );
999 ctx.h("header with multiple functions", linux_x64,999 ctx.h("header with multiple functions", linux_x64,
...@@ -1009,7 +1009,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1009,7 +1009,7 @@ pub fn addCases(ctx: *TestContext) !void {
1009 ctx.h("header with multiple includes", linux_x64,1009 ctx.h("header with multiple includes", linux_x64,
1010 \\export fn start(a: u32, b: usize) void{ _ = a; _ = b; }1010 \\export fn start(a: u32, b: usize) void{ _ = a; _ = b; }
1011 ,1011 ,
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);
1013 \\1013 \\
1014 );1014 );
1015}1015}