diff --git a/compiler/ast2nif.nim b/compiler/ast2nif.nim index 935637a94b..97e6343da0 100644 --- a/compiler/ast2nif.nim +++ b/compiler/ast2nif.nim @@ -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: diff --git a/compiler/deps.nim b/compiler/deps.nim index 7f3dfb797b..6b891fac9f 100644 --- a/compiler/deps.nim +++ b/compiler/deps.nim @@ -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 diff --git a/compiler/importer.nim b/compiler/importer.nim index 927502240d..a02a5e96a1 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -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) diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 0aedfa1b26..55f751cda7 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -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 diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index ddcc834c7e..9576fd3a99 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -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) = diff --git a/tests/ic/myimp.nim b/tests/ic/myimp.nim new file mode 100644 index 0000000000..3e0bebe141 --- /dev/null +++ b/tests/ic/myimp.nim @@ -0,0 +1,4 @@ + +proc foo*(x: var int) = + inc x + diff --git a/tests/ic/timp.nim b/tests/ic/timp.nim new file mode 100644 index 0000000000..61f73a59a1 --- /dev/null +++ b/tests/ic/timp.nim @@ -0,0 +1,10 @@ +discard """ + output: "hi 1" +""" + +import myimp + +var x = 0 +foo(x) + +echo "hi ", x