Sema: fix intFitsInType implementation

The function did not handle comptime_int in the case of lazy_align or
lazy_size.
This commit is contained in:
Andrew Kelley 2022-07-04 16:52:34 -07:00
parent eba8892b84
commit 9ecc47cd7c

View File

@ -26080,12 +26080,12 @@ fn intFitsInType(
sema: *Sema,
block: *Block,
src: LazySrcLoc,
self: Value,
val: Value,
ty: Type,
vector_index: ?*usize,
) CompileError!bool {
const target = sema.mod.getTarget();
switch (self.tag()) {
switch (val.tag()) {
.zero,
.undef,
.bool_false,
@ -26105,30 +26105,38 @@ fn intFitsInType(
else => unreachable,
},
.lazy_align => {
const info = ty.intInfo(target);
const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
// If it is u16 or bigger we know the alignment fits without resolving it.
if (info.bits >= max_needed_bits) return true;
const x = try sema.typeAbiAlignment(block, src, self.castTag(.lazy_align).?.data);
if (x == 0) return true;
const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
return info.bits >= actual_needed_bits;
.lazy_align => switch (ty.zigTypeTag()) {
.Int => {
const info = ty.intInfo(target);
const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
// If it is u16 or bigger we know the alignment fits without resolving it.
if (info.bits >= max_needed_bits) return true;
const x = try sema.typeAbiAlignment(block, src, val.castTag(.lazy_align).?.data);
if (x == 0) return true;
const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
return info.bits >= actual_needed_bits;
},
.ComptimeInt => return true,
else => unreachable,
},
.lazy_size => {
const info = ty.intInfo(target);
const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
// If it is u64 or bigger we know the size fits without resolving it.
if (info.bits >= max_needed_bits) return true;
const x = try sema.typeAbiSize(block, src, self.castTag(.lazy_size).?.data);
if (x == 0) return true;
const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
return info.bits >= actual_needed_bits;
.lazy_size => switch (ty.zigTypeTag()) {
.Int => {
const info = ty.intInfo(target);
const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
// If it is u64 or bigger we know the size fits without resolving it.
if (info.bits >= max_needed_bits) return true;
const x = try sema.typeAbiSize(block, src, val.castTag(.lazy_size).?.data);
if (x == 0) return true;
const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
return info.bits >= actual_needed_bits;
},
.ComptimeInt => return true,
else => unreachable,
},
.int_u64 => switch (ty.zigTypeTag()) {
.Int => {
const x = self.castTag(.int_u64).?.data;
const x = val.castTag(.int_u64).?.data;
if (x == 0) return true;
const info = ty.intInfo(target);
const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
@ -26139,13 +26147,13 @@ fn intFitsInType(
},
.int_i64 => switch (ty.zigTypeTag()) {
.Int => {
const x = self.castTag(.int_i64).?.data;
const x = val.castTag(.int_i64).?.data;
if (x == 0) return true;
const info = ty.intInfo(target);
if (info.signedness == .unsigned and x < 0)
return false;
var buffer: Value.BigIntSpace = undefined;
return (try self.toBigIntAdvanced(&buffer, target, sema.kit(block, src))).fitsInTwosComp(info.signedness, info.bits);
return (try val.toBigIntAdvanced(&buffer, target, sema.kit(block, src))).fitsInTwosComp(info.signedness, info.bits);
},
.ComptimeInt => return true,
else => unreachable,
@ -26153,7 +26161,7 @@ fn intFitsInType(
.int_big_positive => switch (ty.zigTypeTag()) {
.Int => {
const info = ty.intInfo(target);
return self.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
},
.ComptimeInt => return true,
else => unreachable,
@ -26161,7 +26169,7 @@ fn intFitsInType(
.int_big_negative => switch (ty.zigTypeTag()) {
.Int => {
const info = ty.intInfo(target);
return self.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
},
.ComptimeInt => return true,
else => unreachable,
@ -26192,7 +26200,7 @@ fn intFitsInType(
.aggregate => {
assert(ty.zigTypeTag() == .Vector);
for (self.castTag(.aggregate).?.data) |elem, i| {
for (val.castTag(.aggregate).?.data) |elem, i| {
if (!(try sema.intFitsInType(block, src, elem, ty.scalarType(), null))) {
if (vector_index) |some| some.* = i;
return false;