sema_test: show human-readable AIR tag names in mismatch diagnostics

Export air_tag_name from verbose_air.zig to convert AIR tag u8 values
to their string names (e.g. "arg", "ret", "block"). Use it in
sema_test.zig error messages so mismatches show readable names instead
of raw numbers. Also add refKindStr to distinguish ip/inst refs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-21 20:01:30 +00:00
parent ccc454b3f2
commit 2eab127081
3 changed files with 25 additions and 6 deletions

View File

@@ -298,3 +298,10 @@ fn zigCompileAirImpl(
}
return .{ .items = allocated.ptr, .len = len, .callback_count = collector.callback_count };
}
/// Return the tag name for an AIR instruction tag (u8).
/// Exported for use by stage0 sema tests.
export fn air_tag_name(tag_val: u8) [*:0]const u8 {
const e: Air.Inst.Tag = @enumFromInt(tag_val);
return @tagName(e);
}

View File

@@ -110,7 +110,8 @@ typedef struct {
typedef struct {
char* name; // function FQN (owned, null-terminated)
InternPoolIndex func_ip; // IP index of function value (for name resolution)
InternPoolIndex
func_ip; // IP index of function value (for name resolution)
Air air; // per-function Air (owns its arrays)
} SemaFuncAir;

View File

@@ -309,6 +309,17 @@ fn cToOpt(comptime T: type, ptr: [*c]T) ?[*]const T {
return if (ptr == null) null else @ptrCast(ptr);
}
fn airTagNameSlice(tag_val: u8) []const u8 {
return std.mem.span(air_tag_name(tag_val));
}
extern fn air_tag_name(tag: u8) [*:0]const u8;
fn refKindStr(ref: u32) []const u8 {
if (ref == 0xFFFFFFFF) return "none";
if ((ref >> 31) != 0) return "inst";
return "ip";
}
/// Canonicalize an AIR Ref for comparison. Inst refs (bit 31 set)
/// and the special NONE sentinel are returned as-is. IP refs (bit 31
/// clear) are assigned a sequential canonical ID via the map, in
@@ -535,12 +546,12 @@ fn airCompareOne(name: []const u8, zig_air: *const c.Air, c_air: *const c.Air) !
std.debug.print("'{s}': inst_len mismatch: zig={d} c={d}\n", .{ name, zig_air.inst_len, c_air.inst_len });
if (cToOpt(u8, zig_air.inst_tags)) |zt| {
std.debug.print(" zig tags:", .{});
for (0..zig_air.inst_len) |j| std.debug.print(" {d}", .{zt[j]});
for (0..zig_air.inst_len) |j| std.debug.print(" {s}", .{airTagNameSlice(zt[j])});
std.debug.print("\n", .{});
}
if (cToOpt(u8, c_air.inst_tags)) |ct| {
std.debug.print(" c tags:", .{});
for (0..c_air.inst_len) |j| std.debug.print(" {d}", .{ct[j]});
for (0..c_air.inst_len) |j| std.debug.print(" {s}", .{airTagNameSlice(ct[j])});
std.debug.print("\n", .{});
}
return error.AirMismatch;
@@ -568,7 +579,7 @@ fn airCompareOne(name: []const u8, zig_air: *const c.Air, c_air: *const c.Air) !
if (!std.mem.eql(u8, zig_tags[0..inst_len], c_tags[0..inst_len])) {
std.debug.print("'{s}': tags mismatch (inst_len={d}):", .{ name, inst_len });
for (0..inst_len) |j| {
std.debug.print(" zig[{d}]={d} c[{d}]={d}", .{ j, zig_tags[j], j, c_tags[j] });
std.debug.print(" zig[{d}]={d}({s}) c[{d}]={d}({s})", .{ j, zig_tags[j], airTagNameSlice(zig_tags[j]), j, c_tags[j], airTagNameSlice(c_tags[j]) });
}
std.debug.print("\n", .{});
return error.AirMismatch;
@@ -615,13 +626,13 @@ fn airCompareOne(name: []const u8, zig_air: *const c.Air, c_air: *const c.Air) !
const zig_canon = canonicalizeRef(zig_word, &zig_ref_map, &next_zig_id);
const c_canon = canonicalizeRef(c_word, &c_ref_map, &next_c_id);
if (zig_canon != c_canon) {
std.debug.print("'{s}': datas ref mismatch at inst[{d}] slot {d}: zig=0x{x} c=0x{x} (canon: zig={d} c={d}) (tag={d})\n", .{ name, j, slot, zig_word, c_word, zig_canon, c_canon, tag_val });
std.debug.print("'{s}': datas ref mismatch at inst[{d}] slot {d}: zig=0x{x}[{s}] c=0x{x}[{s}] (canon: zig={d} c={d}) (tag={s})\n", .{ name, j, slot, zig_word, refKindStr(zig_word), c_word, refKindStr(c_word), zig_canon, c_canon, airTagNameSlice(tag_val) });
return error.AirMismatch;
}
} else {
// Non-ref field — compare directly.
if (zig_word != c_word) {
std.debug.print("'{s}': datas mismatch at inst[{d}] slot {d}: zig=0x{x} c=0x{x} (tag={d})\n", .{ name, j, slot, zig_word, c_word, tag_val });
std.debug.print("'{s}': datas mismatch at inst[{d}] slot {d}: zig=0x{x} c=0x{x} (tag={s})\n", .{ name, j, slot, zig_word, c_word, airTagNameSlice(tag_val) });
return error.AirMismatch;
}
}