diff --git a/lib/std/math.zig b/lib/std/math.zig index d71cafe5efc9..558f541c0048 100644 --- a/lib/std/math.zig +++ b/lib/std/math.zig @@ -1349,15 +1349,6 @@ pub fn boolMask(comptime MaskInt: type, value: bool) callconv(.Inline) MaskInt { return @bitCast(i1, @as(u1, @boolToInt(value))); } - // At comptime, -% is disallowed on unsigned values. - // So we need to jump through some hoops in that case. - // This is a workaround for #7951 - if (@typeInfo(@TypeOf(.{value})).Struct.fields[0].is_comptime) { - // Since it's comptime, we don't need this to generate nice code. - // We can just do a branch here. - return if (value) ~@as(MaskInt, 0) else 0; - } - return -%@intCast(MaskInt, @boolToInt(value)); } diff --git a/src/stage1/bigint.cpp b/src/stage1/bigint.cpp index 79a05e95a52a..acb3e18e41bf 100644 --- a/src/stage1/bigint.cpp +++ b/src/stage1/bigint.cpp @@ -1446,10 +1446,10 @@ void bigint_negate(BigInt *dest, const BigInt *op) { bigint_normalize(dest); } -void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count) { +void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) { BigInt zero; bigint_init_unsigned(&zero, 0); - bigint_sub_wrap(dest, &zero, op, bit_count, true); + bigint_sub_wrap(dest, &zero, op, bit_count, is_signed); } void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) { diff --git a/src/stage1/bigint.hpp b/src/stage1/bigint.hpp index 044ea6642370..aa37b9302aeb 100644 --- a/src/stage1/bigint.hpp +++ b/src/stage1/bigint.hpp @@ -75,7 +75,7 @@ void bigint_shl_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2); void bigint_negate(BigInt *dest, const BigInt *op); -void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count); +void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed); void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed); void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed); diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 942b6028d924..61a1345327d5 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -21660,8 +21660,8 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, Z { bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat); - bool ok_type = ((scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) || - scalar_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op)); + bool ok_type = scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdComptimeInt || + (is_float && !is_wrap_op); if (!ok_type) { const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'"; @@ -21672,7 +21672,7 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, Z float_negate(scalar_out_val, operand_val); } else if (is_wrap_op) { bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint, - scalar_type->data.integral.bit_count); + scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed); } else { bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint); } diff --git a/test/stage1/behavior/math.zig b/test/stage1/behavior/math.zig index 3835aab0f454..32f484270203 100644 --- a/test/stage1/behavior/math.zig +++ b/test/stage1/behavior/math.zig @@ -229,16 +229,26 @@ fn testSignedWrappingEval(x: i32) void { expect(max_val == maxInt(i32)); } -test "negation wrapping" { - testNegationWrappingEval(minInt(i16)); - comptime testNegationWrappingEval(minInt(i16)); +test "signed negation wrapping" { + testSignedNegationWrappingEval(minInt(i16)); + comptime testSignedNegationWrappingEval(minInt(i16)); } -fn testNegationWrappingEval(x: i16) void { +fn testSignedNegationWrappingEval(x: i16) void { expect(x == -32768); const neg = -%x; expect(neg == -32768); } +test "unsigned negation wrapping" { + testUnsignedNegationWrappingEval(1); + comptime testUnsignedNegationWrappingEval(1); +} +fn testUnsignedNegationWrappingEval(x: u16) void { + expect(x == 1); + const neg = -%x; + expect(neg == maxInt(u16)); +} + test "unsigned 64-bit division" { test_u64_div(); comptime test_u64_div();