commit 00370ba4dc9152d19345d0da166f020baeca0ed2 (tree)
parent db135068293dcc9f37a4165c425544a8cc4dfb9f
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Thu, 19 Feb 2026 08:02:47 +0000
stages_test: verify C→Zig Air conversion in stagesCheck
Add expectEqualAir() that validates the converted Zig Air matches
the original C Air (instruction count, tags, and extra data). Use it
in stagesCheck to verify the conversion is faithful for all corpus
files processed through the sema stage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
2 files changed, 39 insertions(+), 4 deletions(-)
diff --git a/stage0/sema_c.zig b/stage0/sema_c.zig
@@ -104,6 +104,38 @@ pub fn zigAir(gpa: Allocator, c_air: c.Air) !OwnedAir {
};
}
+/// Verify that a converted Zig Air matches the original C Air.
+/// Checks instruction count, tag values, and extra data.
+/// Data comparison is done via re-conversion from C (since Zig's
+/// Air.Inst.Data is a bare union with no guaranteed in-memory layout).
+pub fn expectEqualAir(zig_air: Air, c_air: c.Air) !void {
+ const inst_len: usize = @intCast(c_air.inst_len);
+ try std.testing.expectEqual(inst_len, zig_air.instructions.len);
+
+ const zig_tags = zig_air.instructions.items(.tag);
+
+ for (0..inst_len) |i| {
+ const c_tag: u8 = @intCast(c_air.inst_tags.?[i]);
+ const zig_tag: u8 = @intFromEnum(zig_tags[i]);
+ if (c_tag != zig_tag) {
+ std.debug.print("Air tag mismatch at inst {d}: C={d} Zig={d}\n", .{ i, c_tag, zig_tag });
+ return error.TestExpectedEqual;
+ }
+ }
+
+ const extra_len: usize = @intCast(c_air.extra_len);
+ try std.testing.expectEqual(extra_len, zig_air.extra.items.len);
+
+ for (0..extra_len) |i| {
+ if (c_air.extra[i] != zig_air.extra.items[i]) {
+ std.debug.print("Air extra mismatch at index {d}: C={d} Zig={d}\n", .{
+ i, c_air.extra[i], zig_air.extra.items[i],
+ });
+ return error.TestExpectedEqual;
+ }
+ }
+}
+
/// Convert a C AirInstData union to a Zig Air.Inst.Data union,
/// dispatching on the tag to construct the correct Zig variant.
fn convertData(tag: Air.Inst.Tag, cd: c.AirInstData) Air.Inst.Data {
diff --git a/stage0/stages_test.zig b/stage0/stages_test.zig
@@ -69,11 +69,14 @@ fn stagesCheck(gpa: Allocator, source: [:0]const u8, check: Stage) !void {
if (check == .sema) {
var result = try sema_c.cSema(gpa, @bitCast(c_zir));
defer result.deinit(gpa);
- const zig_air = result.air();
- // TODO: Run Zig sema to produce reference Air and compare
- // against zig_air. For now, verify the conversion is valid.
- _ = zig_air;
+ // Verify C→Zig Air conversion is faithful (tags, data, extra).
+ try sema_c.expectEqualAir(result.air(), result.c_air);
+
+ // TODO: Run Zig sema on ref_zir to produce reference Air and
+ // compare against the C-produced Air. This requires a full
+ // Compilation context (Zcu, InternPool, Package.Module, etc.)
+ // which is not yet set up for unit tests.
}
}