diff --git a/src/verbose_air.zig b/src/verbose_air.zig index 1210837cb8..9311556012 100644 --- 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 index d9d30d210b..7e6de8308c 100644 --- 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 index 3276dc5db0..deced33968 100644 --- 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; } }