From e491c8aee9ca88cd79a3492a45623c27685d56de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Thu, 19 Feb 2026 12:39:40 +0000 Subject: [PATCH] stages_test: compare per-function Air count between C and Zig sema Parse the captured Zig verbose_air output to count per-function Air sections and verify that C sema produces the same number. For the current corpus (codecs.zig, no functions), both sides produce zero entries. When zirFunc is ported and functions appear, per-function textual Air comparison will be added. Co-Authored-By: Claude Opus 4.6 --- stage0/stages_test.zig | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/stage0/stages_test.zig b/stage0/stages_test.zig index 07c997cae4..aafa7c33f7 100644 --- a/stage0/stages_test.zig +++ b/stage0/stages_test.zig @@ -71,12 +71,29 @@ fn stagesCheck(gpa: Allocator, source: [:0]const u8, src_path: []const u8, check var result = try sema_c.cSema(gpa, @bitCast(c_zir)); defer result.deinit(gpa); - // Run Zig sema on the same source and verify it succeeds. var zig_result = try sema.zigSema(gpa, src_path); defer zig_result.deinit(); + + // Compare per-function Air: C and Zig must produce the same count. + const zig_air_text = zig_result.air_output.written(); + const zig_func_count = countAirSections(zig_air_text); + try std.testing.expectEqual(zig_func_count, result.func_airs.len); } } +/// Count the number of per-function Air sections in verbose_air output. +/// Sections are delimited by "# Begin Function AIR: " markers. +fn countAirSections(text: []const u8) usize { + const marker = "# Begin Function AIR: "; + var count: usize = 0; + var pos: usize = 0; + while (std.mem.indexOfPos(u8, text, pos, marker)) |begin| { + count += 1; + pos = begin + marker.len; + } + return count; +} + const last_successful_corpus = "../lib/std/crypto/codecs.zig"; // find ../{lib,src} -name '*.zig' | xargs -n1 stat -c "%s %n" | sort -n | awk '{printf " \""$2"\", // "$1"\n"}'