zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

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:
Mstage0/sema.c | 59+++++------------------------------------------------------
Mstage0/sema_test.zig | 4++--
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); } // ---------------------------------------------------------------------------