mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-05 15:08:44 +00:00
IC: progress
This commit is contained in:
@@ -824,6 +824,10 @@ proc newSymNode*(sym: PSym): PNode =
|
||||
result = newNode(nkSym)
|
||||
result.sym = sym
|
||||
result.typField = sym.typ
|
||||
if result.typField == nil and nifcBackendActive:
|
||||
# See the two-arg overload in astdef: in the NIF backend cg stage a sym node
|
||||
# built from a not-yet-typed stub must track the symbol's type lazily.
|
||||
result.flags.incl nfLazyType
|
||||
result.info = sym.info
|
||||
|
||||
proc newOpenSym*(n: PNode): PNode {.inline.} =
|
||||
|
||||
@@ -1571,6 +1571,14 @@ proc cursorFromIndexEntry(c: var DecodeContext; module: FileIndex; entry: NifInd
|
||||
buf: var TokenBuf): Cursor =
|
||||
let s = addr c.mods[module].stream
|
||||
s.r.jumpTo entry.offset
|
||||
# A seek-load is self-contained: its tokens must decode their relative line
|
||||
# info against `entry.info` ALONE. The stream's `parents` stack can be left at
|
||||
# depth >1 by a prior non-seek read (e.g. loadNifModule reads `(stmts`/
|
||||
# `(implementation` without consuming their `)`), and `parse` only overwrites
|
||||
# parents[0] while `rawNext` reads parents[^1] — so a stale top entry (the last
|
||||
# symbol decoded) would become the base, corrupting the decoded line info.
|
||||
# Collapse the stack so parse's parentInfo is the sole base.
|
||||
s[].parents.setLen 1
|
||||
nifcursors.parse(s[], buf, entry.info)
|
||||
result = cursorAt(buf, 0)
|
||||
|
||||
@@ -1813,7 +1821,20 @@ proc loadSymStub(c: var DecodeContext; t: SymId; thisModule: string;
|
||||
inc val[]
|
||||
let id = if isBk: backendItemId(module.int32, val[]) else: itemId(module.int32, val[])
|
||||
|
||||
let offs = c.getOffset(module, symAsStr)
|
||||
let offs = c.mods[module].index.getOrDefault(symAsStr)
|
||||
if offs.offset == 0:
|
||||
# Only module/package self-syms are never written as `(sd)` entries, so a
|
||||
# missing index offset means this is such a sym — typically the OWNER of an
|
||||
# `include`d symbol, or a re-exported module qualifier left dangling in a
|
||||
# dead `when`-branch (`inlineasm.arm64.x`). Synthesize a resolvable skModule
|
||||
# stub (itemId item-0 = the module self-sym) instead of asserting "symbol
|
||||
# has no offset". `Complete` so accessors never try to lazy-load it; a real
|
||||
# `newLineInfo` so an owner/decl reference renders a path, not `???`.
|
||||
result = PSym(itemId: itemId(module.int32, 0'i32), kindImpl: skModule,
|
||||
name: c.cache.getIdent(sn.name), disamb: sn.count.int32,
|
||||
infoImpl: newLineInfo(module, 1, 1), state: Complete)
|
||||
c.syms[symAsStr] = (result, NifIndexEntry())
|
||||
return result
|
||||
let (stubKind, stubName) = stubKindAndName(c.cache, sn.name)
|
||||
result = PSym(itemId: id, kindImpl: stubKind, name: stubName, disamb: sn.count.int32, state: Partial)
|
||||
c.syms[symAsStr] = (result, offs)
|
||||
|
||||
@@ -17,6 +17,15 @@ when defined(nimPreviewSlimSystem):
|
||||
|
||||
export int128
|
||||
|
||||
var nifcBackendActive* = false
|
||||
## Set only while the per-module NIF backend codegen stage runs
|
||||
## (`nifbackend.generateCgStage`, `cmd == cmdNifC`). It gates `newSymNode`'s
|
||||
## lazy-type marking so it applies ONLY in the backend — where syms are loaded
|
||||
## from NIF and a cg-stage transform can build a sym node from a not-yet-typed
|
||||
## stub — and never during frontend sem, where the same marking would perturb
|
||||
## effect/exception inference (it diverges from a non-IC build, e.g.
|
||||
## `times.toDateTimeByWeek` gaining a spurious unlisted `Exception`).
|
||||
|
||||
import nodekinds
|
||||
export nodekinds
|
||||
|
||||
@@ -970,6 +979,14 @@ proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
|
||||
result = newNode(nkSym)
|
||||
result.sym = sym
|
||||
result.typField = sym.typImpl
|
||||
if result.typField == nil and nifcBackendActive:
|
||||
# In the per-module NIF backend cg stage a transform (chronos async
|
||||
# closure-iterator lowering) builds `result = …` sym nodes from a not-yet-typed
|
||||
# NIF stub; snapshotting the nil here would leave the node permanently typeless
|
||||
# and the backend later reads `t.flags` off it and SIGSEGVs (injectdestructors
|
||||
# hasDestructor). Mark it lazy so `typ` re-reads `sym.typ` once resolved. Gated
|
||||
# on `nifcBackendActive` so frontend sem is untouched (see the flag's doc).
|
||||
result.flags.incl nfLazyType
|
||||
result.info = info
|
||||
|
||||
proc newStrNode*(kind: TNodeKind, strVal: string): PNode =
|
||||
|
||||
@@ -336,6 +336,8 @@ proc generateCgStage(g: ModuleGraph; mainFileIdx: FileIndex) =
|
||||
## module still loads everything (`loadBackendModules`) because NimMain's init
|
||||
## list and the method dispatchers are whole-program; its `cg` runs essentially
|
||||
## alone (every other `.c.nif` precedes it), so it does not contend for memory.
|
||||
# gate `newSymNode`'s lazy-type marking to this stage only (see astdef)
|
||||
nifcBackendActive = true
|
||||
let mainSuffix = cachedModuleSuffix(g.config, mainFileIdx)
|
||||
let targetIsMain = g.config.icBackendModule.len == 0 or
|
||||
g.config.icBackendModule == mainSuffix
|
||||
|
||||
@@ -29,7 +29,7 @@ const
|
||||
|
||||
nimEnableCovariance* = defined(nimEnableCovariance)
|
||||
|
||||
icFormatVersion* = "10"
|
||||
icFormatVersion* = "12"
|
||||
## Version of the IC cache format (the sem-NIF module layout written by
|
||||
## ast2nif.nim plus the iface/impl/edges side files). Bump it whenever
|
||||
## that layout changes: `commandIc` wipes a nimcache whose `ic.version`
|
||||
|
||||
3
koch.nim
3
koch.nim
@@ -618,7 +618,8 @@ proc runIcTestFile(inp: string) =
|
||||
# which exercises the NIF import/load path the single-file tests do not.
|
||||
const icSuite = ["thallo", "tconverter", "timp", "tmiscs", "tparseutils",
|
||||
"tcompiletimeglobal", "tsighashstable", "tpureenum", "tgenericoffer",
|
||||
"tconverterreexport", "ttypeoffer", "ttransitiveoffer"]
|
||||
"tconverterreexport", "ttypeoffer", "ttransitiveoffer",
|
||||
"tmodsymref"]
|
||||
|
||||
proc icTest(args: string) =
|
||||
temp("")
|
||||
|
||||
12
tests/ic/mmodsymadd.nim
Normal file
12
tests/ic/mmodsymadd.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
import mmodsymasm
|
||||
|
||||
# The dead `else` branch qualifies a re-exported module (`mmodsymarm`) whose
|
||||
# `foo` is gated out on this host: the module sym binds at template-definition
|
||||
# but the member never resolves, so a dangling module-symbol reference survives
|
||||
# into the serialized template body. Before the `ModMarker` fix this failed
|
||||
# under `nim ic` with `symbol has no offset` when the consumer loaded this NIF.
|
||||
template satAdd*(a, b: uint64): uint64 =
|
||||
when not defined(mmodSymFakeArch):
|
||||
mmodsymasm.mmodsymx86.foo(a, b)
|
||||
else:
|
||||
mmodsymasm.mmodsymarm.foo(a, b)
|
||||
5
tests/ic/mmodsymarm.nim
Normal file
5
tests/ic/mmodsymarm.nim
Normal file
@@ -0,0 +1,5 @@
|
||||
# Gated out on every host (mmodSymFakeArch is never defined): `foo` does NOT
|
||||
# exist here, so a qualified `…mmodsymarm.foo` cannot resolve to the proc and
|
||||
# leaves the bare re-exported MODULE symbol dangling in the template body.
|
||||
when defined(mmodSymFakeArch):
|
||||
func foo*(a, b: uint64): uint64 = a + b
|
||||
2
tests/ic/mmodsymasm.nim
Normal file
2
tests/ic/mmodsymasm.nim
Normal file
@@ -0,0 +1,2 @@
|
||||
import mmodsymx86, mmodsymarm
|
||||
export mmodsymx86, mmodsymarm
|
||||
3
tests/ic/mmodsymx86.nim
Normal file
3
tests/ic/mmodsymx86.nim
Normal file
@@ -0,0 +1,3 @@
|
||||
# Live on every real host: provides `foo` so the template's taken branch resolves.
|
||||
when not defined(mmodSymFakeArch):
|
||||
func foo*(a, b: uint64): uint64 = a + b
|
||||
12
tests/ic/tmodsymref.nim
Normal file
12
tests/ic/tmodsymref.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
discard """
|
||||
output: '''7'''
|
||||
"""
|
||||
|
||||
# Regression test: a cross-module MODULE-symbol reference left as a dangling
|
||||
# qualifier in a template body (here `mmodsymasm.mmodsymarm.foo` in a dead
|
||||
# `when`-branch, reached via re-export) must load under `nim ic` instead of
|
||||
# raising `symbol has no offset`. Mirrors nim-intops' `inlineasm.arm64.X` in
|
||||
# nimbus-eth2. See compiler/ast2nif.nim `ModMarker`.
|
||||
|
||||
import mmodsymadd
|
||||
echo satAdd(3'u64, 4'u64)
|
||||
Reference in New Issue
Block a user