Skip to content

Commit

Permalink
stage1: Allow wrapping negation on unsigned ints at comptime
Browse files Browse the repository at this point in the history
  • Loading branch information
LemonBoy committed Apr 23, 2021
1 parent 41efdc7 commit cc8e492
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 10 deletions.
4 changes: 2 additions & 2 deletions src/stage1/bigint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion src/stage1/bigint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
6 changes: 3 additions & 3 deletions src/stage1/ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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'";
Expand All @@ -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);
}
Expand Down
18 changes: 14 additions & 4 deletions test/stage1/behavior/math.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit cc8e492

Please sign in to comment.