From 865f329e4f9fd097bb9739566045f9b7179521c4 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 25 Jun 2026 01:53:50 -0400 Subject: [PATCH] cbe: update for compiler_rt abi changes * `tools/generate_c_size_and_align_checks.zig`: superceded by any cbe output artifact * `cTypePreferredAlignment`: no uses, if brought back, cbe should be updated to verify `__alignof` Closes #19991 Closes #20881 Closes #35523 --- lib/compiler/test_runner.zig | 1 + lib/std/Io/Semaphore.zig | 2 - lib/std/Io/Writer.zig | 6 +- lib/std/Random/RomuTrio.zig | 1 - lib/std/Random/Xoshiro256.zig | 2 - lib/std/Target.zig | 114 - lib/std/bit_set.zig | 2 - lib/std/crypto/aes.zig | 4 +- lib/std/crypto/aes_ocb.zig | 10 - lib/std/crypto/ecdsa.zig | 21 - lib/std/crypto/ff.zig | 4 - lib/std/crypto/pcurves/p384.zig | 10 +- lib/std/crypto/pcurves/secp256k1.zig | 12 +- lib/std/debug/cpu_context.zig | 2 + lib/std/fmt.zig | 2 - lib/std/fmt/float.zig | 2 +- lib/std/fs/test.zig | 5 +- lib/std/hash/auto_hash.zig | 2 +- lib/std/hash/xxhash.zig | 4 - lib/std/math.zig | 3 +- lib/std/math/big/int_test.zig | 39 +- lib/std/math/log10.zig | 5 - lib/std/math/signbit.zig | 1 + lib/std/mem.zig | 88 +- lib/std/os/linux/aarch64.zig | 2 +- lib/std/os/linux/s390x.zig | 36 +- lib/std/testing/Smith.zig | 2 +- lib/std/zon/parse.zig | 7 +- lib/std/zon/stringify.zig | 3 - lib/zig.h | 3933 +++++++++++++++----- src/codegen/c.zig | 1207 +++--- src/codegen/c/type/render_defs.zig | 182 +- src/link.zig | 2 +- src/link/C.zig | 49 +- test/behavior/abs.zig | 2 - test/behavior/align.zig | 2 - test/behavior/basic.zig | 1 - test/behavior/bit_shifting.zig | 1 - test/behavior/bitcast.zig | 7 +- test/behavior/cast.zig | 11 +- test/behavior/cast_int.zig | 1 - test/behavior/eval.zig | 1 - test/behavior/extern.zig | 1 - test/behavior/field_parent_ptr.zig | 2 - test/behavior/floatop.zig | 8 - test/behavior/fn.zig | 1 - test/behavior/math.zig | 29 - test/behavior/maximum_minimum.zig | 1 - test/behavior/muladd.zig | 4 - test/behavior/packed-struct.zig | 4 - test/behavior/pointers.zig | 2 +- test/behavior/saturating_arithmetic.zig | 7 - test/behavior/struct.zig | 8 +- test/behavior/switch_loop.zig | 3 +- test/behavior/truncate.zig | 1 - test/behavior/union.zig | 6 - test/behavior/vector.zig | 5 - test/standalone/build.zig | 1 - test/tests.zig | 64 +- tools/generate_c_size_and_align_checks.zig | 62 - 60 files changed, 3993 insertions(+), 2007 deletions(-) delete mode 100644 tools/generate_c_size_and_align_checks.zig diff --git a/lib/compiler/test_runner.zig b/lib/compiler/test_runner.zig index 62c09fe22800abc8aeb462dbd8c8beffe0ef7925..4e9502656c56f1e8cc43a03529d5d2599abbace5 100644 --- a/lib/compiler/test_runner.zig +++ b/lib/compiler/test_runner.zig @@ -377,6 +377,7 @@ pub fn mainSimple() anyerror!void { else => false, }; + testing.allocator_instance = .init(std.heap.page_allocator, .{}); testing.io_instance = .init(testing.allocator, .{}); var passed: u64 = 0; diff --git a/lib/std/Io/Semaphore.zig b/lib/std/Io/Semaphore.zig index 1f486750487ed8cd66c39306998d7434e8cd4df7..8f2137b80220fa26c19173d8a3db1098eb24f570 100644 --- a/lib/std/Io/Semaphore.zig +++ b/lib/std/Io/Semaphore.zig @@ -4,8 +4,6 @@ //! This API supports static initialization and does not require deinitialization. const Semaphore = @This(); -const builtin = @import("builtin"); - const std = @import("../std.zig"); const Io = std.Io; const testing = std.testing; diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig index ca9564edff39fe329f5114aa2a2fba41c4a6fe02..c243c8551f4917ef210159743f0d55ba749d1e6a 100644 --- a/lib/std/Io/Writer.zig +++ b/lib/std/Io/Writer.zig @@ -874,7 +874,7 @@ pub fn splatBytes(w: *Writer, bytes: []const u8, n: usize) Error!usize { } /// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes. -pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { +pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.lang.Endian) Error!void { var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined; std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); return w.writeAll(&bytes); @@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built /// The function is inline to avoid the dead code in case `endian` is /// comptime-known and matches host endianness. -pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void { +pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.lang.Endian) Error!void { switch (@typeInfo(@TypeOf(value))) { .@"struct" => |info| switch (info.layout) { .auto => @compileError("ill-defined memory layout"), @@ -907,7 +907,7 @@ pub inline fn writeSliceEndian( w: *Writer, Elem: type, slice: []const Elem, - endian: std.builtin.Endian, + endian: std.lang.Endian, ) Error!void { switch (@typeInfo(Elem)) { .@"struct" => |info| comptime assert(info.layout != .auto), diff --git a/lib/std/Random/RomuTrio.zig b/lib/std/Random/RomuTrio.zig index 9f005bf2f9fac8082eb4e71355dc90c73280d2b9..7352308f0d18eb6ccbe0b506bdfd4138443c89de 100644 --- a/lib/std/Random/RomuTrio.zig +++ b/lib/std/Random/RomuTrio.zig @@ -122,7 +122,6 @@ test fill { } test "buf seeding test" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 }); const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 }; var r = RomuTrio.init(0); diff --git a/lib/std/Random/Xoshiro256.zig b/lib/std/Random/Xoshiro256.zig index 6cb0583d982622b3f7df21b94368b03ddeb80c17..9c1ea9cfec6843cf2b9151ac08cb44aebd810936 100644 --- a/lib/std/Random/Xoshiro256.zig +++ b/lib/std/Random/Xoshiro256.zig @@ -89,8 +89,6 @@ pub fn fill(self: *Xoshiro256, buf: []u8) void { } test "sequence" { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - var r = Xoshiro256.init(0); const seq1 = [_]u64{ diff --git a/lib/std/Target.zig b/lib/std/Target.zig index 6124ffd96597d33dbd1027ae8b5757989b536c7a..5dc5075bada694841849a65904acdaa60471a23b 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -3575,120 +3575,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { ); } -pub fn cTypePreferredAlignment(target: *const Target, c_type: CType) u16 { - // Overrides for unusual alignments - switch (target.cpu.arch) { - .arc, .arceb => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - .avr, - .ez80, - => return 1, - .x86 => switch (target.os.tag) { - .windows, .uefi => switch (c_type) { - .longdouble => switch (target.abi) { - .gnu => return 4, - else => return 8, - }, - else => {}, - }, - else => switch (c_type) { - .longdouble => return 4, - else => {}, - }, - }, - .m68k => switch (c_type) { - .int, .uint, .long, .ulong => return 2, - else => {}, - }, - .wasm32, .wasm64 => switch (target.os.tag) { - .emscripten => switch (c_type) { - .longdouble => return 8, - else => {}, - }, - else => {}, - }, - else => {}, - } - - // Next-power-of-two-aligned, up to a maximum. - return @min( - std.math.ceilPowerOfTwoAssert(u16, (cTypeBitSize(target, c_type) + 7) / 8), - @as(u16, switch (target.cpu.arch) { - .x86_16, - .msp430, - => 2, - - .arc, - .arceb, - .csky, - .kalimba, - .microblaze, - .microblazeel, - .or1k, - .propeller, - .sh, - .sheb, - .xcore, - .xtensa, - .xtensaeb, - => 4, - - .amdgcn, - .arm, - .armeb, - .bpfeb, - .bpfel, - .hexagon, - .hppa, - .lanai, - .m68k, - .m88k, - .mips, - .mipsel, - .nvptx, - .nvptx64, - .s390x, - .sparc, - .thumb, - .thumbeb, - .x86, - => 8, - - .aarch64, - .aarch64_be, - .alpha, - .hppa64, - .kvx, - .loongarch32, - .loongarch64, - .mips64, - .mips64el, - .powerpc, - .powerpcle, - .powerpc64, - .powerpc64le, - .riscv32, - .riscv32be, - .riscv64, - .riscv64be, - .sparc64, - .spirv32, - .spirv64, - .ve, - .wasm32, - .wasm64, - .x86_64, - => 16, - - .avr, - .ez80, - => unreachable, // Handled above. - }), - ); -} - pub fn cMaxIntAlignment(target: *const Target) u16 { return switch (target.cpu.arch) { .avr, diff --git a/lib/std/bit_set.zig b/lib/std/bit_set.zig index b7920e20124d4e04f78662a14861ed7f9f6ae711..1a31e3b1a50b55cb8f26aa63789c1a04e9f6bc84 100644 --- a/lib/std/bit_set.zig +++ b/lib/std/bit_set.zig @@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void { } test Integer { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - try testStaticBitSet(Integer(0)); try testStaticBitSet(Integer(1)); try testStaticBitSet(Integer(2)); diff --git a/lib/std/crypto/aes.zig b/lib/std/crypto/aes.zig index acf3a72e1fd2616a6074f896c3cf53da02364c48..54d1bd0dc8474d9eb299ca823864fdc9a1a001ea 100644 --- a/lib/std/crypto/aes.zig +++ b/lib/std/crypto/aes.zig @@ -6,9 +6,9 @@ const has_aesni = builtin.cpu.has(.x86, .aes); const has_avx = builtin.cpu.has(.x86, .avx); const has_armaes = builtin.cpu.has(.aarch64, .aes); // C backend doesn't currently support passing vectors to inline asm. -const impl = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c and has_aesni and has_avx) impl: { +const impl = if (builtin.cpu.arch == .x86_64 and has_aesni and has_avx) impl: { break :impl @import("aes/aesni.zig"); -} else if (builtin.cpu.arch == .aarch64 and builtin.zig_backend != .stage2_c and has_armaes) impl: { +} else if (builtin.cpu.arch == .aarch64 and (builtin.zig_backend != .stage2_c or !builtin.os.tag.isDarwin()) and has_armaes) impl: { break :impl @import("aes/armcrypto.zig"); } else impl: { break :impl @import("aes/soft.zig"); diff --git a/lib/std/crypto/aes_ocb.zig b/lib/std/crypto/aes_ocb.zig index 36e2aaa84cbb852ab0dc8b20ccf4aca8ecfea710..5c3af0615112822c58c892fa373150e23050dfcc 100644 --- a/lib/std/crypto/aes_ocb.zig +++ b/lib/std/crypto/aes_ocb.zig @@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes; const testing = std.testing; test "AesOcb test vector 1" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -281,8 +279,6 @@ test "AesOcb test vector 1" { } test "AesOcb test vector 2" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -303,8 +299,6 @@ test "AesOcb test vector 2" { } test "AesOcb test vector 3" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -329,8 +323,6 @@ test "AesOcb test vector 3" { } test "AesOcb test vector 4" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; @@ -356,8 +348,6 @@ test "AesOcb test vector 4" { } test "AesOcb in-place encryption-decryption" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var k: [Aes128Ocb.key_length]u8 = undefined; var nonce: [Aes128Ocb.nonce_length]u8 = undefined; var tag: [Aes128Ocb.tag_length]u8 = undefined; diff --git a/lib/std/crypto/ecdsa.zig b/lib/std/crypto/ecdsa.zig index b111b8e52a706b7b869a8091747934291912eff6..8977851b44ea04596ff686ec46fa576aa9b9693f 100644 --- a/lib/std/crypto/ecdsa.zig +++ b/lib/std/crypto/ecdsa.zig @@ -1,4 +1,3 @@ -const builtin = @import("builtin"); const std = @import("std"); const crypto = std.crypto; const fmt = std.fmt; @@ -415,8 +414,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { } test "Basic operations over EcdsaP384Sha384" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP384Sha384; const kp = Scheme.KeyPair.generate(io); @@ -432,8 +429,6 @@ test "Basic operations over EcdsaP384Sha384" { } test "Basic operations over Secp256k1" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaSecp256k1Sha256oSha256; const kp = Scheme.KeyPair.generate(io); @@ -449,8 +444,6 @@ test "Basic operations over Secp256k1" { } test "Basic operations over EcdsaP384Sha256" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); const kp = Scheme.KeyPair.generate(io); @@ -466,8 +459,6 @@ test "Basic operations over EcdsaP384Sha256" { } test "Verifying a existing signature with EcdsaP384Sha256" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); // zig fmt: off const sk_bytes = [_]u8{ @@ -503,8 +494,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" { } test "Prehashed message operations" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP256Sha256; @@ -539,8 +528,6 @@ const TestVector = struct { }; test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // well-formed DER encoding -> expected valid .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" }, @@ -711,8 +698,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { } test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // S encoded with negative sign -> expected invalid .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" }, @@ -1026,8 +1011,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { } test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" }, @@ -1243,8 +1226,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { } test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const vectors: []const TestVector = &.{ // S encoded with negative sign -> expected invalid .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" }, @@ -1631,8 +1612,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void { } test "Sec1 encoding/decoding" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const io = testing.io; const Scheme = EcdsaP384Sha384; const kp = Scheme.KeyPair.generate(io); diff --git a/lib/std/crypto/ff.zig b/lib/std/crypto/ff.zig index bf9584dfa3ad033652130705937972171370669c..c59dc92c61d66a457aabd11175f9ee0c5f83e582 100644 --- a/lib/std/crypto/ff.zig +++ b/lib/std/crypto/ff.zig @@ -966,8 +966,6 @@ const ct_unprotected = struct { }; test "finite field arithmetic" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const M = Modulus(256); const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233); var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733); @@ -1066,8 +1064,6 @@ test "finite field arithmetic" { } fn testCt(ct_: anytype) !void { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const l0: Limb = 0; const l1: Limb = 1; try testing.expectEqual(l1, ct_.select(true, l1, l0)); diff --git a/lib/std/crypto/pcurves/p384.zig b/lib/std/crypto/pcurves/p384.zig index 8bc0ec36f2d64e3c6d73e5d782b6df143c6a859f..7b97bf92b1b5ab138659e1348822d06885017fc5 100644 --- a/lib/std/crypto/pcurves/p384.zig +++ b/lib/std/crypto/pcurves/p384.zig @@ -56,7 +56,7 @@ pub const P384 = struct { } /// Create a point from serialized affine coordinates. - pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!P384 { + pub fn fromSerializedAffineCoordinates(xs: [48]u8, ys: [48]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!P384 { const x = try Fe.fromBytes(xs, endian); const y = try Fe.fromBytes(ys, endian); return fromAffineCoordinates(.{ .x = x, .y = y }); @@ -395,7 +395,7 @@ pub const P384 = struct { /// Multiply an elliptic curve point by a scalar. /// Return error.IdentityElement if the result is the identity element. - pub fn mul(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mul(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, false); @@ -407,7 +407,7 @@ pub const P384 = struct { /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulPublic(p: P384, s_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mulPublic(p: P384, s_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, true); @@ -419,7 +419,7 @@ pub const P384 = struct { /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.builtin.Endian) IdentityElementError!P384 { + pub fn mulDoubleBasePublic(p1: P384, s1_: [48]u8, p2: P384, s2_: [48]u8, endian: std.lang.Endian) IdentityElementError!P384 { const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); try p1.rejectIdentity(); @@ -478,7 +478,5 @@ pub const AffineCoordinates = struct { }; test { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - _ = @import("tests/p384.zig"); } diff --git a/lib/std/crypto/pcurves/secp256k1.zig b/lib/std/crypto/pcurves/secp256k1.zig index 9ce8b944ebbffc071bcdd3be90fa47463525289e..3c36b9b2ed49d45dc1a13c0d9aab2a69d6dd3398 100644 --- a/lib/std/crypto/pcurves/secp256k1.zig +++ b/lib/std/crypto/pcurves/secp256k1.zig @@ -51,7 +51,7 @@ pub const Secp256k1 = struct { }; /// Compute r1 and r2 so that k = r1 + r2*lambda (mod L). - pub fn splitScalar(s: [32]u8, endian: std.builtin.Endian) NonCanonicalError!SplitScalar { + pub fn splitScalar(s: [32]u8, endian: std.lang.Endian) NonCanonicalError!SplitScalar { const b1_neg_s = comptime s: { var buf: [32]u8 = undefined; mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little); @@ -109,7 +109,7 @@ pub const Secp256k1 = struct { } /// Create a point from serialized affine coordinates. - pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.builtin.Endian) (NonCanonicalError || EncodingError)!Secp256k1 { + pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: std.lang.Endian) (NonCanonicalError || EncodingError)!Secp256k1 { const x = try Fe.fromBytes(xs, endian); const y = try Fe.fromBytes(ys, endian); return fromAffineCoordinates(.{ .x = x, .y = y }); @@ -423,7 +423,7 @@ pub const Secp256k1 = struct { /// Multiply an elliptic curve point by a scalar. /// Return error.IdentityElement if the result is the identity element. - pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + pub fn mul(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); if (p.is_base) { return pcMul16(&basePointPc, s, false); @@ -435,7 +435,7 @@ pub const Secp256k1 = struct { /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.builtin.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 { + pub fn mulPublic(p: Secp256k1, s_: [32]u8, endian: std.lang.Endian) (IdentityElementError || NonCanonicalError)!Secp256k1 { const s = if (endian == .little) s_ else Fe.orderSwap(s_); const zero = comptime scalar.Scalar.zero.toBytes(.little); if (mem.eql(u8, &zero, &s)) { @@ -497,7 +497,7 @@ pub const Secp256k1 = struct { /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* /// This can be used for signature verification. - pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.builtin.Endian) IdentityElementError!Secp256k1 { + pub fn mulDoubleBasePublic(p1: Secp256k1, s1_: [32]u8, p2: Secp256k1, s2_: [32]u8, endian: std.lang.Endian) IdentityElementError!Secp256k1 { const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); try p1.rejectIdentity(); @@ -556,7 +556,5 @@ pub const AffineCoordinates = struct { }; test { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - _ = @import("tests/secp256k1.zig"); } diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 36be9fe60e0ebe084ab2e045702bc91628ff9bf6..ab90b9b2c27e374ef56148334eb83fcc13d6ba75 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) { .mips64el, .or1k, .s390x, + .sh, + .sheb, .x86, .x86_64, .xtensa, diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 7cdc44269cdc95b492eb8ac718a53d7fe721af55..0c3dba4a7a95ff9a68f8d9f64d082c35565134a7 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1082,8 +1082,6 @@ test "float.libc.sanity" { } test "union" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const TU = union(enum) { float: f32, int: u32, diff --git a/lib/std/fmt/float.zig b/lib/std/fmt/float.zig index 25bf97f22ae52df136be9dbbdeab2e0fdedfdc18..e055959825832e1889d6d2c0fb6cfd131d06d50b 100644 --- a/lib/std/fmt/float.zig +++ b/lib/std/fmt/float.zig @@ -65,7 +65,7 @@ pub fn render(buf: []u8, value: anytype, options: Options) Error![]const u8 { const DT = if (@bitSizeOf(T) <= 64) u64 else u128; const tables = switch (DT) { - u64 => if (@import("builtin").mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull, + u64 => if (builtin.mode == .small) &Backend64_TablesSmall else &Backend64_TablesFull, u128 => &Backend128_Tables, else => unreachable, }; diff --git a/lib/std/fs/test.zig b/lib/std/fs/test.zig index fc613ccdaa313d46dab643f849149293f422a9a5..e9c2d5f8f8e167b7556ec5eaec20d994cc2f5d73 100644 --- a/lib/std/fs/test.zig +++ b/lib/std/fs/test.zig @@ -2205,7 +2205,7 @@ test "'.' and '..' in absolute functions" { } test "chmod" { - if (native_os == .windows or native_os == .wasi) return; + if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; const io = testing.io; @@ -2228,8 +2228,7 @@ test "chmod" { } test "change ownership" { - if (native_os == .windows or native_os == .wasi) - return error.SkipZigTest; + if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; const io = testing.io; diff --git a/lib/std/hash/auto_hash.zig b/lib/std/hash/auto_hash.zig index 3964ad5f946f899a51cbfdefb38cb42d2973b74d..1cb8e93092ec55534810432e78e896d88ffa881a 100644 --- a/lib/std/hash/auto_hash.zig +++ b/lib/std/hash/auto_hash.zig @@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 { test "typeContainsSlice" { comptime { - try testing.expect(!typeContainsSlice(std.meta.Tag(std.builtin.Type))); + try testing.expect(!typeContainsSlice(std.meta.Tag(std.lang.Type))); try testing.expect(typeContainsSlice([]const u8)); try testing.expect(!typeContainsSlice(u8)); diff --git a/lib/std/hash/xxhash.zig b/lib/std/hash/xxhash.zig index 27f2701443cc919a9cd2686165ecc8ae087ae002..72c8bff280548134abcb34a71857c7c101683dae 100644 --- a/lib/std/hash/xxhash.zig +++ b/lib/std/hash/xxhash.zig @@ -1,5 +1,4 @@ const std = @import("std"); -const builtin = @import("builtin"); const mem = std.mem; const expectEqual = std.testing.expectEqual; @@ -788,7 +787,6 @@ fn testExpect(comptime H: type, seed: anytype, input: []const u8, expected: u64) } test "xxhash3" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const H = XxHash3; // Non-Seeded Tests try testExpect(H, 0, "", 0x2d06800538d394c2); @@ -820,7 +818,6 @@ test "xxhash3" { } test "xxhash3 smhasher" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const Test = struct { fn do() !void { try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405); @@ -832,7 +829,6 @@ test "xxhash3 smhasher" { } test "xxhash3 iterative api" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const Test = struct { fn do() !void { try verify.iterativeApi(XxHash3); diff --git a/lib/std/math.zig b/lib/std/math.zig index 0beb62ae6a9eb10cdb78e887f900bebcde0612f4..ae644d6fceff795c5cb1864acada365867a19521 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { } test lerp { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isX86()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .fma)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5)); diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig index 485ae4918cce7545119b5b014f7c8133656aaf0b..271041e761a1d6f089c7733aa2964913c771dc0d 100644 --- a/lib/std/math/big/int_test.zig +++ b/lib/std/math/big/int_test.zig @@ -1,5 +1,4 @@ const std = @import("../../std.zig"); -const builtin = @import("builtin"); const mem = std.mem; const testing = std.testing; const Managed = std.math.big.int.Managed; @@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void { try expectNormalized(1 << 10, res.toConst()); } test setFloat { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - try setFloat(f16); try setFloat(f32); try setFloat(f64); @@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void { ); } test toFloat { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; try toFloat(f16); try toFloat(f32); try toFloat(f64); @@ -1391,8 +1387,6 @@ test "mul multi-single" { } test "mul multi-multi" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var op1: u256 = 0x998888efefefefefefefef; var op2: u256 = 0x333000abababababababab; _ = .{ &op1, &op2 }; @@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" { } test "mulWrap multi-multi unsigned" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var op1: u256 = 0x998888efefefefefefefef; var op2: u256 = 0x333000abababababababab; _ = .{ &op1, &op2 }; @@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" { } test "mulWrap multi-multi signed" { - switch (builtin.zig_backend) { - .stage2_c => return error.SkipZigTest, - else => {}, - } - var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1); defer a.deinit(); var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb)); @@ -1744,8 +1731,6 @@ test "div q=0 alias" { } test "div multi-multi q < r" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - const op1 = 0x1ffffffff0078f432; const op2 = 0x1ffffffff01000000; var a = try Managed.initSet(testing.allocator, op1); @@ -2166,8 +2151,6 @@ test "div ceil multi-limb" { } test "div multi-multi with rem" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); @@ -2184,8 +2167,6 @@ test "div multi-multi with rem" { } test "div multi-multi no rem" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); @@ -2202,8 +2183,6 @@ test "div multi-multi no rem" { } test "div multi-multi (2 branch)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333); @@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" { } test "div multi-multi (3.1/3.3 branch)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171); @@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" { } test "div multi-single zero-limb trailing" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x10000000000000000); @@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" { } test "div multi-multi zero-limb trailing (with rem)" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); @@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" { } test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count > divisor zero-limb count" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); @@ -2300,8 +2271,6 @@ test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count } test "div multi-multi zero-limb trailing (with rem) and dividend zero-limb count < divisor zero-limb count" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000); @@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" { } test "bitNotWrap more than two limbs" { - // This test requires int sizes greater than 128 bits. - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - var a = try Managed.initSet(testing.allocator, maxInt(Limb)); defer a.deinit(); @@ -3179,8 +3144,6 @@ test "gcd non-one large" { } test "gcd large multi-limb result" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; - var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678); defer a.deinit(); var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567); @@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" { var buffer1 = try testing.allocator.alloc(u8, 64); defer testing.allocator.free(buffer1); - const endians = [_]std.builtin.Endian{ .little, .big }; + const endians = [_]std.lang.Endian{ .little, .big }; const abi_size = 64; for (endians) |endian| { diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig index a46948cac54dddf2dd7a822a68188f219086a9af..0dc5b2a8be90cd88276ec344c9de51a492b6430a 100644 --- a/lib/std/math/log10.zig +++ b/lib/std/math/log10.zig @@ -1,5 +1,4 @@ const std = @import("../std.zig"); -const builtin = @import("builtin"); const testing = std.testing; /// Returns the base-10 logarithm of x. @@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 { } test log10_int { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - inline for ( .{ u8, u16, u32, u64, u128, u256, u512 }, .{ 2, 4, 9, 19, 38, 77, 154 }, diff --git a/lib/std/math/signbit.zig b/lib/std/math/signbit.zig index 115aaa26eb056e31c423695cd2a2cde79050d0a1..36a933e641ce35985523b25bb403f234143c20bc 100644 --- a/lib/std/math/signbit.zig +++ b/lib/std/math/signbit.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("../std.zig"); const math = std.math; const expect = std.testing.expect; diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 8353c0ca8e209dd1516371926e0fbfd00f874ded..9529f73b93586014b6338eef2ecd780461b9cd37 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -4780,62 +4780,47 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize { pub fn doNotOptimizeAway(val: anytype) void { if (@inComptime()) return; + if (builtin.zig_backend == .stage2_c and builtin.abi == .msvc) { + _ = @atomicRmw(*const anyopaque, @as(*volatile *const anyopaque, &struct { + var escape: *const anyopaque = undefined; + }.escape), .Xchg, &val, .acq_rel); // TODO: syncscope("singlethreaded") + return; + } + const max_gp_register_bits = @bitSizeOf(c_long); - const t = @typeInfo(@TypeOf(val)); - switch (t) { + switch (@typeInfo(@TypeOf(val))) { .void, .null, .comptime_int, .comptime_float => return, .@"enum" => doNotOptimizeAway(@backingInt(val)), .bool => doNotOptimizeAway(@intFromBool(val)), - .int => { - const bits = t.int.bits; - if (bits <= max_gp_register_bits and builtin.zig_backend != .stage2_c) { - const val2 = @as( - @Int(t.int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, bits))), - val, - ); - asm volatile ("" - : - : [_] "r" (val2), - ); - } else doNotOptimizeAway(&val); - }, - .float => { - if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) { - asm volatile ("" - : - : [_] "rm" (val), - ); - } else doNotOptimizeAway(&val); - }, - .pointer => { - if (builtin.zig_backend == .stage2_c) { - doNotOptimizeAwayC(val); - } else { - asm volatile ("" - : - : [_] "m" (val), - : .{ .memory = true }); - } - }, - .array => { - if (t.array.len * @sizeOf(t.array.child) <= 64) { - for (val) |v| doNotOptimizeAway(v); - } else doNotOptimizeAway(&val); + .int => |int| if (int.bits <= max_gp_register_bits) { + const val2 = @as( + @Int(int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, int.bits))), + val, + ); + asm volatile ("" + : + : [_] "r" (val2), + ); + } else doNotOptimizeAway(&val), + .float => |float| switch (float.bits) { + else => comptime unreachable, + 16, 80, 128 => doNotOptimizeAway(&val), + 32, 64 => asm volatile ("" + : + : [_] "rm" (val), + ), }, + .pointer => asm volatile ("" + : + : [_] "m" (val), + : .{ .memory = true }), + .array => |array| if (array.len * @sizeOf(array.child) <= 64) { + for (val) |v| doNotOptimizeAway(v); + } else doNotOptimizeAway(&val), else => doNotOptimizeAway(&val), } } -/// .stage2_c doesn't support asm blocks yet, so use volatile stores instead -var deopt_target: if (builtin.zig_backend == .stage2_c) u8 else void = undefined; -fn doNotOptimizeAwayC(ptr: anytype) void { - const dest = @as(*volatile u8, @ptrCast(&deopt_target)); - for (asBytes(ptr)) |b| { - dest.* = b; - } - dest.* = 0; -} - test doNotOptimizeAway { comptime doNotOptimizeAway("test"); @@ -4994,12 +4979,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice } test "read/write(Var)PackedInt" { - switch (builtin.cpu.arch) { - // This test generates too much code to execute on WASI. - // LLVM backend fails with "too many locals: locals exceed maximum" - .wasm32, .wasm64 => return error.SkipZigTest, - else => {}, - } + // This test generates too much code to execute on WASI. + // LLVM backend fails with "too many locals: locals exceed maximum" + if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; const foreign_endian: Endian = if (native_endian == .big) .little else .big; const expect = std.testing.expect; diff --git a/lib/std/os/linux/aarch64.zig b/lib/std/os/linux/aarch64.zig index a49c1d48bedd05331da4a7a25c6f1006797aa251..431097feccf104eba84a3f347fac6fe29ae1eb57 100644 --- a/lib/std/os/linux/aarch64.zig +++ b/lib/std/os/linux/aarch64.zig @@ -154,7 +154,7 @@ pub const restore = restore_rt; pub fn restore_rt() callconv(.naked) noreturn { switch (builtin.zig_backend) { .stage2_c => asm volatile ( - \\ mov x8, %[number] + \\ mov w8, %[number] \\ svc #0 : : [number] "i" (@backingInt(SYS.rt_sigreturn)), diff --git a/lib/std/os/linux/s390x.zig b/lib/std/os/linux/s390x.zig index 9b9ca0cd0327c93c1260128f42a497e8d96a3094..3c44beeb8df7bb5d7f0d7d7fb13f3c35c840da01 100644 --- a/lib/std/os/linux/s390x.zig +++ b/lib/std/os/linux/s390x.zig @@ -174,19 +174,35 @@ pub fn clone() callconv(.naked) u64 { } pub fn restore() callconv(.naked) noreturn { - asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.sigreturn)), - ); + switch (builtin.zig_backend) { + .stage2_c => asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.sigreturn)), + ), + else => asm volatile ( + \\svc 0 + : + : [number] "{r1}" (@backingInt(SYS.sigreturn)), + ), + } } pub fn restore_rt() callconv(.naked) noreturn { - asm volatile ( - \\svc 0 - : - : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), - ); + switch (builtin.zig_backend) { + .stage2_c => asm volatile ( + \\lghi %%r1, %[number] + \\svc 0 + : + : [number] "K" (@backingInt(SYS.rt_sigreturn)), + ), + else => asm volatile ( + \\svc 0 + : + : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), + ), + } } pub const time_t = i64; diff --git a/lib/std/testing/Smith.zig b/lib/std/testing/Smith.zig index 7e3235fe0e5ffd1163a2cc7bf46f7583eb0a06ae..a60a9802391078fe6ca400fb4409216bd73ff345 100644 --- a/lib/std/testing/Smith.zig +++ b/lib/std/testing/Smith.zig @@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) { } test value { - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = struct { v: void = {}, diff --git a/lib/std/zon/parse.zig b/lib/std/zon/parse.zig index b22de08eacccf9c75e24a6f32e85ce7d795e12a8..16294f3df6d763df2587b48fbb99e3b6615d478f 100644 --- a/lib/std/zon/parse.zig +++ b/lib/std/zon/parse.zig @@ -9,7 +9,6 @@ //! For lower level control over parsing, see `std.zig.Zoir`. const std = @import("std"); -const builtin = @import("builtin"); const Allocator = std.mem.Allocator; const Ast = std.zig.Ast; const Zoir = std.zig.Zoir; @@ -1868,8 +1867,6 @@ test "std.zon tuples" { // Test sizes 0 to 3 since small sizes get parsed differently test "std.zon arrays and slices" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881 - const gpa = std.testing.allocator; // Literals @@ -2802,8 +2799,6 @@ test "std.zon negative char" { } test "std.zon parse float" { - if (builtin.cpu.arch == .x86) return error.SkipZigTest; - const gpa = std.testing.allocator; // Test decimals @@ -3135,7 +3130,7 @@ test "std.zon free on error" { } test "std.zon vector" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330 + const builtin = @import("builtin"); if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957 const gpa = std.testing.allocator; diff --git a/lib/std/zon/stringify.zig b/lib/std/zon/stringify.zig index 57b62d41cac6c3f9aa0e442bd276edb33f2679c2..a1c6b39ebe25a350d08eba57008fbd3522c16f76 100644 --- a/lib/std/zon/stringify.zig +++ b/lib/std/zon/stringify.zig @@ -1151,9 +1151,6 @@ test "std.zon depth limits" { } test "std.zon stringify primitives" { - // Issue: https://github.com/ziglang/zig/issues/20880 - if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; - try expectSerializeEqual( \\.{ \\ .a = 1.5, diff --git a/lib/zig.h b/lib/zig.h index fc2f9479bea2bf9599dfcaebe35294fed98b4db4..139263d11132833d2c64539c2b39cf44b3bd0b89 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -166,6 +166,12 @@ #endif #define zig_expand_has_builtin(b) zig_has_builtin(b) +#if defined(__has_feature) +#define zig_has_feature(feature) __has_feature(feature) +#else +#define zig_has_feature(feature) 0 +#endif + #if defined(__has_attribute) #define zig_has_attribute(attribute) __has_attribute(attribute) #else @@ -175,9 +181,9 @@ #if __STDC_VERSION__ >= 201112L #define zig_static_assert(cond, msg) _Static_assert(cond, msg) #elif zig_has_attribute(unused) -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] __attribute__((unused)) +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] __attribute__((unused)) #else -#define zig_static_assert(cond, _) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[!!(cond)] +#define zig_static_assert(cond, msg) typedef char zig_expand_concat(zig_static_assert_fail_, __LINE__)[(cond) ? 1 : -1] #endif #if __STDC_VERSION__ >= 202311L @@ -267,12 +273,20 @@ #if __STDC_VERSION__ >= 202311L #define zig_align(alignment) alignas(alignment) -#elif __STDC_VERSION__ >= 201112L +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas) #define zig_align(alignment) _Alignas(alignment) #else #define zig_align(alignment) zig_under_align(alignment) #endif +#if __STDC_VERSION__ >= 202311L +#define zig_alignOf(Type) alignof(Type) +#elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignof) +#define zig_alignOf(Type) _Alignof(Type) +#else +#define zig_alignOf(Type) (sizeof(struct { char c; Type t; }) - sizeof(Type)) +#endif + #if zig_has_attribute(aligned) || defined(zig_tinyc) #define zig_align_fn(alignment) __attribute__((aligned(alignment))) #elif defined(zig_msvc) @@ -350,11 +364,9 @@ #define zig_export(symbol, name) __attribute__((alias(symbol))) #else #define zig_export(symbol, name) ; \ - __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol)) + __asm("\t.globl\t" zig_mangle_c(name) "\n" zig_mangle_c(name) " = " zig_mangle_c(symbol)) #endif -#define zig_mangled_tentative zig_mangled -#define zig_mangled_final zig_mangled #if defined(zig_msvc) #define zig_mangled(mangled, unmangled) ; \ zig_export(#mangled, unmangled) @@ -364,7 +376,7 @@ #else /* zig_msvc */ #define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled)) #define zig_mangled_export(mangled, unmangled, symbol) \ - zig_mangled_final(mangled, unmangled) \ + zig_mangled(mangled, unmangled) \ zig_export(symbol, unmangled) #endif /* zig_msvc */ @@ -550,6 +562,9 @@ #define zig_noreturn #endif +#define zig_has_always 1 +#define zig_has_never 0 + #define zig_compiler_rt_abbrev_uint32_t si #define zig_compiler_rt_abbrev_int32_t si #define zig_compiler_rt_abbrev_uint64_t di @@ -560,7 +575,11 @@ #define zig_compiler_rt_abbrev_zig_f32 sf #define zig_compiler_rt_abbrev_zig_f64 df #define zig_compiler_rt_abbrev_zig_f80 xf +#ifdef zig_powerpc +#define zig_compiler_rt_abbrev_zig_f128 kf +#else #define zig_compiler_rt_abbrev_zig_f128 tf +#endif zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); zig_extern void *memset (void *, int, size_t); @@ -645,16 +664,6 @@ typedef signed long long int16_t; #define INT16_MAX ( INT16_C(0x7FFF)) #define UINT16_MAX ( INT16_C(0xFFFF)) -#if defined(zig_ez80) -typedef unsigned int uint24_t; -typedef signed int int24_t; -#define INT24_C(c) c -#define UINT24_C(c) c##U -#endif -#define INT24_MIN (~INT24_C(0x7FFF)) -#define INT24_MAX ( INT24_C(0x7FFF)) -#define UINT24_MAX ( INT24_C(0xFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF typedef unsigned char uint32_t; typedef signed char int32_t; @@ -685,17 +694,6 @@ typedef signed long long int32_t; #define INT32_MAX ( INT32_C(0x7FFFFFFF)) #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) -#if defined(zig_ez80) -typedef unsigned __int48 uint48_t; -typedef signed __int48 int48_t; -#define INT48_C(c) c -/* no suffix */ -#define UINT48_C(c) ((uint48_t)(c)) -#endif -#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) -#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) -#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) - #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF typedef unsigned char uint64_t; typedef signed char int64_t; @@ -726,6 +724,27 @@ typedef signed long long int64_t; #define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF)) #define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF)) +#if defined(zig_ez80) + +typedef unsigned int uint24_t; +typedef signed int int24_t; +#define INT24_C(c) c +#define UINT24_C(c) c##U +#define INT24_MIN (~INT24_C(0x7FFF)) +#define INT24_MAX ( INT24_C(0x7FFF)) +#define UINT24_MAX ( INT24_C(0xFFFF)) + +typedef unsigned __int48 uint48_t; +typedef signed __int48 int48_t; +#define INT48_C(c) c +/* no suffix */ +#define UINT48_C(c) ((uint48_t)(c)) +#define INT48_MIN (~INT48_C(0x7FFFFFFFFFFF)) +#define INT48_MAX ( INT48_C(0x7FFFFFFFFFFF)) +#define UINT48_MAX ( INT48_C(0xFFFFFFFFFFFF)) + +#endif + typedef size_t uintptr_t; typedef ptrdiff_t intptr_t; @@ -739,23 +758,145 @@ typedef ptrdiff_t intptr_t; #define zig_maxInt_i16 INT16_MAX #define zig_minInt_u16 UINT16_C(0) #define zig_maxInt_u16 UINT16_MAX -#define zig_minInt_i24 INT24_MIN -#define zig_maxInt_i24 INT24_MAX -#define zig_minInt_u24 UINT24_C(0) -#define zig_maxInt_u24 UINT24_MAX #define zig_minInt_i32 INT32_MIN #define zig_maxInt_i32 INT32_MAX #define zig_minInt_u32 UINT32_C(0) #define zig_maxInt_u32 UINT32_MAX -#define zig_minInt_i48 INT48_MIN -#define zig_maxInt_i48 INT48_MAX -#define zig_minInt_u48 UINT48_C(0) -#define zig_maxInt_u48 UINT48_MAX #define zig_minInt_i64 INT64_MIN #define zig_maxInt_i64 INT64_MAX #define zig_minInt_u64 UINT64_C(0) #define zig_maxInt_u64 UINT64_MAX +// zig_promoted_T implements C integral promotions except with signedness preserved, which +// allows wrapping operations to avoid the ub that would be caused by the normal promotion. + +#if INT8_MAX <= INT_MAX +typedef unsigned int zig_promoted_i8; +#elif INT8_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i8; +#elif INT8_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i8; +#else +typedef int8_t zig_promoted_i8; +#endif +#if UINT8_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u8; +#elif UINT8_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u8; +#elif UINT8_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u8; +#else +typedef uint8_t zig_promoted_u8; +#endif + +#if INT16_MAX <= INT_MAX +typedef unsigned int zig_promoted_i16; +#elif INT16_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i16; +#elif INT16_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i16; +#else +typedef int16_t zig_promoted_i16; +#endif +#if UINT16_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u16; +#elif UINT16_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u16; +#elif UINT16_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u16; +#else +typedef uint16_t zig_promoted_u16; +#endif + +#if INT32_MAX <= INT_MAX +typedef unsigned int zig_promoted_i32; +#elif INT32_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i32; +#elif INT32_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i32; +#else +typedef int32_t zig_promoted_i32; +#endif +#if UINT32_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u32; +#elif UINT32_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u32; +#elif UINT32_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u32; +#else +typedef uint32_t zig_promoted_u32; +#endif + +#if INT64_MAX <= INT_MAX +typedef unsigned int zig_promoted_i64; +#elif INT64_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i64; +#elif INT64_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i64; +#else +typedef int64_t zig_promoted_i64; +#endif +#if UINT64_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u64; +#elif UINT64_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u64; +#elif UINT64_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u64; +#else +typedef uint64_t zig_promoted_u64; +#endif + +#ifdef zig_ez80 + +#define zig_minInt_i24 INT24_MIN +#define zig_maxInt_i24 INT24_MAX +#define zig_minInt_u24 UINT24_C(0) +#define zig_maxInt_u24 UINT24_MAX +#define zig_minInt_i48 INT48_MIN +#define zig_maxInt_i48 INT48_MAX +#define zig_minInt_u48 UINT48_C(0) +#define zig_maxInt_u48 UINT48_MAX + +#if INT24_MAX <= INT_MAX +typedef unsigned int zig_promoted_i24; +#elif INT24_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i24; +#elif INT24_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i24; +#else +typedef int24_t zig_promoted_i24; +#endif +#if UINT24_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u24; +#elif UINT24_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u24; +#elif UINT24_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u24; +#else +typedef uint24_t zig_promoted_u24; +#endif + +#if INT48_MAX <= INT_MAX +typedef unsigned int zig_promoted_i48; +#elif INT48_MAX <= LONG_MAX +typedef unsigned long zig_promoted_i48; +#elif INT48_MAX <= LLONG_MAX +typedef unsigned long long zig_promoted_i48; +#else +typedef int48_t zig_promoted_i48; +#endif +#if UINT48_MAX <= UINT_MAX +typedef unsigned int zig_promoted_u48; +#elif UINT48_MAX <= ULONG_MAX +typedef unsigned long zig_promoted_u48; +#elif UINT48_MAX <= ULLONG_MAX +typedef unsigned long long zig_promoted_u48; +#else +typedef uint48_t zig_promoted_u48; +#endif + +#endif + #define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits)) #define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits) #define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits) @@ -770,7 +911,33 @@ typedef ptrdiff_t intptr_t; zig_operator(Type, Type, operation, operator) #define zig_shift_operator(Type, operation, operator) \ zig_operator(Type, uint8_t, operation, operator) -#define zig_int_helpers(w, PromotedUnsigned) \ + +#define zig_int_casts_common(bw, sw) \ + static inline uint##bw##_t zig_u##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##bw##_t zig_u##bw##_intCast_i##sw(int##sw##_t arg) { \ + return (uint##bw##_t)arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_u##sw(uint##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline int##bw##_t zig_i##bw##_intCast_i##sw(int##sw##_t arg) { \ + return arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_truncate_u##bw(uint##bw##_t arg, uint8_t bits) { \ + return (uint##sw##_t)arg & zig_maxInt_u(sw, bits); \ + } \ +\ + static inline int##sw##_t zig_i##sw##_truncate_i##bw(int##bw##_t arg, uint8_t bits) { \ + return ((uint##sw##_t)arg & UINT##sw##_C(1) << (bits - UINT8_C(1))) != UINT##sw##_C(0) \ + ? (int##sw##_t)arg | zig_minInt_i(sw, bits) : (int##sw##_t)arg & zig_maxInt_i(sw, bits); \ + } +#define zig_int_operators(w) \ zig_basic_operator(uint##w##_t, and_u##w, &) \ zig_basic_operator( int##w##_t, and_i##w, &) \ zig_basic_operator(uint##w##_t, or_u##w, |) \ @@ -786,44 +953,48 @@ typedef ptrdiff_t intptr_t; return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \ } \ \ - static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \ - return val ^ zig_maxInt_u(w, bits); \ + static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \ + return arg ^ zig_maxInt_u(w, bits); \ } \ \ - static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \ + static inline int##w##_t zig_not_i##w(int##w##_t arg, uint8_t bits) { \ (void)bits; \ - return ~val; \ + return ~arg; \ } \ \ - static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \ - return val & zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \ - return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \ - ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \ - } \ -\ - static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \ - return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \ - } \ -\ - zig_basic_operator(uint##w##_t, div_floor_u##w, /) \ + zig_basic_operator(uint##w##_t, divFloor_u##w, /) \ \ - static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ } \ \ - static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ } \ \ - static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \ + static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \ return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ } \ \ zig_basic_operator(uint##w##_t, mod_u##w, %) \ + zig_int_casts_common(w, w) \ +\ + static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w(arg, bits); \ + } \ +\ + static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w(arg, bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_i##w##_bitCast_i##w((int##w##_t)arg, bits); \ + } \ \ static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \ int##w##_t rem = lhs % rhs; \ @@ -831,100 +1002,102 @@ typedef ptrdiff_t intptr_t; } \ \ static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \ + return zig_u##w##_truncate_u##w(zig_shl_u##w(lhs, rhs), bits); \ } \ \ static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_shl_u##w(zig_u##w##_bitCast_i##w(lhs, bits), rhs), bits); \ } \ \ static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs + rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs + rhs, bits); \ } \ \ static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_addw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs - rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs - rhs, bits); \ } \ \ static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_subw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ } \ \ static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \ + return zig_u##w##_truncate_u##w((zig_promoted_u##w)lhs * rhs, bits); \ } \ \ static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ - return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \ + return zig_i##w##_bitCast_u##w(zig_mulw_u##w(zig_u##w##_bitCast_i##w(lhs, bits), zig_u##w##_bitCast_i##w(rhs, bits), bits), bits); \ + } \ +\ + static inline uint##w##_t zig_abs_i##w(int##w##_t arg) { \ + int##w##_t tmp = zig_shr_i##w(arg, UINT8_C(w) - UINT8_C(1)); \ + return zig_u##w##_bitCast_i##w(zig_subw_i##w(zig_xor_i##w(arg, tmp), tmp, UINT8_C(w)), UINT8_C(w)); \ + } \ +\ + static inline uint##w##_t zig_min_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_min_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs < rhs ? lhs : rhs; \ + } \ +\ + static inline uint##w##_t zig_max_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ + } \ +\ + static inline int##w##_t zig_max_i##w(int##w##_t lhs, int##w##_t rhs) { \ + return lhs >= rhs ? lhs : rhs; \ } -#if UINT8_MAX <= UINT_MAX -zig_int_helpers(8, unsigned int) -#elif UINT8_MAX <= ULONG_MAX -zig_int_helpers(8, unsigned long) -#elif UINT8_MAX <= ULLONG_MAX -zig_int_helpers(8, unsigned long long) -#else -zig_int_helpers(8, uint8_t) +zig_int_operators(8) +zig_int_operators(16) +zig_int_operators(32) +zig_int_operators(64) +#ifdef zig_ez80 +zig_int_operators(24) +zig_int_operators(48) #endif -#if UINT16_MAX <= UINT_MAX -zig_int_helpers(16, unsigned int) -#elif UINT16_MAX <= ULONG_MAX -zig_int_helpers(16, unsigned long) -#elif UINT16_MAX <= ULLONG_MAX -zig_int_helpers(16, unsigned long long) -#else -zig_int_helpers(16, uint16_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(24, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(24, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(24, unsigned long long) -#else -zig_int_helpers(24, uint24_t) -#endif -#endif -#if UINT32_MAX <= UINT_MAX -zig_int_helpers(32, unsigned int) -#elif UINT32_MAX <= ULONG_MAX -zig_int_helpers(32, unsigned long) -#elif UINT32_MAX <= ULLONG_MAX -zig_int_helpers(32, unsigned long long) -#else -zig_int_helpers(32, uint32_t) -#endif -#if defined(zig_ez80) -#if UINT24_MAX <= UINT_MAX -zig_int_helpers(48, unsigned int) -#elif UINT24_MAX <= ULONG_MAX -zig_int_helpers(48, unsigned long) -#elif UINT24_MAX <= ULLONG_MAX -zig_int_helpers(48, unsigned long long) -#else -zig_int_helpers(48, uint48_t) -#endif -#endif -#if UINT64_MAX <= UINT_MAX -zig_int_helpers(64, unsigned int) -#elif UINT64_MAX <= ULONG_MAX -zig_int_helpers(64, unsigned long) -#elif UINT64_MAX <= ULLONG_MAX -zig_int_helpers(64, unsigned long long) -#else -zig_int_helpers(64, uint64_t) + +#define zig_int_casts(bw, sw) \ + static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (uint##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \ + return (int##sw##_t)arg; \ + } \ +\ + zig_int_casts_common(bw, sw) +zig_int_casts(16, 8) +zig_int_casts(32, 8) +zig_int_casts(64, 8) +zig_int_casts(32, 16) +zig_int_casts(64, 16) +zig_int_casts(64, 32) +#ifdef zig_ez80 +zig_int_casts(32, 24) +zig_int_casts(48, 24) +zig_int_casts(64, 24) +zig_int_casts(64, 48) #endif static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_addw_u32(lhs, rhs, bits); @@ -936,19 +1109,19 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i32(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_addw_u64(lhs, rhs, bits); @@ -960,24 +1133,24 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs); - bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; + *res = zig_addw_i64(lhs, rhs, bits); + return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -986,12 +1159,12 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(add_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1000,12 +1173,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1014,27 +1187,28 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1043,28 +1217,26 @@ static inline bool zig_addo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(add_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_addo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1073,22 +1245,23 @@ static inline bool zig_addo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(add_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_addo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_subw_u32(lhs, rhs, bits); @@ -1100,20 +1273,19 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i32_truncate_i32(full_res, bits); + return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); #else - int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i32(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0); #endif - *res = zig_wrap_i32(full_res, bits); - return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } - static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_subw_u64(lhs, rhs, bits); @@ -1125,24 +1297,24 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); + *res = zig_i64_truncate_i64(full_res, bits); + return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); #else - int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs); - bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; + *res = zig_subw_i64(lhs, rhs, bits); + return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0); #endif - *res = zig_wrap_i64(full_res, bits); - return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1151,12 +1323,12 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1165,12 +1337,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1179,27 +1351,28 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1208,28 +1381,26 @@ static inline bool zig_subo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_subo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1238,22 +1409,23 @@ static inline bool zig_subo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(sub_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_subo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u32(full_res, bits); + *res = zig_u32_truncate_u32(full_res, bits); return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); #else *res = zig_mulw_u32(lhs, rhs, bits); @@ -1261,8 +1433,8 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 #endif } -zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { + zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1271,7 +1443,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t int32_t full_res = __mulosi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i32(full_res, bits); + *res = zig_i32_truncate_i32(full_res, bits); return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); } @@ -1279,7 +1451,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u64(full_res, bits); + *res = zig_u64_truncate_u64(full_res, bits); return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); #else *res = zig_mulw_u64(lhs, rhs, bits); @@ -1287,8 +1459,8 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 #endif } -zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { + zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -1297,7 +1469,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t int64_t full_res = __mulodi4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i64(full_res, bits); + *res = zig_i64_truncate_i64(full_res, bits); return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); } @@ -1305,12 +1477,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u8(full_res, bits); + *res = zig_u8_truncate_u8(full_res, bits); return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint8_t)full_res; + *res = zig_u8_intCast_u32(full_res); return overflow; #endif } @@ -1319,12 +1491,12 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i8(full_res, bits); + *res = zig_i8_truncate_i8(full_res, bits); return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int8_t)full_res; + *res = zig_i8_intCast_i32(full_res); return overflow; #endif } @@ -1333,12 +1505,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u16(full_res, bits); + *res = zig_u16_truncate_u16(full_res, bits); return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint16_t)full_res; + *res = zig_u16_intCast_u32(full_res); return overflow; #endif } @@ -1347,27 +1519,28 @@ static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i16(full_res, bits); + *res = zig_i16_truncate_i16(full_res, bits); return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int16_t)full_res; + *res = zig_i16_intCast_i32(full_res); return overflow; #endif } #if defined(zig_ez80) + static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u24(full_res, bits); + *res = zig_u24_truncate_u24(full_res, bits); return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); #else uint32_t full_res; bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits); - *res = (uint24_t)full_res; + *res = zig_u24_intCast_u32(full_res); return overflow; #endif } @@ -1376,28 +1549,26 @@ static inline bool zig_mulo_i24(int24_t *res, int24_t lhs, int24_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int24_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i24(full_res, bits); + *res = zig_i24_truncate_i24(full_res, bits); return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); #else int32_t full_res; bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits); - *res = (int24_t)full_res; + *res = zig_i24_intCast_i32(full_res); return overflow; #endif } -#endif -#if defined(zig_ez80) static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { #if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u48(full_res, bits); + *res = zig_u48_truncate_u48(full_res, bits); return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); #else uint64_t full_res; bool overflow = zig_mulo_u64(&full_res, lhs, rhs, bits); - *res = (uint48_t)full_res; + *res = zig_u48_intCast_u64(full_res); return overflow; #endif } @@ -1406,18 +1577,32 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t #if zig_has_builtin(mul_overflow) || defined(zig_gcc) int48_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_i48(full_res, bits); + *res = zig_i48_truncate_i48(full_res, bits); return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); #else int64_t full_res; bool overflow = zig_mulo_i64(&full_res, lhs, rhs, bits); - *res = (int48_t)full_res; + *res = zig_i48_intCast_i64(full_res); return overflow; #endif } + #endif -#define zig_int_builtins(w) \ +#define zig_shls_builtins(lw, rw) \ + static inline uint##lw##_t zig_shls_u##lw##_u##rw(uint##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + uint##lw##_t res; \ + if (rhs < bits && !zig_shlo_u##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? zig_minInt_u(lw, bits) : zig_maxInt_u(lw, bits); \ + } \ +\ + static inline int##lw##_t zig_shls_i##lw##_u##rw(int##lw##_t lhs, uint##rw##_t rhs, uint8_t bits) { \ + int##lw##_t res; \ + if (rhs < bits && !zig_shlo_i##lw(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + return lhs == INT##lw##_C(0) ? INT##lw##_C(0) : \ + lhs < INT##lw##_C(0) ? zig_minInt_i(lw, bits) : zig_maxInt_i(lw, bits); \ + } +#define zig_int_sat_builtins(w) \ static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ *res = zig_shlw_u##w(lhs, rhs, bits); \ return lhs > zig_maxInt_u(w, bits) >> rhs; \ @@ -1429,18 +1614,10 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \ } \ \ - static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - uint##w##_t res; \ - if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ - } \ -\ - static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - int##w##_t res; \ - if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ - return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ - lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ - } \ + zig_shls_builtins(w, 8) \ + zig_shls_builtins(w, 16) \ + zig_shls_builtins(w, 32) \ + zig_shls_builtins(w, 64) \ \ static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ uint##w##_t res; \ @@ -1474,332 +1651,321 @@ static inline bool zig_mulo_i48(int48_t *res, int48_t lhs, int48_t rhs, uint8_t if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \ return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ } -zig_int_builtins(8) -zig_int_builtins(16) +zig_int_sat_builtins(8) +zig_int_sat_builtins(16) +zig_int_sat_builtins(32) +zig_int_sat_builtins(64) #if defined(zig_ez80) -zig_int_builtins(24) +zig_int_sat_builtins(24) +zig_int_sat_builtins(48) #endif -zig_int_builtins(32) -#if defined(zig_ez80) -zig_int_builtins(48) -#endif -zig_int_builtins(64) -#define zig_builtin8(name, val) __builtin_##name(val) +#define zig_builtin8(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin8; -#define zig_builtin16(name, val) __builtin_##name(val) +#define zig_builtin16(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin16; -#if defined(zig_ez80) -#define zig_builtin24(name, val) __builtin_##name(val) -typedef unsigned int zig_Builtin24; -#endif - #if INT_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name(val) +#define zig_builtin32(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin32; #elif LONG_MIN <= INT32_MIN -#define zig_builtin32(name, val) __builtin_##name##l(val) +#define zig_builtin32(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin32; #endif -#if defined(zig_ez80) -#define zig_builtin48(name, val) __builtin_##name(val) -typedef unsigned long long zig_Builtin48; -#endif - #if INT_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name(val) +#define zig_builtin64(name, arg) __builtin_##name(arg) typedef unsigned int zig_Builtin64; #elif LONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##l(val) +#define zig_builtin64(name, arg) __builtin_##name##l(arg) typedef unsigned long zig_Builtin64; #elif LLONG_MIN <= INT64_MIN -#define zig_builtin64(name, val) __builtin_##name##ll(val) +#define zig_builtin64(name, arg) __builtin_##name##ll(arg) typedef unsigned long long zig_Builtin64; #endif -static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { - return zig_wrap_u8(val >> (8 - bits), bits); +#if defined(zig_ez80) +#define zig_builtin24(name, arg) __builtin_##name(arg) +typedef unsigned int zig_Builtin24; +#define zig_builtin48(name, arg) __builtin_##name(arg) +typedef unsigned long long zig_Builtin48; +#endif + +static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) { + return zig_u8_truncate_u8(arg >> (8 - bits), bits); } -static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits); +static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bswap16) || defined(zig_gcc) - full_res = __builtin_bswap16(val); + full_res = __builtin_bswap16(arg); #else - full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); +static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { +static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bswap24) || defined(zig_gcc) - full_res = __builtin_bswap24(val); + full_res = __builtin_bswap24(arg); #else - full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); +static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bswap32) || defined(zig_gcc) - full_res = __builtin_bswap32(val); + full_res = __builtin_bswap32(arg); #else - full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); +static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bswap48) || defined(zig_gcc) - full_res = __builtin_bswap48(val); + full_res = __builtin_bswap48(arg); #else - full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u48(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); +static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bswap64) || defined(zig_gcc) - full_res = __builtin_bswap64(val); + full_res = __builtin_bswap64(arg); #else - full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits); +static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits); } -static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) { +static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) { uint8_t full_res; #if zig_has_builtin(bitreverse8) - full_res = __builtin_bitreverse8(val); + full_res = __builtin_bitreverse8(arg); #else static uint8_t const lut[0x10] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; - full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0; + full_res = lut[arg >> 0 & 0xF] << 4 | lut[arg >> 4 & 0xF] << 0; #endif - return zig_wrap_u8(full_res >> (8 - bits), bits); + return zig_u8_truncate_u8(full_res >> (8 - bits), bits); } -static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) { - return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits); +static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) { + return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits); } -static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) { +static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) { uint16_t full_res; #if zig_has_builtin(bitreverse16) - full_res = __builtin_bitreverse16(val); + full_res = __builtin_bitreverse16(arg); #else - full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 | - (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0; + full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 | + (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0; #endif - return zig_wrap_u16(full_res >> (16 - bits), bits); + return zig_u16_truncate_u16(full_res >> (16 - bits), bits); } -static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { - return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); +static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) { + return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { +static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) { uint24_t full_res; #if zig_has_builtin(bitreverse24) - full_res = __builtin_bitreverse24(val); + full_res = __builtin_bitreverse24(arg); #else - full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | - (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; + full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 | + (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0; #endif - return zig_wrap_u24(full_res >> (24 - bits), bits); + return zig_u24_truncate_u24(full_res >> (24 - bits), bits); } -static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { - return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); +static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) { + return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits); } #endif -static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) { uint32_t full_res; #if zig_has_builtin(bitreverse32) - full_res = __builtin_bitreverse32(val); + full_res = __builtin_bitreverse32(arg); #else - full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 | - (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0; + full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 | + (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0; #endif - return zig_wrap_u32(full_res >> (32 - bits), bits); + return zig_u32_truncate_u32(full_res >> (32 - bits), bits); } -static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { - return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); +static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) { + return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits); } #if defined(zig_ez80) -static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { +static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) { uint48_t full_res; #if zig_has_builtin(bitreverse48) - full_res = __builtin_bitreverse48(val); + full_res = __builtin_bitreverse48(arg); #else - full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | - (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; + full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 | + (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0; #endif - return zig_wrap_u32(full_res >> (48 - bits), bits); + return zig_u48_truncate_u48(full_res >> (48 - bits), bits); } -static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { - return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); +static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) { + return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits); } #endif -static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { +static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) { uint64_t full_res; #if zig_has_builtin(bitreverse64) - full_res = __builtin_bitreverse64(val); + full_res = __builtin_bitreverse64(arg); #else - full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 | - (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0; + full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 | + (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0; #endif - return zig_wrap_u64(full_res >> (64 - bits), bits); + return zig_u64_truncate_u64(full_res >> (64 - bits), bits); } -static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { - return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits); +static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) { + return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits); } -#define zig_builtin_popcount_common(w) \ - static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w((uint##w##_t)val, bits); \ +#define zig_builtin_popCount_common(w) \ + static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w((uint##w##_t)arg, bits); \ } -#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc) +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - return zig_builtin##w(popcount, val); \ + return zig_builtin##w(popcount, arg); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #else -#define zig_builtin_popcount(w) \ - static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ +#define zig_builtin_popCount(w) \ + static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ (void)bits; \ - uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \ + uint##w##_t temp = arg - ((arg >> 1) & (UINT##w##_MAX / 3)); \ temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \ temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \ return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \ } \ \ - zig_builtin_popcount_common(w) + zig_builtin_popCount_common(w) #endif -zig_builtin_popcount(8) -zig_builtin_popcount(16) +zig_builtin_popCount(8) +zig_builtin_popCount(16) +zig_builtin_popCount(32) +zig_builtin_popCount(64) #if defined(zig_ez80) -zig_builtin_popcount(24) +zig_builtin_popCount(24) +zig_builtin_popCount(48) #endif -zig_builtin_popcount(32) -#if defined(zig_ez80) -zig_builtin_popcount(48) -#endif -zig_builtin_popcount(64) #define zig_builtin_ctz_common(w) \ - static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(ctz, val); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(ctz, arg); \ } \ \ zig_builtin_ctz_common(w) #else #define zig_builtin_ctz(w) \ - static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \ + static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \ } \ \ zig_builtin_ctz_common(w) #endif zig_builtin_ctz(8) zig_builtin_ctz(16) -#if defined(zig_ez80) -zig_builtin_ctz(24) -#endif zig_builtin_ctz(32) -#if defined(zig_ez80) -zig_builtin_ctz(48) -#endif zig_builtin_ctz(64) +#if defined(zig_ez80) +zig_builtin_ctz(24) +zig_builtin_ctz(48) +#endif #define zig_builtin_clz_common(w) \ - static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ - return zig_clz_u##w((uint##w##_t)val, bits); \ + static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \ + return zig_clz_u##w((uint##w##_t)arg, bits); \ } #if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - if (val == 0) return bits; \ - return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + if (arg == 0) return bits; \ + return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ } \ \ zig_builtin_clz_common(w) #else #define zig_builtin_clz(w) \ - static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ - return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \ + static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ + return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \ } \ \ zig_builtin_clz_common(w) #endif zig_builtin_clz(8) zig_builtin_clz(16) -#if defined(zig_ez80) -zig_builtin_clz(24) -#endif zig_builtin_clz(32) -#if defined(zig_ez80) -zig_builtin_clz(48) -#endif zig_builtin_clz(64) +#if defined(zig_ez80) +zig_builtin_clz(24) +zig_builtin_clz(48) +#endif /* ======================== 128-bit Integer Support ========================= */ @@ -1816,16 +1982,14 @@ zig_builtin_clz(64) typedef unsigned __int128 zig_u128; typedef signed __int128 zig_i128; -#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) -#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#define zig_hi_u128(val) ((uint64_t)((val) >> 64)) -#define zig_lo_u128(val) ((uint64_t)((val) >> 0)) -#define zig_hi_i128(val) (( int64_t)((val) >> 64)) -#define zig_lo_i128(val) ((uint64_t)((val) >> 0)) -#define zig_bitCast_u128(val) ((zig_u128)(val)) -#define zig_bitCast_i128(val) ((zig_i128)(val)) +#define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) +#define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) +#define zig_make_u128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) zig_init_i128(hi, lo) +#define zig_hi_u128(arg) ((uint64_t)((arg) >> 64)) +#define zig_lo_u128(arg) ((uint64_t)((arg) >> 0)) +#define zig_hi_i128(arg) (( int64_t)((arg) >> 64)) +#define zig_lo_i128(arg) ((uint64_t)((arg) >> 0)) #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs > rhs) - (lhs < rhs); \ @@ -1835,32 +1999,49 @@ typedef signed __int128 zig_i128; return lhs operator rhs; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + return lhs >> rhs; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + return lhs << rhs; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + // This works around a GCC miscompilation, but it has the side benefit of + // emitting better code. It is behind the `#if` because it depends on + // arithmetic right shift, which is implementation-defined in C, but should + // be guaranteed on any GCC-compatible compiler. +#if defined(zig_gnuc) + return lhs >> rhs; +#else + zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); + return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; +#endif +} + #else /* zig_has_int128 */ #if zig_little_endian -typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; -typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128; #else -typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128; -typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128; +typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128; #endif -#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) -#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) - -#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */ -#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } -#else /* But non-MSVC doesn't like the unprotected commas */ -#define zig_init_u128(hi, lo) zig_make_u128(hi, lo) -#define zig_init_i128(hi, lo) zig_make_i128(hi, lo) -#endif -#define zig_hi_u128(val) ((val).hi) -#define zig_lo_u128(val) ((val).lo) -#define zig_hi_i128(val) ((val).hi) -#define zig_lo_i128(val) ((val).lo) -#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo) -#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo) +#define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo) +#define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo) +#define zig_hi_u128(arg) (arg).hi +#define zig_lo_u128(arg) (arg).lo +#define zig_hi_i128(arg) (arg).hi +#define zig_lo_i128(arg) (arg).lo #define zig_cmp_int128(Type) \ static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ return (lhs.hi == rhs.hi) \ @@ -1872,6 +2053,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \ } +static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; + return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; +} + +static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; + return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +} + +static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { + if (rhs == UINT8_C(0)) return lhs; + 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))) }; + return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; +} + #endif /* zig_has_int128 */ #define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64) @@ -1891,42 +2096,177 @@ zig_bit_int128(i128, or, |) zig_bit_int128(u128, xor, ^) zig_bit_int128(i128, xor, ^) -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs); +static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) { + return (uint8_t)zig_lo_u128(arg); +} +static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) { + return (uint8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_i128(zig_i128 arg) { + return (int8_t)zig_lo_i128(arg); +} +static inline int8_t zig_i8_intCast_u128(zig_u128 arg) { + return (int8_t)zig_lo_u128(arg); +} -#if zig_has_int128 +static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) { + return (uint16_t)zig_lo_u128(arg); +} +static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) { + return (uint16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_i128(zig_i128 arg) { + return (int16_t)zig_lo_i128(arg); +} +static inline int16_t zig_i16_intCast_u128(zig_u128 arg) { + return (int16_t)zig_lo_u128(arg); +} -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return val ^ zig_maxInt_u(128, bits); +static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) { + return (uint32_t)zig_lo_u128(arg); +} +static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) { + return (uint32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_i128(zig_i128 arg) { + return (int32_t)zig_lo_i128(arg); +} +static inline int32_t zig_i32_intCast_u128(zig_u128 arg) { + return (int32_t)zig_lo_u128(arg); } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - (void)bits; - return ~val; +static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) { + return zig_lo_u128(arg); +} +static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) { + return zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_i128(zig_i128 arg) { + return (int64_t)zig_lo_i128(arg); +} +static inline int64_t zig_i64_intCast_u128(zig_u128 arg) { + return (int64_t)zig_lo_u128(arg); +} + +static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) { + return zig_make_u128(UINT8_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i8(int8_t arg) { + return zig_make_u128(UINT8_C(0), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_i8(int8_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg); +} +static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) { + return zig_make_i128(INT8_C(0), arg); } -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) { + return zig_make_u128(UINT16_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i16(int16_t arg) { + return zig_make_u128(UINT16_C(0), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_i16(int16_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg); +} +static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) { + return zig_make_i128(INT16_C(0), arg); } -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - return lhs << rhs; +static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) { + return zig_make_u128(UINT32_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i32(int32_t arg) { + return zig_make_u128(UINT32_C(0), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_i32(int32_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg); +} +static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) { + return zig_make_i128(INT32_C(0), arg); } -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - // This works around a GCC miscompilation, but it has the side benefit of - // emitting better code. It is behind the `#if` because it depends on - // arithmetic right shift, which is implementation-defined in C, but should - // be guaranteed on any GCC-compatible compiler. -#if defined(zig_gnuc) - return lhs >> rhs; +static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) { + return zig_make_u128(UINT64_C(0), arg); +} +static inline zig_u128 zig_u128_intCast_i64(int64_t arg) { + return zig_make_u128(UINT64_C(0), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_i64(int64_t arg) { + return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg); +} +static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) { + return zig_make_i128(INT64_C(0), arg); +} + +static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) { + return arg; +} +static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) { +#if zig_has_int128 + return (zig_u128)arg; +#else + return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); +#endif +} +static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) { + return arg; +} +static inline zig_i128 zig_i128_intCast_u128(zig_u128 arg) { +#if zig_has_int128 + return (zig_i128)arg; #else - zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); - return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; + return zig_make_i128(zig_i64_bitCast_u64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); #endif } -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - return lhs << rhs; +#define zig_int128_cast_builtins(w) \ + static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \ + return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \ + } \ +\ + static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \ + return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \ + } +zig_int128_cast_builtins(8) +zig_int128_cast_builtins(16) +zig_int128_cast_builtins(32) +zig_int128_cast_builtins(64) + +static inline zig_u128 zig_u128_truncate_u128(zig_u128 arg, uint8_t bits) { + return zig_and_u128(arg, zig_maxInt_u(128, bits)); +} +static inline zig_i128 zig_i128_truncate_i128(zig_i128 arg, uint8_t bits) { + if (bits > UINT8_C(64)) return zig_make_i128(zig_i64_truncate_i64(zig_hi_i128(arg), bits - UINT8_C(64)), zig_lo_i128(arg)); + int64_t lo = zig_i64_truncate_i128(arg, bits); + return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); +} + +static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_u128 zig_u128_bitCast_i128(zig_i128 arg, uint8_t bits) { + return zig_u128_truncate_u128(zig_u128_intCast_i128(arg), bits); +} +static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return arg; +} +static inline zig_i128 zig_i128_bitCast_u128(zig_u128 arg, uint8_t bits) { + return zig_i128_truncate_i128(zig_i128_intCast_u128(arg), bits); +} + +#if zig_has_int128 + +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + return arg ^ zig_maxInt_u(128, bits); +} + +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return ~arg; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -1953,11 +2293,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { return lhs * rhs; } -static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { return lhs / rhs; } -static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { return lhs / rhs; } @@ -1971,36 +2311,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { #else /* zig_has_int128 */ -static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { - return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; +static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) }; + return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) }; } -static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { - return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; -} - -static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) }; - return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs }; -} - -static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; -} - -static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - 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))) }; - return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) }; -} - -static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { - if (rhs == UINT8_C(0)) return lhs; - if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; - return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; +static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { + (void)bits; + return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo }; } static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { @@ -2027,59 +2345,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { return res; } -zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); return __multi3(lhs, rhs); } static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { - return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs))); + return zig_u128_bitCast_i128(zig_mul_i128(zig_i128_bitCast_u128(lhs, UINT8_C(128)), zig_i128_bitCast_u128(rhs, UINT8_C(128))), UINT8_C(128)); } -zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); -static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { +static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); return __udivti3(lhs, rhs); } -zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); -static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { +static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); return __divti3(lhs, rhs); } -zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) { + zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); return __umodti3(lhs, rhs); } -zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { + zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); return __modti3(lhs, rhs); } #endif /* zig_has_int128 */ -#define zig_div_floor_u128 zig_div_trunc_u128 +#define zig_divFloor_u128 zig_divTrunc_u128 -static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask)); } -static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) { +static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) { zig_u128 rem = zig_rem_u128(lhs, rhs); uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0) ? UINT64_C(1) : UINT64_C(0); - return zig_add_u128(zig_div_trunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); + return zig_add_u128(zig_divTrunc_u128(lhs, rhs), zig_make_u128(UINT64_C(0), mask)); } -static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) { +static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) { zig_i128 rem = zig_rem_i128(lhs, rhs); int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1) : INT64_C(0); - return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); + return zig_add_i128(zig_divTrunc_i128(lhs, rhs), zig_make_i128(INT64_C(0), (uint64_t)mask)); } #define zig_mod_u128 zig_rem_u128 @@ -2107,51 +2425,41 @@ static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) { return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; } -static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) { - return zig_and_u128(val, zig_maxInt_u(128, bits)); -} - -static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) { - if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val)); - int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits); - return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo); -} - static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_shl_u128(lhs, rhs), bits); } static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_shl_u128(zig_u128_bitCast_i128(lhs, bits), rhs), bits), bits); } static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_add_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_add_u128(lhs, rhs), bits); } static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_add_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_sub_u128(lhs, rhs), bits); } static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_sub_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits); + return zig_u128_truncate_u128(zig_mul_u128(lhs, rhs), bits); } static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits); + return zig_i128_truncate_i128(zig_i128_bitCast_u128(zig_mul_u128(zig_u128_bitCast_i128(lhs, bits), zig_u128_bitCast_i128(rhs, bits)), bits), bits); } -static inline zig_u128 zig_abs_i128(zig_i128 val) { - zig_i128 tmp = zig_shr_i128(val, 127); - return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); +static inline zig_u128 zig_abs_i128(zig_i128 arg) { + zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128)); + return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp); } #if zig_has_int128 @@ -2160,7 +2468,7 @@ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(add_overflow) zig_u128 full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_addw_u128(lhs, rhs, bits); @@ -2176,7 +2484,7 @@ static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs); bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2184,7 +2492,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(sub_overflow) zig_u128 full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_subw_u128(lhs, rhs, bits); @@ -2200,7 +2508,7 @@ static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs); bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } @@ -2208,7 +2516,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #if zig_has_builtin(mul_overflow) zig_u128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); - *res = zig_wrap_u128(full_res, bits); + *res = zig_u128_truncate_u128(full_res, bits); return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); #else *res = zig_mulw_u128(lhs, rhs, bits); @@ -2216,8 +2524,8 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint #endif } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); #if zig_has_builtin(mul_overflow) zig_i128 full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); @@ -2226,50 +2534,78 @@ static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0; #endif - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); } #else /* zig_has_int128 */ static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { - uint64_t hi; - bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + uint64_t lo; + bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); + *res = zig_u128_intCast_u64(lo); + return overflow; + } else { + uint64_t hi; + bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { - int64_t hi; - bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); - return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); + if (bits <= UINT8_C(64)) { + int64_t lo; + bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); + *res = zig_i128_intCast_i64(lo); + return overflow; + } else { + int64_t hi; + bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); + return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); + } } static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { *res = zig_mulw_u128(lhs, rhs, bits); - return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) && - zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); + return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) && + zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); } -zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { + zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); int overflow_int; zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); bool overflow = overflow_int != 0 || zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0); - *res = zig_wrap_i128(full_res, bits); + *res = zig_i128_truncate_i128(full_res, bits); return overflow; } @@ -2282,28 +2618,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8 static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) { *res = zig_shlw_i128(lhs, rhs, bits); - zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1))); + zig_i128 mask = zig_i128_bitCast_u128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)), bits); return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) && zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0); } -static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { +#define zig_int128_shls_builtins(rw) \ + static inline zig_u128 zig_shls_u128_u##rw(zig_u128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_u128 res; \ + if (rhs < bits && !zig_shlo_u128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_u128(lhs, zig_make_u128(UINT64_C(0), UINT64_C(0)))) { \ + case 0: return zig_minInt_u(128, bits); \ + case 1: return zig_maxInt_u(128, bits); \ + default: zig_unreachable(); \ + } \ + } \ +\ + static inline zig_i128 zig_shls_i128_u##rw(zig_i128 lhs, uint##rw##_t rhs, uint8_t bits) { \ + zig_i128 res; \ + if (rhs < bits && !zig_shlo_i128(&res, lhs, zig_u8_intCast_u##rw(rhs), bits)) return res; \ + switch (zig_cmp_i128(lhs, zig_make_i128(INT64_C(0), UINT64_C(0)))) { \ + case -1: return zig_minInt_i(128, bits); \ + case 0: return zig_make_i128(INT64_C(0), UINT64_C(0)); \ + case 1: return zig_maxInt_i(128, bits); \ + default: zig_unreachable(); \ + } \ + } +zig_int128_shls_builtins(8) +zig_int128_shls_builtins(16) +zig_int128_shls_builtins(32) +zig_int128_shls_builtins(64) + +static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { zig_u128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { - case 0: return zig_make_u128(0, 0); - case 1: return zig_maxInt_u(128, bits); + case INT32_C(0): return zig_make_u128(0, 0); + case INT32_C(1): return zig_maxInt_u(128, bits); default: zig_unreachable(); } } -static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { +static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { zig_i128 res; if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits)) return res; switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { - case -1: return zig_minInt_i(128, bits); - case 0: return zig_make_i128(0, 0); - case 1: return zig_maxInt_i(128, bits); + case -INT32_C(1): return zig_minInt_i(128, bits); + case INT32_C(0): return zig_make_i128(0, 0); + case INT32_C(1): return zig_maxInt_i(128, bits); default: zig_unreachable(); } } @@ -2341,57 +2703,60 @@ static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) { 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); } -static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) { - if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits); - if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64)); - return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64)); +static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) { + if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits); + if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64)); + return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64)); } -static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) { - return zig_clz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) { + return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) { - if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64)); - return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64); +static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) { + if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64)); + return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64); } -static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) { - return zig_ctz_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) { + return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) { - return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) + - zig_popcount_u64(zig_lo_u128(val), UINT8_C(64)); +static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) { + return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) + + zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64)); } -static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) { - return zig_popcount_u128(zig_bitCast_u128(val), bits); +static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) { + return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits); } -static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) { +static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) { zig_u128 full_res; #if zig_has_builtin(bswap128) - full_res = __builtin_bswap128(val); + full_res = __builtin_bswap128(arg); #else - full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)), - zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64))); + full_res = zig_make_u128( + zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64)) + ); #endif return zig_shr_u128(full_res, UINT8_C(128) - bits); } -static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } -static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) { - return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)), - zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))), - UINT8_C(128) - bits); +static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) { + return zig_shr_u128(zig_make_u128( + zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)), + zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64)) + ), UINT8_C(128) - bits); } -static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { - return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits)); +static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) { + return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); } #if zig_has_int128 @@ -2411,12 +2776,378 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { /* ========================== Big Integer Support =========================== */ static inline uint16_t zig_int_bytes(uint16_t bits) { - uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT; + uint16_t bytes = (bits - UINT16_C(1)) / CHAR_BIT + UINT16_C(1); uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; + while (alignment / 2 >= bytes) alignment /= 2; return (bytes + alignment - 1) / alignment * alignment; } +static inline void zig_minInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_minInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_minInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_minInt_u8, size - byte_offset); +#endif +} + +static inline void zig_maxInt_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + + if (is_signed) { + int8_t signed_sign_byte = zig_maxInt_i(8, remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_maxInt_u(8, remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memset(&res_bytes[0], zig_maxInt_u8, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + byte_offset = size - UINT16_C(1) - byte_offset; + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], zig_maxInt_u8, size - byte_offset); +#endif +} + +static inline int8_t zig_signFill_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + + if (!is_signed) return INT8_C(0); +#if zig_little_endian + byte_offset = zig_int_bytes(bits) - 1; +#endif + return zig_shr_i8(zig_i8_bitCast_u8(arg_bytes[byte_offset], UINT8_C(8)), UINT8_C(7)); +} + +static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + uint16_t arg_size = zig_int_bytes(arg_bits); + uint16_t copy_size = zig_min_u16(res_size, arg_size); + uint8_t sign_fill = zig_u8_bitCast_i8(zig_signFill_big(arg, arg_is_signed, arg_bits), UINT8_C(8)); + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], copy_size); + memset(&res_bytes[copy_size], sign_fill, res_size - copy_size); +#else + memset(&res_bytes[0], sign_fill, res_size - copy_size); + memcpy(&res_bytes[res_size - copy_size], &arg_bytes[arg_size - copy_size], copy_size); +#endif +} + +static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_size = zig_int_bytes(res_bits); + + if (res_is_signed != arg_is_signed) zig_unreachable(); + if (res_bits > arg_bits) zig_unreachable(); + + if (res_is_signed) { + uint16_t arg_byte_offset = UINT16_C(0); + +#if zig_big_endian + arg_byte_offset = zig_int_bytes(arg_bits) - res_size; +#endif + + memcpy(&res_bytes[0], &arg_bytes[arg_byte_offset], res_size); + } else { + uint16_t res_byte_offset = zig_shr_u16(res_bits - UINT16_C(1), UINT8_C(3)); + uint16_t arg_byte_offset = res_byte_offset; + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], res_byte_offset); +#else + res_byte_offset = res_size - UINT16_C(1) - res_byte_offset; + arg_byte_offset = zig_int_bytes(arg_bits) - UINT16_C(1) - arg_byte_offset; + + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + + res_bytes[res_byte_offset] = zig_u8_truncate_u8( + arg_bytes[arg_byte_offset], + zig_u8_truncate_u8(res_bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1) + ); + res_byte_offset += UINT16_C(1); + arg_byte_offset += UINT16_C(1); + +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, res_size - res_byte_offset); +#else + memcpy(&res_bytes[res_byte_offset], &arg_bytes[arg_byte_offset], res_size - res_byte_offset); +#endif + } +} + +#define zig_big_casts(is, s, w, IntType) \ + static inline IntType zig_##s##w##_intCast_big(const void *arg, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_intCast_big(&res, arg, is, w, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_intCast_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_intCast_big(res, &arg, res_is_signed, res_bits, is, w); \ + } \ +\ + static inline IntType zig_##s##w##_truncate_big(const void *arg, uint8_t res_bits, bool arg_is_signed, uint16_t arg_bits) { \ + IntType res; \ + zig_big_truncate_big(&res, arg, is, res_bits, arg_is_signed, arg_bits); \ + return res; \ + } \ +\ + static inline void zig_big_truncate_##s##w(void *res, IntType arg, bool res_is_signed, uint16_t res_bits) { \ + zig_big_truncate_big(res, &arg, res_is_signed, res_bits, is, w); \ + } +zig_big_casts(false, u, 8, uint8_t) +zig_big_casts(true , i, 8, int8_t) +zig_big_casts(false, u, 16, uint16_t) +zig_big_casts(true , i, 16, int16_t) +zig_big_casts(false, u, 32, uint32_t) +zig_big_casts(true , i, 32, int32_t) +zig_big_casts(false, u, 64, uint64_t) +zig_big_casts(true , i, 64, int64_t) +zig_big_casts(false, u, 128, zig_u128) +zig_big_casts(true , i, 128, zig_i128) + +static inline void zig_big_bitCast_big(void *res, const void *arg, bool res_is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)); + uint16_t remainder_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1); + uint8_t sign_byte; + uint8_t fill_byte; + +#if zig_big_endian + byte_offset = size - UINT16_C(1) - byte_offset; +#endif + + if (res_is_signed) { + int8_t signed_sign_byte = zig_i8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + + sign_byte = zig_u8_bitCast_i8(signed_sign_byte, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(signed_sign_byte, UINT8_C(7)), UINT8_C(8)); + } else { + sign_byte = zig_u8_bitCast_u8(arg_bytes[byte_offset], remainder_bits); + fill_byte = UINT8_C(0); + } + +#if zig_little_endian + memcpy(&res_bytes[0], &arg_bytes[0], byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memset(&res_bytes[byte_offset], fill_byte, size - byte_offset); +#else + memset(&res_bytes[0], fill_byte, byte_offset); + res_bytes[byte_offset] = sign_byte; + byte_offset += UINT16_C(1); + memcpy(&res_bytes[byte_offset], &arg_bytes[byte_offset], size - byte_offset); +#endif +} + +static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) { + const uint8_t *lhs_bytes = lhs; + uint16_t byte_offset = 0; + bool do_signed = is_signed; + uint16_t remaining_bytes = zig_int_bytes(bits); + +#if zig_little_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0); + int32_t limb_cmp; + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (do_signed) { + zig_i128 lhs_limb; + zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); + do_signed = false; + } else { + zig_u128 lhs_limb; + zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); + } + + if (limb_cmp != 0) return limb_cmp; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (do_signed) { + int64_t lhs_limb; + int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint64_t lhs_limb; + uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (do_signed) { + int32_t lhs_limb; + int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint32_t lhs_limb; + uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (do_signed) { + int16_t lhs_limb; + int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + do_signed = false; + } else { + uint16_t lhs_limb; + uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (do_signed) { + int8_t lhs_limb; + int16_t lhs_cmp_limb; + int16_t rhs_cmp_limb = zig_i16_intCast_u8(rhs_byte); + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb); + if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb); + do_signed = false; + } else { + uint8_t lhs_limb; + uint8_t rhs_limb = rhs_byte; + + memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); + if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return 0; +} + static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; @@ -2579,6 +3310,168 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign return 0; } +static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + if (remaining_bytes != 128 / CHAR_BIT || is_signed) { + zig_i128 res_limb; + zig_i128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u128(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + if (remaining_bytes != 64 / CHAR_BIT || is_signed) { + int64_t res_limb; + int64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u64(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + if (remaining_bytes != 32 / CHAR_BIT || is_signed) { + int32_t res_limb; + int32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u32(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + if (remaining_bytes != 16 / CHAR_BIT || is_signed) { + int16_t res_limb; + int16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u16(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + if (remaining_bytes != 8 / CHAR_BIT || is_signed) { + int8_t res_limb; + int8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_i8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } else { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + res_limb = zig_not_u8(arg_limb, limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; @@ -2816,13 +3709,415 @@ static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool } } +static inline void zig_increment_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_addo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_decrement_big(void *res, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u128(&res_limb, res_limb, zig_make_u128(UINT64_C(0), UINT64_C(1)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u64(&res_limb, res_limb, UINT64_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u32(&res_limb, res_limb, UINT32_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u16(&res_limb, res_limb, UINT16_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + bool limb_overflow; + + memcpy(&res_limb, &res_bytes[byte_offset], sizeof(res_limb)); + limb_overflow = zig_subo_u8(&res_limb, res_limb, UINT8_C(1), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + if (!limb_overflow) return; + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_abs_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = 0; + uint16_t remaining_bytes = zig_int_bytes(bits); + if (zig_signFill_big(arg, is_signed, bits) >= INT8_C(0)) { + memcpy(res, arg, remaining_bytes); + return; + } + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool overflow = true; + +#if zig_big_endian + byte_offset = remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 res_limb; + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u128(&res_limb, zig_not_u128(arg_limb, UINT8_C(128)), zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t res_limb; + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u64(&res_limb, zig_not_u64(arg_limb, UINT8_C(64)), overflow ? UINT64_C(1) : UINT64_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t res_limb; + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u32(&res_limb, zig_not_u32(arg_limb, UINT8_C(32)), overflow ? UINT32_C(1) : UINT32_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t res_limb; + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u16(&res_limb, zig_not_u16(arg_limb, UINT8_C(16)), overflow ? UINT16_C(1) : UINT16_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t res_limb; + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + overflow = zig_addo_u8(&res_limb, zig_not_u8(arg_limb, UINT8_C(8)), overflow ? UINT8_C(1) : UINT8_C(0), limb_bits); + memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); + } + + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } +} + +static inline void zig_min_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) < INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + +static inline void zig_max_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + memcpy(res, zig_cmp_big(lhs, rhs, is_signed, bits) >= INT32_C(0) ? lhs : rhs, zig_int_bytes(bits)); +} + static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { uint8_t *res_bytes = res; const uint8_t *lhs_bytes = lhs; const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3038,7 +4333,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo const uint8_t *rhs_bytes = rhs; uint16_t byte_offset = 0; uint16_t remaining_bytes = zig_int_bytes(bits); - uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); bool overflow = false; #if zig_big_endian @@ -3248,323 +4543,755 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo return overflow; } +static inline void zig_add_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_addo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_addo_big(res, lhs, rhs, is_signed, bits); } +static inline void zig_adds_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits); + + if (!zig_addo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } +} + +static inline void zig_sub_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_subo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow +} + static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { (void)zig_subo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __udivei4(res, lhs, rhs, bits); - return; - } +static inline void zig_subs_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = is_signed ? zig_signFill_big(lhs, is_signed, bits) : -INT8_C(1); - zig_trap(); + if (!zig_subo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); + } } -static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_div_trunc_big(res, lhs, rhs, is_signed, bits); - return; +static inline bool zig_mulo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + const uint8_t *rhs_bytes = rhs; + uint16_t size = zig_int_bytes(bits); + uint16_t sign_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint8_t rhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(rhs, is_signed, bits), UINT8_C(8)); + uint16_t lhs_byte_offset = sign_byte_offset; + uint16_t lhs_end_byte_offset = UINT16_C(0); + bool overflow = false; + +#if zig_big_endian + lhs_byte_offset = size - lhs_byte_offset; + lhs_end_byte_offset = size - lhs_end_byte_offset; +#endif + + while (lhs_byte_offset != lhs_end_byte_offset) { + uint16_t rhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint16_t res_byte_offset; + uint16_t lhs_byte; + uint8_t res_byte = UINT8_C(0); + uint16_t mul_res = UINT16_C(0); + uint8_t carry = UINT8_C(0); + +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#else + rhs_byte_offset = size - rhs_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + + lhs_byte = zig_u16_intCast_u8(lhs_bytes[lhs_byte_offset]) ^ lhs_sign_fill; + +#if zig_big_endian + lhs_byte_offset += UINT16_C(1); +#endif + + res_byte_offset = lhs_byte_offset; + + while (res_byte_offset != end_byte_offset) { + bool res_byte_initialized = res_byte_offset != lhs_byte_offset; + +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); + res_byte_offset -= UINT16_C(1); +#endif + + if (res_byte_initialized) res_byte = res_bytes[res_byte_offset]; + carry = zig_addo_u8(&res_byte, res_byte, carry, UINT8_C(8)); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_intCast_u16( + zig_shr_u16(mul_res, UINT8_C(8)) + ), UINT8_C(8)); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_bytes[res_byte_offset], res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); + res_byte_offset += UINT16_C(1); +#endif + } + + while (rhs_byte_offset != end_byte_offset) { +#if zig_big_endian + rhs_byte_offset -= UINT16_C(1); +#endif + + carry = zig_addo_u8( + &res_byte, + zig_u8_intCast_u16(zig_shr_u16(mul_res, UINT8_C(8))), + carry, + UINT8_C(8) + ); + mul_res = lhs_byte * zig_u16_intCast_u8(rhs_bytes[rhs_byte_offset] ^ rhs_sign_fill); + carry += zig_addo_u8(&res_byte, res_byte, zig_u8_truncate_u16( + mul_res, + UINT8_C(8) + ), UINT8_C(8)); + overflow |= res_byte != UINT8_C(0); + +#if zig_little_endian + rhs_byte_offset += UINT16_C(1); +#endif + } + + overflow |= zig_shr_u16(mul_res, UINT8_C(8)) != UINT16_C(0); + overflow |= carry != UINT8_C(0); } - zig_trap(); +#if zig_little_endian + sign_byte_offset -= UINT64_C(1); +#else + sign_byte_offset = size - sign_byte_offset; +#endif + + if (lhs_sign_fill != rhs_sign_fill) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(0); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, UINT8_C(0), carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, res_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8( + &res_bytes[byte_offset], + res_byte, + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, INT8_C(0), signed_res_byte, UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + (lhs_sign_fill == UINT8_C(0) ? lhs_bytes : rhs_bytes)[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (lhs_sign_fill != UINT8_C(0)) { + uint16_t byte_offset = UINT16_C(0); + uint16_t end_byte_offset = sign_byte_offset; + uint8_t res_byte; + int8_t signed_res_byte; + uint8_t carry = UINT8_C(1); + +#if zig_big_endian + byte_offset = size - byte_offset; + end_byte_offset += UINT16_C(1); +#endif + + while (byte_offset != end_byte_offset) { +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + carry = zig_subo_u8(&res_byte, res_bytes[byte_offset], carry, UINT8_C(8)); + carry += zig_subo_u8(&res_byte, res_byte, lhs_bytes[byte_offset], UINT8_C(8)); + carry += zig_subo_u8(&res_bytes[byte_offset], res_byte, rhs_bytes[byte_offset], UINT8_C(8)); + +#if zig_little_endian + byte_offset += UINT16_C(1); +#endif + } + +#if zig_big_endian + byte_offset -= UINT16_C(1); +#endif + + signed_res_byte = zig_i8_bitCast_u8(res_bytes[byte_offset], UINT8_C(8)); + overflow |= signed_res_byte < INT8_C(0); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_intCast_u8(carry), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + lhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + overflow |= zig_subo_i8(&signed_res_byte, signed_res_byte, zig_i8_bitCast_u8( + rhs_bytes[byte_offset], + UINT8_C(8) + ), UINT8_C(8)); + res_bytes[byte_offset] = zig_i8_bitCast_u8(signed_res_byte, UINT8_C(8)); + } else if (is_signed) { + int8_t signed_res_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + + overflow |= signed_res_byte < INT8_C(0); + } + + { + uint8_t truncate_bits = zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t fill_byte = UINT8_C(0); + + if (is_signed) { + int8_t sign_byte = zig_i8_bitCast_u8(res_bytes[sign_byte_offset], UINT8_C(8)); + int8_t truncated = zig_i8_truncate_i8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + fill_byte = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + } else { + uint8_t sign_byte = res_bytes[sign_byte_offset]; + uint8_t truncated = zig_u8_truncate_u8(sign_byte, truncate_bits); + + overflow |= sign_byte != truncated; + res_bytes[sign_byte_offset] = truncated; + } + +#if zig_little_endian + sign_byte_offset += UINT16_C(1); + memset(&res_bytes[sign_byte_offset], fill_byte, size - sign_byte_offset); +#else + memset(&res_bytes[0], fill_byte, sign_byte_offset); +#endif + } + + return overflow; +} + +static inline void zig_mul_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + if (zig_mulo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: integer overflow } -static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - zig_trap(); +static inline void zig_mulw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + (void)zig_mulo_big(res, lhs, rhs, is_signed, bits); } -zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); -static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - __umodei4(res, lhs, rhs, bits); - return; +static inline void zig_muls_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { + int8_t sat_sign = zig_signFill_big(lhs, is_signed, bits) ^ zig_signFill_big(rhs, is_signed, bits); + + if (!zig_mulo_big(res, lhs, rhs, is_signed, bits)) return; + switch (sat_sign) { + case -INT8_C(1): return zig_minInt_big(res, is_signed, bits); + case INT8_C(0): return zig_maxInt_big(res, is_signed, bits); } +} + +static inline void zig_divTrunc_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __divei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __divei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __udivei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __udivei5(res, lhs, rhs, temp, bits); + } +} - zig_trap(); +static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + if (is_signed) { + zig_extern void __modei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __modei5(res, lhs, rhs, temp, bits); + } else { + zig_extern void __umodei5(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uint32_t *temp, uintptr_t bits); + __umodei5(res, lhs, rhs, temp, bits); + } } -static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { - if (!is_signed) { - zig_rem_big(res, lhs, rhs, is_signed, bits); - return; +static inline void zig_divFloor_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool decrement = false; + + if (is_signed) { + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + decrement = zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32)); } + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (decrement) zig_decrement_big(res, is_signed, bits); +} - zig_trap(); +static inline void zig_divCeil_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool increment = false; + + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + increment = zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ) > INT32_C(0); + zig_divTrunc_big(res, lhs, rhs, temp, is_signed, bits); + if (increment) zig_increment_big(res, is_signed, bits); } -static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t skip_bits = remaining_bytes * 8 - bits; - uint16_t total_lz = 0; - uint16_t limb_lz; - (void)is_signed; +static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, void *temp, bool is_signed, uint16_t bits) { + bool fixup = false; -#if zig_little_endian - byte_offset = remaining_bytes; + zig_rem_big(res, lhs, rhs, temp, is_signed, bits); + if (is_signed && zig_u32_bitCast_i32(zig_xor_i32( + zig_cmp_big_u8(res, UINT8_C(0), is_signed, bits), + zig_and_i32(zig_i32_intCast_i8(zig_signFill_big(rhs, is_signed, bits)), zig_minInt_i32) + ), UINT8_C(32)) > zig_u32_bitCast_i32(zig_minInt_i32, UINT8_C(32))) zig_add_big(res, res, rhs, is_signed, bits); +} + +static inline void zig_shr_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t lhs_byte_offset = zig_shr_u16(rhs, UINT8_C(3)); + uint16_t end_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t lhs_prev_byte; + uint8_t byte_shift = zig_u8_truncate_u16(rhs, UINT8_C(3)); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + lhs_byte_offset = size - lhs_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - while (remaining_bytes >= 128 / CHAR_BIT) { + { +#if zig_big_endian + lhs_byte_offset -= UINT16_C(1); +#endif + + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; + #if zig_little_endian - byte_offset -= 128 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); +#endif + } + + while (lhs_byte_offset != end_byte_offset) { +#if zig_big_endian + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - zig_u128 val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_prev_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 128 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 128 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 128 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 64 / CHAR_BIT) { -#if zig_little_endian - byte_offset -= 64 / CHAR_BIT; + { + uint8_t lhs_sign_fill = UINT8_C(0); + +#if zig_big_endian + res_byte_offset -= UINT16_C(1); #endif - { - uint64_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(lhs_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + lhs_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(lhs_prev_byte, byte_shift); } - total_lz += limb_lz; - if (limb_lz < 64 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 64 / CHAR_BIT; - -#if zig_big_endian - byte_offset += 64 / CHAR_BIT; +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], lhs_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], lhs_sign_fill, res_byte_offset); #endif } +} + +static inline bool zig_shlo_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *lhs_bytes = lhs; + uint8_t lhs_sign_fill = zig_u8_bitCast_i8(zig_signFill_big(lhs, is_signed, bits), UINT8_C(8)); + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t lhs_byte_offset = UINT16_C(0); + uint16_t end_byte_offset = res_byte_offset - UINT16_C(1) - zig_shr_u16(rhs, UINT8_C(3)); + uint8_t lhs_prev_byte = lhs_sign_fill; + uint8_t byte_shift = UINT8_C(8) - zig_u8_truncate_u16(rhs, UINT8_C(3)); + bool overflow = false; - while (remaining_bytes >= 32 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 32 / CHAR_BIT; + lhs_byte_offset = size - lhs_byte_offset; +#else + res_byte_offset = size - res_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint32_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); - } + while (lhs_byte_offset != end_byte_offset) { +#if zig_little_endian + lhs_byte_offset -= UINT16_C(1); +#endif - total_lz += limb_lz; - if (limb_lz < 32 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 32 / CHAR_BIT; + overflow |= lhs_prev_byte != lhs_sign_fill; + lhs_prev_byte = lhs_bytes[lhs_byte_offset]; #if zig_big_endian - byte_offset += 32 / CHAR_BIT; + lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { #if zig_little_endian - byte_offset -= 16 / CHAR_BIT; + end_byte_offset = UINT16_C(0); +#else + end_byte_offset = size; +#endif + + { + bool lhs_more_bytes = lhs_byte_offset != end_byte_offset; + +#if zig_little_endian + if (lhs_more_bytes) lhs_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t lhs_byte = UINT8_C(0); + + if (lhs_more_bytes) lhs_byte = lhs_bytes[lhs_byte_offset]; + + if (is_signed) { + int16_t shifted = zig_shr_i16(zig_or_i16( + zig_shl_i16(zig_i16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_i16_intCast_u8(lhs_byte) + ), byte_shift); + int8_t truncated = zig_i8_truncate_i16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + uint8_t fill = zig_u8_bitCast_i8(zig_shr_i8(truncated, UINT8_C(7)), UINT8_C(8)); + + overflow |= zig_i16_intCast_i8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif + res_bytes[res_byte_offset] = zig_u8_bitCast_i8(truncated, UINT8_C(8)); + } else { + uint16_t shifted = zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift); + uint8_t truncated = zig_u8_truncate_u16( + shifted, + zig_u8_truncate_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT8_C(1) + ); + + overflow |= zig_u16_intCast_u8(truncated) != shifted; +#if zig_little_endian + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); + res_byte_offset -= UINT16_C(1); +#else + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#endif + res_bytes[res_byte_offset] = truncated; + } - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 16 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_big_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + if (lhs_more_bytes) lhs_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + while (lhs_byte_offset != end_byte_offset) { #if zig_little_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); + lhs_byte_offset -= UINT16_C(1); #endif { - uint8_t val_limb; + uint8_t lhs_byte = lhs_bytes[lhs_byte_offset]; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + zig_u16_intCast_u8(lhs_byte) + ), byte_shift)); + lhs_prev_byte = lhs_byte; } - total_lz += limb_lz; - if (limb_lz < 8 - skip_bits) return total_lz; - skip_bits = 0; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_big_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + lhs_byte_offset += UINT16_C(1); #endif } - return total_lz; -} + { +#if zig_little_endian + res_byte_offset -= UINT16_C(1); +#endif -static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; - uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); - uint16_t total_tz = 0; - uint16_t limb_tz; - (void)is_signed; + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16( + zig_shl_u16(zig_u16_intCast_u8(lhs_prev_byte), UINT8_C(8)), + byte_shift + )); #if zig_big_endian - byte_offset = remaining_bytes; + res_byte_offset += UINT16_C(1); #endif + } - while (remaining_bytes >= 128 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 128 / CHAR_BIT; +#if zig_little_endian + memset(&res_bytes[0], zig_minInt_u8, res_byte_offset); +#else + memset(&res_bytes[res_byte_offset], zig_minInt_u8, size - res_byte_offset); #endif - { - zig_u128 val_limb; + return overflow; +} - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u128(val_limb, 128); - } +static inline void zig_shl_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + if (zig_shlo_big(res, lhs, rhs, is_signed, bits)) zig_trap(); // panic: left shift overflowed bits +} - total_tz += limb_tz; - if (limb_tz < 128) return total_tz; - remaining_bytes -= 128 / CHAR_BIT; +static inline void zig_shlw_big(void *res, const void *lhs, uint16_t rhs, bool is_signed, uint16_t bits) { + (void)zig_shlo_big(res, lhs, rhs, is_signed, bits); +} -#if zig_little_endian - byte_offset += 128 / CHAR_BIT; -#endif +#define zig_big_shls_builtin(w) \ + static inline uint##w##_t zig_shls_u##w##_big(uint##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + uint##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_u##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? zig_minInt_u(w, lhs_bits) : zig_maxInt_u(w, lhs_bits); \ + } \ +\ + static inline int##w##_t zig_shls_i##w##_big(int##w##_t lhs, const void *rhs, \ + uint8_t lhs_bits, bool rhs_is_signed, uint16_t rhs_bits) { \ + int##w##_t res; \ + const uint8_t *rhs_bytes = rhs; \ + if (zig_cmp_big_u8(rhs, lhs_bits, rhs_is_signed, rhs_bits) < INT32_C(0) && \ + !zig_shlo_i##w(&res, lhs, rhs_bytes[0], lhs_bits)) return res; \ + return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ + lhs < INT##w##_C(0) ? zig_minInt_i(w, lhs_bits) : zig_maxInt_i(w, lhs_bits); \ + } \ +\ + static inline void zig_shls_big_u##w(void *res, const void *lhs, uint##w##_t rhs, bool is_signed, uint16_t bits) { \ + const uint8_t *lhs_bytes = lhs; \ + if (rhs < bits && !zig_shlo_big(res, lhs, zig_u16_intCast_u##w(rhs), is_signed, bits)) return; \ + switch (zig_cmp_big_u8(lhs, UINT8_C(0), is_signed, bits)) { \ + case -INT32_C(1): return zig_minInt_big(res, is_signed, bits); \ + case INT32_C(0): return zig_minInt_big(res, false, bits); \ + case INT32_C(1): return zig_maxInt_big(res, is_signed, bits); \ + default: zig_unreachable(); \ + } \ } +zig_big_shls_builtin(8) +zig_big_shls_builtin(16) +zig_big_shls_builtin(32) +zig_big_shls_builtin(64) + +static inline void zig_byteSwap_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = bits / CHAR_BIT; + uint16_t end_byte_offset = UINT16_C(1); + uint16_t size = zig_int_bytes(bits); - while (remaining_bytes >= 64 / CHAR_BIT) { #if zig_big_endian - byte_offset -= 64 / CHAR_BIT; + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; #endif - { - uint64_t val_limb; - - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u64(val_limb, 64); - } + while (arg_byte_offset != end_byte_offset) { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); +#endif - total_tz += limb_tz; - if (limb_tz < 64) return total_tz; - remaining_bytes -= 64 / CHAR_BIT; + res_bytes[res_byte_offset] = arg_bytes[arg_byte_offset]; #if zig_little_endian - byte_offset += 64 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 32 / CHAR_BIT) { -#if zig_big_endian - byte_offset -= 32 / CHAR_BIT; + { +#if zig_little_endian + arg_byte_offset -= UINT16_C(1); +#else + res_byte_offset -= UINT16_C(1); #endif { - uint32_t val_limb; + uint8_t byte = arg_bytes[arg_byte_offset]; + uint8_t fill = is_signed + ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8)) + : UINT8_C(0); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u32(val_limb, 32); + res_bytes[res_byte_offset] = byte; + +#if zig_little_endian + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); +#else + memset(&res_bytes[0], fill, res_byte_offset); +#endif } + } +} - total_tz += limb_tz; - if (limb_tz < 32) return total_tz; - remaining_bytes -= 32 / CHAR_BIT; +static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) { + uint8_t *res_bytes = res; + const uint8_t *arg_bytes = arg; + uint16_t size = zig_int_bytes(bits); + uint16_t res_byte_offset = UINT16_C(0); + uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t end_byte_offset = UINT16_C(0); + uint8_t arg_prev_byte; + uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3))); + +#if zig_big_endian + res_byte_offset = size - res_byte_offset; + arg_byte_offset = size - arg_byte_offset; + end_byte_offset = size - end_byte_offset; +#endif + { #if zig_little_endian - byte_offset += 32 / CHAR_BIT; + arg_byte_offset -= UINT16_C(1); +#endif + + arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); + +#if zig_big_endian + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 16 / CHAR_BIT) { + while (arg_byte_offset != end_byte_offset) { #if zig_big_endian - byte_offset -= 16 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); +#else + arg_byte_offset -= UINT16_C(1); #endif { - uint16_t val_limb; + uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u16(val_limb, 16); + res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( + zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)), + zig_u16_intCast_u8(arg_prev_byte) + ), byte_shift)); + arg_prev_byte = arg_byte; } - total_tz += limb_tz; - if (limb_tz < 16) return total_tz; - remaining_bytes -= 16 / CHAR_BIT; - #if zig_little_endian - byte_offset += 16 / CHAR_BIT; + res_byte_offset += UINT16_C(1); +#else + arg_byte_offset += UINT16_C(1); #endif } - while (remaining_bytes >= 8 / CHAR_BIT) { + { + uint8_t arg_sign_fill = UINT8_C(0); + #if zig_big_endian - byte_offset -= 8 / CHAR_BIT; + res_byte_offset -= UINT16_C(1); #endif - { - uint8_t val_limb; + if (is_signed) { + int8_t signed_byte = zig_i8_bitCast_u8(arg_prev_byte, UINT8_C(8)); - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - limb_tz = zig_ctz_u8(val_limb, 8); + res_bytes[res_byte_offset] = zig_shr_i8(signed_byte, byte_shift); + arg_sign_fill = zig_u8_bitCast_i8(zig_shr_i8(signed_byte, UINT8_C(7)), UINT8_C(8)); + } else { + res_bytes[res_byte_offset] = zig_shr_u8(arg_prev_byte, byte_shift); } - total_tz += limb_tz; - if (limb_tz < 8) return total_tz; - remaining_bytes -= 8 / CHAR_BIT; - #if zig_little_endian - byte_offset += 8 / CHAR_BIT; + res_byte_offset += UINT16_C(1); + memset(&res_bytes[res_byte_offset], arg_sign_fill, size - res_byte_offset); +#else + memset(&res_bytes[0], arg_sign_fill, res_byte_offset); #endif } - - return total_tz; } -static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { - const uint8_t *val_bytes = val; +static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; uint16_t byte_offset = 0; - uint16_t remaining_bytes = zig_int_bytes(bits); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); uint16_t total_pc = 0; (void)is_signed; #if zig_big_endian - byte_offset = remaining_bytes; + byte_offset = zig_int_bytes(bits); #endif while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 128 / CHAR_BIT; #endif { - zig_u128 val_limb; + zig_u128 arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u128(val_limb, 128); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 128 / CHAR_BIT; @@ -3575,15 +5302,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 64 / CHAR_BIT; #endif { - uint64_t val_limb; + uint64_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u64(val_limb, 64); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 64 / CHAR_BIT; @@ -3594,15 +5323,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 32 / CHAR_BIT; #endif { - uint32_t val_limb; + uint32_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc += zig_popcount_u32(val_limb, 32); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 32 / CHAR_BIT; @@ -3613,15 +5344,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 16 / CHAR_BIT; #endif { - uint16_t val_limb; + uint16_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u16(val_limb, 16); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 16 / CHAR_BIT; @@ -3632,15 +5365,17 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ } while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + #if zig_big_endian byte_offset -= 8 / CHAR_BIT; #endif { - uint8_t val_limb; + uint8_t arg_limb; - memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); - total_pc = zig_popcount_u8(val_limb, 8); + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); } remaining_bytes -= 8 / CHAR_BIT; @@ -3653,6 +5388,274 @@ static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_ return total_pc; } +static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = UINT16_C(0); + uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + uint16_t total_tz = UINT16_C(0); + uint16_t limb_tz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits); +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); + +#if zig_big_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_tz += limb_tz; + if (limb_tz < limb_bits) return total_tz; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_little_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_tz; +} + +static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) { + const uint8_t *arg_bytes = arg; + uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); + uint16_t remaining_bytes = byte_offset; + uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); + bool sign_limb = true; + uint16_t total_lz = UINT16_C(0); + uint16_t limb_lz; + (void)is_signed; + +#if zig_big_endian + byte_offset = zig_int_bytes(bits) - remaining_bytes; +#endif + + while (remaining_bytes >= 128 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 128 / CHAR_BIT; +#endif + + { + zig_u128 arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 128 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 128 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 64 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 64 / CHAR_BIT; +#endif + + { + uint64_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 64 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 64 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 32 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 32 / CHAR_BIT; +#endif + + { + uint32_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 32 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 32 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 16 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 16 / CHAR_BIT; +#endif + + { + uint16_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 16 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 16 / CHAR_BIT; +#endif + } + + while (remaining_bytes >= 8 / CHAR_BIT) { + uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0)); + +#if zig_little_endian + byte_offset -= 8 / CHAR_BIT; +#endif + + { + uint8_t arg_limb; + + memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); + limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); + } + + total_lz += limb_lz; + if (limb_lz < limb_bits) return total_lz; + sign_limb = false; + remaining_bytes -= 8 / CHAR_BIT; + +#if zig_big_endian + byte_offset += 8 / CHAR_BIT; +#endif + } + + return total_lz; +} + /* ========================= Floating Point Support ========================= */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ @@ -3687,29 +5690,29 @@ long double __cdecl nanl(char const* input); #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg) #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) #else -#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr) -#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr) -#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr) -#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr) -#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr) +#define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr) +#define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr) +#define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr) +#define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr) +#define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr) #endif #define zig_has_f16 1 #define zig_libc_name_f16(name) __##name##h #define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) -#if FLT_MANT_DIG == 11 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11 typedef float zig_f16; #define zig_make_f16(fp, repr) fp##f -#elif DBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11 typedef double zig_f16; #define zig_make_f16(fp, repr) fp -#elif LDBL_MANT_DIG == 11 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11 typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l -#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) typedef _Float16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 -#elif defined(__SIZEOF_FP16__) +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && defined(__SIZEOF_FP16__) typedef __fp16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 #else @@ -3723,11 +5726,6 @@ typedef uint16_t zig_f16; #undef zig_init_special_f16 #define zig_init_special_f16(sign, name, arg, repr) repr #endif -#if defined(zig_darwin) && defined(zig_x86) -typedef uint16_t zig_compiler_rt_f16; -#else -typedef zig_f16 zig_compiler_rt_f16; -#endif #define zig_has_f32 1 #define zig_libc_name_f32(name) name##f @@ -3736,16 +5734,16 @@ typedef zig_f16 zig_compiler_rt_f16; #else #define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 24 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24 typedef float zig_f32; #define zig_make_f32(fp, repr) fp##f -#elif DBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24 typedef double zig_f32; #define zig_make_f32(fp, repr) fp -#elif LDBL_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24 typedef long double zig_f32; #define zig_make_f32(fp, repr) fp##l -#elif FLT32_MANT_DIG == 24 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24 typedef _Float32 zig_f32; #define zig_make_f32(fp, repr) fp##f32 #else @@ -3768,19 +5766,19 @@ typedef uint32_t zig_f32; #else #define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) #endif -#if FLT_MANT_DIG == 53 +#if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53 typedef float zig_f64; #define zig_make_f64(fp, repr) fp##f -#elif DBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53 typedef double zig_f64; #define zig_make_f64(fp, repr) fp -#elif LDBL_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53 typedef long double zig_f64; #define zig_make_f64(fp, repr) fp##l -#elif FLT64_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53 typedef _Float64 zig_f64; #define zig_make_f64(fp, repr) fp##f64 -#elif FLT32X_MANT_DIG == 53 +#elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53 typedef _Float32x zig_f64; #define zig_make_f64(fp, repr) fp##f32x #else @@ -3798,7 +5796,14 @@ typedef uint64_t zig_f64; #define zig_has_f80 1 #define zig_libc_name_f80(name) __##name##x #define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) -#if FLT_MANT_DIG == 64 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI +#undef zig_has_f80 +typedef struct { uint64_t mantissa; uint16_t exponent; } zig_f80; +#define zig_init_repr_f80(mantissa, exponent) { .mant##issa = mantissa, .expo##nent = exponent } +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#define zig_mantissa_repr_f80(arg) (arg).mantissa +#define zig_exponent_repr_f80(arg) (arg).exponent +#elif FLT_MANT_DIG == 64 typedef float zig_f80; #define zig_make_f80(fp, repr) fp##f #elif DBL_MANT_DIG == 64 @@ -3818,10 +5823,18 @@ typedef __float80 zig_f80; #define zig_make_f80(fp, repr) fp##l #else #undef zig_has_f80 -#define zig_has_f80 0 -#define zig_repr_f80 u128 typedef zig_u128 zig_f80; +#define zig_init_repr_f80(mantissa, exponent) zig_init_u128(exponent, mantissa) +#define zig_make_repr_f80(mantissa, exponent) zig_make_u128(exponent, mantissa) +#define zig_mantissa_repr_f80(arg) zig_lo_u128(arg) +#define zig_exponent_repr_f80(arg) (uint16_t)zig_hi_u128(arg) +#endif +#ifndef zig_has_f80 +#define zig_has_f80 0 #define zig_make_f80(fp, repr) repr +#ifndef zig_make_repr_f80 +#define zig_make_repr_f80(mantissa, exponent) (zig_f80)zig_init_repr_f80(mantissa, exponent) +#endif #undef zig_make_special_f80 #define zig_make_special_f80(sign, name, arg, repr) repr #undef zig_init_special_f80 @@ -3833,11 +5846,20 @@ typedef zig_u128 zig_f80; #else #define zig_f128_has_miscompilations 0 #endif - #define zig_has_f128 1 #define zig_libc_name_f128(name) name##f128 #define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr) -#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 +#ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI +#undef zig_has_f128 +#if zig_little_endian +typedef struct { uint64_t lo, hi; } zig_f128; +#else +typedef struct { uint64_t hi, lo; } zig_f128; +#endif +#define zig_init_repr_f128(hi, lo) { .h##i = hi, .l##o = lo } +#define zig_lo_repr_f128(arg) (arg).lo +#define zig_hi_repr_f128(arg) (arg).hi +#elif !zig_f128_has_miscompilations && FLT_MANT_DIG == 113 typedef float zig_f128; #define zig_make_f128(fp, repr) fp##f #elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 @@ -3859,27 +5881,38 @@ typedef __float128 zig_f128; #define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) #else #undef zig_has_f128 -#define zig_has_f128 0 -#undef zig_make_special_f128 -#undef zig_init_special_f128 -#if defined(zig_darwin) || defined(zig_aarch64) -typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64; -zig_basic_operator(zig_v2u64, xor_v2u64, ^) -#define zig_repr_f128 v2u64 -typedef zig_v2u64 zig_f128; -#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi } -#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128 -#define zig_make_f128(fp, repr) zig_make_f128_##repr -#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr -#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr +#if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC) +#if defined(zig_msvc) && !defined(__clang__) +#include +typedef __m128i zig_f128; +#define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } } +#define zig_lo_repr_f128(arg) (arg).m128i_u64[0] +#define zig_hi_repr_f128(arg) (arg).m128i_u64[1] +#else +typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128; +#define zig_init_repr_f128(hi, lo) { lo, hi } +#define zig_lo_repr_f128(arg) (arg)[0] +#define zig_hi_repr_f128(arg) (arg)[1] +#endif #else -#define zig_repr_f128 u128 typedef zig_u128 zig_f128; +#define zig_init_repr_f128(hi, lo) zig_init_u128(hi, lo) +#define zig_make_repr_f128(hi, lo) zig_make_u128(hi, lo) +#define zig_lo_repr_f128(arg) zig_lo_u128(arg) +#define zig_hi_repr_f128(arg) zig_hi_u128(arg) +#endif +#endif +#ifndef zig_has_f128 +#define zig_has_f128 0 #define zig_make_f128(fp, repr) repr +#ifndef zig_make_repr_f128 +#define zig_make_repr_f128(hi, lo) (zig_f128)zig_init_repr_f128(hi, lo) +#endif +#undef zig_make_special_f128 #define zig_make_special_f128(sign, name, arg, repr) repr +#undef zig_init_special_f128 #define zig_init_special_f128(sign, name, arg, repr) repr #endif -#endif #if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC) /* Emulate msvc abi on a gnu compiler */ @@ -3892,84 +5925,141 @@ typedef zig_f128 zig_c_longdouble; typedef long double zig_c_longdouble; #endif -#define zig_bitCast_float(Type, ReprType) \ - static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \ - zig_##Type result; \ - memcpy(&result, &repr, sizeof(result)); \ - return result; \ +#if __AVR__ +typedef signed char zig_FloatCompareResult; +#elif defined(zig_aarch64) +typedef signed int zig_FloatCompareResult; +#elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__ +typedef signed long zig_FloatCompareResult; +#else +typedef signed long long zig_FloatCompareResult; +#endif + +#define zig_bitCast_float(w, iw, UnsignedReprType, SignedReprType) \ + static inline zig_f##w zig_f##w##_bitCast_u##iw(UnsignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline zig_f##w zig_f##w##_bitCast_i##iw(SignedReprType arg) { \ + zig_f##w res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return res; \ + } \ + static inline UnsignedReprType zig_u##iw##_bitCast_f##w(zig_f##w arg) { \ + UnsignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_u##iw##_truncate_u##iw(res, w); \ + } \ + static inline SignedReprType zig_i##iw##_bitCast_f##w(zig_f##w arg) { \ + SignedReprType res; \ + memcpy(&res, &arg, sizeof(zig_f##w)); \ + return zig_i##iw##_truncate_i##iw(res, w); \ + } +zig_bitCast_float(16, 16, uint16_t, int16_t) +zig_bitCast_float(32, 32, uint32_t, int32_t) +zig_bitCast_float(64, 64, uint64_t, int64_t) +#if zig_has_f80 +zig_bitCast_float(80, 128, zig_u128, zig_i128) +#else +static inline zig_f80 zig_f80_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f80(zig_lo_u128(arg), (uint16_t)zig_hi_u128(arg)); +} +static inline zig_f80 zig_f80_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f80(zig_lo_i128(arg), (uint16_t)zig_hi_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f80(zig_f80 arg) { + return zig_make_u128(zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +static inline zig_i128 zig_i128_bitCast_f80(zig_f80 arg) { + return zig_make_i128((int16_t)zig_exponent_repr_f80(arg), zig_mantissa_repr_f80(arg)); +} +#endif +static inline zig_f80 zig_f80_bitCast_big(const void *arg) { + return zig_f80_bitCast_u128(zig_u128_truncate_big(arg, UINT8_C(80), false, UINT16_C(80))); +} +static inline void zig_big_bitCast_f80(void *res, zig_f80 arg, bool res_is_signed, uint16_t res_bits) { + if (res_is_signed) { + zig_big_truncate_i128(res, zig_i128_bitCast_f80(arg), res_is_signed, res_bits); + } else { + zig_big_truncate_u128(res, zig_u128_bitCast_f80(arg), res_is_signed, res_bits); } -zig_bitCast_float(f16, uint16_t) -zig_bitCast_float(f32, uint32_t) -zig_bitCast_float(f64, uint64_t) -zig_bitCast_float(f80, zig_u128) -zig_bitCast_float(f128, zig_u128) +} +#if zig_has_f128 +zig_bitCast_float(128, 128, zig_u128, zig_i128) +#else +static inline zig_f128 zig_f128_bitCast_u128(zig_u128 arg) { + return zig_make_repr_f128(zig_hi_u128(arg), zig_lo_u128(arg)); +} +static inline zig_f128 zig_f128_bitCast_i128(zig_i128 arg) { + return zig_make_repr_f128((uint64_t)zig_hi_i128(arg), zig_lo_i128(arg)); +} +static inline zig_u128 zig_u128_bitCast_f128(zig_f128 arg) { + return zig_make_u128(zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +static inline zig_i128 zig_i128_bitCast_f128(zig_f128 arg) { + return zig_make_i128((int64_t)zig_hi_repr_f128(arg), zig_lo_repr_f128(arg)); +} +#endif -#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ - zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ +#define zig_convert_float_00(ResType, operation, ArgType, version) \ + zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \ + return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ + zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg) +#define zig_convert_float_01(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_10(ResType, operation, ArgType, version) \ + zig_convert_float_00(ResType, operation, ArgType, version) +#define zig_convert_float_11(ResType, operation, ArgType, version) \ + return (ResType)arg +#define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \ static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \ zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \ - ResType res; \ - ExternResType extern_res; \ - ExternArgType extern_arg; \ - memcpy(&extern_arg, &arg, sizeof(extern_arg)); \ - extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ - zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \ - memcpy(&res, &extern_res, sizeof(res)); \ - return extern_res; \ + zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \ + zig_has_##arg_when)(ResType, operation, ArgType, version); \ } -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2) -zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2) -#ifdef __ARM_EABI__ +#define zig_convert_floats(SmallType, BigType) \ + zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \ + zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2) +zig_convert_floats(f16, f32) +zig_convert_floats(f16, f64) +zig_convert_floats(f16, f80) +zig_convert_floats(f16, f128) +zig_convert_floats(f32, f64) +zig_convert_floats(f32, f80) +zig_convert_floats(f32, f128) +zig_convert_floats(f64, f80) +zig_convert_floats(f64, f128) +zig_convert_floats(f80, f128) -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64); -static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32); -static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); } - -#else /* __ARM_EABI__ */ - -zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2) -zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2) - -#endif /* __ARM_EABI__ */ - -#define zig_float_negate_builtin_0(w, c, sb) \ - zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb)) -#define zig_float_negate_builtin_1(w, c, sb) -arg -#define zig_float_negate_builtin(w, c, sb) \ +#define zig_float_negate_builtin_0(w, sb) \ + zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb)) +#define zig_float_negate_builtin_1(w, sb) -arg +#define zig_float_negate_builtin(w, sb) \ static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \ - return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \ + return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, sb); \ } -zig_float_negate_builtin(16, , UINT16_C(1) << 15 ) -zig_float_negate_builtin(32, , UINT32_C(1) << 31 ) -zig_float_negate_builtin(64, , UINT64_C(1) << 63 ) -zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0))) -zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) +zig_float_negate_builtin(16, UINT16_C(1) << 15) +zig_float_negate_builtin(32, UINT32_C(1) << 31) +zig_float_negate_builtin(64, UINT64_C(1) << 63) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb)) +zig_float_negate_builtin(80, UINT16_C(1) << 15) + +#undef zig_float_negate_builtin_0 +#define zig_float_negate_builtin_0(w, sb) \ + zig_make_repr_f##w(zig_xor_u64(zig_hi_repr_f##w(arg), sb), zig_lo_repr_f##w(arg)) +zig_float_negate_builtin(128, UINT64_C(1) << 63) #define zig_float_less_builtin_0(Type, operation) \ - zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \ + zig_extern zig_FloatCompareResult zig_expand_concat(zig_expand_concat(__##operation, \ zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ - return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ + return (int32_t)zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \ } #define zig_float_less_builtin_1(Type, operation) \ static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \ @@ -3994,13 +6084,52 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) return lhs operator rhs; \ } +#define zig_float_builtins(w) \ + zig_common_float_builtins(w) \ + zig_convert_float(f##w, zig_f##w, float, int128, zig_i128, ) \ + zig_convert_float(f##w, zig_f##w, floatun, int128, zig_u128, ) #define zig_common_float_builtins(w) \ - zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \ + zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \ + zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \ + zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \ + zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fix, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ + zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ + zig_expand_concat(zig_expand_concat(__fixuns, \ + zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ + static inline zig_f##w zig_expand_concat(zig_floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ + zig_extern zig_f##w zig_expand_concat(__floatunei, \ + zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ + return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ + } \ +\ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \ zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \ @@ -4031,82 +6160,48 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \ zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \ \ - static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divTrunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divFloor_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ - static inline zig_f##w zig_div_ceil_f##w(zig_f##w lhs, zig_f##w rhs) { \ + static inline zig_f##w zig_divCeil_f##w(zig_f##w lhs, zig_f##w rhs) { \ return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \ } \ \ static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \ - return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \ + return zig_sub_f##w(lhs, zig_mul_f##w(zig_divFloor_f##w(lhs, rhs), rhs)); \ } -zig_common_float_builtins(16) -zig_common_float_builtins(32) -zig_common_float_builtins(64) -zig_common_float_builtins(80) -zig_common_float_builtins(128) - -#define zig_float_builtins(w) \ - zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \ - zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, ) zig_float_builtins(16) -zig_float_builtins(80) -zig_float_builtins(128) - -#ifdef __ARM_EABI__ - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32); -static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32); -static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32); -static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t); -static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t); -static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t); -static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); } - -zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64); -static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64); -static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64); -static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t); -static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t); -static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); } - -zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t); -static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); } - -#else /* __ARM_EABI__ */ - zig_float_builtins(32) zig_float_builtins(64) - -#endif /* __ARM_EABI__ */ +zig_float_builtins(80) +#if defined(zig_x86_32) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_f128 arg); + return __floattitf(zig_f128_bitCast_i128(arg)); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(zig_f128 arg); + return __floatuntitf(zig_f128_bitCast_u128(arg)); +} +#elif defined(zig_x86_64) && defined(zig_windows) +zig_common_float_builtins(128) +static inline zig_f128 zig_floattitf(zig_i128 arg) { + extern zig_f128 __floattitf(zig_i128 arg); + return __floattitf(arg); +} +static inline zig_f128 zig_floatuntitf(zig_u128 arg) { + extern zig_f128 __floatuntitf(uint64_t arg_lo, uint64_t arg_hi); + return __floatuntitf(zig_lo_u128(arg), zig_hi_u128(arg)); +} +#else +zig_float_builtins(128) +#endif /* ============================ Atomics Support ============================= */ @@ -4410,19 +6505,19 @@ typedef int zig_memory_order; } \ static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \ (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \ - } \ + } \ static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \ return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } \ static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \ - Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ + Type value = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - return val; \ + return value; \ } zig_msvc_atomics( u8, uint8_t, char, 8, 8) @@ -4465,14 +6560,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64) zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } \ static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \ zig_##Type result; \ SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ _ReadWriteBarrier(); \ - memcpy(&result, &initial, sizeof(result)); \ + memcpy(&result, &initial, sizeof(result)); \ return result; \ } @@ -4502,9 +6597,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) { - void* val = (void*)__iso_volatile_load32(obj); + void* value = (void*)__iso_volatile_load32(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) { @@ -4532,9 +6627,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat } static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) { - void* val = (void*)__iso_volatile_load64(obj); + void* value = (void*)__iso_volatile_load64(obj); _ReadWriteBarrier(); - return val; + return value; } static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 9ecd3a4e0b1f4483c878e056cf3786bccafed62b..d1605b457e2f3673807c16fd10836612aae804d5 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -164,7 +164,8 @@ const BlockData = struct { const LocalType = struct { type: Type, - alignment: Alignment, + alignment: Alignment = .none, + array_len: u2 = 1, }; const LocalIndex = u16; @@ -184,13 +185,11 @@ const ValueRenderLocation = enum { } }; -const BuiltinInfo = enum { none, bits }; +const BuiltinInfo = enum { none, bits, bits_none, big_temp_bits }; const reserved_idents = std.StaticStringMap(void).initComptime(.{ // C language - .{ "alignas", { - @setEvalBranchQuota(4000); - } }, + .{ "alignas", {} }, .{ "alignof", {} }, .{ "asm", {} }, .{ "atomic_bool", {} }, @@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ // stddef.h .{ "offsetof", {} }, + // math.h (only symbols exported by compiler-rt) + .{ "ceil", {} }, + .{ "ceilf", {} }, + .{ "ceilf128", {} }, + .{ "ceill", {} }, + .{ "cos", {} }, + .{ "cosf", {} }, + .{ "cosf128", {} }, + .{ "cosl", {} }, + .{ "exp", {} }, + .{ "exp2", {} }, + .{ "exp2f", {} }, + .{ "exp2f128", {} }, + .{ "exp2l", {} }, + .{ "expf", {} }, + .{ "expf128", {} }, + .{ "expl", {} }, + .{ "fabs", {} }, + .{ "fabsf", {} }, + .{ "fabsf128", {} }, + .{ "fabsl", {} }, + .{ "floor", {} }, + .{ "floorf", {} }, + .{ "floorf128", {} }, + .{ "floorl", {} }, + .{ "fma", {} }, + .{ "fmaf", {} }, + .{ "fmaf128", {} }, + .{ "fmal", {} }, + .{ "fmax", {} }, + .{ "fmaxf", {} }, + .{ "fmaxf128", {} }, + .{ "fmaxl", {} }, + .{ "fmin", {} }, + .{ "fminf", {} }, + .{ "fminf128", {} }, + .{ "fminl", {} }, + .{ "fmod", {} }, + .{ "fmodf", {} }, + .{ "fmodf128", {} }, + .{ "fmodl", {} }, + .{ "log", {} }, + .{ "log10", {} }, + .{ "log10f", {} }, + .{ "log10f128", {} }, + .{ "log10l", {} }, + .{ "log2", {} }, + .{ "log2f", {} }, + .{ "log2f128", {} }, + .{ "log2l", {} }, + .{ "logf", {} }, + .{ "logf128", {} }, + .{ "logl", {} }, + .{ "round", {} }, + .{ "roundf", {} }, + .{ "roundf128", {} }, + .{ "roundl", {} }, + .{ "sin", {} }, + .{ "sincos", {} }, + .{ "sincosf", {} }, + .{ "sincosf128", {} }, + .{ "sincosl", {} }, + .{ "sinf", {} }, + .{ "sinf128", {} }, + .{ "sinl", {} }, + .{ "sqrt", {} }, + .{ "sqrtf", {} }, + .{ "sqrtf128", {} }, + .{ "sqrtl", {} }, + .{ "tan", {} }, + .{ "tanf", {} }, + .{ "tanf128", {} }, + .{ "tanl", {} }, + .{ "trunc", {} }, + .{ "truncf", {} }, + .{ "truncf128", {} }, + .{ "truncl", {} }, + // windows.h + .{"DUMMYSTRUCTNAME"}, + .{"DUMMYSTRUCTNAME2"}, + .{"DUMMYSTRUCTNAME3"}, + .{"DUMMYSTRUCTNAME4"}, + .{"DUMMYSTRUCTNAME5"}, + .{"DUMMYSTRUCTNAME6"}, + .{"DUMMYUNIONNAME"}, + .{"DUMMYUNIONNAME2"}, + .{"DUMMYUNIONNAME3"}, + .{"DUMMYUNIONNAME4"}, + .{"DUMMYUNIONNAME5"}, + .{"DUMMYUNIONNAME6"}, + .{"DUMMYUNIONNAME7"}, + .{"DUMMYUNIONNAME8"}, + .{"DUMMYUNIONNAME9"}, .{ "max", {} }, .{ "min", {} }, }); @@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool { } } - // windows.h - if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or - mem.startsWith(u8, ident, "DUMMYUNIONNAME")) - { - return true; - } - // CType if (mem.startsWith(u8, ident, "enum__") or mem.startsWith(u8, ident, "bitpack__") or @@ -469,10 +554,7 @@ pub const Function = struct { } fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { - return f.allocAlignedLocal(inst, .{ - .type = ty, - .alignment = .none, - }); + return f.allocAlignedLocal(inst, .{ .type = ty }); } /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should @@ -564,10 +646,6 @@ pub const Function = struct { return f.dg.renderType(w, ty); } - fn renderIntCast(f: *Function, w: *Writer, dest_ty: Type, src: CValue, v: Vectorize, src_ty: Type, location: ValueRenderLocation) !void { - return f.dg.renderIntCast(w, dest_ty, .{ .c_value = .{ .f = f, .value = src, .v = v } }, src_ty, location); - } - fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { return f.dg.fmtIntLiteralDec(val, .other); } @@ -672,7 +750,9 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const ptr_ty: Type = .fromInterned(uav.orig_ty); if (ptr_ty.isPtrAtRuntime(zcu) and !uav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.renderUndefValue(w, ptr_ty, location); + try w.writeByte('('); + try dg.renderOpvPointer(w, ptr_ty, location); + return w.writeByte(')'); } switch (ip.indexToKey(uav.val)) { @@ -737,8 +817,10 @@ pub const DeclGen = struct { // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type); const ptr_ty = try pt.navPtrType(owner_nav); - if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { - return dg.renderUndefValue(w, ptr_ty, location); + if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { + try w.writeByte('('); + try dg.renderOpvPointer(w, ptr_ty, location); + return w.writeByte(')'); } // We shouldn't cast C function pointers as this is UB (when you call @@ -758,6 +840,26 @@ pub const DeclGen = struct { if (need_cast) try w.writeByte(')'); } + fn renderOpvPointer( + dg: *DeclGen, + w: *Writer, + ptr_ty: Type, + location: ValueRenderLocation, + ) Error!void { + const zcu = dg.pt.zcu; + const target = zcu.getTarget(); + try w.writeByte('('); + try dg.renderType(w, ptr_ty); + return w.print("){f}", .{fmtUnsignedIntLiteralSmall( + target, + .uintptr_t, + ptr_ty.ptrAlignment(zcu).forward(undefPattern(u64) >> @intCast(64 - target.ptrBitWidth())), + location == .static_initializer, + 16, + .lower, + )}); + } + fn renderPointer( dg: *DeclGen, w: *Writer, @@ -959,9 +1061,6 @@ pub const DeclGen = struct { const bits = ty.floatBits(target); const f128_val = val.toFloat(f128, zcu); - // All unsigned ints matching float types are pre-allocated. - const repr_ty = pt.intType(.unsigned, bits) catch unreachable; - assert(bits <= 128); var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; var repr_val_big = BigInt.Mutable{ @@ -971,29 +1070,27 @@ pub const DeclGen = struct { }; switch (bits) { + else => unreachable, 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))), 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))), 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))), 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))), 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))), - else => unreachable, } - var empty = true; if (std.math.isFinite(f128_val)) { try w.writeAll("zig_make_"); try dg.renderTypeForBuiltinFnName(w, ty); try w.writeByte('('); switch (bits) { + else => unreachable, 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}), 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}), 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}), 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}), 128 => try w.print("{x}", .{f128_val}), - else => unreachable, } try w.writeAll(", "); - empty = false; } else { // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan const operation = if (std.math.isNan(f128_val)) @@ -1028,6 +1125,7 @@ pub const DeclGen = struct { try w.writeAll(operation); try w.writeAll(", "); if (std.math.isNan(f128_val)) switch (bits) { + else => unreachable, // We only actually need to pass the significand, but it will get // properly masked anyway, so just pass the whole value. 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), @@ -1035,16 +1133,23 @@ pub const DeclGen = struct { 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), - else => unreachable, }; try w.writeAll(", "); - empty = false; } - try w.print("{f}", .{try dg.fmtIntLiteralHex( - try pt.intValue_big(repr_ty, repr_val_big.toConst()), - location, - )}); - if (!empty) try w.writeByte(')'); + switch (bits) { + else => unreachable, + 16, 32, 64 => { + // All unsigned ints matching float types are pre-allocated. + const repr_ty = pt.intType(.unsigned, bits) catch unreachable; + try w.print("{f}", .{try dg.fmtIntLiteralHex( + try pt.intValue_big(repr_ty, repr_val_big.toConst()), + location, + )}); + }, + 80 => try F80Repr.write(@bitCast(val.toFloat(f80, zcu)), w, target, location == .static_initializer), + 128 => try F128Repr.write(@bitCast(f128_val), w, target, location == .static_initializer), + } + try w.writeByte(')'); }, .slice => |slice| { if (!location.isInitializer()) { @@ -1319,22 +1424,29 @@ pub const DeclGen = struct { .f128_type, => { const bits = ty.floatBits(target); - // All unsigned ints matching float types are pre-allocated. - const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable; try w.writeAll("zig_make_"); try dg.renderTypeForBuiltinFnName(w, ty); try w.writeByte('('); switch (bits) { - 16 => try w.print("{x}", .{@as(f16, @bitCast(undefPattern(i16)))}), - 32 => try w.print("{x}", .{@as(f32, @bitCast(undefPattern(i32)))}), - 64 => try w.print("{x}", .{@as(f64, @bitCast(undefPattern(i64)))}), - 80 => try w.print("{x}", .{@as(f80, @bitCast(undefPattern(i80)))}), - 128 => try w.print("{x}", .{@as(f128, @bitCast(undefPattern(i128)))}), else => unreachable, + 16 => try w.print("{x}", .{undefPattern(f16)}), + 32 => try w.print("{x}", .{undefPattern(f32)}), + 64 => try w.print("{x}", .{undefPattern(f64)}), + 80 => try w.print("{x}", .{undefPattern(f80)}), + 128 => try w.print("{x}", .{undefPattern(f128)}), } try w.writeAll(", "); - try dg.renderUndefValue(w, repr_ty, .other); + switch (bits) { + else => unreachable, + 16, 32, 64 => { + // All unsigned ints matching float types are pre-allocated. + const repr_ty = dg.pt.intType(.unsigned, bits) catch unreachable; + try dg.renderUndefValue(w, repr_ty, .other); + }, + 80 => try undefPattern(F80Repr).write(w, target, location == .static_initializer), + 128 => try undefPattern(F128Repr).write(w, target, location == .static_initializer), + } return w.writeByte(')'); }, .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"), @@ -1726,136 +1838,6 @@ pub const DeclGen = struct { try w.print("{f}", .{cty.fmtTypeName(zcu)}); } - const IntCastContext = union(enum) { - c_value: struct { - f: *Function, - value: CValue, - v: Vectorize, - }, - value: struct { - value: Value, - }, - - pub fn writeValue(self: *const IntCastContext, dg: *DeclGen, w: *Writer, location: ValueRenderLocation) !void { - switch (self.*) { - .c_value => |v| { - try v.f.writeCValue(w, v.value, location); - try v.v.elem(v.f, w); - }, - .value => |v| try dg.renderValue(w, v.value, location), - } - } - }; - fn intCastIsNoop(dg: *DeclGen, dest_ty: Type, src_ty: Type) bool { - const pt = dg.pt; - const zcu = pt.zcu; - const dest_bits = dest_ty.bitSize(zcu); - const dest_int_info = dest_ty.intInfo(pt.zcu); - - const src_is_ptr = src_ty.isPtrAtRuntime(pt.zcu); - const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { - .unsigned => .usize, - .signed => .isize, - } else src_ty; - - const src_bits = src_eff_ty.bitSize(zcu); - const src_int_info = if (src_eff_ty.isAbiInt(pt.zcu)) src_eff_ty.intInfo(pt.zcu) else null; - if (dest_bits <= 64 and src_bits <= 64) { - const needs_cast = src_int_info == null or - (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or - dest_int_info.signedness != src_int_info.?.signedness); - return !needs_cast and !src_is_ptr; - } else return false; - } - /// Renders a cast to an int type, from either an int or a pointer. - /// - /// Some platforms don't have 128 bit integers, so we need to use - /// the zig_make_ and zig_lo_ macros in those cases. - /// - /// | Dest type bits | Src type | Result - /// |------------------|------------------|---------------------------| - /// | < 64 bit integer | pointer | (zig_)(zig_size)src - /// | < 64 bit integer | < 64 bit integer | (zig_)src - /// | < 64 bit integer | > 64 bit integer | zig_lo(src) - /// | > 64 bit integer | pointer | zig_make_(0, (zig_size)src) - /// | > 64 bit integer | < 64 bit integer | zig_make_(0, src) - /// | > 64 bit integer | > 64 bit integer | zig_make_(zig_hi_(src), zig_lo_(src)) - fn renderIntCast( - dg: *DeclGen, - w: *Writer, - dest_ty: Type, - context: IntCastContext, - src_ty: Type, - location: ValueRenderLocation, - ) !void { - const pt = dg.pt; - const zcu = pt.zcu; - const dest_bits = dest_ty.bitSize(zcu); - const dest_int_info = dest_ty.intInfo(zcu); - - const src_is_ptr = src_ty.isPtrAtRuntime(zcu); - const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) { - .unsigned => .usize, - .signed => .isize, - } else src_ty; - - const src_bits = src_eff_ty.bitSize(zcu); - const src_int_info = if (src_eff_ty.isAbiInt(zcu)) src_eff_ty.intInfo(zcu) else null; - if (dest_bits <= 64 and src_bits <= 64) { - const needs_cast = src_int_info == null or - (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or - dest_int_info.signedness != src_int_info.?.signedness); - - if (needs_cast) { - try w.writeByte('('); - try dg.renderType(w, dest_ty); - try w.writeByte(')'); - } - if (src_is_ptr) { - try w.writeByte('('); - try dg.renderType(w, src_eff_ty); - try w.writeByte(')'); - } - try context.writeValue(dg, w, location); - } else if (dest_bits <= 64 and src_bits > 64) { - assert(!src_is_ptr); - if (dest_bits < 64) { - try w.writeByte('('); - try dg.renderType(w, dest_ty); - try w.writeByte(')'); - } - try w.writeAll("zig_lo_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeByte(')'); - } else if (dest_bits > 64 and src_bits <= 64) { - try w.writeAll("zig_make_"); - try dg.renderTypeForBuiltinFnName(w, dest_ty); - try w.writeAll("(0, "); - if (src_is_ptr) { - try w.writeByte('('); - try dg.renderType(w, src_eff_ty); - try w.writeByte(')'); - } - try context.writeValue(dg, w, .other); - try w.writeByte(')'); - } else { - assert(!src_is_ptr); - try w.writeAll("zig_make_"); - try dg.renderTypeForBuiltinFnName(w, dest_ty); - try w.writeAll("(zig_hi_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeAll("), zig_lo_"); - try dg.renderTypeForBuiltinFnName(w, src_eff_ty); - try w.writeByte('('); - try context.writeValue(dg, w, .other); - try w.writeAll("))"); - } - } - /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type. fn renderTypeAndName( dg: *DeclGen, @@ -2000,6 +1982,7 @@ pub const DeclGen = struct { switch (info) { .none => if (!is_big) return, .bits => {}, + .bits_none, .big_temp_bits => unreachable, } const int_info: std.lang.Type.Int = if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else .{ @@ -2056,6 +2039,72 @@ const CQualifiers = packed struct { restrict: bool = false, }; +pub fn genHeader(zcu: *Zcu, w: *Writer) !void { + const gpa = zcu.comp.gpa; + + var arena: std.heap.ArenaAllocator = .init(gpa); + defer arena.deinit(); + var ctype_deps: CType.Dependencies = .empty; + defer ctype_deps.deinit(gpa); + + const target = zcu.getTarget(); + switch (target.abi) { + .msvc, .itanium => try w.writeAll("#define ZIG_TARGET_ABI_MSVC\n"), + else => {}, + } + for ([_]u16{ 16, 32, 64, 80, 128 }) |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { + .hard => {}, + .soft => try w.print("#define ZIG_TARGET_SOFT_COMPILER_RT_F{d}_ABI\n", .{bits}), + }; + try w.print( + \\#define ZIG_TARGET_MAX_INT_ALIGNMENT {d} + \\#include "zig.h" + \\ + \\ + , + .{target.cMaxIntAlignment()}, + ); + + var basic_ty: Type = .fromInterned(.first_type); + while (true) : ({ + basic_ty = .fromInterned(@fromBackingInt(@intCast(@backingInt(basic_ty.toIntern()) + 1))); + if (basic_ty.toIntern() == InternPool.Index.last_type) break; + }) { + switch (basic_ty.toIntern()) { + else => {}, + .anyframe_type, + .adhoc_inferred_error_set_type, + .generic_poison_type, + => continue, // skip unsupported types + } + const basic_cty: CType = try .lower(basic_ty, &ctype_deps, arena.allocator(), zcu); + switch (basic_cty) { + .void => {}, // no layout to check + .bool, + .int, + .float, + => try CType.render_defs.writeStaticAssertTypeLayout(basic_ty, basic_cty, w, zcu), + .@"fn", + .@"enum", + .bitpack, + .@"struct", + .union_auto, + .union_extern, + .slice, + .opt, + .arr, + .vec, + .errunion, + .aligned, + .bigint, + .pointer, + .array, + .function, + => {}, + } + } +} + pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { for (zcu.global_assembly.values()) |asm_source| { try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)}); @@ -2070,16 +2119,16 @@ pub fn genErrDecls( const ip = &zcu.intern_pool; const names = ip.global_error_set.getNamesFromMainThread(); - // Don't generate an invalid empty enum if the global error set is empty! - if (names.len > 0) { - try w.writeAll("enum {\n"); - for (names, 1..) |name_nts, value| { - try w.writeByte(' '); - try renderErrorName(w, name_nts.toSlice(ip)); - try w.print(" = {d}u,\n", .{value}); - } - try w.writeAll("};\n"); + // Don't generate an invalid empty enum/array if the global error set is empty! + if (names.len == 0) return; + + try w.writeAll("enum {\n"); + for (names, 1..) |name_nts, value| { + try w.writeByte(' '); + try renderErrorName(w, name_nts.toSlice(ip)); + try w.print(" = {d}u,\n", .{value}); } + try w.writeAll("};\n"); for (names) |name_nts| { const name = name_nts.toSlice(ip); @@ -2093,7 +2142,7 @@ pub fn genErrDecls( "static {s} const zig_errorName[{d}] = {{", .{ slice_const_u8_sentinel_0_type_name, names.len }, ); - if (names.len > 0) try w.writeByte('\n'); + try w.writeByte('\n'); for (names) |name_nts| { const name = name_nts.toSlice(ip); try w.print( @@ -2114,10 +2163,18 @@ pub fn genTagNameFn( const ip = &zcu.intern_pool; const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); assert(loaded_enum.field_names.len > 0); - if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) { - @panic("TODO CBE: tagName for enum over 64 bits"); + switch (CType.classifyInt(enum_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => {}, + .zig_u128, .zig_i128 => @panic("TODO CBE: tagName for 128-bit enums"), + }, + .big => @panic("TODO CBE: tagName for bigint enums"), } + if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{ + loaded_enum.name.fmt(ip), + }); try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ slice_const_u8_sentinel_0_type_name, fmtIdentUnsolo(loaded_enum.name.toSlice(ip)), @@ -2291,6 +2348,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E .{ .nav = nav_index }, ); try header_writer.writeAll(" {\n "); + if (!f.dg.mod.strip) try header_writer.print("/* {f} */\n ", .{nav.fqn.fmt(ip)}); f.free_locals_map.clearRetainingCapacity(); @@ -2346,6 +2404,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E for (list.keys()) |local_index| { const local = f.locals.items[local_index]; try f.dg.renderTypeAndName(header_writer, local.type, .{ .local = local_index }, .{}, local.alignment); + if (local.array_len != 1) try header_writer.print("[{d}]", .{local.array_len}); try header_writer.writeAll(";\n "); } } @@ -2461,7 +2520,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct { try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); try w.writeAll(" = "); try dg.renderValue(w, options.init_val, .static_initializer); - try w.writeAll(";\n"); + try w.writeByte(';'); + if (dg.owner_nav.unwrap()) |nav_index| { + const ip = &zcu.intern_pool; + if (!dg.mod.strip) try w.print(" /* {f} */", .{ip.getNav(nav_index).fqn.fmt(ip)}); + } + try w.writeByte('\n'); } pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct { name: CValue, @@ -2662,22 +2726,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .mul => try airBinOp(f, inst, "*", "mul", .none), .neg => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "neg", .none), - .div_float => try airBinBuiltinCall(f, inst, "div", .none), + .div_float => try airBinBuiltinCall(f, inst, "div", .big_temp_bits), - .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none), + .div_trunc, .div_exact => try airBinOp(f, inst, "/", "divTrunc", .big_temp_bits), .rem => blk: { const bin_op = air_datas[@intFromEnum(inst)].bin_op; const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu); // For binary operations @TypeOf(lhs)==@TypeOf(rhs), // so we only check one. break :blk if (lhs_scalar_ty.isInt(zcu)) - try airBinOp(f, inst, "%", "rem", .none) + try airBinOp(f, inst, "%", "rem", .big_temp_bits) else try airBinBuiltinCall(f, inst, "fmod", .none); }, - .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), - .div_ceil => try airBinBuiltinCall(f, inst, "div_ceil", .none), - .mod => try airBinBuiltinCall(f, inst, "mod", .none), + .div_floor => try airBinBuiltinCall(f, inst, "divFloor", .big_temp_bits), + .div_ceil => try airBinBuiltinCall(f, inst, "divCeil", .big_temp_bits), + .mod => try airBinBuiltinCall(f, inst, "mod", .big_temp_bits), .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none), .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits), @@ -2687,7 +2751,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits), .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits), .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits), - .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits), + .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits_none), .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none), .sin => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sin", .none), @@ -2764,8 +2828,8 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .int_from_error => try airNopCast(f, inst), .union_from_enum => try airUnionFromEnum(f, inst), .bit_cast => try airBitCast(f, inst), - .int_cast => try airIntCast(f, inst), - .trunc => try airTrunc(f, inst), + .int_cast => try airIntCast(f, inst, "intCast", .none), + .trunc => try airIntCast(f, inst, "truncate", .bits), .load => try airLoad(f, inst), .store => try airStore(f, inst, false), .store_safe => try airStore(f, inst, true), @@ -2783,9 +2847,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { .get_union_tag => try airGetUnionTag(f, inst), .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits), .ctz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "ctz", .bits), - .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popcount", .bits), - .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byte_swap", .bits), - .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits), + .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popCount", .bits), + .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byteSwap", .bits), + .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bitReverse", .bits), .tag_name => try airTagName(f, inst), .error_name => try airErrorName(f, inst), .splat => try airSplat(f, inst), @@ -3124,7 +3188,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = pt.zcu; const inst_ty = f.typeOfIndex(inst); const elem_ty = inst_ty.childType(zcu); - if (!elem_ty.hasRuntimeBits(zcu)) return .{ .undef = inst_ty }; + if (!elem_ty.hasRuntimeBits(zcu)) { + const w = &f.code.writer; + const local = try f.allocLocal(inst, inst_ty); + try f.writeCValue(w, local, .other); + try w.writeAll(" = "); + try f.dg.renderOpvPointer(w, inst_ty, .other); + try w.writeByte(';'); + try f.newline(); + return local; + } const local = try f.allocLocalValue(.{ .type = elem_ty, @@ -3298,120 +3371,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { } } -fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { +fn airIntCast(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { const pt = f.dg.pt; const zcu = pt.zcu; const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; - const operand = try f.resolveInst(ty_op.operand); - try reap(f, inst, &.{ty_op.operand}); - - const inst_ty = f.typeOfIndex(inst); + const inst_ty = ty_op.ty.toType(); const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(zcu); - - // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct. - if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) { - return f.moveCValue(inst, inst_ty, operand); - } - - const w = &f.code.writer; - const local = try f.allocLocal(inst, inst_ty); - const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); - try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other); - try w.writeByte(';'); - try f.newline(); - try v.end(f, inst, w); - return local; -} - -fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { - const pt = f.dg.pt; - const zcu = pt.zcu; - const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; + const operand_scalar_ty = operand_ty.scalarType(zcu); + const is_big = lowersToBigInt(operand_ty, zcu); const operand = try f.resolveInst(ty_op.operand); - try reap(f, inst, &.{ty_op.operand}); - - const inst_ty = f.typeOfIndex(inst); - const inst_scalar_ty = inst_ty.scalarType(zcu); - const dest_int_info = inst_scalar_ty.intInfo(zcu); - const dest_bits = dest_int_info.bits; - const dest_c_bits = toCIntBits(dest_bits) orelse - return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const operand_ty = f.typeOf(ty_op.operand); - const scalar_ty = operand_ty.scalarType(zcu); - const scalar_int_info = scalar_ty.intInfo(zcu); + if (!is_big) try reap(f, inst, &.{ty_op.operand}); - const need_cast = dest_c_bits < 64; - const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64; - const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); - if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); + if (is_big) try reap(f, inst, &.{ty_op.operand}); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); - if (need_cast) { - try w.writeByte('('); - try f.renderType(w, inst_scalar_ty); - try w.writeByte(')'); - } - if (need_lo) { - try w.writeAll("zig_lo_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - try w.writeByte('('); + if (!ref_ret) { + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(" = "); } - if (!need_mask) { - try f.writeCValue(w, operand, .other); + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try w.print("_{s}_", .{operation}); + try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty); + try w.writeByte('('); + if (ref_ret) { + try w.writeByte('&'); + try f.writeCValue(w, local, .other); try v.elem(f, w); - } else switch (dest_int_info.signedness) { - .unsigned => { - try w.writeAll("zig_and_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - try w.writeByte('('); - try f.writeCValue(w, operand, .other); - try v.elem(f, w); - try w.print(", {f})", .{ - try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), - }); - }, - .signed => { - const c_bits = toCIntBits(scalar_int_info.bits) orelse - return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); - const shift_val = try pt.intValue(.u8, c_bits - dest_bits); - - try w.writeAll("zig_shr_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); - if (c_bits == 128) { - try w.print("(zig_bitCast_i{d}(", .{c_bits}); - } else { - try w.print("((int{d}_t)", .{c_bits}); - } - try w.print("zig_shl_u{d}(", .{c_bits}); - if (c_bits == 128) { - try w.print("zig_bitCast_u{d}(", .{c_bits}); - } else { - try w.print("(uint{d}_t)", .{c_bits}); - } - try f.writeCValue(w, operand, .other); - try v.elem(f, w); - if (c_bits == 128) try w.writeByte(')'); - try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); - if (c_bits == 128) try w.writeByte(')'); - try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); - }, + try w.writeAll(", "); } - if (need_lo) try w.writeByte(')'); - try w.writeByte(';'); + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, inst_scalar_ty, info); + try f.dg.renderBuiltinInfo(w, operand_scalar_ty, .none); + try w.writeAll(");"); try f.newline(); try v.end(f, inst, w); + return local; } @@ -3525,39 +3535,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl; const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; + const lhs_ty = f.typeOf(bin_op.lhs); + const rhs_ty = f.typeOf(bin_op.rhs); + const is_big = lowersToBigInt(lhs_ty, zcu); + const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const inst_ty = f.typeOfIndex(inst); - const operand_ty = f.typeOf(bin_op.lhs); - const scalar_ty = operand_ty.scalarType(zcu); + const lhs_scalar_ty = lhs_ty.scalarType(zcu); + const rhs_scalar_ty = rhs_ty.scalarType(zcu); - const ref_arg = lowersToBigInt(scalar_ty, zcu); + const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu); + const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu); const w = &f.code.writer; - const local = try f.allocLocal(inst, inst_ty); - const v = try Vectorize.start(f, inst, w, operand_ty); + const local = try f.allocLocal(inst, f.typeOfIndex(inst)); + if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); + const v = try Vectorize.start(f, inst, w, lhs_ty); try f.writeCValueMember(w, local, .{ .field = 1 }); try v.elem(f, w); - try w.writeAll(" = zig_"); + try w.writeAll(" = "); + try w.writeAll("zig_"); try w.writeAll(operation); try w.writeAll("o_"); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty); try w.writeByte('('); // '&dest', possibly preceded by a cast - switch (zcu.intern_pool.indexToKey(scalar_ty.toIntern())) { + switch (zcu.intern_pool.indexToKey(lhs_scalar_ty.toIntern())) { .int_type => {}, // we already have a '[u]intX_t *' .simple_type => { // '&dest' will be something like a 'uintptr_t *', which might be a different C type to // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a // cast on the *operands* because they are passed by value (except for big integers, // where this issue doesn't exist because no "simple" int type needs bigint repr). - try w.print("({s}int{d}_t *)", .{ - if (scalar_ty.isUnsignedInt(zcu)) "u" else "", - scalar_ty.abiSize(zcu) * 8, - }); + const inst_int_info = lhs_scalar_ty.intInfo(zcu); + try w.print("({s}int{d}_t *)", .{ switch (inst_int_info.signedness) { + .signed => "", + .unsigned => "u", + }, inst_int_info.bits }); }, else => unreachable, } @@ -3566,14 +3583,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_lhs) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); - if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, scalar_ty, info); + if (ref_rhs) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info); try w.writeAll(");"); try f.newline(); try v.end(f, inst, w); @@ -3622,8 +3649,18 @@ fn airBinOp( const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; const operand_ty = f.typeOf(bin_op.lhs); const scalar_ty = operand_ty.scalarType(zcu); - if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat()) - return try airBinBuiltinCall(f, inst, operation, info); + + builtin: { + if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } else if (!scalar_ty.isRuntimeFloat()) break :builtin; + return airBinBuiltinCall(f, inst, operation, info); + } const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3662,19 +3699,21 @@ fn airCmpOp( const lhs_ty = f.typeOf(data.lhs); const scalar_ty = lhs_ty.scalarType(zcu); - if (scalar_ty.isInt(zcu)) { - const scalar_bits = scalar_ty.bitSize(zcu); - if (scalar_bits > 64) return airCmpBuiltinCall( - f, - inst, - data, - operator, - .cmp, - if (scalar_bits > 128) .bits else .none, - ); + builtin: { + if (scalar_ty.isInt(zcu)) { + switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } + return airCmpBuiltinCall(f, inst, data, operator, .cmp, .none); + } + if (scalar_ty.isRuntimeFloat()) + return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); } - if (scalar_ty.isRuntimeFloat()) - return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); const inst_ty = f.typeOfIndex(inst); const lhs = try f.resolveInst(data.lhs); @@ -3716,21 +3755,23 @@ fn airEquality( const pt = f.dg.pt; const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; - const operand_ty = f.typeOf(bin_op.lhs); - if (operand_ty.isAbiInt(zcu)) { - const operand_bits = operand_ty.bitSize(zcu); - if (operand_bits > 64) return airCmpBuiltinCall( - f, - inst, - bin_op, - operator, - .cmp, - if (operand_bits > 128) .bits else .none, - ); + + builtin: { + if (operand_ty.isAbiInt(zcu)) { + switch (CType.classifyInt(operand_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } + return airCmpBuiltinCall(f, inst, bin_op, operator, .cmp, .none); + } + if (operand_ty.isRuntimeFloat()) + return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); } - if (operand_ty.isRuntimeFloat()) - return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3809,7 +3850,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { try f.writeCValue(w, local, .other); try w.writeAll(" = "); try f.writeCValue(w, operand, .other); - try w.writeAll(" < sizeof(zig_errorName) / sizeof(*zig_errorName);"); + try w.writeAll(" <= sizeof(zig_errorName) / sizeof(*zig_errorName);"); try f.newline(); return local; } @@ -3862,8 +3903,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - if ((inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) or inst_scalar_ty.isRuntimeFloat()) - return try airBinBuiltinCall(f, inst, operation, .none); + builtin: { + if (inst_scalar_ty.isInt(zcu)) switch (CType.classifyInt(inst_scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => break :builtin, + .zig_u128, .zig_i128 => {}, + }, + .big => {}, + } else if (!inst_scalar_ty.isRuntimeFloat()) break :builtin; + return airBinBuiltinCall(f, inst, operation, .none); + } const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -3979,10 +4029,7 @@ fn airCall( try w.writeAll("(void)"); break :result .none; } else { - const local = try f.allocAlignedLocal(inst, .{ - .type = ret_ty, - .alignment = .none, - }); + const local = try f.allocAlignedLocal(inst, .{ .type = ret_ty }); try f.writeCValue(w, local, .other); try w.writeAll(" = "); break :result local; @@ -4058,16 +4105,7 @@ fn airCall( fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt; const w = &f.code.writer; - // TODO re-evaluate whether to emit these or not. If we naively emit - // these directives, the output file will report bogus line numbers because - // every newline after the #line directive adds one to the line. - // We also don't print the filename yet, so the output is strictly unhelpful. - // If we wanted to go this route, we would need to go all the way and not output - // newlines until the next dbg_stmt occurs. - // Perhaps an additional compilation option is in order? - //try w.print("#line {d}", .{dbg_stmt.line + 1}); - //try f.newline(); - try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); + try w.print("/* {d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); try f.newline(); return .none; } @@ -4433,12 +4471,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { const operand_scalar_ty = operand_ty.scalarType(zcu); const dest_scalar_ty = dest_ty.scalarType(zcu); - // Some cases are handled with a simple cast: - // * float -> float - // * bool -> int if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or (operand_scalar_ty.toIntern() == .bool_type and dest_scalar_ty.isAbiInt(zcu))) { + // Some cases are handled with a simple cast: + // * float -> float + // * bool -> int try f.writeCValue(w, dest_local, .other); try v.elem(f, w); try w.writeAll(" = ("); @@ -4458,85 +4496,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { try v.elem(f, w); try w.writeAll(" != 0;"); try f.newline(); - } else if (dest_scalar_ty.isRuntimeFloat()) { - // For int->float, just do a memcpy. - assert(operand_scalar_ty.isAbiInt(zcu)); - try w.writeAll("memcpy(&"); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(", &"); - switch (operand) { - .constant => |val| try f.dg.renderValueAsLvalue(w, val), - else => try f.writeCValue(w, operand, .other), - } - try v.elem(f, w); - try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))}); - try f.newline(); } else { - // The only remaining possibility is that the result is an integer. We will need to use - // `zig_wrap_*` to correct the "padding" bits after we populate the value bits. - assert(dest_scalar_ty.isAbiInt(zcu)); assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu)); + assert(dest_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isAbiInt(zcu)); - // memcpy the value... - try w.writeAll("memcpy(&"); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(", &"); - switch (operand) { - .constant => |val| try f.dg.renderValueAsLvalue(w, val), - else => try f.writeCValue(w, operand, .other), + const ref_ret = lowersToBigInt(dest_scalar_ty, zcu); + const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); + + if (!ref_ret) { + try f.writeCValue(w, dest_local, .other); + try v.elem(f, w); + try w.writeAll(" = "); + } + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty); + try w.writeAll("_bitCast_"); + try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty); + try w.writeByte('('); + if (ref_ret) { + try w.writeByte('&'); + try f.writeCValue(w, dest_local, .other); + try v.elem(f, w); + try w.writeAll(", "); } + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); - try w.print(", {d});", .{@min(operand_scalar_ty.abiSize(zcu), dest_scalar_ty.abiSize(zcu))}); + try f.dg.renderBuiltinInfo( + w, + dest_scalar_ty, + if (operand_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isRuntimeFloat()) .none else .bits, + ); + try w.writeAll(");"); try f.newline(); - - // ...and ensure padding bits have the correct value. - switch (CType.classifyInt(dest_scalar_ty, zcu)) { - .void => unreachable, // opv - .small => { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.writeAll(" = zig_wrap_"); - try f.dg.renderTypeForBuiltinFnName(w, dest_scalar_ty); - try w.writeByte('('); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, dest_scalar_ty, .bits); - try w.writeAll(");"); - try f.newline(); - }, - .big => |big| { - const dest_info = dest_scalar_ty.intInfo(zcu); - const padding_index: u16 = switch (f.dg.mod.resolved_target.result.cpu.arch.endian()) { - .little => big.limbs_len - 1, - .big => 0, - }; - const wrap_bits = ((dest_info.bits - 1) % big.limb_size.bits()) + 1; - if (big.limb_size != .@"128" or dest_info.signedness == .unsigned) { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}] = zig_wrap_{c}{d}(", .{ - padding_index, - signAbbrev(dest_info.signedness), - big.limb_size.bits(), - }); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}], {d});", .{ padding_index, wrap_bits }); - } else { - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}] = zig_bitCast_u128(zig_wrap_i128(zig_bitCast_i128(", .{ - padding_index, - }); - try f.writeCValue(w, dest_local, .other); - try v.elem(f, w); - try w.print(".limbs[{d}]), {d}));", .{ padding_index, wrap_bits }); - try f.newline(); - } - }, - } } try v.end(f, inst, w); @@ -4906,11 +4903,9 @@ fn lowerSwitchCmp( fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { const dg = f.dg; - const target = &dg.mod.resolved_target.result; return switch (constraint[0]) { '{' => true, - 'i', 'r' => false, - 'I' => !target.cpu.arch.isArm(), + 'r', 'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' => false, else => switch (value) { .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) { .ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) { @@ -4937,10 +4932,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const w = &f.code.writer; const inst_ty = f.typeOfIndex(inst); const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { - const inst_local = try f.allocLocalValue(.{ - .type = inst_ty, - .alignment = .none, - }); + const inst_local = try f.allocLocalValue(.{ .type = inst_ty }); if (f.wantSafety()) { try f.writeCValue(w, inst_local, .other); try w.writeAll(" = "); @@ -4967,10 +4959,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (is_reg) { const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu); try w.writeAll("register "); - const output_local = try f.allocLocalValue(.{ - .type = output_ty, - .alignment = .none, - }); + const output_local = try f.allocLocalValue(.{ .type = output_ty }); try f.allocs.put(gpa, output_local.new_local, false); try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none); try w.writeAll(" __asm(\""); @@ -5000,10 +4989,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (asmInputNeedsLocal(f, constraint, input_val)) { const input_ty = f.typeOf(input.operand); if (is_reg) try w.writeAll("register "); - const input_local = try f.allocLocalValue(.{ - .type = input_ty, - .alignment = .none, - }); + const input_local = try f.allocLocalValue(.{ .type = input_ty }); try f.allocs.put(gpa, input_local.new_local, false); // Do not render the declaration as `const` qualified if we're generating an // explicit `register` local, as GCC will ignore the constraint completely. @@ -5853,28 +5839,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { else unreachable; + const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); + const ref_operand = lowersToBigInt(scalar_ty, zcu); + const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, local, .other); - try v.elem(f, w); - try w.writeAll(" = "); + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try w.writeAll("zig_"); + try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); + try w.print("_intCast_{c}{d}", .{ + @as(u8, switch (inst_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), + }); + try w.writeAll("(&"); + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(", "); + } + } else { + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(" = "); + } if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { - try w.writeAll("zig_wrap_"); - try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); - try w.writeByte('('); + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) try w.print("zig_{c}{d}_truncate_{[0]c}{[1]d}(", .{ + @as(u8, switch (inst_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), + }); } try w.writeAll("zig_"); try w.writeAll(operation); try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); try w.writeByte('('); - try f.writeCValue(w, operand, .other); - try v.elem(f, w); + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits > 128) { + try w.writeByte('&'); + try f.writeCValue(w, local, .other); + try v.elem(f, w); + try w.writeAll(", "); + } + } + if (ref_operand) { + const operand_int_info = scalar_ty.intInfo(zcu); + if (operand_int_info.bits <= 128) { + try w.print("zig_{c}{d}_intCast_", .{ + @as(u8, switch (operand_int_info.signedness) { + .signed => 'i', + .unsigned => 'u', + }), + std.math.ceilPowerOfTwoAssert(u16, @max(operand_int_info.bits, 32)), + }); + try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try w.writeAll("(&"); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, scalar_ty, .none); + try w.writeByte(')'); + } else { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + try v.elem(f, w); + try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( + target, + .uint16_t, + operand_int_info.bits, + false, + 10, + .lower, + )}); + } + } else { + try f.writeCValue(w, operand, .other); + try v.elem(f, w); + } + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits > 128) try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( + target, + .uint16_t, + inst_int_info.bits, + false, + 10, + .lower, + )}); + } try w.writeByte(')'); if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { - try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); - try w.writeByte(')'); + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try w.print(", {f}", .{ + try f.dg.fmtIntLiteralDec(try pt.intValue(.u8, inst_int_info.bits), .other), + }); + try w.writeByte(')'); + } + } + if (ref_ret) { + const inst_int_info = inst_scalar_ty.intInfo(zcu); + if (inst_int_info.bits <= 128) { + try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .none); + try w.writeByte(')'); + } } try w.writeByte(';'); try f.newline(); @@ -5893,18 +5975,21 @@ fn airUnBuiltinCall( const pt = f.dg.pt; const zcu = pt.zcu; - const operand = try f.resolveInst(operand_ref); - try reap(f, inst, &.{operand_ref}); const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); const operand_ty = f.typeOf(operand_ref); const scalar_ty = operand_ty.scalarType(zcu); + const is_big = lowersToBigInt(operand_ty, zcu); + + const operand = try f.resolveInst(operand_ref); + if (!is_big) try reap(f, inst, &.{operand_ref}); const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); const ref_arg = lowersToBigInt(scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); + if (is_big) try reap(f, inst, &.{operand_ref}); const v = try Vectorize.start(f, inst, w, operand_ty); if (!ref_ret) { try f.writeCValue(w, local, .other); @@ -5920,8 +6005,13 @@ fn airUnBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, operand, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeAll(");"); @@ -5941,8 +6031,9 @@ fn airBinBuiltinCall( const zcu = pt.zcu; const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; - const operand_ty = f.typeOf(bin_op.lhs); - const is_big = lowersToBigInt(operand_ty, zcu); + const lhs_ty = f.typeOf(bin_op.lhs); + const rhs_ty = f.typeOf(bin_op.rhs); + const is_big = lowersToBigInt(lhs_ty, zcu); const lhs = try f.resolveInst(bin_op.lhs); const rhs = try f.resolveInst(bin_op.rhs); @@ -5950,22 +6041,31 @@ fn airBinBuiltinCall( const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); - const scalar_ty = operand_ty.scalarType(zcu); + const lhs_scalar_ty = lhs_ty.scalarType(zcu); + const rhs_scalar_ty = rhs_ty.scalarType(zcu); const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); - const ref_arg = lowersToBigInt(scalar_ty, zcu); + const ref_lhs = lowersToBigInt(lhs_scalar_ty, zcu); + const ref_rhs = lowersToBigInt(rhs_scalar_ty, zcu); const w = &f.code.writer; const local = try f.allocLocal(inst, inst_ty); if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - const v = try Vectorize.start(f, inst, w, operand_ty); + const v = try Vectorize.start(f, inst, w, lhs_ty); if (!ref_ret) { try f.writeCValue(w, local, .other); try v.elem(f, w); try w.writeAll(" = "); } try w.print("zig_{s}_", .{operation}); - try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); + try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty); + switch (info) { + .bits, .none, .big_temp_bits => {}, + .bits_none => { + try w.writeByte('_'); + try f.dg.renderTypeForBuiltinFnName(w, rhs_scalar_ty); + }, + } try w.writeByte('('); if (ref_ret) { try w.writeByte('&'); @@ -5973,15 +6073,45 @@ fn airBinBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_lhs) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); - if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); - try f.dg.renderBuiltinInfo(w, scalar_ty, info); - try w.writeAll(");\n"); + if (ref_rhs) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); + try v.elem(f, w); + try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info: switch (info) { + .none => .none, + .bits, .bits_none => .bits, + .big_temp_bits => { + if (lowersToBigInt(lhs_scalar_ty, zcu)) { + const temp_local = try f.allocAlignedLocal(inst, .{ + .type = lhs_scalar_ty, + .array_len = 2, + }); + try w.writeAll(", &"); + try f.writeCValue(w, temp_local, .other); + try freeLocal(f, inst, temp_local.new_local, null); + } + break :info .none; + }, + }); + switch (info) { + .none, .bits, .big_temp_bits => {}, + .bits_none => try f.dg.renderBuiltinInfo(w, rhs_scalar_ty, .none), + } + try w.writeAll(");"); + try f.newline(); try v.end(f, inst, w); return local; @@ -6029,12 +6159,22 @@ fn airCmpBuiltinCall( try v.elem(f, w); try w.writeAll(", "); } - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, lhs, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (lhs) { + .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), + else => try f.writeCValue(w, lhs, .other), + } + } else try f.writeCValue(w, lhs, .other); try v.elem(f, w); try w.writeAll(", "); - if (ref_arg) try w.writeByte('&'); - try f.writeCValue(w, rhs, .other); + if (ref_arg) { + try w.writeByte('&'); + switch (rhs) { + .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), + else => try f.writeCValue(w, rhs, .other), + } + } else try f.writeCValue(w, rhs, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, info); try w.writeByte(')'); @@ -6595,7 +6735,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { }, .value => |val| try f.dg.renderValue(w, .fromInterned(val), .other), } - try w.writeAll(";\n"); + try w.writeByte(';'); + try f.newline(); } return local; @@ -6653,7 +6794,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { const operand_ty = f.typeOf(reduce.operand); const w = &f.code.writer; - const use_operator = scalar_ty.bitSize(zcu) <= 64; + const use_operator, const is_big = if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) { + .void => unreachable, + .small => |int| switch (int) { + else => .{ true, false }, + .zig_u128, .zig_i128 => .{ false, false }, + }, + .big => .{ false, true }, + } else .{ false, false }; const op: union(enum) { const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; builtin: Func, @@ -6742,25 +6890,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { try f.newline(); const v = try Vectorize.start(f, inst, w, operand_ty); - try f.writeCValue(w, accum, .other); switch (op) { .builtin => |func| { - try w.print(" = zig_{s}_", .{func.operation}); + const prev_accum = if (is_big) prev_accum: { + const prev_accum = try f.allocLocal(inst, scalar_ty); + try f.writeCValue(w, prev_accum, .other); + try w.writeAll(" = "); + try f.writeCValue(w, accum, .other); + try w.writeByte(';'); + try f.newline(); + break :prev_accum prev_accum; + } else prev_accum: { + try f.writeCValue(w, accum, .other); + try w.writeAll(" = "); + break :prev_accum accum; + }; + try w.print("zig_{s}_", .{func.operation}); try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); try w.writeByte('('); - try f.writeCValue(w, accum, .other); + if (is_big) { + try w.writeByte('&'); + switch (accum) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, accum, .other), + } + try w.writeAll(", &"); + switch (prev_accum) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, prev_accum, .other), + } + } else try f.writeCValue(w, prev_accum, .other); try w.writeAll(", "); - try f.writeCValue(w, operand, .other); + if (is_big) { + try w.writeByte('&'); + switch (operand) { + .constant => |val| try f.dg.renderValueAsLvalue(w, val), + else => try f.writeCValue(w, operand, .other), + } + } else try f.writeCValue(w, operand, .other); try v.elem(f, w); try f.dg.renderBuiltinInfo(w, scalar_ty, func.info); try w.writeByte(')'); + if (is_big) try freeLocal(f, inst, prev_accum.new_local, null); }, .infix => |ass| { + try f.writeCValue(w, accum, .other); try w.writeAll(ass); try f.writeCValue(w, operand, .other); try v.elem(f, w); }, .ternary => |cmp| { + try f.writeCValue(w, accum, .other); try w.writeAll(" = "); try f.writeCValue(w, accum, .other); try w.writeAll(cmp); @@ -7224,17 +7404,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 { fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 { return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) { + 0 => unreachable, 1...32 => "si", 33...64 => "di", 65...128 => "ti", - else => unreachable, + else => "ei", } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { + else => unreachable, 16 => "hf", 32 => "sf", 64 => "df", 80 => "xf", - 128 => "tf", - else => unreachable, + 128 => if (target.cpu.arch.isPowerPC()) "kf" else "tf", } else unreachable; } @@ -7390,10 +7571,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont return .{ .data = .{ .str = str, .sentinel = sentinel } }; } -fn undefPattern(comptime IntType: type) IntType { - const int_info = @typeInfo(IntType).int; - const UnsignedType = @Int(.unsigned, int_info.bits); - return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); +fn undefPattern(comptime Result: type) Result { + return @bitCast(@as(@Int(.unsigned, @bitSizeOf(Result)), (1 << (@bitSizeOf(Result) | 1)) / 3)); } const FormatIntLiteralContext = struct { @@ -7580,11 +7759,9 @@ const FormatSignedIntLiteralSmall = struct { case: std.fmt.Case, pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void { const bits = data.int_cty.bits(data.target); - const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1); - const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1)); - if (data.val == max_int) { + if (data.val == @as(i64, std.math.maxInt(i64)) >> @intCast(64 - bits)) { return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); - } else if (data.val == min_int) { + } else if (data.val == @as(i64, std.math.minInt(i64)) >> @intCast(64 - bits)) { return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)}); } if (data.val < 0) try w.writeByte('-'); @@ -7596,7 +7773,7 @@ const FormatSignedIntLiteralSmall = struct { 16 => try w.writeAll("0x"), else => unreachable, } - // This `@abs` is safe thanks to the `min_int` case above. + // This `@abs` is safe thanks to the min int check above. try w.printInt(@abs(data.val), data.base, data.case, .{}); try w.writeAll(intLiteralSuffix(data.int_cty)); } @@ -7610,8 +7787,7 @@ const FormatUnsignedIntLiteralSmall = struct { case: std.fmt.Case, pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void { const bits = data.int_cty.bits(data.target); - const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits); - if (data.val == max_int) { + if (data.val == @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)) { return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); } try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); @@ -7735,6 +7911,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 { }; } +const F80Repr = packed struct { + mantissa: u64, + exponent: u16, + + fn write(repr: F80Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void { + try w.print("zig_{s}_repr_f80({f}, {f})", .{ + if (is_global) "init" else "make", + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.mantissa, is_global, 16, .lower), + fmtUnsignedIntLiteralSmall(target, .uint16_t, repr.exponent, is_global, 16, .lower), + }); + } +}; +const F128Repr = packed struct { + lo: u64, + hi: u64, + + fn write(repr: F128Repr, w: *Writer, target: *const std.Target, is_global: bool) Writer.Error!void { + try w.print("zig_{s}_repr_f128({f}, {f})", .{ + if (is_global) "init" else "make", + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.hi, is_global, 16, .lower), + fmtUnsignedIntLiteralSmall(target, .uint64_t, repr.lo, is_global, 16, .lower), + }); + } +}; + const Materialize = struct { local: CValue, diff --git a/src/codegen/c/type/render_defs.zig b/src/codegen/c/type/render_defs.zig index 866ea38cc44be5a44e0dba9aa6c75cf989cb664b..bfa368d3ceee36ac575898019e1b48d19a20d066 100644 --- a/src/codegen/c/type/render_defs.zig +++ b/src/codegen/c/type/render_defs.zig @@ -21,16 +21,21 @@ pub fn defineAligned( if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); } - try w.print("{f}{f}{f}; /* align({d}) {f} */\n", .{ + try w.print("{f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), + }); + if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{ alignment.toByteUnits().?, ty.fmt(pt), }); + try w.writeByte('\n'); } /// Renders the definition of a big-int `struct`. pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error!void { + const target = zcu.getTarget(); + const bits = big.limb_size.bits() *| big.limbs_len; const name_cty: CType = .{ .bigint = .{ .limb_size = big.limb_size, .limbs_len = big.limbs_len, @@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error .elem_ty = &limb_cty, .nonstring = limb_cty.isStringElem(), } }; - try w.print("{f} {{ {f}limbs{f}; }}; /* {d} bits */\n", .{ + try w.print("{f} {{ {f}limbs{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - big.limb_size.bits() * @as(u17, big.limbs_len), }); + if (!zcu.comp.config.root_strip) try w.print(" /* u{d}, i{d} */", .{ bits, bits }); + try w.writeByte('\n'); + try writeStaticAssertCTypeLayout( + name_cty, + std.zig.target.intByteSize(target, bits), + .fromByteUnits(std.zig.target.intAlignment(target, bits)), + w, + zcu, + ); } /// Renders a forward declaration of the `struct` which represents an error union whose payload type @@ -81,27 +94,28 @@ pub fn errunionDefineComplete( if (payload_ty.hasRuntimeBits(zcu)) { const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu); try w.print( - \\{f} {{ /* anyerror!{f} */ + \\{f} {{ \\ {f}payload{f}; \\ {f}error{f}; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - payload_ty.fmt(pt), payload_cty.fmtDeclaratorPrefix(zcu), payload_cty.fmtDeclaratorSuffix(zcu), error_cty.fmtDeclaratorPrefix(zcu), error_cty.fmtDeclaratorSuffix(zcu), }); } else { - try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{ + try w.print("{f} {{ {f}error{f}; }};", .{ name_cty.fmtTypeName(zcu), error_cty.fmtDeclaratorPrefix(zcu), error_cty.fmtDeclaratorSuffix(zcu), - payload_ty.fmt(pt), }); } + if (!zcu.comp.config.root_strip) try w.print(" /* anyerror!{f} */", .{ + payload_ty.fmt(pt), + }); + try w.writeByte('\n'); } /// If the Zig type `ty` lowers to a `struct` or `union` type, renders a forward declaration of that @@ -141,10 +155,13 @@ pub fn defineIncomplete(ty: Type, w: *Writer, pt: Zcu.PerThread) Writer.Error!vo }, else => return, }; - try w.print("typedef void {f}; /* {f} */\n", .{ + try w.print("typedef void {f};", .{ name_cty.fmtTypeName(zcu), + }); + if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ ty.fmt(pt), }); + try w.writeByte('\n'); } /// If the Zig type `ty` lowers to a `struct` or `union` type, or to a `typedef`, renders the @@ -163,13 +180,13 @@ pub fn defineComplete( ty.assertHasLayout(zcu); - switch (ty.zigTypeTag(zcu)) { + const check_cty = check_cty: switch (ty.zigTypeTag(zcu)) { .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) { const name_cty: CType = .{ .@"fn" = ty }; - try w.print("typedef void {f}; /* {f} */\n", .{ + try w.print("typedef void {f};", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); + break :check_cty null; } else { const ip = &zcu.intern_pool; const func_type = ip.indexToKey(ty.toIntern()).func_type; @@ -205,82 +222,82 @@ pub fn defineComplete( } else if (!any_params) { try w.writeAll("void"); } - try w.print("){f}; /* {f} */\n", .{ + try w.print("){f};", .{ ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), - ty.fmt(pt), }); + break :check_cty null; }, .@"enum" => { const name_cty: CType = .{ .@"enum" = ty }; const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu); - try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + try w.print("typedef {f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); + break :check_cty null; }, - .@"struct" => if (ty.isTuple(zcu)) { - try defineTuple(ty, deps, arena, w, pt); - } else switch (ty.containerLayout(zcu)) { - .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt), + .@"struct" => if (ty.isTuple(zcu)) + if (ty.hasRuntimeBits(zcu)) try defineTuple(ty, deps, arena, w, pt) else return + else switch (ty.containerLayout(zcu)) { + .auto, .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineStruct(ty, deps, arena, w, pt) else return, .@"packed" => try defineBitpack(ty, deps, arena, w, pt), }, .@"union" => switch (ty.containerLayout(zcu)) { - .auto => try defineUnionAuto(ty, deps, arena, w, pt), - .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt), + .auto => if (ty.hasRuntimeBits(zcu)) try defineUnionAuto(ty, deps, arena, w, pt) else return, + .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineUnionExtern(ty, deps, arena, w, pt) else return, .@"packed" => try defineBitpack(ty, deps, arena, w, pt), }, .pointer => if (ty.isSlice(zcu)) { const name_cty: CType = .{ .slice = ty }; const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu); try w.print( - \\{f} {{ /* {f} */ + \\{f} {{ \\ {f}ptr{f}; \\ size_t len; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), ptr_cty.fmtDeclaratorPrefix(zcu), ptr_cty.fmtDeclaratorSuffix(zcu), }); - // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess - // slices up, and they're all obviously the same layout. - }, + break :check_cty switch (ty.toIntern()) { + .slice_const_u8_sentinel_0_type => name_cty, + else => null, + }; + } else return, .optional => switch (CType.classifyOptional(ty, zcu)) { .error_set, .ptr_like, .slice_like, .npv_payload, - => {}, + => return, .opv_payload => { const name_cty: CType = .{ .opt = ty }; - try w.print("{f} {{ bool is_null; }}; /* {f} */\n", .{ + try w.print("{f} {{ bool is_null; }};", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); + break :check_cty switch (ty.toIntern()) { + .optional_noreturn_type => name_cty, + else => null, + }; }, .@"struct" => { const name_cty: CType = .{ .opt = ty }; const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu); try w.print( - \\{f} {{ /* {f} */ + \\{f} {{ \\ {f}payload{f}; \\ bool is_null; \\}}; - \\ , .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), payload_cty.fmtDeclaratorPrefix(zcu), payload_cty.fmtDeclaratorSuffix(zcu), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); + break :check_cty name_cty; }, }, .array => if (ty.hasRuntimeBits(zcu)) { @@ -295,14 +312,13 @@ pub fn defineComplete( break :nonstring Value.compareHetero(s, .neq, .zero_comptime_int, zcu); }, } }; - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + try w.print("{f} {{ {f}array{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); - }, + break :check_cty name_cty; + } else return, .vector => if (ty.hasRuntimeBits(zcu)) { const name_cty: CType = .{ .vec = ty }; const elem_cty: CType = try .lower(ty.childType(zcu), deps, arena, zcu); @@ -311,16 +327,20 @@ pub fn defineComplete( .elem_ty = &elem_cty, .nonstring = elem_cty.isStringElem(), } }; - try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ + try w.print("{f} {{ {f}array{f}; }};", .{ name_cty.fmtTypeName(zcu), array_cty.fmtDeclaratorPrefix(zcu), array_cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); - try writeStaticAssertLayout(ty, name_cty, w, zcu); - }, - else => {}, - } + break :check_cty name_cty; + } else return, + else => return, + }; + if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ + ty.fmt(pt), + }); + try w.writeByte('\n'); + if (check_cty) |cty| try writeStaticAssertTypeLayout(ty, cty, w, zcu); } fn defineBitpack( ty: Type, @@ -328,16 +348,16 @@ fn defineBitpack( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!?CType { const zcu = pt.zcu; const name_cty: CType = .{ .bitpack = ty }; const cty: CType = try .lower(ty.backingIntType(zcu), deps, arena, zcu); - try w.print("typedef {f}{f}{f}; /* {f} */\n", .{ + try w.print("typedef {f}{f}{f};", .{ cty.fmtDeclaratorPrefix(zcu), name_cty.fmtTypeName(zcu), cty.fmtDeclaratorSuffix(zcu), - ty.fmt(pt), }); + return null; } fn defineTuple( ty: Type, @@ -345,9 +365,8 @@ fn defineTuple( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const tuple = ip.indexToKey(ty.toIntern()).tuple_type; @@ -367,9 +386,8 @@ fn defineTuple( } else true; const name_cty: CType = .{ .@"struct" = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); var zig_offset: u64 = 0; var c_offset: u64 = 0; @@ -403,9 +421,8 @@ fn defineTuple( zig_offset += field_size; c_offset += field_size; } - try w.writeAll("};\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeAll("};"); + return name_cty; } fn defineStruct( ty: Type, @@ -413,9 +430,8 @@ fn defineStruct( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const struct_type = ip.loadStructType(ty.toIntern()); @@ -457,9 +473,8 @@ fn defineStruct( if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .@"struct" = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); var it = struct_type.iterateRuntimeOrder(ip); var offset: u64 = 0; @@ -497,9 +512,8 @@ fn defineStruct( assert(struct_type.alignment.forward(offset) == struct_type.size); try w.writeByte('}'); if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeByte(';'); + return name_cty; } fn defineUnionAuto( ty: Type, @@ -507,9 +521,8 @@ fn defineUnionAuto( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const union_type = ip.loadUnionType(ty.toIntern()); @@ -553,9 +566,8 @@ fn defineUnionAuto( const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu); const name_cty: CType = .{ .union_auto = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); if (payload_has_bits) { try w.writeByte(' '); @@ -587,9 +599,8 @@ fn defineUnionAuto( tag_cty.fmtDeclaratorSuffix(zcu), }); } - try w.writeAll("};\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeAll("};"); + return name_cty; } fn defineUnionExtern( ty: Type, @@ -597,9 +608,8 @@ fn defineUnionExtern( arena: Allocator, w: *Writer, pt: Zcu.PerThread, -) (Allocator.Error || Writer.Error)!void { +) (Allocator.Error || Writer.Error)!CType { const zcu = pt.zcu; - if (!ty.hasRuntimeBits(zcu)) return; const ip = &zcu.intern_pool; const union_type = ip.loadUnionType(ty.toIntern()); @@ -636,9 +646,8 @@ fn defineUnionExtern( if (pack) try w.writeAll("zig_packed("); const name_cty: CType = .{ .union_extern = ty }; - try w.print("{f} {{ /* {f} */\n", .{ + try w.print("{f} {{\n", .{ name_cty.fmtTypeName(zcu), - ty.fmt(pt), }); for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { @@ -659,9 +668,8 @@ fn defineUnionExtern( } try w.writeByte('}'); if (pack) try w.writeByte(')'); - try w.writeAll(";\n"); - - try writeStaticAssertLayout(ty, name_cty, w, zcu); + try w.writeByte(';'); + return name_cty; } /// Writes an annotation which, placed before a struct/union field declaration with field type `ty`, @@ -680,19 +688,29 @@ fn writeFieldAlign( } /// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`. -fn writeStaticAssertLayout( +pub fn writeStaticAssertTypeLayout( ty: Type, cty: CType, w: *Writer, zcu: *const Zcu, +) Writer.Error!void { + try writeStaticAssertCTypeLayout(cty, ty.abiSize(zcu), ty.abiAlignment(zcu), w, zcu); +} + +/// Emits static assertions that the size and alignment of `cty` match the provided values. +pub fn writeStaticAssertCTypeLayout( + cty: CType, + expected_size: u64, + expected_alignment: Alignment, + w: *Writer, + zcu: *const Zcu, ) Writer.Error!void { try w.print( - \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size"); - \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment"); + \\zig_static_assert(sizeof({f}) == {d} && zig_alignOf({f}) == {d}, "abi mismatch"); \\ , .{ - cty.fmtTypeName(zcu), ty.abiSize(zcu), - cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?, + cty.fmtTypeName(zcu), expected_size, + cty.fmtTypeName(zcu), expected_alignment.toByteUnits().?, }); } diff --git a/src/link.zig b/src/link.zig index 7ce8363a3d77d9191b813cc86f2896e0285bec4e..15d9fcb513a8b329d6ebfbc6cf66d92b02352bc8 100644 --- a/src/link.zig +++ b/src/link.zig @@ -1238,7 +1238,7 @@ pub const File = struct { } switch (base.tag) { - inline .elf2, .coff2, .wasm => |tag| { + inline .elf2, .coff2, .wasm, .c => |tag| { dev.check(tag.devFeature()); try @as(*tag.Type(), @fieldParentPtr("base", base)).prelink(base.comp.link_prog_node); }, diff --git a/src/link/C.zig b/src/link/C.zig index a6830126fb2f048af065093adf6e99e2778e0c88..cf82ed146fa853cc449074721eb294834cde6d1b 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index), /// one array. align_dependency_masks: std.ArrayList(u64), +/// Emitted at the top of the file. This can be cached since it only depends on the target. +header: String, /// All NAVs, regardless of whether they are functions or simple constants, are put in this map. navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl), /// All UAVs which may be referenced are in this map. The UAV alignment is not included in the @@ -404,9 +406,8 @@ pub fn createEmpty( emit: Path, options: link.File.OpenOptions, ) !*C { + assert(comp.root_mod.resolved_target.result.ofmt == .c); const io = comp.io; - const target = &comp.root_mod.resolved_target.result; - assert(target.ofmt == .c); const optimize_mode = comp.root_mod.optimize_mode; const use_lld = build_options.have_llvm and comp.config.use_lld; const use_llvm = comp.config.use_llvm; @@ -422,9 +423,8 @@ pub fn createEmpty( }); errdefer file.close(io); - const c_file = try arena.create(C); - - c_file.* = .{ + const c = try arena.create(C); + c.* = .{ .base = .{ .tag = .c, .comp = comp, @@ -439,6 +439,7 @@ pub fn createEmpty( .string_bytes = .empty, .type_dependencies = .empty, .align_dependency_masks = .empty, + .header = .empty, .navs = .empty, .uavs = .empty, .type_pool = .empty, @@ -447,8 +448,7 @@ pub fn createEmpty( .exported_navs = .empty, .exported_uavs = .empty, }; - - return c_file; + return c; } pub fn deinit(c: *C) void { @@ -469,6 +469,21 @@ pub fn deinit(c: *C) void { c.exported_uavs.deinit(gpa); } +pub fn prelink(c: *C, prog_node: std.Progress.Node) !void { + const comp = c.base.comp; + + const sub_prog_node = prog_node.start("Generate Header", 0); + defer sub_prog_node.end(); + + var header_aw: std.Io.Writer.Allocating = .init(comp.gpa); + defer header_aw.deinit(); + codegen.genHeader(comp.zcu.?, &header_aw.writer) catch |err| switch (err) { + error.WriteFailed => return error.OutOfMemory, + else => |e| return e, + }; + c.header = try c.addString(&.{header_aw.written()}); +} + pub fn updateContainerType( c: *C, pt: Zcu.PerThread, @@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog const io = comp.io; const zcu = c.base.comp.zcu.?; const ip = &zcu.intern_pool; - const target = zcu.getTarget(); const active = zcu.activate(tid); defer active.deactivate(); const pt = active.pt; @@ -943,7 +957,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin // to build the output buffer. Our strategy is to emit the C source in this order: // - // * ABI defines and `#include "zig.h"` + // * Header // * Big-int type definitions // * Other CType definitions (traversing the dependency graph to sort topologically) // * Global assembly @@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers! - try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"` + try f.all_buffers.ensureUnusedCapacity(gpa, 1 + // Header 1 + // Big-int type definitions need_types.count() + // `RenderedType.fwd_decl` (worst-case) need_types.count() + // `RenderedType.definition` @@ -984,20 +998,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "") need_navs.count() * 2); // NAV definitions ("static ", "") - // ABI defines and `#include "zig.h"` - switch (target.abi) { - .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"), - else => {}, - } - f.appendBufAssumeCapacity(try std.fmt.allocPrint( - arena, - "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", - .{target.cMaxIntAlignment()}, - )); - f.appendBufAssumeCapacity( - \\#include "zig.h" - \\ - ); + f.appendBufAssumeCapacity(c.header.get(c)); // Big-int type definitions var bigint_aw: std.Io.Writer.Allocating = .init(gpa); diff --git a/test/behavior/abs.zig b/test/behavior/abs.zig index 895f9bbf8d956e61bdf5455084cd4d58ebd2b1e9..9c140d35499fe43c6dfb1b5309e4dbd8bd7263c0 100644 --- a/test/behavior/abs.zig +++ b/test/behavior/abs.zig @@ -144,7 +144,6 @@ test "@abs big int <= 128 bits" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try comptime testAbsSignedBigInt(); try testAbsSignedBigInt(); @@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void { test "@abs int vectors" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 9ffb238dfdb9994bf587b7e4e4b5743842dbcc4c..957ac6b1796c3ce962c139fc3669c4760c8ede87 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -547,7 +547,6 @@ test "sub-aligned pointer field access" { } test "alignment of zero-bit types is respected" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO @@ -582,7 +581,6 @@ test "zero-bit fields in extern struct pad fields appropriately" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const S = extern struct { x: u8, diff --git a/test/behavior/basic.zig b/test/behavior/basic.zig index 16fdfc8c15cbd9f5e9ad3cc11d72461092cf839c..964de5d20ff8754e81d3c0deae59fd44a672b6f8 100644 --- a/test/behavior/basic.zig +++ b/test/behavior/basic.zig @@ -800,7 +800,6 @@ test "extern variable with non-pointer opaque type" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO @export(&var_to_export, .{ .name = "opaque_extern_var" }); diff --git a/test/behavior/bit_shifting.zig b/test/behavior/bit_shifting.zig index 9eed252ac8ddc055038a0bf227616f3df49369bd..a9d81b6b53e6d1761e99234200fdcc155e2efa1f 100644 --- a/test/behavior/bit_shifting.zig +++ b/test/behavior/bit_shifting.zig @@ -147,7 +147,6 @@ test "Saturating Shift Left where lhs is of a computed type" { test "Saturating Shift Left" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/bitcast.zig b/test/behavior/bitcast.zig index b3b64af19b9d99ed922ec087209d02ecab14354a..785daa0d3194b00d43c00760a11199075d9377dd 100644 --- a/test/behavior/bitcast.zig +++ b/test/behavior/bitcast.zig @@ -210,7 +210,6 @@ test "triple level result location with bitcast sandwich passed as tuple element test "@bitCast packed struct of floats" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" { test "comptime @bitCast packed struct to int and back" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" { test "bitcast vector to integer and back" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 { } test "bitcast nan float does not modify signaling bit" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const snan_u16: u16 = 0x7D00; const snan_u32: u32 = 0x7FA00000; @@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" { test "@bitCast of packed struct of bools all true" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO @@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" { test "@bitCast of packed struct of bools all false" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO const P = packed struct { diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 0117c647880eb21fb9226abfc816a22ad2bcd2a7..4cbe2f1aed593d513d58691ec7baf5613494f9e7 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -134,7 +134,6 @@ test "@intFromFloat > 128 bits" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testIntFromFloat(f16, 1024, u140, 1024); try testIntFromFloat(f16, -1024, i140, -1024); @@ -160,7 +159,6 @@ test "@floatFromInt > 128 bits" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testFloatFromInt(u140, 1024, f16, 1024); try testFloatFromInt(i140, -1024, f16, -1024); @@ -182,7 +180,6 @@ test "@floatFromInt(f80)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -281,6 +278,7 @@ test "type coercion from int to float" { test "@intFromFloat" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + try testIntFromFloats(); try comptime testIntFromFloats(); } @@ -1473,11 +1471,6 @@ fn foobar(func: PFN_void) !void { test "cast function with an opaque parameter" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) { - // https://github.com/ziglang/zig/issues/16845 - return error.SkipZigTest; - } - const Container = struct { const Ctx = opaque {}; ctx: *Ctx, @@ -1724,7 +1717,6 @@ test "cast f16 to wider types" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; @@ -1831,7 +1823,6 @@ test "pointer to empty struct literal to mutable slice" { test "coerce between pointers of compatible differently-named floats" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows and !builtin.link_libc) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/cast_int.zig b/test/behavior/cast_int.zig index 34adedf7267030379ee573cb519ce6dbe29c95e3..50a1b74d8ab76bdccf8b04795a04ca77bdee078b 100644 --- a/test/behavior/cast_int.zig +++ b/test/behavior/cast_int.zig @@ -168,7 +168,6 @@ test "@intCast <= 64 bits" { test "@intCast > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testIntCast(u8, 123, u140, 123); diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 60a06886d45ac988b55d0a51f5bc40101f098e7e..f86ab963d2a4ea5dd0cec5493f583ac672a174e7 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -513,7 +513,6 @@ test "runtime 128 bit integer division" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: u128 = 152313999999999991610955792383; diff --git a/test/behavior/extern.zig b/test/behavior/extern.zig index 4de68589468790419a9e993fd68caf2f20e6eae9..ed95406aa889d361abbf87a79764eb23d62021ca 100644 --- a/test/behavior/extern.zig +++ b/test/behavior/extern.zig @@ -3,7 +3,6 @@ const std = @import("std"); const expect = std.testing.expect; test "anyopaque extern symbol" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/field_parent_ptr.zig b/test/behavior/field_parent_ptr.zig index 85250c54ad7d083be1a2f132b7fdc0a2785e10b2..c3d0c0087cc7eb9694310d5f8ff3755e35ca8077 100644 --- a/test/behavior/field_parent_ptr.zig +++ b/test/behavior/field_parent_ptr.zig @@ -586,7 +586,6 @@ test "@fieldParentPtr extern struct last zero-bit field" { } test "@fieldParentPtr unaligned packed struct" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" { } test "@fieldParentPtr aligned packed struct" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig index f8fbab0aaefd3d3d4b39d472eb84e41b9382dc8f..7e9f58e46b0cfa6632234c2136344da6240f468f 100644 --- a/test/behavior/floatop.zig +++ b/test/behavior/floatop.zig @@ -142,7 +142,6 @@ test "cmp f64" { test "cmp f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -152,7 +151,6 @@ test "cmp f128" { test "cmp f80/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -253,7 +251,6 @@ test "vector cmp f64" { test "vector cmp f128" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .powerpc64le) return error.SkipZigTest; @@ -1055,7 +1052,6 @@ test "@abs f32/f64" { test "@abs f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1173,7 +1169,6 @@ test "@floor f32/f64" { test "@floor f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1262,7 +1257,6 @@ test "@ceil f32/f64" { test "@ceil f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1282,7 +1276,6 @@ test "@ceil f80/f128/c_longdouble" { test "@ceil f80 maxInt(u64)" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1369,7 +1362,6 @@ test "@trunc f32/f64" { test "@trunc f80/f128/c_longdouble" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; diff --git a/test/behavior/fn.zig b/test/behavior/fn.zig index 14cb20f5442a452695ccad2134bd4d0c306ab4b2..47e6be86bb715f90bae1eb08a9237af2f07c1515 100644 --- a/test/behavior/fn.zig +++ b/test/behavior/fn.zig @@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn { test "extern struct with stdcallcc fn pointer" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = extern struct { diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 22b91be640579e1e8fe460f4652f998c5c1b9b6d..8750c7723149a9c772ec2dae6aaeda0b4ba03f8b 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -873,7 +873,6 @@ test "umax wrapped squaring" { test "128-bit multiplication" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; { @@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; try testAddWithOverflow(u129, 4, 105, 109, 0); try testAddWithOverflow(u129, 1000, 100, 1100, 0); @@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" { test "@mulWithOverflow bitsize 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO @@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" { test "@mulWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0); @@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" { test "@mulWithOverflow bitsize 256 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c and builtin.target.abi == .msvc) return error.SkipZigTest; try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1); try testSubWithOverflow(u129, 1000, 100, 900, 0); @@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" { test "@shlWithOverflow > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testShlWithOverflow(u140, 1 << 100, 20, 1 << 120, 0); @@ -1419,7 +1412,6 @@ fn testAnd(comptime T: type, a: T, b: T, expected: T) !void { test "and > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88); try testAnd(u140, maxInt(u140), 1 << 100, 1 << 100); @@ -1448,7 +1440,6 @@ fn testOr(comptime T: type, a: T, b: T, expected: T) !void { test "or > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testOr(u140, 0, 1 << 139, 1 << 139); try testOr(u140, (1 << 70) | 0xa, (1 << 69) | 0x5, (1 << 70) | (1 << 69) | 0xf); @@ -1477,7 +1468,6 @@ fn testXor(comptime T: type, a: T, b: T, expected: T) !void { test "xor > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testXor(u140, 0, maxInt(u140), maxInt(u140)); try testXor(u140, 1 << 139, 1 << 139, 0); @@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void { test "not > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testNot(u140, 0, maxInt(u140)); try testNot(u140, maxInt(u140), 0); @@ -1535,7 +1524,6 @@ fn testShl(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void { test "shl > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testShl(u140, 1 << 5, 10, 1 << 15); try testShl(u140, 3, 138, (1 << 139) | (1 << 138)); @@ -1564,7 +1552,6 @@ fn testShr(comptime T: type, a: T, b: std.math.Log2Int(T), expected: T) !void { test "shr > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testShr(u140, 1 << 139, 39, 1 << 100); try testShr(u140, (1 << 70) | 8, 3, (1 << 67) | 1); @@ -1593,7 +1580,6 @@ fn testClz(comptime T: type, a: T, expected: u16) !void { test "@clz > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testClz(u140, 0, 140); @@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void { test "@ctz > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testCtz(u140, 0, 140); @@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void { test "@popCount > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testPopCount(u140, 0, 0); @@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void { test "@bitReverse > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testBitReverse(u140, 1 << 139, 1); @@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void { test "@byteSwap > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testByteSwap(u144, 1 << 136, 1); @@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void { test "@max > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMax(u140, 0, maxInt(u140), maxInt(u140)); @@ -1773,7 +1754,6 @@ fn testMin(comptime T: type, a: T, b: T, expected: T) !void { test "@min > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMin(u140, 0, maxInt(u140), 0); @@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void { test "@abs > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; try testAbs(u140, 0, 0); try testAbs(u140, 1 << 139, 1 << 139); @@ -1827,7 +1806,6 @@ fn testRem(comptime T: type, numerator: T, denominator: T, expected: T) !void { test "@rem > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testRem(u140, 0, maxInt(u140), 0); @@ -1855,7 +1833,6 @@ fn testMod(comptime T: type, numerator: T, denominator: T, expected: T) !void { test "@mod > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testMod(u140, 0, maxInt(u140), 0); @@ -1883,7 +1860,6 @@ fn testDivFloor(comptime T: type, numerator: T, denominator: T, expected: T) !vo test "@divFloor > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivFloor(u140, 0, maxInt(u140), 0); @@ -1912,7 +1888,6 @@ fn testDivCeil(comptime T: type, numerator: T, denominator: T, expected: T) !voi test "@divCeil > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivCeil(u140, 0, maxInt(u140), 0); @@ -1941,7 +1916,6 @@ fn testDivTrunc(comptime T: type, numerator: T, denominator: T, expected: T) !vo test "@divTrunc > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testDivTrunc(u140, 0, maxInt(u140), 0); @@ -2166,7 +2140,6 @@ test "remainder division" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) { @@ -2315,7 +2288,6 @@ test "@round f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testRound(f80, 12.0); @@ -2326,7 +2298,6 @@ test "@round f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testRound(f128, 12.0); diff --git a/test/behavior/maximum_minimum.zig b/test/behavior/maximum_minimum.zig index 22db5a75502f8456ac0637ef134a137434d3da75..533f44869573a924e50a08b3806a03c4243fc7ee 100644 --- a/test/behavior/maximum_minimum.zig +++ b/test/behavior/maximum_minimum.zig @@ -115,7 +115,6 @@ test "@min/max for floats" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { diff --git a/test/behavior/muladd.zig b/test/behavior/muladd.zig index 086a325bd6246dd660641aec924c20339494f8a2..bde6459e849c14384d69fc57811f59b747a0f2de 100644 --- a/test/behavior/muladd.zig +++ b/test/behavior/muladd.zig @@ -49,7 +49,6 @@ test "@mulAdd f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime testMulAdd80(); @@ -68,7 +67,6 @@ test "@mulAdd f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime testMulAdd128(); @@ -169,7 +167,6 @@ test "vector f80" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime vector80(); @@ -194,7 +191,6 @@ test "vector f128" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try comptime vector128(); diff --git a/test/behavior/packed-struct.zig b/test/behavior/packed-struct.zig index 96585d056cdf4c13b1aff3610ad08088fc0bf61c..045c19767454b64d970fe6c7a46dafcb9b2a1ac4 100644 --- a/test/behavior/packed-struct.zig +++ b/test/behavior/packed-struct.zig @@ -404,7 +404,6 @@ test "nested packed struct field pointers" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // ubsan unaligned pointer access if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO const S2 = packed struct { base: u8, @@ -579,7 +578,6 @@ test "packed struct fields modification" { } test "nested packed struct field access test" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -1171,7 +1168,6 @@ test "packed struct equality" { test "packed struct equality ignores padding bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = packed struct { b: bool }; diff --git a/test/behavior/pointers.zig b/test/behavior/pointers.zig index 9ac875fad4990e03554fc217fb38f42d0dfa6e62..807f4f5450d3fb372e18e2fc78f71fea9ce4d5bb 100644 --- a/test/behavior/pointers.zig +++ b/test/behavior/pointers.zig @@ -275,7 +275,7 @@ test "compare equality of optional and non-optional pointer" { } test "allowzero pointer and slice" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; diff --git a/test/behavior/saturating_arithmetic.zig b/test/behavior/saturating_arithmetic.zig index c434f014f36e40f2cfea9fc0c2508320d09c74a4..c5fa221c124d4113a73db22ab33778e521a9c52a 100644 --- a/test/behavior/saturating_arithmetic.zig +++ b/test/behavior/saturating_arithmetic.zig @@ -144,7 +144,6 @@ test "saturating multiplication <= 32 bits" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; try testSatMul(u8, 0, maxInt(u8), 0); @@ -238,7 +237,6 @@ test "saturating multiplication" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { @@ -313,7 +311,6 @@ test "saturating shift-left" { test "saturating shift-left large rhs" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; @@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" { test "sat add > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatAdd(u140, 0, 0, 0); @@ -377,7 +373,6 @@ test "sat add > 128 bits" { test "sat sub > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatSub(u140, 0, 1, 0); @@ -393,7 +388,6 @@ test "sat sub > 128 bits" { test "sat mul > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatMul(u140, 0, maxInt(u140), 0); @@ -409,7 +403,6 @@ test "sat mul > 128 bits" { test "sat shl > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testSatShl(u140, 0, u8, 17, 0); diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 379e5ec18343c226b0e2d67b1dca8b8d53f13340..2aa7920ab4b17ae56df165a880d3242e3a3fedb0 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -535,7 +535,6 @@ test "zero-bit field in packed struct" { test "packed struct with non-ABI-aligned field" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; @@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const U = union(enum) { @@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" { } test "struct field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" { } test "extern struct field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" { } test "struct containing optional pointer to array of @This()" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; const S = struct { @@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" { test "struct contains underaligned field with overaligned pointer to itself" { if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const S = struct { ptr: *align(8) @This() align(1), }; diff --git a/test/behavior/switch_loop.zig b/test/behavior/switch_loop.zig index 9f4859789c9c3f23488ae0814c67b132112a3335..caaea13e7f8aa3571a0f3f34c7b05b0ee37eea3b 100644 --- a/test/behavior/switch_loop.zig +++ b/test/behavior/switch_loop.zig @@ -223,7 +223,6 @@ test "unanalyzed continue with operand" { test "switch loop on larger than pointer integer" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined; @@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" { test "switch loop with discarded tag capture" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; + const S = struct { const U = union(enum) { a: u32, diff --git a/test/behavior/truncate.zig b/test/behavior/truncate.zig index 07d19f29c0da73a045ae58d35836502cbebe5cdc..506a0d2bea99b768c6761cc3da31558b88eddf11 100644 --- a/test/behavior/truncate.zig +++ b/test/behavior/truncate.zig @@ -49,7 +49,6 @@ fn testTruncate(comptime S: type, a: S, comptime D: type, expected: D) !void { test "@truncate > 128 bits" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; try testTruncate(u140, 0, u128, 0); diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 340f7006e72b7f48ecaf7280cd9cd982f8600060..8ed483d02278160bc13f52b60a6b5cf5344eb40e 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1437,7 +1437,6 @@ test "coerce enum literal to union in result loc" { } test "defined-layout union field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" { } test "undefined-layout union field pointer has correct alignment" { - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; @@ -1758,8 +1756,6 @@ test "reinterpret packed union" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try S.doTheTest(); } @@ -1800,8 +1796,6 @@ test "reinterpret packed union inside packed struct" { }; try comptime S.doTheTest(); - - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO try S.doTheTest(); } diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 7d63b136fda14fca1358123c1546820a42f0dcf9..9f8d277774f278dd2e7ee138e5d54e52fbfaa491 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -128,7 +128,6 @@ test "vector float operators" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .aarch64) { // Triggers an assertion with LLVM 18: @@ -736,7 +735,6 @@ test "vector reduce operation" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/195562 @@ -1437,7 +1435,6 @@ test "store packed vector element" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var v = @Vector(4, u1){ 1, 1, 1, 1 }; @@ -1469,7 +1466,6 @@ test "store vector with memset" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: [5]@Vector(2, i1) = undefined; @@ -1610,7 +1606,6 @@ test "bitcast vector to array of smaller vectors" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; const u8x32 = @Vector(32, u8); const u8x64 = @Vector(64, u8); diff --git a/test/standalone/build.zig b/test/standalone/build.zig index dc8d85d399477256b65c60dc1b4850144c641738..f14d17562d4715ca75340d67b6b2ce5b7344b73d 100644 --- a/test/standalone/build.zig +++ b/test/standalone/build.zig @@ -39,7 +39,6 @@ pub fn build(b: *std.Build) void { "../../tools/gen_parser_oracle.zig", "../../tools/gen_spirv_spec.zig", "../../tools/gen_stubs.zig", - "../../tools/generate_c_size_and_align_checks.zig", "../../tools/generate_JSONTestSuite.zig", "../../tools/generate_linux_syscalls.zig", "../../tools/process_headers.zig", diff --git a/test/tests.zig b/test/tests.zig index 9a11d7c496a5179e02c74969f4481034764baa55..849267617f0cfe5e8c8f227a3758a397ba047083 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -274,6 +274,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .arm, + .os_tag = .linux, + .abi = .musleabi, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .arm, @@ -292,6 +301,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .arm, + .os_tag = .linux, + .abi = .musleabihf, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .arm, @@ -341,6 +359,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .armeb, + .os_tag = .linux, + .abi = .musleabi, + .ofmt = .c, + }, + .link_libc = true, + }, // Crashes in weird ways when applying relocations. // .{ // .target = .{ @@ -360,6 +387,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .armeb, + .os_tag = .linux, + .abi = .musleabihf, + .ofmt = .c, + }, + .link_libc = true, + }, // Crashes in weird ways when applying relocations. // .{ // .target = .{ @@ -1107,6 +1143,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .x86, + .os_tag = .linux, + .abi = .musl, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ .cpu_arch = .x86, @@ -1645,6 +1690,15 @@ const module_test_targets = blk: { }, .link_libc = true, }, + .{ + .target = .{ + .cpu_arch = .x86, + .os_tag = .windows, + .abi = .gnu, + .ofmt = .c, + }, + .link_libc = true, + }, .{ .target = .{ @@ -2782,16 +2836,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { const target = &resolved_target.result; - if (target.cpu.arch == .s390x and target.ofmt == .c) { - // https://codeberg.org/ziglang/zig/issues/35523 - continue; - } - - if (target.cpu.arch == .riscv64 and target.ofmt == .c) { - // https://codeberg.org/ziglang/zig/issues/30930 - continue; - } - if (std.mem.eql(u8, options.name, "libc")) { // The libc API tests obviously need to link libc. So for test // target entries where we wouldn't link libc by default, skip the diff --git a/tools/generate_c_size_and_align_checks.zig b/tools/generate_c_size_and_align_checks.zig deleted file mode 100644 index 09400615f2c526bdde3ce99c62b0f5a0bf386932..0000000000000000000000000000000000000000 --- a/tools/generate_c_size_and_align_checks.zig +++ /dev/null @@ -1,62 +0,0 @@ -//! Usage: zig run tools/generate_c_size_and_align_checks.zig -- [target_triple] -//! e.g. zig run tools/generate_c_size_and_align_checks.zig -- x86_64-linux-gnu -//! -//! Prints _Static_asserts for the size and alignment of all the basic built-in C -//! types. The output can be run through a compiler for the specified target to -//! verify that Zig's values are the same as those used by a C compiler for the -//! target. - -const std = @import("std"); -const Io = std.Io; - -fn cName(ty: std.Target.CType) []const u8 { - return switch (ty) { - .char => "char", - .short => "short", - .ushort => "unsigned short", - .int => "int", - .uint => "unsigned int", - .long => "long", - .ulong => "unsigned long", - .longlong => "long long", - .ulonglong => "unsigned long long", - .float => "float", - .double => "double", - .longdouble => "long double", - }; -} - -var general_purpose_allocator: std.heap.DebugAllocator(.{}) = .init; - -pub fn main(init: std.process.Init) !void { - const args = try init.minimal.args.toSlice(init.arena.allocator()); - const io = init.io; - - if (args.len != 2) { - std.debug.print("Usage: {s} [target_triple]\n", .{args[0]}); - std.process.exit(1); - } - - const query = try std.Target.Query.parse(.{ .arch_os_abi = args[1] }); - const target = try std.zig.system.resolveTargetQuery(io, query); - - var buffer: [2000]u8 = undefined; - var stdout_writer = Io.File.stdout().writerStreaming(io, &buffer); - const w = &stdout_writer.interface; - inline for (@typeInfo(std.Target.CType).@"enum".field_values) |field_value| { - const c_type: std.Target.CType = @fromBackingInt(@intCast(field_value)); - try w.print("_Static_assert(sizeof({0s}) == {1d}, \"sizeof({0s}) == {1d}\");\n", .{ - cName(c_type), - target.cTypeByteSize(c_type), - }); - try w.print("_Static_assert(_Alignof({0s}) == {1d}, \"_Alignof({0s}) == {1d}\");\n", .{ - cName(c_type), - target.cTypeAlignment(c_type), - }); - try w.print("_Static_assert(__alignof({0s}) == {1d}, \"__alignof({0s}) == {1d}\");\n\n", .{ - cName(c_type), - target.cTypePreferredAlignment(c_type), - }); - } - try w.flush(); -} -- 2.54.0