commit 2eab127081086e4032e0f6fe91dd8b9cf8a2bb28 (tree)
parent ccc454b3f28f99f15369c7a7fc2825692a5a0c94
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Sat, 21 Feb 2026 20:01:30 +0000
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>
Diffstat:
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/src/verbose_air.zig b/src/verbose_air.zig
@@ -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);
+}
diff --git a/stage0/sema.h b/stage0/sema.h
@@ -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;
diff --git a/stage0/sema_test.zig b/stage0/sema_test.zig
@@ -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;
}
}