mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
Merge pull request #8599 from LemonBoy/unsigned-neg
stage1: Allow wrapping negation on unsigned ints at comptime
This commit is contained in:
commit
a279f18bce
@ -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));
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user