From f4666678886c2a7a993ad30b63de4ff25594085a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 29 Nov 2022 13:40:57 -0700 Subject: [PATCH] stage2: fix crash on comptime lazy `@ctz` and `@clz` --- lib/std/math/big/int.zig | 28 ++++++++++++++++++++++++++++ src/Sema.zig | 1 + src/value.zig | 38 ++++++++++++++------------------------ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index 9d0228db4b..534e8a570d 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -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. diff --git a/src/Sema.zig b/src/Sema.zig index ae64b4d981..be44ca6a5f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -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); diff --git a/src/value.zig b/src/value.zig index 94769b4da7..a029be6c7b 100644 --- a/src/value.zig +++ b/src/value.zig @@ -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, } }