IC: remember which modules are from the NIF cache (#25443)

This commit is contained in:
Andreas Rumpf
2026-01-22 04:26:20 +01:00
committed by GitHub
parent 9a23ff36bd
commit 86a4ddc847
7 changed files with 48 additions and 13 deletions

View File

@@ -345,6 +345,8 @@ proc writeSymDef(w: var Writer; dest: var TokenBuf; sym: PSym) =
if sym.kindImpl == skModule:
dest.addDotToken() # position will be set by the loader!
elif sym.kindImpl in {skVar, skLet, skForVar, skResult}:
dest.addIntLit 0 # hack for the VM which uses this field to store information
else:
dest.addIntLit sym.positionImpl
@@ -879,7 +881,11 @@ proc readEmbeddedIndex(s: var Stream): Table[string, NifIndexEntry] =
proc moduleId(c: var DecodeContext; suffix: string; flags: set[LoadFlag] = {}): FileIndex =
var isKnownFile = false
result = c.infos.config.registerNifSuffix(suffix, isKnownFile)
if not isKnownFile or AlwaysLoadInterface in flags:
# Always load the module's index if it's not already in c.mods
# This is needed when resolving symbols from modules that were registered elsewhere
# but haven't had their NIF index loaded yet
let hasEntry = c.mods.hasKey(result)
if not hasEntry or AlwaysLoadInterface in flags:
let modFile = (getNimcacheDir(c.infos.config) / RelativeFile(suffix & ".nif")).string
if not fileExists(modFile):
raiseAssert "NIF file not found for module suffix '" & suffix & "': " & modFile &
@@ -1438,7 +1444,13 @@ proc resolveSym(c: var DecodeContext; symAsStr: string; alsoConsiderPrivate: boo
return nil # Local symbols shouldn't be hooks
let module = moduleId(c, sn.module)
# Look up the symbol in the module's index
# Try both formats: with module suffix (e.g., "foo.0.modulename") and without (e.g., "foo.0.")
# NIF spec allows local symbols to be stored without module suffix
var offs = c.mods[module].index.getOrDefault(symAsStr)
if offs.offset == 0:
# Try the format without module suffix
let localKey = sn.name & "." & $sn.count & "."
offs = c.mods[module].index.getOrDefault(localKey)
if offs.offset == 0:
return nil
if not alsoConsiderPrivate and offs.vis == Hidden:

View File

@@ -32,6 +32,7 @@ type
nodes: seq[Node]
processedModules: Table[string, int] # modname -> node index
includeStack: seq[string]
systemNodeId: int # ID of the system.nim node
proc toPair(c: DepContext; f: string): FilePair =
FilePair(nimFile: f, modname: moduleSuffix(f, cast[seq[string]](c.config.searchPaths)))
@@ -128,6 +129,9 @@ proc processImport(c: var DepContext; importPath: string; current: Node) =
# New module - create node and process it
let newNode = Node(files: @[pair], id: c.nodes.len)
current.deps.add newNode.id
# Every module depends on system.nim
if c.systemNodeId >= 0:
newNode.deps.add c.systemNodeId
c.processedModules[pair.modname] = newNode.id
c.nodes.add newNode
traverseDeps(c, pair, newNode)
@@ -223,9 +227,9 @@ proc traverseDeps(c: var DepContext; pair: FilePair; current: Node) =
proc generateBuildFile(c: DepContext): string =
## Generate the .build.nif file for nifmake
createDir("nifcache")
result = "nifcache" / c.nodes[0].files[0].modname & ".build.nif"
#getNimcacheDir(c.config).string / c.nodes[0].files[0].modname & ".build.nif"
let nimcache = getNimcacheDir(c.config).string
createDir(nimcache)
result = nimcache / c.nodes[0].files[0].modname & ".build.nif"
var b = nifbuilder.open(result)
defer: b.close()
@@ -250,7 +254,7 @@ proc generateBuildFile(c: DepContext): string =
b.addSymbolDef "nim_m"
b.addStrLit getAppFilename()
b.addStrLit "m"
b.addStrLit "--nimcache:nifcache"
b.addStrLit "--nimcache:" & nimcache
# Add search paths
for p in c.config.searchPaths:
b.addStrLit "--path:" & p.string
@@ -265,7 +269,7 @@ proc generateBuildFile(c: DepContext): string =
b.addSymbolDef "nim_nifc"
b.addStrLit getAppFilename()
b.addStrLit "nifc"
b.addStrLit "--nimcache:nifcache"
b.addStrLit "--nimcache:" & nimcache
# Add search paths
for p in c.config.searchPaths:
b.addStrLit "--path:" & p.string
@@ -354,7 +358,8 @@ proc commandIc*(conf: ConfigRef) =
nifler: nifler,
nodes: @[],
processedModules: initTable[string, int](),
includeStack: @[]
includeStack: @[],
systemNodeId: -1
)
# Create root node for main project file
@@ -366,6 +371,7 @@ proc commandIc*(conf: ConfigRef) =
# model the system.nim dependency:
let sysNode = Node(files: @[toPair(c, (conf.libpath / RelativeFile"system.nim").string)], id: 1)
c.nodes.add sysNode
c.systemNodeId = sysNode.id
rootNode.deps.add sysNode.id
# Process dependencies

View File

@@ -289,9 +289,8 @@ proc myImportModule(c: PContext, n: var PNode, importStmtResult: PNode): PSym =
c.recursiveDep = err
let trackUnusedImport = warnUnusedImportX in c.config.notes
var realModule: PSym
discard pushOptionEntry(c)
realModule = c.graph.importModuleCallback(c.graph, c.module, f)
let realModule = c.graph.importModuleCallback(c.graph, c.module, f)
result = importModuleAs(c, n, realModule, transf.importHidden, trackUnusedImport)
popOptionEntry(c)

View File

@@ -375,11 +375,12 @@ proc loadCompilerProc*(g: ModuleGraph; name: string): PSym =
if g.config.symbolFiles == disabledSf and optWithinConfigSystem notin g.config.globalOptions:
# For NIF-based compilation, search in loaded NIF modules
when not defined(nimKochBootstrap):
# Only try to resolve from NIF if we're actually using NIF files (cmdNifC)
if g.config.cmd == cmdNifC:
# Try to resolve from NIF for both cmdNifC and cmdM (which uses NIF files)
if g.config.cmd in {cmdNifC, cmdM}:
# First try system module (most compilerprocs are there)
let systemFileIdx = g.config.m.systemFileIdx
if systemFileIdx != InvalidFileIdx:
if systemFileIdx != InvalidFileIdx and not g.withinSystem:
# Only try to load from NIF if the file exists (it may not during initial ic build)
result = tryResolveCompilerProc(ast.program, name, systemFileIdx)
if result != nil:
strTableAdd(g.compilerprocs, result)
@@ -536,6 +537,7 @@ proc initModuleGraphFields(result: ModuleGraph) =
result.operators = initOperators(result)
result.emittedTypeInfo = initTable[string, FileIndex]()
result.cachedFiles = newStringTable()
result.cachedMods = initIntSet()
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
result = ModuleGraph()
@@ -677,6 +679,9 @@ when not defined(nimKochBootstrap):
g.ifaces[fileIdx.int].interfHidden, flags)
result.module = m
# Mark module as cached
g.cachedMods.incl fileIdx.int
# Register hooks from NIF index with the module graph
for x in result.logOps:
case x.kind

View File

@@ -1586,7 +1586,6 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
proc setSlot(c: PCtx; v: PSym) =
# XXX generate type initialization here?
if v.position == 0:
# IC: review this solution again later
v.positionImpl = getFreeRegister(c, if v.kind == skLet: slotFixedLet else: slotFixedVar, start = 1)
template cannotEval(c: PCtx; n: PNode) =

4
tests/ic/myimp.nim Normal file
View File

@@ -0,0 +1,4 @@
proc foo*(x: var int) =
inc x

10
tests/ic/timp.nim Normal file
View File

@@ -0,0 +1,10 @@
discard """
output: "hi 1"
"""
import myimp
var x = 0
foo(x)
echo "hi ", x