verbose_air: zero padding in Air.Inst.Data when collecting
Air.Inst.Data is a union; variants smaller than 8 bytes (un_op, no_op, ty, repeat) leave padding bytes uninitialised. Zero the destination buffer and copy only the meaningful bytes per instruction so that byte-level comparisons in tests are deterministic and valgrind-clean. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user