diff --git a/src/verbose_air.zig b/src/verbose_air.zig index 736beaa724..22cd44265c 100644 --- a/src/verbose_air.zig +++ b/src/verbose_air.zig @@ -10,6 +10,34 @@ const Compilation = zig_internals.Compilation; const Package = zig_internals.Package; const Air = zig_internals.Air; +/// Number of meaningful bytes in Air.Inst.Data for a given tag. +/// Variants smaller than 8 bytes leave padding uninitialised; callers +/// must only copy this many bytes and zero the rest. +fn airInstDataSize(tag: Air.Inst.Tag) usize { + return switch (tag) { + // no_op: 0 meaningful bytes + .ret_addr, .frame_addr => 0, + // un_op: 4 meaningful bytes (single Ref / u32) + .sqrt, .sin, .cos, .tan, .exp, .exp2, + .log, .log2, .log10, + .floor, .ceil, .round, .trunc_float, + .neg, .neg_optimized, + .is_null, .is_non_null, .is_null_ptr, .is_non_null_ptr, + .is_err, .is_non_err, .is_err_ptr, .is_non_err_ptr, + .ret, .ret_safe, .ret_load, + .is_named_enum_value, .tag_name, .error_name, + .cmp_lt_errors_len, + .c_va_end, + => 4, + // ty: 4 meaningful bytes (single Type / u32) + .alloc, .ret_ptr, .c_va_start => 4, + // repeat: 4 meaningful bytes (single Index / u32) + .repeat => 4, + // All other variants use the full 8 bytes. + else => 8, + }; +} + /// Matches C `Air` struct layout (air.h). const CAir = extern struct { inst_len: u32, @@ -64,20 +92,20 @@ const AirCollector = struct { break :blk dst.ptr; } else null; - // Copy datas (8 bytes per instruction) + // Copy datas (8 bytes per instruction). + // Air.Inst.Data is a union; variants smaller than 8 bytes + // (un_op, no_op, ty, repeat) leave padding bytes uninitialised. + // Zero the buffer first, then copy only the meaningful bytes + // per instruction so that padding is deterministically zero. const datas_byte_len = inst_len * 8; const datas_copy: ?[*]u8 = if (inst_len > 0) blk: { const dst = try gpa.alloc(u8, datas_byte_len); + @memset(dst, 0); const zig_datas = air.instructions.items(.data); - if (@sizeOf(Air.Inst.Data) == 8) { - const src = @as([*]const u8, @ptrCast(zig_datas.ptr))[0..datas_byte_len]; - @memcpy(dst, src); - } else { - // Safety build: @sizeOf(Data) may be > 8, copy first 8 bytes per element - for (zig_datas, 0..) |*d, i| { - const src = @as(*const [8]u8, @ptrCast(d)); - @memcpy(dst[i * 8 ..][0..8], src); - } + for (0..inst_len) |i| { + const src = @as(*const [8]u8, @ptrCast(&zig_datas[i])); + const n = airInstDataSize(zig_tags[i]); + @memcpy(dst[i * 8 ..][0..n], src[0..n]); } break :blk dst.ptr; } else null;