Skip to content

Sema: Improve comptime arithmetic undef handling #24674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Aug 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/langref.html.in
Original file line number Diff line number Diff line change
Expand Up @@ -6077,7 +6077,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
{#header_close#}
{#header_open|Exact Left Shift Overflow#}
<p>At compile-time:</p>
{#code|test_comptime_shlExact_overwlow.zig#}
{#code|test_comptime_shlExact_overflow.zig#}

<p>At runtime:</p>
{#code|runtime_shlExact_overflow.zig#}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ comptime {
_ = x;
}

// test_error=operation caused overflow
// test_error=overflow of integer type 'u8' with value '340'
15 changes: 3 additions & 12 deletions src/Air/Legalize.zig
Original file line number Diff line number Diff line change
Expand Up @@ -941,10 +941,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form:
.lhs = Air.internedToRef(try pt.intern(.{ .ptr = .{
.ty = (try pt.manyConstPtrType(mask_elem_ty)).toIntern(),
.base_addr = .{ .uav = .{
.val = try pt.intern(.{ .aggregate = .{
.ty = mask_ty.toIntern(),
.storage = .{ .elems = mask_elems },
} }),
.val = (try pt.aggregateValue(mask_ty, mask_elems)).toIntern(),
.orig_ty = (try pt.singleConstPtrType(mask_ty)).toIntern(),
} },
.byte_offset = 0,
Expand Down Expand Up @@ -1023,10 +1020,7 @@ fn scalarizeBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index, comptime form:
break :operand_b Air.internedToRef(try pt.intern(.{ .ptr = .{
.ty = (try pt.manyConstPtrType(elem_ty)).toIntern(),
.base_addr = .{ .uav = .{
.val = try pt.intern(.{ .aggregate = .{
.ty = ct_elems_ty.toIntern(),
.storage = .{ .elems = ct_elems.keys() },
} }),
.val = (try pt.aggregateValue(ct_elems_ty, ct_elems.keys())).toIntern(),
.orig_ty = (try pt.singleConstPtrType(ct_elems_ty)).toIntern(),
} },
.byte_offset = 0,
Expand Down Expand Up @@ -2550,10 +2544,7 @@ fn floatFromBigIntVal(
else => unreachable,
};
if (is_vector) {
return .fromInterned(try pt.intern(.{ .aggregate = .{
.ty = float_ty.toIntern(),
.storage = .{ .repeated_elem = scalar_val.toIntern() },
} }));
return pt.aggregateSplatValue(float_ty, scalar_val);
} else {
return scalar_val;
}
Expand Down
15 changes: 13 additions & 2 deletions src/InternPool.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2036,6 +2036,8 @@ pub const Key = union(enum) {
/// Each element/field stored as an `Index`.
/// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
/// so the slice length will be one more than the type's array length.
/// There must be at least one element which is not `undefined`. If all elements are
/// undefined, instead create an undefined value of the aggregate type.
aggregate: Aggregate,
/// An instance of a union.
un: Union,
Expand Down Expand Up @@ -8401,24 +8403,33 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
assert(sentinel == .none or elem == sentinel);
},
}
switch (ty_key) {
if (aggregate.storage.values().len > 0) switch (ty_key) {
.array_type, .vector_type => {
var any_defined = false;
for (aggregate.storage.values()) |elem| {
if (!ip.isUndef(elem)) any_defined = true;
assert(ip.typeOf(elem) == child);
}
assert(any_defined); // aggregate fields must not be all undefined
},
.struct_type => {
var any_defined = false;
for (aggregate.storage.values(), ip.loadStructType(aggregate.ty).field_types.get(ip)) |elem, field_ty| {
if (!ip.isUndef(elem)) any_defined = true;
assert(ip.typeOf(elem) == field_ty);
}
assert(any_defined); // aggregate fields must not be all undefined
},
.tuple_type => |tuple_type| {
var any_defined = false;
for (aggregate.storage.values(), tuple_type.types.get(ip)) |elem, ty| {
if (!ip.isUndef(elem)) any_defined = true;
assert(ip.typeOf(elem) == ty);
}
assert(any_defined); // aggregate fields must not be all undefined
},
else => unreachable,
}
};

if (len == 0) {
items.appendAssumeCapacity(.{
Expand Down
Loading