authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-04-23 19:15:52+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2021-04-23 19:15:52+02:00
logcc8e49283d68075c4e842405d651d0d36b8d10af
tree9c53039e654cc99385f5886026b58dc468e02a4c
parent41efdc73b9a57dfcc57474310c64724f58a95493

stage1: Allow wrapping negation on unsigned ints at comptime

Closes #7951 Closes #8574

4 files changed, 20 insertions(+), 10 deletions(-)

src/stage1/bigint.cpp+2-2
......@@ -1446,10 +1446,10 @@ void bigint_negate(BigInt *dest, const BigInt *op) {
14461446 bigint_normalize(dest);
14471447}
14481448
1449void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count) {
1449void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
14501450 BigInt zero;
14511451 bigint_init_unsigned(&zero, 0);
1452 bigint_sub_wrap(dest, &zero, op, bit_count, true);
1452 bigint_sub_wrap(dest, &zero, op, bit_count, is_signed);
14531453}
14541454
14551455void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed) {
src/stage1/bigint.hpp+1-1
......@@ -75,7 +75,7 @@ void bigint_shl_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t
7575void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2);
7676
7777void bigint_negate(BigInt *dest, const BigInt *op);
78void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count);
78void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
7979void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
8080void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed);
8181
src/stage1/ir.cpp+3-3
......@@ -21660,8 +21660,8 @@ static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInst* source_instr, Z
2166021660{
2166121661 bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat);
2166221662
21663 bool ok_type = ((scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) ||
21664 scalar_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op));
21663 bool ok_type = scalar_type->id == ZigTypeIdInt || scalar_type->id == ZigTypeIdComptimeInt ||
21664 (is_float && !is_wrap_op);
2166521665
2166621666 if (!ok_type) {
2166721667 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
2167221672 float_negate(scalar_out_val, operand_val);
2167321673 } else if (is_wrap_op) {
2167421674 bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint,
21675 scalar_type->data.integral.bit_count);
21675 scalar_type->data.integral.bit_count, scalar_type->data.integral.is_signed);
2167621676 } else {
2167721677 bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint);
2167821678 }
test/stage1/behavior/math.zig+14-4
......@@ -229,16 +229,26 @@ fn testSignedWrappingEval(x: i32) void {
229229 expect(max_val == maxInt(i32));
230230}
231231
232test "negation wrapping" {
233 testNegationWrappingEval(minInt(i16));
234 comptime testNegationWrappingEval(minInt(i16));
232test "signed negation wrapping" {
233 testSignedNegationWrappingEval(minInt(i16));
234 comptime testSignedNegationWrappingEval(minInt(i16));
235235}
236fn testNegationWrappingEval(x: i16) void {
236fn testSignedNegationWrappingEval(x: i16) void {
237237 expect(x == -32768);
238238 const neg = -%x;
239239 expect(neg == -32768);
240240}
241241
242test "unsigned negation wrapping" {
243 testUnsignedNegationWrappingEval(1);
244 comptime testUnsignedNegationWrappingEval(1);
245}
246fn testUnsignedNegationWrappingEval(x: u16) void {
247 expect(x == 1);
248 const neg = -%x;
249 expect(neg == maxInt(u16));
250}
251
242252test "unsigned 64-bit division" {
243253 test_u64_div();
244254 comptime test_u64_div();