summary refs log tree commit diff stats
path: root/compiler/ic/cbackend.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/ic/cbackend.nim')
-rw-r--r--compiler/ic/cbackend.nim87
1 files changed, 66 insertions, 21 deletions
diff --git a/compiler/ic/cbackend.nim b/compiler/ic/cbackend.nim
index 34ee59d52..83f1b4cc7 100644
--- a/compiler/ic/cbackend.nim
+++ b/compiler/ic/cbackend.nim
@@ -19,9 +19,12 @@
 ## anymore. DCE is now done as prepass over the entire packed module graph.
 
 import std/[packedsets, algorithm, tables]
-  # std/intsets would give `UnusedImport`, pending https://github.com/nim-lang/Nim/issues/14246
+
+when defined(nimPreviewSlimSystem):
+  import std/assertions
+
 import ".."/[ast, options, lineinfos, modulegraphs, cgendata, cgen,
-  pathutils, extccomp, msgs]
+  pathutils, extccomp, msgs, modulepaths]
 
 import packed_ast, ic, dce, rodfiles
 
@@ -30,12 +33,16 @@ proc unpackTree(g: ModuleGraph; thisModule: int;
   var decoder = initPackedDecoder(g.config, g.cache)
   result = loadNodes(decoder, g.packed, thisModule, tree, n)
 
-proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var AliveSyms) =
+proc setupBackendModule(g: ModuleGraph; m: var LoadedModule) =
   if g.backend == nil:
     g.backend = cgendata.newModuleList(g)
-
+  assert g.backend != nil
   var bmod = cgen.newModule(BModuleList(g.backend), m.module, g.config)
   bmod.idgen = idgenFromLoadedModule(m)
+
+proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var AliveSyms) =
+  var bmod = BModuleList(g.backend).modules[m.module.position]
+  assert bmod != nil
   bmod.flags.incl useAliveDataFromDce
   bmod.alive = move alive[m.module.position]
 
@@ -44,9 +51,13 @@ proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var Alive
     cgen.genTopLevelStmt(bmod, n)
 
   finalCodegenActions(g, bmod, newNodeI(nkStmtList, m.module.info))
+  for disp in getDispatchers(g):
+    genProcAux(bmod, disp)
+  m.fromDisk.backendFlags = cgen.whichInitProcs(bmod)
 
 proc replayTypeInfo(g: ModuleGraph; m: var LoadedModule; origin: FileIndex) =
   for x in mitems(m.fromDisk.emittedTypeInfo):
+    #echo "found type ", x, " for file ", int(origin)
     g.emittedTypeInfo[x] = origin
 
 proc addFileToLink(config: ConfigRef; m: PSym) =
@@ -55,7 +66,8 @@ proc addFileToLink(config: ConfigRef; m: PSym) =
       if config.backend == backendCpp: ".nim.cpp"
       elif config.backend == backendObjc: ".nim.m"
       else: ".nim.c"
