stage2: fix crash on comptime lazy @ctz and @clz

This commit is contained in:
Andrew Kelley 2022-11-29 13:40:57 -07:00
parent ceb0a632cf
commit f466667888
3 changed files with 43 additions and 24 deletions

View File

@ -2376,6 +2376,34 @@ pub const Const = struct {
pub fn eq(a: Const, b: Const) bool {
return order(a, b) == .eq;
}
pub fn clz(a: Const, bits: Limb) Limb {
// Limbs are stored in little-endian order but we need
// to iterate big-endian.
var total_limb_lz: Limb = 0;
var i: usize = a.limbs.len;
const bits_per_limb = @sizeOf(Limb) * 8;
while (i != 0) {
i -= 1;
const limb = a.limbs[i];
const this_limb_lz = @clz(limb);
total_limb_lz += this_limb_lz;
if (this_limb_lz != bits_per_limb) break;
}
const total_limb_bits = a.limbs.len * bits_per_limb;
return total_limb_lz + bits - total_limb_bits;
}
pub fn ctz(a: Const) Limb {
// Limbs are stored in little-endian order.
var result: Limb = 0;
for (a.limbs) |limb| {
const limb_tz = @ctz(limb);
result += limb_tz;
if (limb_tz != @sizeOf(Limb) * 8) break;
}
return result;
}
};
/// An arbitrary-precision big integer along with an allocator which manages the memory.

View File

@ -19299,6 +19299,7 @@ fn zirBitCount(
.Int => {
if (try sema.resolveMaybeUndefVal(operand)) |val| {
if (val.isUndef()) return sema.addConstUndef(result_scalar_ty);
try sema.resolveLazyValue(val);
return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, target));
} else {
try sema.requireRuntimeBlock(block, src, operand_src);

View File

@ -1677,22 +1677,8 @@ pub const Value = extern union {
@panic("TODO implement i64 Value clz");
},
.int_big_positive => {
// TODO: move this code into std lib big ints
const bigint = val.castTag(.int_big_positive).?.asBigInt();
// Limbs are stored in little-endian order but we need
// to iterate big-endian.
var total_limb_lz: u64 = 0;
var i: usize = bigint.limbs.len;
const bits_per_limb = @sizeOf(std.math.big.Limb) * 8;
while (i != 0) {
i -= 1;
const limb = bigint.limbs[i];
const this_limb_lz = @clz(limb);
total_limb_lz += this_limb_lz;
if (this_limb_lz != bits_per_limb) break;
}
const total_limb_bits = bigint.limbs.len * bits_per_limb;
return total_limb_lz + ty_bits - total_limb_bits;
return bigint.clz(ty_bits);
},
.int_big_negative => {
@panic("TODO implement int_big_negative Value clz");
@ -1703,6 +1689,12 @@ pub const Value = extern union {
return ty_bits;
},
.lazy_align, .lazy_size => {
var bigint_buf: BigIntSpace = undefined;
const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable;
return bigint.clz(ty_bits);
},
else => unreachable,
}
}
@ -1721,16 +1713,8 @@ pub const Value = extern union {
@panic("TODO implement i64 Value ctz");
},
.int_big_positive => {
// TODO: move this code into std lib big ints
const bigint = val.castTag(.int_big_positive).?.asBigInt();
// Limbs are stored in little-endian order.
var result: u64 = 0;
for (bigint.limbs) |limb| {
const limb_tz = @ctz(limb);
result += limb_tz;
if (limb_tz != @sizeOf(std.math.big.Limb) * 8) break;
}
return result;
return bigint.ctz();
},
.int_big_negative => {
@panic("TODO implement int_big_negative Value ctz");
@ -1741,6 +1725,12 @@ pub const Value = extern union {
return ty_bits;
},
.lazy_align, .lazy_size => {
var bigint_buf: BigIntSpace = undefined;
const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable;
return bigint.ctz();
},
else => unreachable,
}
}