make koch-boot work again

This commit is contained in:
Araq
2026-06-27 21:03:48 +02:00
parent 8f36d6080d
commit d4edf4e4da
3 changed files with 35 additions and 1 deletions

View File

@@ -546,6 +546,14 @@ proc idGeneratorForPackage*(nextIdWillBe: int32): IdGenerator =
proc nextSymId(x: IdGenerator): ItemId {.inline.} =
assert(not x.sealed)
when not defined(nimKochBootstrap):
if x.backendMinted:
# Share the loader's per-module backend counter so a freshly-minted
# backend sym never collides with an `@bk` sym loaded from the module's
# `.t.bif` (see ast2nif.nextBackendSymItem).
let it = nextBackendSymItem(program, x.module)
if it >= 0'i32:
return backendItemId(x.module, it)
inc x.symId
result = if x.backendMinted: backendItemId(x.module, x.symId)
else: itemId(x.module, x.symId)

View File

@@ -1716,6 +1716,27 @@ proc createDecodeContext*(config: ConfigRef; cache: IdentCache): DecodeContext =
## Supposed to be a global variable
result = DecodeContext(infos: LineInfoWriter(config: config), cache: cache)
proc nextBackendSymItem*(c: var DecodeContext; module: int32): int32 =
## Allocate the next backend-minted SYM item for `module` from the SAME
## per-module counter the loader uses when it re-homes `@bk` syms loaded from
## the module's `.t.bif` (loadSymStub/extractLocalSymsFromTree). The `lower`
## stage serializes its lifted hooks/temps as `@bk` syms, and cg mints MORE
## backend syms (RTTI destroy wrappers, ...) into the same module. Both are
## keyed by `.id` (= `toId(itemId)`) in `declaredThings`/`declaredProtos`, so
## if the two id producers (the loader's `symCounter` and cg's idgen) ran
## independently they could mint the same item: e.g. a `rttiDestroy` wrapper
## and the very `=destroy` hook it wraps both land on backend item 21 -> one
## masks the other in `declaredThings` -> the hook's body is never emitted ->
## "undefined reference" at link. Drawing every backend sym from this one
## counter keeps them disjoint. Returns -1 if the module is not loaded yet
## (then the caller falls back to the idgen's own counter — only reachable
## for sem-time `@bk` minting, whose module is never loaded in that process).
let fi = module.FileIndex
if not c.mods.hasKey(fi): return -1'i32
let p = addr c.mods[fi].symCounter
inc p[]
result = p[]
proc setMainModule*(c: var DecodeContext; fileIdx: FileIndex) =
## Records the module that is being compiled fresh so that re-exports of its
## own symbols by dependencies are not turned into duplicate stubs.

View File

@@ -1480,7 +1480,12 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
# process (owned by nobody → undefined at link). So inject ONLY when the body
# was re-derived in this process (`wasLoaded == false`). Capture before
# `transformBody`, which returns the cached body (non-nil) when it was loaded.
let wasLoaded = prc.transformedBody != nil
# ONLY under IC: in a normal `nim c` build `transformedBody` is the ordinary
# transform cache (set whenever `transformBody` already ran for `prc`, e.g. a
# CT-evaluated or earlier-referenced routine), NOT a `.t.bif` load — gating on
# it there would WRONGLY skip destructor injection and miscompile (orc
# decref-on-freed). The `.t.bif`-loaded-body concept exists only under cmdNifC.
let wasLoaded = m.config.cmd == cmdNifC and prc.transformedBody != nil
var procBody = transformBody(m.g.graph, m.idgen, prc, {})
if sfInjectDestructors in prc.flags and not wasLoaded:
procBody = injectDestructorCalls(m.g.graph, m.idgen, prc, procBody)