mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-14 15:43:45 +00:00
IC: NimMain init orchestration for the per-module backend (Phase 2b)
In the per-module model each module's init/datInit proc is generated by its own cg process, but NimMain (emitted with the main module) must call them all. Previously the main module's cg only registered its own init, so a/b's globals stayed at their defaults -- the linked exe ran but printed wrong values. When the cg target is the main module, register every other loaded module's init/datInit into NimMain via registerReusedModuleToMain (exported), reading each module's initRequired/datInitRequired from its .c.nif meta head. This is the same no-codegen registration the whole-program backend uses for reused TUs; it requires the main module's cg to run last, after every other .c.nif exists (the per-module nifmake graph will order it so). Modules without init code have no .c.nif and register nothing. Validated: the 3-module diamond now builds end-to-end through the per-module pipeline (cg all with main last, merge, emit all, cc, link) and the resulting executable prints the correct "16 23" -- matching the whole-program build. koch ic thallo green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2270,7 +2270,7 @@ proc registerReusedInit*(g: BModuleList; moduleBase: string;
|
||||
g.mainModProcs.finishProcHeaderAsProto()
|
||||
g.otherModsInit.addCallStmt(init)
|
||||
|
||||
proc registerReusedModuleToMain(g: BModuleList; m: BModule;
|
||||
proc registerReusedModuleToMain*(g: BModuleList; m: BModule;
|
||||
initRequired, datInitRequired: bool) =
|
||||
## `registerModuleToMain` for a module whose cached translation unit is
|
||||
## reused: the init/datInit presence comes from the artifact's meta head
|
||||
|
||||
@@ -569,10 +569,19 @@ proc generateCgStage(g: ModuleGraph; mainFileIdx: FileIndex) =
|
||||
return
|
||||
|
||||
generateCodeForModule(g, target)
|
||||
let bl = BModuleList(g.backend)
|
||||
# The main module also owns the whole-program method dispatchers + NimMain.
|
||||
if sfMainModule in target.module.flags:
|
||||
emitMethodDispatchers(g)
|
||||
let bl = BModuleList(g.backend)
|
||||
# NimMain (generated when the main module is finished) must call every other
|
||||
# module's init/datInit. Those translation units are produced by their own
|
||||
# `cg` processes, so the calls are registered here from each `.c.nif` meta
|
||||
# head — which is why the main module's `cg` runs last, after every other
|
||||
# `.c.nif` exists. Modules without init code (no `.c.nif`) register nothing.
|
||||
for m in bl.mods:
|
||||
if m != nil and sfMainModule notin m.module.flags:
|
||||
let heads = readCnifHeads(getCFile(m).string & ".nif")
|
||||
registerReusedModuleToMain(bl, m, heads.initRequired, heads.datInitRequired)
|
||||
let tb = bl.mods[target.module.position]
|
||||
if tb != nil:
|
||||
finishModule(g, tb)
|
||||
|
||||
Reference in New Issue
Block a user