commit dc67c0c21e1493f0f4762da3d1de6de1f34b7f6d (tree)
parent 0047dc8086d8c2d52358af18b66ffa440834bcce
Author: Motiejus <motiejus@jakstys.lt>
Date: Sun, 1 Mar 2026 14:01:41 +0000
sema: analyze all named functions, remove pass 2c deferral
zirFunc now analyzes all named functions with bodies, not just
exported ones. The pass 2c deferral (which re-analyzed functions
after comptime blocks) was causing an infinite deferral — zirFunc
checked !s_in_main_analysis but pass 2c ran under s_in_main_analysis.
Changes:
- Remove is_exported filter and s_exported_decl_names pre-scan usage
- Remove pass 2c (redundant — functions analyzed directly in pass 2a)
- Skip unnamed declarations (test blocks) since Zig doesn't produce
AIR for them in non-test mode
- Update smoke test expectation
Next blocker: neghf2.zig produces incomplete AIR (2 instructions
instead of 7) because common.fneg cross-module inline call isn't
resolved yet.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
2 files changed, 7 insertions(+), 56 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -8288,6 +8288,9 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) {
FuncZirInfo fi = parseFuncZir(sema, inst);
if (fi.body_len == 0 || !sema->func_air_list)
return;
+ // Skip unnamed declarations (test blocks, comptime blocks).
+ if (sema->cur_decl_name == 0)
+ return;
// Create function type and func_decl IP entries before analyzing
// the function body. This matches the Zig compiler's processing
@@ -8457,15 +8460,8 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) {
}
}
- // Body analysis is deferred to Pass 2c (after @export comptime
- // blocks) so that IP entry ordering matches the Zig compiler.
- // In the Zig compiler, ensureNavValUpToDate creates the func_type
- // and func_decl entries, but body analysis happens later via
- // maybeQueueFuncBodyAnalysis.
- if (!s_in_main_analysis) {
- analyzeFuncBodyAndRecord(sema, block, inst, sema->cur_decl_name, NULL,
- 0, NULL, IP_INDEX_NONE);
- }
+ analyzeFuncBodyAndRecord(
+ sema, block, inst, sema->cur_decl_name, NULL, 0, NULL, IP_INDEX_NONE);
}
// parseDeclValueBody: parse a declaration instruction to find its value body.
@@ -8751,51 +8747,6 @@ static void zirStructDecl(Sema* sema, SemaBlock* block, uint32_t inst) {
semaBlockDeinit(&decl_block);
}
}
-
- // === Pass 2c: Analyze function bodies ===
- // Deferred from Pass 2a so that @export comptime block entries
- // (Pass 2b) appear before function body entries in the IP.
- if (s_in_main_analysis) {
- for (uint32_t d = 0; d < decls_len; d++) {
- uint32_t decl_inst = decl_list[d];
- uint32_t payload
- = sema->code.inst_datas[decl_inst].declaration.payload_index;
- uint32_t flags_1 = sema->code.extra[payload + 5];
- uint32_t id = (flags_1 >> 27) & 0x1F;
-
- uint32_t decl_name = 0;
- if (declIdHasName(id))
- decl_name = sema->code.extra[payload + 6];
-
- uint32_t vb_len = 0;
- const uint32_t* vb = parseDeclValueBody(sema, decl_inst, &vb_len);
- if (!vb)
- continue;
-
- bool is_func = false;
- for (uint32_t vi = 0; vi < vb_len; vi++) {
- ZirInstTag vtag = sema->code.inst_tags[vb[vi]];
- if (vtag == ZIR_INST_FUNC || vtag == ZIR_INST_FUNC_FANCY) {
- is_func = true;
- break;
- }
- }
- if (!is_func)
- continue;
-
- uint32_t old_decl_name = sema->cur_decl_name;
- bool old_decl_is_export = sema->cur_decl_is_export;
- sema->cur_decl_name = decl_name;
- sema->cur_decl_is_export = declIdIsExport(id);
- sema->has_compile_errors = false;
-
- // Only analyze functions — zirFunc with body analysis.
- (void)analyzeBodyInner(sema, block, vb, vb_len);
-
- sema->cur_decl_name = old_decl_name;
- sema->cur_decl_is_export = old_decl_is_export;
- }
- }
}
// --- Comptime ZIR handlers for cross-module inline evaluation ---
diff --git a/stage0/sema_test.zig b/stage0/sema_test.zig
@@ -215,8 +215,8 @@ test "sema: function decl smoke test" {
var result = try semaCheck("fn foo() void {}");
defer result.deinit();
- // Non-export functions are not analyzed, so func_airs should be empty.
- try std.testing.expectEqual(@as(u32, 0), result.c_func_air_list.len);
+ // All named functions with bodies are analyzed.
+ try std.testing.expectEqual(@as(u32, 1), result.c_func_air_list.len);
}
// ---------------------------------------------------------------------------