From d81a68c753c527f109247c1d3cf27ebe36ce0135 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 21 Dec 2022 16:40:30 +0200 Subject: [PATCH] update uses of overflow arithmetic builtins --- lib/compiler_rt/trunctfxf2.zig | 14 +- lib/std/compress/deflate/compressor_test.zig | 4 +- lib/std/crypto/pcurves/p256/p256_64.zig | 16 +- .../crypto/pcurves/p256/p256_scalar_64.zig | 16 +- lib/std/crypto/pcurves/p384/p384_64.zig | 16 +- .../crypto/pcurves/p384/p384_scalar_64.zig | 16 +- .../crypto/pcurves/secp256k1/secp256k1_64.zig | 16 +- .../pcurves/secp256k1/secp256k1_scalar_64.zig | 16 +- lib/std/crypto/salsa20.zig | 4 +- lib/std/crypto/utils.zig | 24 +- lib/std/heap.zig | 2 +- lib/std/leb128.zig | 16 +- lib/std/math.zig | 23 +- lib/std/math/big/int.zig | 200 +++++---- lib/std/math/powi.zig | 18 +- lib/std/mem.zig | 8 +- lib/std/net.zig | 36 +- lib/std/os/linux.zig | 2 +- lib/std/process.zig | 24 +- lib/std/zig/c_builtins.zig | 4 +- lib/std/zig/number_literal.zig | 12 +- src/link/Coff.zig | 4 +- src/link/Dwarf.zig | 4 +- src/link/Elf.zig | 4 +- src/link/MachO.zig | 4 +- test/behavior/eval.zig | 15 +- test/behavior/math.zig | 385 +++++++++++------- test/behavior/vector.zig | 40 +- 28 files changed, 540 insertions(+), 403 deletions(-) diff --git a/lib/compiler_rt/trunctfxf2.zig b/lib/compiler_rt/trunctfxf2.zig index 731f58f19205..fece695b65c0 100644 --- a/lib/compiler_rt/trunctfxf2.zig +++ b/lib/compiler_rt/trunctfxf2.zig @@ -49,14 +49,16 @@ pub fn __trunctfxf2(a: f128) callconv(.C) f80 { const round_bits = a_abs & round_mask; if (round_bits > halfway) { // Round to nearest - const carry = @boolToInt(@addWithOverflow(u64, res.fraction, 1, &res.fraction)); - res.exp += carry; - res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry + const ov = @addWithOverflow(res.fraction, 1); + res.fraction = ov[0]; + res.exp += ov[1]; + res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry } else if (round_bits == halfway) { // Ties to even - const carry = @boolToInt(@addWithOverflow(u64, res.fraction, res.fraction & 1, &res.fraction)); - res.exp += carry; - res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry + const ov = @addWithOverflow(res.fraction, res.fraction & 1); + res.fraction = ov[0]; + res.exp += ov[1]; + res.fraction |= @as(u64, ov[1]) << 63; // Restore integer bit after carry } if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals } diff --git a/lib/std/compress/deflate/compressor_test.zig b/lib/std/compress/deflate/compressor_test.zig index a02df5526c67..c51f68236da3 100644 --- a/lib/std/compress/deflate/compressor_test.zig +++ b/lib/std/compress/deflate/compressor_test.zig @@ -172,9 +172,7 @@ test "deflate/inflate" { defer testing.allocator.free(large_data_chunk); // fill with random data for (large_data_chunk) |_, i| { - var mul: u8 = @truncate(u8, i); - _ = @mulWithOverflow(u8, mul, mul, &mul); - large_data_chunk[i] = mul; + large_data_chunk[i] = @truncate(u8, i) *% @truncate(u8, i); } try testToFromWithLimit(large_data_chunk, limits); } diff --git a/lib/std/crypto/pcurves/p256/p256_64.zig b/lib/std/crypto/pcurves/p256/p256_64.zig index 4ea8f268f3dc..e8ba37e845e0 100644 --- a/lib/std/crypto/pcurves/p256/p256_64.zig +++ b/lib/std/crypto/pcurves/p256/p256_64.zig @@ -75,10 +75,10 @@ pub const NonMontgomeryDomainFieldElement = [4]u64; inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @addWithOverflow(u64, arg2, arg3, &t); - const carry2 = @addWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @addWithOverflow(arg2, arg3); + const ov2 = @addWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function subborrowxU64 is a subtraction with borrow. @@ -97,10 +97,10 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @subWithOverflow(u64, arg2, arg3, &t); - const carry2 = @subWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @subWithOverflow(arg2, arg3); + const ov2 = @subWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function mulxU64 is a multiplication, returning the full double-width result. diff --git a/lib/std/crypto/pcurves/p256/p256_scalar_64.zig b/lib/std/crypto/pcurves/p256/p256_scalar_64.zig index 9c99d18ccfb0..ea102360cf8c 100644 --- a/lib/std/crypto/pcurves/p256/p256_scalar_64.zig +++ b/lib/std/crypto/pcurves/p256/p256_scalar_64.zig @@ -75,10 +75,10 @@ pub const NonMontgomeryDomainFieldElement = [4]u64; inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @addWithOverflow(u64, arg2, arg3, &t); - const carry2 = @addWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @addWithOverflow(arg2, arg3); + const ov2 = @addWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function subborrowxU64 is a subtraction with borrow. @@ -97,10 +97,10 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @subWithOverflow(u64, arg2, arg3, &t); - const carry2 = @subWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @subWithOverflow(arg2, arg3); + const ov2 = @subWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function mulxU64 is a multiplication, returning the full double-width result. diff --git a/lib/std/crypto/pcurves/p384/p384_64.zig b/lib/std/crypto/pcurves/p384/p384_64.zig index bd39fc527adf..45c12835b345 100644 --- a/lib/std/crypto/pcurves/p384/p384_64.zig +++ b/lib/std/crypto/pcurves/p384/p384_64.zig @@ -44,10 +44,10 @@ pub const NonMontgomeryDomainFieldElement = [6]u64; inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @addWithOverflow(u64, arg2, arg3, &t); - const carry2 = @addWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @addWithOverflow(arg2, arg3); + const ov2 = @addWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function subborrowxU64 is a subtraction with borrow. @@ -66,10 +66,10 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @subWithOverflow(u64, arg2, arg3, &t); - const carry2 = @subWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @subWithOverflow(arg2, arg3); + const ov2 = @subWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function mulxU64 is a multiplication, returning the full double-width result. diff --git a/lib/std/crypto/pcurves/p384/p384_scalar_64.zig b/lib/std/crypto/pcurves/p384/p384_scalar_64.zig index e45e43f98cf3..0ce7727148fc 100644 --- a/lib/std/crypto/pcurves/p384/p384_scalar_64.zig +++ b/lib/std/crypto/pcurves/p384/p384_scalar_64.zig @@ -44,10 +44,10 @@ pub const NonMontgomeryDomainFieldElement = [6]u64; inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @addWithOverflow(u64, arg2, arg3, &t); - const carry2 = @addWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @addWithOverflow(arg2, arg3); + const ov2 = @addWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function subborrowxU64 is a subtraction with borrow. @@ -66,10 +66,10 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @subWithOverflow(u64, arg2, arg3, &t); - const carry2 = @subWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @subWithOverflow(arg2, arg3); + const ov2 = @subWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function mulxU64 is a multiplication, returning the full double-width result. diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig index 2309b48ac97f..5643ea88d509 100644 --- a/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig +++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_64.zig @@ -44,10 +44,10 @@ pub const NonMontgomeryDomainFieldElement = [4]u64; inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @addWithOverflow(u64, arg2, arg3, &t); - const carry2 = @addWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @addWithOverflow(arg2, arg3); + const ov2 = @addWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function subborrowxU64 is a subtraction with borrow. @@ -66,10 +66,10 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @subWithOverflow(u64, arg2, arg3, &t); - const carry2 = @subWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @subWithOverflow(arg2, arg3); + const ov2 = @subWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function mulxU64 is a multiplication, returning the full double-width result. diff --git a/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig index 8e9687f0a1a3..aca1bd3063bb 100644 --- a/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig +++ b/lib/std/crypto/pcurves/secp256k1/secp256k1_scalar_64.zig @@ -44,10 +44,10 @@ pub const NonMontgomeryDomainFieldElement = [4]u64; inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @addWithOverflow(u64, arg2, arg3, &t); - const carry2 = @addWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @addWithOverflow(arg2, arg3); + const ov2 = @addWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function subborrowxU64 is a subtraction with borrow. @@ -66,10 +66,10 @@ inline fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) vo inline fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) void { @setRuntimeSafety(mode == .Debug); - var t: u64 = undefined; - const carry1 = @subWithOverflow(u64, arg2, arg3, &t); - const carry2 = @subWithOverflow(u64, t, arg1, out1); - out2.* = @boolToInt(carry1) | @boolToInt(carry2); + const ov1 = @subWithOverflow(arg2, arg3); + const ov2 = @subWithOverflow(ov1[0], arg1); + out1.* = ov2[0]; + out2.* = ov1[1] | ov2[1]; } /// The function mulxU64 is a multiplication, returning the full double-width result. diff --git a/lib/std/crypto/salsa20.zig b/lib/std/crypto/salsa20.zig index c4cd86b0e43b..2027403ee228 100644 --- a/lib/std/crypto/salsa20.zig +++ b/lib/std/crypto/salsa20.zig @@ -263,7 +263,9 @@ fn SalsaNonVecImpl(comptime rounds: comptime_int) type { while (j < 64) : (j += 1) { xout[j] ^= buf[j]; } - ctx[9] += @boolToInt(@addWithOverflow(u32, ctx[8], 1, &ctx[8])); + const ov = @addWithOverflow(ctx[8], 1); + ctx[8] = ov[0]; + ctx[9] += ov[1]; } if (i < in.len) { salsaCore(x[0..], ctx, true); diff --git a/lib/std/crypto/utils.zig b/lib/std/crypto/utils.zig index 0a3540d8950a..fd7264e73786 100644 --- a/lib/std/crypto/utils.zig +++ b/lib/std/crypto/utils.zig @@ -87,15 +87,19 @@ pub fn timingSafeAdd(comptime T: type, a: []const T, b: []const T, result: []T, if (endian == .Little) { var i: usize = 0; while (i < len) : (i += 1) { - const tmp = @boolToInt(@addWithOverflow(u8, a[i], b[i], &result[i])); - carry = tmp | @boolToInt(@addWithOverflow(u8, result[i], carry, &result[i])); + const ov1 = @addWithOverflow(a[i], b[i]); + const ov2 = @addWithOverflow(ov1[0], carry); + result[i] = ov2[0]; + carry = ov1[1] | ov2[1]; } } else { var i: usize = len; while (i != 0) { i -= 1; - const tmp = @boolToInt(@addWithOverflow(u8, a[i], b[i], &result[i])); - carry = tmp | @boolToInt(@addWithOverflow(u8, result[i], carry, &result[i])); + const ov1 = @addWithOverflow(a[i], b[i]); + const ov2 = @addWithOverflow(ov1[0], carry); + result[i] = ov2[0]; + carry = ov1[1] | ov2[1]; } } return @bitCast(bool, carry); @@ -110,15 +114,19 @@ pub fn timingSafeSub(comptime T: type, a: []const T, b: []const T, result: []T, if (endian == .Little) { var i: usize = 0; while (i < len) : (i += 1) { - const tmp = @boolToInt(@subWithOverflow(u8, a[i], b[i], &result[i])); - borrow = tmp | @boolToInt(@subWithOverflow(u8, result[i], borrow, &result[i])); + const ov1 = @subWithOverflow(a[i], b[i]); + const ov2 = @subWithOverflow(ov1[0], borrow); + result[i] = ov2[0]; + borrow = ov1[1] | ov2[1]; } } else { var i: usize = len; while (i != 0) { i -= 1; - const tmp = @boolToInt(@subWithOverflow(u8, a[i], b[i], &result[i])); - borrow = tmp | @boolToInt(@subWithOverflow(u8, result[i], borrow, &result[i])); + const ov1 = @subWithOverflow(a[i], b[i]); + const ov2 = @subWithOverflow(ov1[0], borrow); + result[i] = ov2[0]; + borrow = ov1[1] | ov2[1]; } } return @bitCast(bool, borrow); diff --git a/lib/std/heap.zig b/lib/std/heap.zig index ee6525659eae..081e65fa2788 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -789,7 +789,7 @@ pub fn testAllocatorLargeAlignment(base_allocator: mem.Allocator) !void { const large_align: usize = mem.page_size / 2; var align_mask: usize = undefined; - _ = @shlWithOverflow(usize, ~@as(usize, 0), @as(Allocator.Log2Align, @ctz(large_align)), &align_mask); + align_mask = @shlWithOverflow(~@as(usize, 0), @as(Allocator.Log2Align, @ctz(large_align)))[0]; var slice = try allocator.alignedAlloc(u8, large_align, 500); try testing.expect(@ptrToInt(slice.ptr) & align_mask == @ptrToInt(slice.ptr)); diff --git a/lib/std/leb128.zig b/lib/std/leb128.zig index f72070d13d84..bc5955d16a6c 100644 --- a/lib/std/leb128.zig +++ b/lib/std/leb128.zig @@ -15,11 +15,11 @@ pub fn readULEB128(comptime T: type, reader: anytype) !T { while (group < max_group) : (group += 1) { const byte = try reader.readByte(); - var temp = @as(U, byte & 0x7f); - if (@shlWithOverflow(U, temp, group * 7, &temp)) return error.Overflow; + const ov = @shlWithOverflow(@as(U, byte & 0x7f), group * 7); + if (ov[1] != 0) return error.Overflow; - value |= temp; + value |= ov[0]; if (byte & 0x80 == 0) break; } else { return error.Overflow; @@ -65,13 +65,13 @@ pub fn readILEB128(comptime T: type, reader: anytype) !T { while (group < max_group) : (group += 1) { const byte = try reader.readByte(); - var temp = @as(U, byte & 0x7f); const shift = group * 7; - if (@shlWithOverflow(U, temp, shift, &temp)) { + const ov = @shlWithOverflow(@as(U, byte & 0x7f), shift); + if (ov[1] != 0) { // Overflow is ok so long as the sign bit is set and this is the last byte if (byte & 0x80 != 0) return error.Overflow; - if (@bitCast(S, temp) >= 0) return error.Overflow; + if (@bitCast(S, ov[0]) >= 0) return error.Overflow; // and all the overflowed bits are 1 const remaining_shift = @intCast(u3, @typeInfo(U).Int.bits - @as(u16, shift)); @@ -80,14 +80,14 @@ pub fn readILEB128(comptime T: type, reader: anytype) !T { } else { // If we don't overflow and this is the last byte and the number being decoded // is negative, check that the remaining bits are 1 - if ((byte & 0x80 == 0) and (@bitCast(S, temp) < 0)) { + if ((byte & 0x80 == 0) and (@bitCast(S, ov[0]) < 0)) { const remaining_shift = @intCast(u3, @typeInfo(U).Int.bits - @as(u16, shift)); const remaining_bits = @bitCast(i8, byte | 0x80) >> remaining_shift; if (remaining_bits != -1) return error.Overflow; } } - value |= temp; + value |= ov[0]; if (byte & 0x80 == 0) { const needs_sign_ext = group + 1 < max_group; if (byte & 0x40 != 0 and needs_sign_ext) { diff --git a/lib/std/math.zig b/lib/std/math.zig index c2e793ca8f3c..d27e4761942c 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -468,21 +468,26 @@ test "clamp" { /// Returns the product of a and b. Returns an error on overflow. pub fn mul(comptime T: type, a: T, b: T) (error{Overflow}!T) { - var answer: T = undefined; - return if (@mulWithOverflow(T, a, b, &answer)) error.Overflow else answer; + if (T == comptime_int) return a * b; + const ov = @mulWithOverflow(a, b); + if (ov[1] != 0) return error.Overflow; + return ov[0]; } /// Returns the sum of a and b. Returns an error on overflow. pub fn add(comptime T: type, a: T, b: T) (error{Overflow}!T) { if (T == comptime_int) return a + b; - var answer: T = undefined; - return if (@addWithOverflow(T, a, b, &answer)) error.Overflow else answer; + const ov = @addWithOverflow(a, b); + if (ov[1] != 0) return error.Overflow; + return ov[0]; } /// Returns a - b, or an error on overflow. pub fn sub(comptime T: type, a: T, b: T) (error{Overflow}!T) { - var answer: T = undefined; - return if (@subWithOverflow(T, a, b, &answer)) error.Overflow else answer; + if (T == comptime_int) return a - b; + const ov = @subWithOverflow(a, b); + if (ov[1] != 0) return error.Overflow; + return ov[0]; } pub fn negate(x: anytype) !@TypeOf(x) { @@ -492,8 +497,10 @@ pub fn negate(x: anytype) !@TypeOf(x) { /// Shifts a left by shift_amt. Returns an error on overflow. shift_amt /// is unsigned. pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T { - var answer: T = undefined; - return if (@shlWithOverflow(T, a, shift_amt, &answer)) error.Overflow else answer; + if (T == comptime_int) return a << shift_amt; + const ov = @shlWithOverflow(a, shift_amt); + if (ov[1] != 0) return error.Overflow; + return ov[0]; } /// Shifts left. Overflowed bits are truncated. diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index c30187445186..8410e25864ee 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -74,42 +74,40 @@ pub fn calcTwosCompLimbCount(bit_count: usize) usize { /// a + b * c + *carry, sets carry to the overflow bits pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb { @setRuntimeSafety(debug_safety); - var r1: Limb = undefined; - // r1 = a + *carry - const c1: Limb = @boolToInt(@addWithOverflow(Limb, a, carry.*, &r1)); + // ov1[0] = a + *carry + const ov1 = @addWithOverflow(a, carry.*); // r2 = b * c const bc = @as(DoubleLimb, math.mulWide(Limb, b, c)); const r2 = @truncate(Limb, bc); const c2 = @truncate(Limb, bc >> limb_bits); - // r1 = r1 + r2 - const c3: Limb = @boolToInt(@addWithOverflow(Limb, r1, r2, &r1)); + // ov2[0] = ov1[0] + r2 + const ov2 = @addWithOverflow(ov1[0], r2); // This never overflows, c1, c3 are either 0 or 1 and if both are 1 then // c2 is at least <= maxInt(Limb) - 2. - carry.* = c1 + c2 + c3; + carry.* = ov1[1] + c2 + ov2[1]; - return r1; + return ov2[0]; } /// a - b * c - *carry, sets carry to the overflow bits fn subMulLimbWithBorrow(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb { - // r1 = a - *carry - var r1: Limb = undefined; - const c1: Limb = @boolToInt(@subWithOverflow(Limb, a, carry.*, &r1)); + // ov1[0] = a - *carry + const ov1 = @subWithOverflow(a, carry.*); // r2 = b * c const bc = @as(DoubleLimb, std.math.mulWide(Limb, b, c)); const r2 = @truncate(Limb, bc); const c2 = @truncate(Limb, bc >> limb_bits); - // r1 = r1 - r2 - const c3: Limb = @boolToInt(@subWithOverflow(Limb, r1, r2, &r1)); - carry.* = c1 + c2 + c3; + // ov2[0] = ov1[0] - r2 + const ov2 = @subWithOverflow(ov1[0], r2); + carry.* = ov1[1] + c2 + ov2[1]; - return r1; + return ov2[0]; } /// Used to indicate either limit of a 2s-complement integer. @@ -673,7 +671,9 @@ pub const Mutable = struct { assert(rma.limbs.ptr != b.limbs.ptr); // illegal aliasing if (a.limbs.len == 1 and b.limbs.len == 1) { - if (!@mulWithOverflow(Limb, a.limbs[0], b.limbs[0], &rma.limbs[0])) { + const ov = @mulWithOverflow(a.limbs[0], b.limbs[0]); + rma.limbs[0] = ov[0]; + if (ov[1] == 0) { rma.len = 1; rma.positive = (a.positive == b.positive); return; @@ -1836,7 +1836,11 @@ pub const Mutable = struct { bit_index += @bitSizeOf(Limb); // 2's complement (bitwise not, then add carry bit) - if (!positive) carry = @boolToInt(@addWithOverflow(Limb, ~limb, carry, &limb)); + if (!positive) { + const ov = @addWithOverflow(~limb, carry); + limb = ov[0]; + carry = ov[1]; + } x.limbs[limb_index] = limb; } @@ -1853,7 +1857,11 @@ pub const Mutable = struct { }; // 2's complement (bitwise not, then add carry bit) - if (!positive) assert(!@addWithOverflow(Limb, ~limb, carry, &limb)); + if (!positive) { + const ov = @addWithOverflow(~limb, carry); + assert(ov[1] == 0); + limb = ov[0]; + } x.limbs[limb_index] = limb; limb_index += 1; @@ -2000,7 +2008,9 @@ pub const Const = struct { // All but the most significant limb. for (self.limbs[0 .. self.limbs.len - 1]) |limb| { - carry = @boolToInt(@addWithOverflow(Limb, ~limb, carry, &add_res)); + const ov = @addWithOverflow(~limb, carry); + add_res = ov[0]; + carry = ov[1]; sum += @popCount(add_res); remaining_bits -= limb_bits; // Asserted not to undeflow by fitsInTwosComp } @@ -2294,7 +2304,11 @@ pub const Const = struct { var limb: Limb = if (limb_index < x.limbs.len) x.limbs[limb_index] else 0; // 2's complement (bitwise not, then add carry bit) - if (!x.positive) carry = @boolToInt(@addWithOverflow(Limb, ~limb, carry, &limb)); + if (!x.positive) { + const ov = @addWithOverflow(~limb, carry); + limb = ov[0]; + carry = ov[1]; + } // Write one Limb of bits mem.writePackedInt(Limb, bytes, bit_index + bit_offset, limb, endian); @@ -2306,7 +2320,7 @@ pub const Const = struct { var limb: Limb = if (limb_index < x.limbs.len) x.limbs[limb_index] else 0; // 2's complement (bitwise not, then add carry bit) - if (!x.positive) _ = @addWithOverflow(Limb, ~limb, carry, &limb); + if (!x.positive) limb = ~limb +% carry; // Write all remaining bits mem.writeVarPackedInt(bytes, bit_index + bit_offset, bit_count - bit_index, limb, endian); @@ -3360,14 +3374,17 @@ fn llaccum(comptime op: AccOp, r: []Limb, a: []const Limb) void { var carry: Limb = 0; while (i < a.len) : (i += 1) { - var c: Limb = 0; - c += @boolToInt(@addWithOverflow(Limb, r[i], a[i], &r[i])); - c += @boolToInt(@addWithOverflow(Limb, r[i], carry, &r[i])); - carry = c; + const ov1 = @addWithOverflow(r[i], a[i]); + r[i] = ov1[0]; + const ov2 = @addWithOverflow(r[i], carry); + r[i] = ov2[0]; + carry = @as(Limb, ov1[1]) + ov2[1]; } while ((carry != 0) and i < r.len) : (i += 1) { - carry = @boolToInt(@addWithOverflow(Limb, r[i], carry, &r[i])); + const ov = @addWithOverflow(r[i], carry); + r[i] = ov[0]; + carry = ov[1]; } } @@ -3435,7 +3452,9 @@ fn llmulLimb(comptime op: AccOp, acc: []Limb, y: []const Limb, xi: Limb) bool { j = 0; while ((carry != 0) and (j < a_hi.len)) : (j += 1) { - carry = @boolToInt(@addWithOverflow(Limb, a_hi[j], carry, &a_hi[j])); + const ov = @addWithOverflow(a_hi[j], carry); + a_hi[j] = ov[0]; + carry = ov[1]; } return carry != 0; @@ -3449,7 +3468,9 @@ fn llmulLimb(comptime op: AccOp, acc: []Limb, y: []const Limb, xi: Limb) bool { j = 0; while ((borrow != 0) and (j < a_hi.len)) : (j += 1) { - borrow = @boolToInt(@subWithOverflow(Limb, a_hi[j], borrow, &a_hi[j])); + const ov = @subWithOverflow(a_hi[j], borrow); + a_hi[j] = ov[0]; + borrow = ov[1]; } return borrow != 0; @@ -3482,14 +3503,17 @@ fn llsubcarry(r: []Limb, a: []const Limb, b: []const Limb) Limb { var borrow: Limb = 0; while (i < b.len) : (i += 1) { - var c: Limb = 0; - c += @boolToInt(@subWithOverflow(Limb, a[i], b[i], &r[i])); - c += @boolToInt(@subWithOverflow(Limb, r[i], borrow, &r[i])); - borrow = c; + const ov1 = @subWithOverflow(a[i], b[i]); + r[i] = ov1[0]; + const ov2 = @subWithOverflow(r[i], borrow); + r[i] = ov2[0]; + borrow = @as(Limb, ov1[1]) + ov2[1]; } while (i < a.len) : (i += 1) { - borrow = @boolToInt(@subWithOverflow(Limb, a[i], borrow, &r[i])); + const ov = @subWithOverflow(a[i], borrow); + r[i] = ov[0]; + borrow = ov[1]; } return borrow; @@ -3512,14 +3536,17 @@ fn lladdcarry(r: []Limb, a: []const Limb, b: []const Limb) Limb { var carry: Limb = 0; while (i < b.len) : (i += 1) { - var c: Limb = 0; - c += @boolToInt(@addWithOverflow(Limb, a[i], b[i], &r[i])); - c += @boolToInt(@addWithOverflow(Limb, r[i], carry, &r[i])); - carry = c; + const ov1 = @addWithOverflow(a[i], b[i]); + r[i] = ov1[0]; + const ov2 = @addWithOverflow(r[i], carry); + r[i] = ov2[0]; + carry = @as(Limb, ov1[1]) + ov2[1]; } while (i < a.len) : (i += 1) { - carry = @boolToInt(@addWithOverflow(Limb, a[i], carry, &r[i])); + const ov = @addWithOverflow(a[i], carry); + r[i] = ov[0]; + carry = ov[1]; } return carry; @@ -3685,11 +3712,11 @@ fn llsignedor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_p var r_carry: u1 = 1; while (i < b.len) : (i += 1) { - var a_limb: Limb = undefined; - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &a_limb)); - - r[i] = a_limb & ~b[i]; - r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); + const ov1 = @subWithOverflow(a[i], a_borrow); + a_borrow = ov1[1]; + const ov2 = @addWithOverflow(ov1[0] & ~b[i], r_carry); + r[i] = ov2[0]; + r_carry = ov2[1]; } // In order for r_carry to be nonzero at this point, ~b[i] would need to be @@ -3702,7 +3729,9 @@ fn llsignedor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_p // Note, if a_borrow is zero we do not need to compute anything for // the higher limbs so we can early return here. while (i < a.len and a_borrow == 1) : (i += 1) { - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &r[i])); + const ov = @subWithOverflow(a[i], a_borrow); + r[i] = ov[0]; + a_borrow = ov[1]; } assert(a_borrow == 0); // a was 0. @@ -3721,11 +3750,11 @@ fn llsignedor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_p var r_carry: u1 = 1; while (i < b.len) : (i += 1) { - var b_limb: Limb = undefined; - b_borrow = @boolToInt(@subWithOverflow(Limb, b[i], b_borrow, &b_limb)); - - r[i] = ~a[i] & b_limb; - r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); + const ov1 = @subWithOverflow(b[i], b_borrow); + b_borrow = ov1[1]; + const ov2 = @addWithOverflow(~a[i] & ov1[0], r_carry); + r[i] = ov2[0]; + r_carry = ov2[1]; } // b is at least 1, so this should never underflow. @@ -3752,14 +3781,13 @@ fn llsignedor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_p var r_carry: u1 = 1; while (i < b.len) : (i += 1) { - var a_limb: Limb = undefined; - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &a_limb)); - - var b_limb: Limb = undefined; - b_borrow = @boolToInt(@subWithOverflow(Limb, b[i], b_borrow, &b_limb)); - - r[i] = a_limb & b_limb; - r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); + const ov1 = @subWithOverflow(a[i], a_borrow); + a_borrow = ov1[1]; + const ov2 = @subWithOverflow(b[i], b_borrow); + b_borrow = ov2[1]; + const ov3 = @addWithOverflow(ov1[0] & ov2[0], r_carry); + r[i] = ov3[0]; + r_carry = ov3[1]; } // b is at least 1, so this should never underflow. @@ -3811,9 +3839,9 @@ fn llsignedand(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_ var a_borrow: u1 = 1; while (i < b.len) : (i += 1) { - var a_limb: Limb = undefined; - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &a_limb)); - r[i] = ~a_limb & b[i]; + const ov = @subWithOverflow(a[i], a_borrow); + a_borrow = ov[1]; + r[i] = ~ov[0] & b[i]; } // With b = 0 we have ~(a - 1) & 0 = 0, so the upper bytes are zero. @@ -3830,9 +3858,9 @@ fn llsignedand(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_ var b_borrow: u1 = 1; while (i < b.len) : (i += 1) { - var a_limb: Limb = undefined; - b_borrow = @boolToInt(@subWithOverflow(Limb, b[i], b_borrow, &a_limb)); - r[i] = a[i] & ~a_limb; + const ov = @subWithOverflow(b[i], b_borrow); + b_borrow = ov[1]; + r[i] = a[i] & ~ov[0]; } assert(b_borrow == 0); // b was 0 @@ -3855,14 +3883,13 @@ fn llsignedand(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_ var r_carry: u1 = 1; while (i < b.len) : (i += 1) { - var a_limb: Limb = undefined; - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &a_limb)); - - var b_limb: Limb = undefined; - b_borrow = @boolToInt(@subWithOverflow(Limb, b[i], b_borrow, &b_limb)); - - r[i] = a_limb | b_limb; - r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); + const ov1 = @subWithOverflow(a[i], a_borrow); + a_borrow = ov1[1]; + const ov2 = @subWithOverflow(b[i], b_borrow); + b_borrow = ov2[1]; + const ov3 = @addWithOverflow(ov1[0] | ov2[0], r_carry); + r[i] = ov3[0]; + r_carry = ov3[1]; } // b is at least 1, so this should never underflow. @@ -3870,8 +3897,11 @@ fn llsignedand(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_ // With b = 0 and b_borrow = 0 we get (-a - 1) | (-0 - 0) = (-a - 1) | 0 = -a - 1. while (i < a.len) : (i += 1) { - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &r[i])); - r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); + const ov1 = @subWithOverflow(a[i], a_borrow); + a_borrow = ov1[1]; + const ov2 = @addWithOverflow(ov1[0], r_carry); + r[i] = ov2[0]; + r_carry = ov2[1]; } assert(a_borrow == 0); // a was 0. @@ -3917,19 +3947,21 @@ fn llsignedxor(r: []Limb, a: []const Limb, a_positive: bool, b: []const Limb, b_ var r_carry = @boolToInt(a_positive != b_positive); while (i < b.len) : (i += 1) { - var a_limb: Limb = undefined; - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &a_limb)); - - var b_limb: Limb = undefined; - b_borrow = @boolToInt(@subWithOverflow(Limb, b[i], b_borrow, &b_limb)); - - r[i] = a_limb ^ b_limb; - r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); + const ov1 = @subWithOverflow(a[i], a_borrow); + a_borrow = ov1[1]; + const ov2 = @subWithOverflow(b[i], b_borrow); + b_borrow = ov2[1]; + const ov3 = @addWithOverflow(ov1[0] ^ ov2[0], r_carry); + r[i] = ov3[0]; + r_carry = ov3[1]; } while (i < a.len) : (i += 1) { - a_borrow = @boolToInt(@subWithOverflow(Limb, a[i], a_borrow, &r[i])); - r_carry = @boolToInt(@addWithOverflow(Limb, r[i], r_carry, &r[i])); + const ov1 = @subWithOverflow(a[i], a_borrow); + a_borrow = ov1[1]; + const ov2 = @addWithOverflow(ov1[0], r_carry); + r[i] = ov2[0]; + r_carry = ov2[1]; } // If both inputs don't share the same sign, an extra limb is required. @@ -4021,7 +4053,9 @@ fn llpow(r: []Limb, a: []const Limb, b: u32, tmp_limbs: []Limb) void { llsquareBasecase(tmp2, tmp1[0..llnormalize(tmp1)]); mem.swap([]Limb, &tmp1, &tmp2); // Multiply by a - if (@shlWithOverflow(u32, exp, 1, &exp)) { + const ov = @shlWithOverflow(exp, 1); + exp = ov[0]; + if (ov[1] != 0) { mem.set(Limb, tmp2, 0); llmulacc(.add, null, tmp2, tmp1[0..llnormalize(tmp1)], a); mem.swap([]Limb, &tmp1, &tmp2); diff --git a/lib/std/math/powi.zig b/lib/std/math/powi.zig index 2e615de5d54f..d7d07985ebdf 100644 --- a/lib/std/math/powi.zig +++ b/lib/std/math/powi.zig @@ -70,22 +70,22 @@ pub fn powi(comptime T: type, x: T, y: T) (error{ while (exp > 1) { if (exp & 1 == 1) { - if (@mulWithOverflow(T, acc, base, &acc)) { - return error.Overflow; - } + const ov = @mulWithOverflow(acc, base); + if (ov[1] != 0) return error.Overflow; + acc = ov[0]; } exp >>= 1; - if (@mulWithOverflow(T, base, base, &base)) { - return error.Overflow; - } + const ov = @mulWithOverflow(base, base); + if (ov[1] != 0) return error.Overflow; + base = ov[0]; } if (exp == 1) { - if (@mulWithOverflow(T, acc, base, &acc)) { - return error.Overflow; - } + const ov = @mulWithOverflow(acc, base); + if (ov[1] != 0) return error.Overflow; + acc = ov[0]; } return acc; diff --git a/lib/std/mem.zig b/lib/std/mem.zig index a392335a7009..774db2caa474 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -3304,13 +3304,13 @@ pub fn alignPointerOffset(ptr: anytype, align_to: usize) ?usize { // Calculate the aligned base address with an eye out for overflow. const addr = @ptrToInt(ptr); - var new_addr: usize = undefined; - if (@addWithOverflow(usize, addr, align_to - 1, &new_addr)) return null; - new_addr &= ~@as(usize, align_to - 1); + var ov = @addWithOverflow(addr, align_to - 1); + if (ov[1] != 0) return null; + ov[0] &= ~@as(usize, align_to - 1); // The delta is expressed in terms of bytes, turn it into a number of child // type elements. - const delta = new_addr - addr; + const delta = ov[0] - addr; const pointee_size = @sizeOf(info.Pointer.child); if (delta % pointee_size != 0) return null; return delta / pointee_size; diff --git a/lib/std/net.zig b/lib/std/net.zig index 6818b91d5a83..4a0582e7f5ef 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -321,11 +321,15 @@ pub const Ip6Address = extern struct { if (scope_id) { if (c >= '0' and c <= '9') { const digit = c - '0'; - if (@mulWithOverflow(u32, result.sa.scope_id, 10, &result.sa.scope_id)) { - return error.Overflow; + { + const ov = @mulWithOverflow(result.sa.scope_id, 10); + if (ov[1] != 0) return error.Overflow; + result.sa.scope_id = ov[0]; } - if (@addWithOverflow(u32, result.sa.scope_id, digit, &result.sa.scope_id)) { - return error.Overflow; + { + const ov = @addWithOverflow(result.sa.scope_id, digit); + if (ov[1] != 0) return error.Overflow; + result.sa.scope_id = ov[0]; } } else { return error.InvalidCharacter; @@ -377,11 +381,15 @@ pub const Ip6Address = extern struct { return result; } else { const digit = try std.fmt.charToDigit(c, 16); - if (@mulWithOverflow(u16, x, 16, &x)) { - return error.Overflow; + { + const ov = @mulWithOverflow(x, 16); + if (ov[1] != 0) return error.Overflow; + x = ov[0]; } - if (@addWithOverflow(u16, x, digit, &x)) { - return error.Overflow; + { + const ov = @addWithOverflow(x, digit); + if (ov[1] != 0) return error.Overflow; + x = ov[0]; } saw_any_digits = true; } @@ -492,11 +500,15 @@ pub const Ip6Address = extern struct { return result; } else { const digit = try std.fmt.charToDigit(c, 16); - if (@mulWithOverflow(u16, x, 16, &x)) { - return error.Overflow; + { + const ov = @mulWithOverflow(x, 16); + if (ov[1] != 0) return error.Overflow; + x = ov[0]; } - if (@addWithOverflow(u16, x, digit, &x)) { - return error.Overflow; + { + const ov = @addWithOverflow(x, digit); + if (ov[1] != 0) return error.Overflow; + x = ov[0]; } saw_any_digits = true; } diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 7f227ffec4a4..ecb8a21d7a6b 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1244,7 +1244,7 @@ pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize var size: i32 = 0; const msg_iovlen = @intCast(usize, msg.msg_hdr.msg_iovlen); // kernel side this is treated as unsigned for (msg.msg_hdr.msg_iov[0..msg_iovlen]) |iov| { - if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(i32, size, @intCast(i32, iov.iov_len), &size)) { + if (iov.iov_len > std.math.maxInt(i32) or @addWithOverflow(size, @intCast(i32, iov.iov_len))[1] != 0) { // batch-send all messages up to the current message if (next_unsent < i) { const batch_size = i - next_unsent; diff --git a/lib/std/process.zig b/lib/std/process.zig index 23fad9e8c67d..849596ebfa16 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -1023,8 +1023,16 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo { '0'...'9' => byte - '0', else => return error.CorruptPasswordFile, }; - if (@mulWithOverflow(u32, uid, 10, &uid)) return error.CorruptPasswordFile; - if (@addWithOverflow(u32, uid, digit, &uid)) return error.CorruptPasswordFile; + { + const ov = @mulWithOverflow(uid, 10); + if (ov[1] != 0) return error.CorruptPasswordFile; + uid = ov[0]; + } + { + const ov = @addWithOverflow(uid, digit); + if (ov[1] != 0) return error.CorruptPasswordFile; + uid = ov[0]; + } }, }, .ReadGroupId => switch (byte) { @@ -1039,8 +1047,16 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo { '0'...'9' => byte - '0', else => return error.CorruptPasswordFile, }; - if (@mulWithOverflow(u32, gid, 10, &gid)) return error.CorruptPasswordFile; - if (@addWithOverflow(u32, gid, digit, &gid)) return error.CorruptPasswordFile; + { + const ov = @mulWithOverflow(gid, 10); + if (ov[1] != 0) return error.CorruptPasswordFile; + gid = ov[0]; + } + { + const ov = @addWithOverflow(gid, digit); + if (ov[1] != 0) return error.CorruptPasswordFile; + gid = ov[0]; + } }, }, } diff --git a/lib/std/zig/c_builtins.zig b/lib/std/zig/c_builtins.zig index 08a2ec78c4e1..9c28e56e3158 100644 --- a/lib/std/zig/c_builtins.zig +++ b/lib/std/zig/c_builtins.zig @@ -246,7 +246,9 @@ pub inline fn __builtin_constant_p(expr: anytype) c_int { return @boolToInt(false); } pub fn __builtin_mul_overflow(a: anytype, b: anytype, result: *@TypeOf(a, b)) c_int { - return @boolToInt(@mulWithOverflow(@TypeOf(a, b), a, b, result)); + const res = @mulWithOverflow(a, b); + result.* = res[0]; + return res[1]; } // __builtin_alloca_with_align is not currently implemented. diff --git a/lib/std/zig/number_literal.zig b/lib/std/zig/number_literal.zig index 118d16f59e7e..1b41908371f6 100644 --- a/lib/std/zig/number_literal.zig +++ b/lib/std/zig/number_literal.zig @@ -151,12 +151,14 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { special = 0; if (float) continue; - if (x != 0) if (@mulWithOverflow(u64, x, base, &x)) { - overflow = true; - }; - if (@addWithOverflow(u64, x, digit, &x)) { - overflow = true; + if (x != 0) { + const res = @mulWithOverflow(x, base); + if (res[1] != 0) overflow = true; + x = res[0]; } + const res = @addWithOverflow(x, digit); + if (res[1] != 0) overflow = true; + x = res[0]; } if (underscore) return .{ .failure = .{ .trailing_underscore = bytes.len - 1 } }; if (special != 0) return .{ .failure = .{ .trailing_special = bytes.len - 1 } }; diff --git a/src/link/Coff.zig b/src/link/Coff.zig index aa94704c5451..232342dd7f36 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1860,9 +1860,7 @@ fn writeHeader(self: *Coff) !void { } pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { - // TODO https://github.com/ziglang/zig/issues/1284 - return math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch - math.maxInt(@TypeOf(actual_size)); + return actual_size +| (actual_size / ideal_factor); } fn detectAllocCollision(self: *Coff, start: u32, size: u32) ?u32 { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 6cc3a7d68f81..1b65bbb04b89 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -2445,9 +2445,7 @@ fn makeString(self: *Dwarf, bytes: []const u8) !u32 { } fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { - // TODO https://github.com/ziglang/zig/issues/1284 - return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch - std.math.maxInt(@TypeOf(actual_size)); + return actual_size +| (actual_size / ideal_factor); } pub fn flushModule(self: *Dwarf, module: *Module) !void { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 30c88fe9b200..466442cd774f 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3032,9 +3032,7 @@ fn getLDMOption(target: std.Target) ?[]const u8 { } fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { - // TODO https://github.com/ziglang/zig/issues/1284 - return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch - std.math.maxInt(@TypeOf(actual_size)); + return actual_size +| (actual_size / ideal_factor); } // Provide a blueprint of csu (c-runtime startup) objects for supported diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 72a24b0ac6a2..0187de21683e 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3768,9 +3768,7 @@ fn writeHeader(self: *MachO, ncmds: u32, sizeofcmds: u32) !void { } pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { - // TODO https://github.com/ziglang/zig/issues/1284 - return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch - std.math.maxInt(@TypeOf(actual_size)); + return actual_size +| (actual_size / ideal_factor); } fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 { diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index 97c3a85bbb89..8c3962e3e492 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -489,18 +489,11 @@ test "comptime bitwise operators" { test "comptime shlWithOverflow" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO - const ct_shifted: u64 = comptime amt: { - var amt = @as(u64, 0); - _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt); - break :amt amt; - }; - - const rt_shifted: u64 = amt: { - var amt = @as(u64, 0); - _ = @shlWithOverflow(u64, ~@as(u64, 0), 16, &amt); - break :amt amt; - }; + const ct_shifted = @shlWithOverflow(~@as(u64, 0), 16)[0]; + var a = ~@as(u64, 0); + const rt_shifted = @shlWithOverflow(a, 16)[0]; try expect(ct_shifted == rt_shifted); } diff --git a/test/behavior/math.zig b/test/behavior/math.zig index 763c249c5028..02a3f999e992 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -534,6 +534,7 @@ fn testUnsignedNegationWrappingEval(x: u16) !void { test "negation wrapping" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO try expectEqual(@as(u1, 1), negateWrap(u1, 1)); @@ -634,42 +635,53 @@ test "128-bit multiplication" { } test "@addWithOverflow" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO { - var result: u8 = undefined; - try expect(@addWithOverflow(u8, 250, 100, &result)); - try expect(result == 94); - try expect(!@addWithOverflow(u8, 100, 150, &result)); - try expect(result == 250); - + var a: u8 = 250; + const ov = @addWithOverflow(a, 100); + try expect(ov[0] == 94); + try expect(ov[1] == 1); + } + { + var a: u8 = 100; + const ov = @addWithOverflow(a, 150); + try expect(ov[0] == 250); + try expect(ov[1] == 0); + } + { var a: u8 = 200; var b: u8 = 99; - try expect(@addWithOverflow(u8, a, b, &result)); - try expect(result == 43); + var ov = @addWithOverflow(a, b); + try expect(ov[0] == 43); + try expect(ov[1] == 1); b = 55; - try expect(!@addWithOverflow(u8, a, b, &result)); - try expect(result == 255); + ov = @addWithOverflow(a, b); + try expect(ov[0] == 255); + try expect(ov[1] == 0); } { var a: usize = 6; var b: usize = 6; - var res: usize = undefined; - try expect(!@addWithOverflow(usize, a, b, &res)); - try expect(res == 12); + const ov = @addWithOverflow(a, b); + try expect(ov[0] == 12); + try expect(ov[1] == 0); } { var a: isize = -6; var b: isize = -6; - var res: isize = undefined; - try expect(!@addWithOverflow(isize, a, b, &res)); - try expect(res == -12); + const ov = @addWithOverflow(a, b); + try expect(ov[0] == -12); + try expect(ov[1] == 0); } } test "small int addition" { + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO var x: u2 = 0; @@ -684,176 +696,200 @@ test "small int addition" { x += 1; try expect(x == 3); - var result: @TypeOf(x) = 3; - try expect(@addWithOverflow(@TypeOf(x), x, 1, &result)); - - try expect(result == 0); + const ov = @addWithOverflow(x, 1); + try expect(ov[0] == 0); + try expect(ov[1] == 1); } test "basic @mulWithOverflow" { - var result: u8 = undefined; - try expect(@mulWithOverflow(u8, 86, 3, &result)); - try expect(result == 2); - try expect(!@mulWithOverflow(u8, 85, 3, &result)); - try expect(result == 255); + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + + { + var a: u8 = 86; + const ov = @mulWithOverflow(a, 3); + try expect(ov[0] == 2); + try expect(ov[1] == 1); + } + { + var a: u8 = 85; + const ov = @mulWithOverflow(a, 3); + try expect(ov[0] == 255); + try expect(ov[1] == 0); + } var a: u8 = 123; var b: u8 = 2; - try expect(!@mulWithOverflow(u8, a, b, &result)); - try expect(result == 246); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 246); + try expect(ov[1] == 0); b = 4; - try expect(@mulWithOverflow(u8, a, b, &result)); - try expect(result == 236); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 236); + try expect(ov[1] == 1); } -// TODO migrate to this for all backends once they handle more cases test "extensive @mulWithOverflow" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO { var a: u5 = 3; var b: u5 = 10; - var res: u5 = undefined; - try expect(!@mulWithOverflow(u5, a, b, &res)); - try expect(res == 30); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 30); + try expect(ov[1] == 0); b = 11; - try expect(@mulWithOverflow(u5, a, b, &res)); - try expect(res == 1); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 1); + try expect(ov[1] == 1); } { var a: i5 = 3; var b: i5 = -5; - var res: i5 = undefined; - try expect(!@mulWithOverflow(i5, a, b, &res)); - try expect(res == -15); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -15); + try expect(ov[1] == 0); b = -6; - try expect(@mulWithOverflow(i5, a, b, &res)); - try expect(res == 14); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 14); + try expect(ov[1] == 1); } { var a: u8 = 3; var b: u8 = 85; - var res: u8 = undefined; - try expect(!@mulWithOverflow(u8, a, b, &res)); - try expect(res == 255); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 255); + try expect(ov[1] == 0); b = 86; - try expect(@mulWithOverflow(u8, a, b, &res)); - try expect(res == 2); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 2); + try expect(ov[1] == 1); } { var a: i8 = 3; var b: i8 = -42; - var res: i8 = undefined; - try expect(!@mulWithOverflow(i8, a, b, &res)); - try expect(res == -126); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -126); + try expect(ov[1] == 0); b = -43; - try expect(@mulWithOverflow(i8, a, b, &res)); - try expect(res == 127); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 127); + try expect(ov[1] == 1); } { var a: u14 = 3; var b: u14 = 0x1555; - var res: u14 = undefined; - try expect(!@mulWithOverflow(u14, a, b, &res)); - try expect(res == 0x3fff); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x3fff); + try expect(ov[1] == 0); b = 0x1556; - try expect(@mulWithOverflow(u14, a, b, &res)); - try expect(res == 2); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 2); + try expect(ov[1] == 1); } { var a: i14 = 3; var b: i14 = -0xaaa; - var res: i14 = undefined; - try expect(!@mulWithOverflow(i14, a, b, &res)); - try expect(res == -0x1ffe); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -0x1ffe); + try expect(ov[1] == 0); b = -0xaab; - try expect(@mulWithOverflow(i14, a, b, &res)); - try expect(res == 0x1fff); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x1fff); } { var a: u16 = 3; var b: u16 = 0x5555; - var res: u16 = undefined; - try expect(!@mulWithOverflow(u16, a, b, &res)); - try expect(res == 0xffff); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0xffff); + try expect(ov[1] == 0); b = 0x5556; - try expect(@mulWithOverflow(u16, a, b, &res)); - try expect(res == 2); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 2); + try expect(ov[1] == 1); } { var a: i16 = 3; var b: i16 = -0x2aaa; - var res: i16 = undefined; - try expect(!@mulWithOverflow(i16, a, b, &res)); - try expect(res == -0x7ffe); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -0x7ffe); + try expect(ov[1] == 0); b = -0x2aab; - try expect(@mulWithOverflow(i16, a, b, &res)); - try expect(res == 0x7fff); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x7fff); + try expect(ov[1] == 1); } { var a: u30 = 3; var b: u30 = 0x15555555; - var res: u30 = undefined; - try expect(!@mulWithOverflow(u30, a, b, &res)); - try expect(res == 0x3fffffff); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x3fffffff); + try expect(ov[1] == 0); b = 0x15555556; - try expect(@mulWithOverflow(u30, a, b, &res)); - try expect(res == 2); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 2); + try expect(ov[1] == 1); } { var a: i30 = 3; var b: i30 = -0xaaaaaaa; - var res: i30 = undefined; - try expect(!@mulWithOverflow(i30, a, b, &res)); - try expect(res == -0x1ffffffe); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -0x1ffffffe); + try expect(ov[1] == 0); b = -0xaaaaaab; - try expect(@mulWithOverflow(i30, a, b, &res)); - try expect(res == 0x1fffffff); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x1fffffff); + try expect(ov[1] == 1); } { var a: u32 = 3; var b: u32 = 0x55555555; - var res: u32 = undefined; - try expect(!@mulWithOverflow(u32, a, b, &res)); - try expect(res == 0xffffffff); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0xffffffff); + try expect(ov[1] == 0); b = 0x55555556; - try expect(@mulWithOverflow(u32, a, b, &res)); - try expect(res == 2); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 2); + try expect(ov[1] == 1); } { var a: i32 = 3; var b: i32 = -0x2aaaaaaa; - var res: i32 = undefined; - try expect(!@mulWithOverflow(i32, a, b, &res)); - try expect(res == -0x7ffffffe); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -0x7ffffffe); + try expect(ov[1] == 0); b = -0x2aaaaaab; - try expect(@mulWithOverflow(i32, a, b, &res)); - try expect(res == 0x7fffffff); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x7fffffff); + try expect(ov[1] == 1); } } @@ -865,140 +901,181 @@ test "@mulWithOverflow bitsize > 32" { { var a: u62 = 3; var b: u62 = 0x1555555555555555; - var res: u62 = undefined; - try expect(!@mulWithOverflow(u62, a, b, &res)); - try expect(res == 0x3fffffffffffffff); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x3fffffffffffffff); + try expect(ov[1] == 0); b = 0x1555555555555556; - try expect(@mulWithOverflow(u62, a, b, &res)); - try expect(res == 2); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 2); + try expect(ov[1] == 1); } { var a: i62 = 3; var b: i62 = -0xaaaaaaaaaaaaaaa; - var res: i62 = undefined; - try expect(!@mulWithOverflow(i62, a, b, &res)); - try expect(res == -0x1ffffffffffffffe); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -0x1ffffffffffffffe); + try expect(ov[1] == 0); b = -0xaaaaaaaaaaaaaab; - try expect(@mulWithOverflow(i62, a, b, &res)); - try expect(res == 0x1fffffffffffffff); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x1fffffffffffffff); + try expect(ov[1] == 1); } { var a: u64 = 3; var b: u64 = 0x5555555555555555; - var res: u64 = undefined; - try expect(!@mulWithOverflow(u64, a, b, &res)); - try expect(res == 0xffffffffffffffff); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0xffffffffffffffff); + try expect(ov[1] == 0); b = 0x5555555555555556; - try expect(@mulWithOverflow(u64, a, b, &res)); - try expect(res == 2); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 2); + try expect(ov[1] == 1); } { var a: i64 = 3; var b: i64 = -0x2aaaaaaaaaaaaaaa; - var res: i64 = undefined; - try expect(!@mulWithOverflow(i64, a, b, &res)); - try expect(res == -0x7ffffffffffffffe); + var ov = @mulWithOverflow(a, b); + try expect(ov[0] == -0x7ffffffffffffffe); + try expect(ov[1] == 0); b = -0x2aaaaaaaaaaaaaab; - try expect(@mulWithOverflow(i64, a, b, &res)); - try expect(res == 0x7fffffffffffffff); + ov = @mulWithOverflow(a, b); + try expect(ov[0] == 0x7fffffffffffffff); + try expect(ov[1] == 1); } } test "@subWithOverflow" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO { - var result: u8 = undefined; - try expect(@subWithOverflow(u8, 1, 2, &result)); - try expect(result == 255); - try expect(!@subWithOverflow(u8, 1, 1, &result)); - try expect(result == 0); + var a: u8 = 1; + const ov = @subWithOverflow(a, 2); + try expect(ov[0] == 255); + try expect(ov[1] == 1); + } + { + var a: u8 = 1; + const ov = @subWithOverflow(a, 1); + try expect(ov[0] == 0); + try expect(ov[1] == 0); + } + { var a: u8 = 1; var b: u8 = 2; - try expect(@subWithOverflow(u8, a, b, &result)); - try expect(result == 255); + var ov = @subWithOverflow(a, b); + try expect(ov[0] == 255); + try expect(ov[1] == 1); b = 1; - try expect(!@subWithOverflow(u8, a, b, &result)); - try expect(result == 0); + ov = @subWithOverflow(a, b); + try expect(ov[0] == 0); + try expect(ov[1] == 0); } { var a: usize = 6; var b: usize = 6; - var res: usize = undefined; - try expect(!@subWithOverflow(usize, a, b, &res)); - try expect(res == 0); + const ov = @subWithOverflow(a, b); + try expect(ov[0] == 0); + try expect(ov[1] == 0); } { var a: isize = -6; var b: isize = -6; - var res: isize = undefined; - try expect(!@subWithOverflow(isize, a, b, &res)); - try expect(res == 0); + const ov = @subWithOverflow(a, b); + try expect(ov[0] == 0); + try expect(ov[1] == 0); } } test "@shlWithOverflow" { + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO { - var result: u4 = undefined; var a: u4 = 2; var b: u2 = 1; - try expect(!@shlWithOverflow(u4, a, b, &result)); - try expect(result == 4); + var ov = @shlWithOverflow(a, b); + try expect(ov[0] == 4); + try expect(ov[1] == 0); b = 3; - try expect(@shlWithOverflow(u4, a, b, &result)); - try expect(result == 0); + ov = @shlWithOverflow(a, b); + try expect(ov[0] == 0); + try expect(ov[1] == 1); } { - var result: i9 = undefined; var a: i9 = 127; var b: u4 = 1; - try expect(!@shlWithOverflow(i9, a, b, &result)); - try expect(result == 254); + var ov = @shlWithOverflow(a, b); + try expect(ov[0] == 254); + try expect(ov[1] == 0); b = 2; - try expect(@shlWithOverflow(i9, a, b, &result)); - try expect(result == -4); + ov = @shlWithOverflow(a, b); + try expect(ov[0] == -4); + try expect(ov[1] == 1); } { - var result: u16 = undefined; - try expect(@shlWithOverflow(u16, 0b0010111111111111, 3, &result)); - try expect(result == 0b0111111111111000); - try expect(!@shlWithOverflow(u16, 0b0010111111111111, 2, &result)); - try expect(result == 0b1011111111111100); - + const ov = @shlWithOverflow(@as(u16, 0b0010111111111111), 3); + try expect(ov[0] == 0b0111111111111000); + try expect(ov[1] == 1); + } + { + const ov = @shlWithOverflow(@as(u16, 0b0010111111111111), 2); + try expect(ov[0] == 0b1011111111111100); + try expect(ov[1] == 0); + } + { var a: u16 = 0b0000_0000_0000_0011; var b: u4 = 15; - try expect(@shlWithOverflow(u16, a, b, &result)); - try expect(result == 0b1000_0000_0000_0000); + var ov = @shlWithOverflow(a, b); + try expect(ov[0] == 0b1000_0000_0000_0000); + try expect(ov[1] == 1); b = 14; - try expect(!@shlWithOverflow(u16, a, b, &result)); - try expect(result == 0b1100_0000_0000_0000); + ov = @shlWithOverflow(a, b); + try expect(ov[0] == 0b1100_0000_0000_0000); + try expect(ov[1] == 0); } } test "overflow arithmetic with u0 values" { - var result: u0 = undefined; - try expect(!@addWithOverflow(u0, 0, 0, &result)); - try expect(result == 0); - try expect(!@subWithOverflow(u0, 0, 0, &result)); - try expect(result == 0); - try expect(!@mulWithOverflow(u0, 0, 0, &result)); - try expect(result == 0); - try expect(!@shlWithOverflow(u0, 0, 0, &result)); - try expect(result == 0); + { + var a: u0 = 0; + const ov = @addWithOverflow(a, 0); + try expect(ov[1] == 0); + try expect(ov[1] == 0); + } + { + var a: u0 = 0; + const ov = @subWithOverflow(a, 0); + try expect(ov[1] == 0); + try expect(ov[1] == 0); + } + { + var a: u0 = 0; + const ov = @mulWithOverflow(a, 0); + try expect(ov[1] == 0); + try expect(ov[1] == 0); + } + { + var a: u0 = 0; + const ov = @shlWithOverflow(a, 0); + try expect(ov[1] == 0); + try expect(ov[1] == 0); + } } test "allow signed integer division/remainder when values are comptime-known and positive or exact" { diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index 322142d8fceb..7a94640655f3 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -963,35 +963,31 @@ test "@addWithOverflow" { const S = struct { fn doTheTest() !void { { - var result: @Vector(4, u8) = undefined; var lhs = @Vector(4, u8){ 250, 250, 250, 250 }; var rhs = @Vector(4, u8){ 0, 5, 6, 10 }; - var overflow = @addWithOverflow(@Vector(4, u8), lhs, rhs, &result); - var expected: @Vector(4, bool) = .{ false, false, true, true }; + var overflow = @addWithOverflow(lhs, rhs)[1]; + var expected: @Vector(4, u1) = .{ 0, 0, 1, 1 }; try expectEqual(expected, overflow); } { - var result: @Vector(4, i8) = undefined; var lhs = @Vector(4, i8){ -125, -125, 125, 125 }; var rhs = @Vector(4, i8){ -3, -4, 2, 3 }; - var overflow = @addWithOverflow(@Vector(4, i8), lhs, rhs, &result); - var expected: @Vector(4, bool) = .{ false, true, false, true }; + var overflow = @addWithOverflow(lhs, rhs)[1]; + var expected: @Vector(4, u1) = .{ 0, 1, 0, 1 }; try expectEqual(expected, overflow); } { - var result: @Vector(4, u1) = undefined; var lhs = @Vector(4, u1){ 0, 0, 1, 1 }; var rhs = @Vector(4, u1){ 0, 1, 0, 1 }; - var overflow = @addWithOverflow(@Vector(4, u1), lhs, rhs, &result); - var expected: @Vector(4, bool) = .{ false, false, false, true }; + var overflow = @addWithOverflow(lhs, rhs)[1]; + var expected: @Vector(4, u1) = .{ 0, 0, 0, 1 }; try expectEqual(expected, overflow); } { - var result: @Vector(4, u0) = undefined; var lhs = @Vector(4, u0){ 0, 0, 0, 0 }; var rhs = @Vector(4, u0){ 0, 0, 0, 0 }; - var overflow = @addWithOverflow(@Vector(4, u0), lhs, rhs, &result); - var expected: @Vector(4, bool) = .{ false, false, false, false }; + var overflow = @addWithOverflow(lhs, rhs)[1]; + var expected: @Vector(4, u1) = .{ 0, 0, 0, 0 }; try expectEqual(expected, overflow); } } @@ -1010,19 +1006,17 @@ test "@subWithOverflow" { const S = struct { fn doTheTest() !void { { - var result: @Vector(2, u8) = undefined; var lhs = @Vector(2, u8){ 5, 5 }; var rhs = @Vector(2, u8){ 5, 6 }; - var overflow = @subWithOverflow(@Vector(2, u8), lhs, rhs, &result); - var expected: @Vector(2, bool) = .{ false, true }; + var overflow = @subWithOverflow(lhs, rhs)[1]; + var expected: @Vector(2, u1) = .{ 0, 1 }; try expectEqual(expected, overflow); } { - var result: @Vector(4, i8) = undefined; var lhs = @Vector(4, i8){ -120, -120, 120, 120 }; var rhs = @Vector(4, i8){ 8, 9, -7, -8 }; - var overflow = @subWithOverflow(@Vector(4, i8), lhs, rhs, &result); - var expected: @Vector(4, bool) = .{ false, true, false, true }; + var overflow = @subWithOverflow(lhs, rhs)[1]; + var expected: @Vector(4, u1) = .{ 0, 1, 0, 1 }; try expectEqual(expected, overflow); } } @@ -1040,11 +1034,10 @@ test "@mulWithOverflow" { const S = struct { fn doTheTest() !void { - var result: @Vector(4, u8) = undefined; var lhs = @Vector(4, u8){ 10, 10, 10, 10 }; var rhs = @Vector(4, u8){ 25, 26, 0, 30 }; - var overflow = @mulWithOverflow(@Vector(4, u8), lhs, rhs, &result); - var expected: @Vector(4, bool) = .{ false, true, false, true }; + var overflow = @mulWithOverflow(lhs, rhs)[1]; + var expected: @Vector(4, u1) = .{ 0, 1, 0, 1 }; try expectEqual(expected, overflow); } }; @@ -1062,11 +1055,10 @@ test "@shlWithOverflow" { const S = struct { fn doTheTest() !void { - var result: @Vector(4, u8) = undefined; var lhs = @Vector(4, u8){ 0, 1, 8, 255 }; var rhs = @Vector(4, u3){ 7, 7, 7, 7 }; - var overflow = @shlWithOverflow(@Vector(4, u8), lhs, rhs, &result); - var expected: @Vector(4, bool) = .{ false, false, true, true }; + var overflow = @shlWithOverflow(lhs, rhs)[1]; + var expected: @Vector(4, u1) = .{ 0, 0, 1, 1 }; try expectEqual(expected, overflow); } };