Sema: Improve comptime arithmetic undef handling

This commit expands on the foundations laid by https://github.com/ziglang/zig/pull/23177
and moves even more `Sema`-only functionality from `Value`
to `Sema.arith`. Specifically all shift and bitwise operations,
`@truncate`, `@bitReverse` and `@byteSwap` have been moved and
adapted to the new rules around `undefined`.

Especially the comptime shift operations have been basically
rewritten, fixing many open issues in the process.

New rules applied to operators:
* `<<`, `@shlExact`, `@shlWithOverflow`, `>>`, `@shrExact`: compile error if any operand is undef
* `<<|`, `~`, `^`, `@truncate`, `@bitReverse`, `@byteSwap`: return undef if any operand is undef
* `&`, `|`: Return undef if both operands are undef, turn undef into actual `0xAA` bytes otherwise

Additionally this commit canonicalizes the representation of
aggregates with all-undefined members in the `InternPool` by
disallowing them and enforcing the usage of a single typed
`undef` value instead. This reduces the amount of edge cases
and fixes a bunch of bugs related to partially undefined vecs.

List of operations directly affected by this patch:
* `<<`, `<<|`, `@shlExact`, `@shlWithOverflow`
* `>>`, `@shrExact`
* `&`, `|`, `~`, `^` and their atomic rmw + reduce pendants
* `@truncate`, `@bitReverse`, `@byteSwap`
This commit is contained in:
Justus Klausecker
2025-08-03 13:43:03 +02:00
parent 749f10af49
commit d0586da18e
22 changed files with 5446 additions and 4759 deletions

View File

@@ -65,10 +65,7 @@ pub const MutableValue = union(enum) {
.ty = sv.ty,
.val = (try sv.child.intern(pt, arena)).toIntern(),
} }),
.repeated => |sv| try pt.intern(.{ .aggregate = .{
.ty = sv.ty,
.storage = .{ .repeated_elem = (try sv.child.intern(pt, arena)).toIntern() },
} }),
.repeated => |sv| return pt.aggregateSplatValue(.fromInterned(sv.ty), try sv.child.intern(pt, arena)),
.bytes => |b| try pt.intern(.{ .aggregate = .{
.ty = b.ty,
.storage = .{ .bytes = try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, pt.tid, b.data, .maybe_embedded_nulls) },
@@ -78,10 +75,7 @@ pub const MutableValue = union(enum) {
for (a.elems, elems) |mut_elem, *interned_elem| {
interned_elem.* = (try mut_elem.intern(pt, arena)).toIntern();
}
return Value.fromInterned(try pt.intern(.{ .aggregate = .{
.ty = a.ty,
.storage = .{ .elems = elems },
} }));
return pt.aggregateValue(.fromInterned(a.ty), elems);
},
.slice => |s| try pt.intern(.{ .slice = .{
.ty = s.ty,