diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-02-01 09:47:01 +0000 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2025-02-01 09:48:18 +0000 |
| commit | 149031204c0c804a66571a751b259da95886640d (patch) | |
| tree | 4c36c2b86776a5c0116e7212bc31dd1f4bfe3f78 /src | |
| parent | d97441d37ef08813187f1b44ec29612619104585 (diff) | |
| download | zig-149031204c0c804a66571a751b259da95886640d.tar.gz zig-149031204c0c804a66571a751b259da95886640d.zip | |
Sema: skip aliasing check and runtime operation for `@memcpy` of zero-bit type
This check isn't valid in such cases, because the source and destination
pointers both refer to zero bits of memory, meaning they effectively
never alias.
Resolves: #21655
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 16 | ||||
| -rw-r--r-- | src/Type.zig | 7 |
2 files changed, 23 insertions, 0 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index caf457a989..93b367b9d8 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -25928,6 +25928,22 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void } } + zero_bit: { + const src_comptime = try src_elem_ty.comptimeOnlySema(pt); + const dest_comptime = try dest_elem_ty.comptimeOnlySema(pt); + assert(src_comptime == dest_comptime); // IMC + if (src_comptime) break :zero_bit; + + const src_has_bits = try src_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt); + const dest_has_bits = try dest_elem_ty.hasRuntimeBitsIgnoreComptimeSema(pt); + assert(src_has_bits == dest_has_bits); // IMC + if (src_has_bits) break :zero_bit; + + // The element type is zero-bit. We've done all validation (aside from the aliasing check, + // which we must skip) so we're done. + return; + } + const runtime_src = rs: { const dest_ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src; const src_ptr_val = try sema.resolveDefinedValue(block, src_src, src_ptr) orelse break :rs src_src; diff --git a/src/Type.zig b/src/Type.zig index e6fc9c7d6a..403caad668 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -452,6 +452,13 @@ pub fn hasRuntimeBitsIgnoreComptime(ty: Type, zcu: *const Zcu) bool { return hasRuntimeBitsInner(ty, true, .eager, zcu, {}) catch unreachable; } +pub fn hasRuntimeBitsIgnoreComptimeSema(ty: Type, pt: Zcu.PerThread) SemaError!bool { + return hasRuntimeBitsInner(ty, true, .sema, pt.zcu, pt.tid) catch |err| switch (err) { + error.NeedLazy => unreachable, // this would require a resolve strat of lazy + else => |e| return e, + }; +} + /// true if and only if the type takes up space in memory at runtime. /// There are two reasons a type will return false: /// * the type is a comptime-only type. For example, the type `type` itself. |