-  let cfile = changeFileExt(completeCfilePath(config, withPackageName(config, filename)), ext)
+  let cfile = changeFileExt(completeCfilePath(config,
+                            mangleModuleName(config, filename).AbsoluteFile), ext)
   let objFile = completeCfilePath(config, toObjFile(config, cfile))
   if fileExists(objFile):
     var cf = Cfile(nimname: m.name.s, cname: cfile,
@@ -64,7 +76,7 @@ proc addFileToLink(config: ConfigRef; m: PSym) =
     addFileToCompile(config, cf)
 
 when defined(debugDce):
-  import std / [os, packedsets]
+  import os, std/packedsets
 
 proc storeAliveSymsImpl(asymFile: AbsoluteFile; s: seq[int32]) =
   var f = rodfiles.create(asymFile.string)
@@ -88,7 +100,7 @@ proc aliveSymsChanged(config: ConfigRef; position: int; alive: AliveSyms): bool
   var f2 = rodfiles.open(asymFile.string)
   f2.loadHeader()
   f2.loadSection aliveSymsSection
-  var oldData: seq[int32]
+  var oldData: seq[int32] = @[]
   f2.loadSeq(oldData)
   f2.close
   if f2.err == ok and oldData == s:
@@ -98,38 +110,71 @@ proc aliveSymsChanged(config: ConfigRef; position: int; alive: AliveSyms): bool
       let oldAsSet = toPackedSet[int32](oldData)
       let newAsSet = toPackedSet[int32](s)
       echo "set of live symbols changed ", asymFile.changeFileExt("rod"), " ", position, " ", f2.err
-      echo "in old but not in new ", oldAsSet.difference(newAsSet)
-      echo "in new but not in old ", newAsSet.difference(oldAsSet)
-
-      if execShellCmd(getAppFilename() & " rod " & quoteShell(asymFile.changeFileExt("rod"))) != 0:
-        echo "command failed"
+      echo "in old but not in new ", oldAsSet.difference(newAsSet), " number of entries in old ", oldAsSet.len
+      echo "in new but not in old ", newAsSet.difference(oldAsSet), " number of entries in new ", newAsSet.len
+      #if execShellCmd(getAppFilename() & " rod " & quoteShell(asymFile.changeFileExt("rod"))) != 0:
+      #  echo "command failed"
     result = true
     storeAliveSymsImpl(asymFile, s)
 
+proc genPackedModule(g: ModuleGraph, i: int; alive: var AliveSyms) =
+  # case statement here to enforce exhaustive checks.
+  case g.packed[i].status
+  of undefined:
+    discard "nothing to do"
+  of loading, stored:
+    assert false
+  of storing, outdated:
+    storeAliveSyms(g.config, g.packed[i].module.position, alive)
+    generateCodeForModule(g, g.packed[i], alive)
+    closeRodFile(g, g.packed[i].module)
+  of loaded:
+    if g.packed[i].loadedButAliveSetChanged:
+      generateCodeForModule(g, g.packed[i], alive)
+    else:
+      addFileToLink(g.config, g.packed[i].module)
+      replayTypeInfo(g, g.packed[i], FileIndex(i))
+
+      if g.backend == nil:
+        g.backend = cgendata.newModuleList(g)
+      registerInitProcs(BModuleList(g.backend), g.packed[i].module, g.packed[i].fromDisk.backendFlags)
+
 proc generateCode*(g: ModuleGraph) =
   ## The single entry point, generate C(++) code for the entire
   ## Nim program aka `ModuleGraph`.
   resetForBackend(g)
   var alive = computeAliveSyms(g.packed, g.config)
 
-  for i in 0..high(g.packed):
+  when false:
+    for i in 0..<len(g.packed):
+      echo i, " is of status ", g.packed[i].status, " ", toFullPath(g.config, FileIndex(i))
+
+  # First pass: Setup all the backend modules for all the modules that have
+  # changed:
+  for i in 0..<len(g.packed):
     # case statement here to enforce exhaustive checks.
     case g.packed[i].status
     of undefined:
       discard "nothing to do"
-    of loading:
+    of loading, stored:
       assert false
     of storing, outdated:
-      generateCodeForModule(g, g.packed[i], alive)
-      closeRodFile(g, g.packed[i].module)
-      storeAliveSyms(g.config, g.packed[i].module.position, alive)
+      setupBackendModule(g, g.packed[i])
     of loaded:
       # Even though this module didn't change, DCE might trigger a change.
       # Consider this case: Module A uses symbol S from B and B does not use
       # S itself. A is then edited not to use S either. Thus we have to
       # recompile B in order to remove S from the final result.
       if aliveSymsChanged(g.config, g.packed[i].module.position, alive):
-        generateCodeForModule(g, g.packed[i], alive)
-      else:
-        addFileToLink(g.config, g.packed[i].module)
-        replayTypeInfo(g, g.packed[i], FileIndex(i))
+        g.packed[i].loadedButAliveSetChanged = true
+        setupBackendModule(g, g.packed[i])
+
+  # Second pass: Code generation.
+  let mainModuleIdx = g.config.projectMainIdx2.int
+  # We need to generate the main module last, because only then
+  # all init procs have been registered:
+  for i in 0..<len(g.packed):
+    if i != mainModuleIdx:
+      genPackedModule(g, i, alive)
+  if mainModuleIdx >= 0:
+    genPackedModule(g, mainModuleIdx, alive)