diff --git a/stage0/sema_c.zig b/stage0/sema_c.zig index a6c51b8b16..404f1afca3 100644 --- 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 index c7004cadf8..af74f9b831 100644 --- 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. } }