summary refs log tree commit diff stats
path: root/compiler/passes.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/passes.nim')
-rw-r--r--compiler/passes.nim86
1 files changed, 53 insertions, 33 deletions
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 29b27627d..8f9f57f3d 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -7,13 +7,14 @@
 #    distribution, for details about the copyright.
 #
 
-# This module implements the passes functionality. A pass must implement the
-# `TPass` interface.
+## This module implements the passes functionality. A pass must implement the
+## `TPass` interface.
 
 import
   strutils, options, ast, astalgo, llstream, msgs, platform, os,
   condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
-  nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder
+  nimsets, syntaxes, times, rodread, idgen, modulegraphs, reorder, rod,
+  configuration
 
 
 type
@@ -29,7 +30,8 @@ type
   TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}
 
   TPass* = tuple[open: TPassOpen, openCached: TPassOpenCached,
-                 process: TPassProcess, close: TPassClose]
+                 process: TPassProcess, close: TPassClose,
+                 isFrontend: bool]
 
   TPassData* = tuple[input: PNode, closeOutput: PNode]
   TPasses* = openArray[TPass]
@@ -41,38 +43,26 @@ type
 proc makePass*(open: TPassOpen = nil,
                openCached: TPassOpenCached = nil,
                process: TPassProcess = nil,
-               close: TPassClose = nil): TPass =
+               close: TPassClose = nil,
+               isFrontend = false): TPass =
   result.open = open
   result.openCached = openCached
   result.close = close
   result.process = process
+  result.isFrontend = isFrontend
 
 # the semantic checker needs these:
 var
-  gImportModule*: proc (graph: ModuleGraph; m: PSym, fileIdx: int32; cache: IdentCache): PSym {.nimcall.}
-  gIncludeFile*: proc (graph: ModuleGraph; m: PSym, fileIdx: int32; cache: IdentCache): PNode {.nimcall.}
+  gImportModule*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex; cache: IdentCache): PSym {.nimcall.}
+  gIncludeFile*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex; cache: IdentCache): PNode {.nimcall.}
 
 # implementation
 
-proc skipCodegen*(n: PNode): bool {.inline.} =
+proc skipCodegen*(config: ConfigRef; n: PNode): bool {.inline.} =
   # can be used by codegen passes to determine whether they should do
   # something with `n`. Currently, this ignores `n` and uses the global
   # error count instead.
-  result = msgs.gErrorCounter > 0
-
-proc astNeeded*(s: PSym): bool =
-  # The ``rodwrite`` module uses this to determine if the body of a proc
-  # needs to be stored. The passes manager frees s.sons[codePos] when
-  # appropriate to free the procedure body's memory. This is important
-  # to keep memory usage down.
-  if (s.kind in {skMethod, skProc, skFunc}) and
-      ({sfCompilerProc, sfCompileTime} * s.flags == {}) and
-      (s.typ.callConv != ccInline) and
-      (s.ast.sons[genericParamsPos].kind == nkEmpty):
-    result = false
-    # XXX this doesn't really make sense with excessive CTFE
-  else:
-    result = true
+  result = config.errorCounter > 0
 
 const
   maxPasses = 10
@@ -150,20 +140,21 @@ proc closePassesCached(graph: ModuleGraph; a: var TPassContextArray) =
       m = gPasses[i].close(graph, a[i], m)
     a[i] = nil                # free the memory here
 
-proc resolveMod(module, relativeTo: string): int32 =
-  let fullPath = findModule(module, relativeTo)
+proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
+  let fullPath = findModule(conf, module, relativeTo)
   if fullPath.len == 0:
     result = InvalidFileIDX
   else:
-    result = fullPath.fileInfoIdx
+    result = fileInfoIdx(conf, fullPath)
 
-proc processImplicits(implicits: seq[string], nodeKind: TNodeKind,
+proc processImplicits(conf: ConfigRef; implicits: seq[string], nodeKind: TNodeKind,
                       a: var TPassContextArray; m: PSym) =
   # XXX fixme this should actually be relative to the config file!
+  let gCmdLineInfo = newLineInfo(FileIndex(0), 1, 1)
   let relativeTo = m.info.toFullPath
   for module in items(implicits):
     # implicit imports should not lead to a module importing itself
-    if m.position != resolveMod(module, relativeTo):
+    if m.position != resolveMod(conf, module, relativeTo).int32:
       var importStmt = newNodeI(nodeKind, gCmdLineInfo)
       var str = newStrNode(nkStrLit, module)
       str.info = gCmdLineInfo
@@ -178,26 +169,55 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
     a: TPassContextArray
     s: PLLStream
     fileIdx = module.fileIdx
-  if rd == nil:
+  if module.id < 0:
+    # new module caching mechanism:
+    for i in 0..<gPassesLen:
+      if not isNil(gPasses[i].open) and not gPasses[i].isFrontend:
+        a[i] = gPasses[i].open(graph, module, cache)
+      else:
+        a[i] = nil
+
+    var stmtIndex = 0
+    var doContinue = true
+    while doContinue:
+      let n = loadNode(module, stmtIndex)
+      if n == nil or graph.stopCompile(): break
+      #if n.kind == nkImportStmt:
+      #  echo "yes and it's ", n
+      inc stmtIndex
+      var m = n
+      for i in 0..<gPassesLen:
+        if not isNil(gPasses[i].process) and not gPasses[i].isFrontend:
+          m = gPasses[i].process(a[i], m)
+          if isNil(m):
+            doContinue = false
+            break
+
+    var m: PNode = nil
+    for i in 0..<gPassesLen:
+      if not isNil(gPasses[i].close) and not gPasses[i].isFrontend:
+        m = gPasses[i].close(graph, a[i], m)
+      a[i] = nil
+  elif rd == nil:
     openPasses(graph, a, module, cache)
     if stream == nil:
       let filename = fileIdx.toFullPathConsiderDirty
       s = llStreamOpen(filename, fmRead)
       if s == nil:
-        rawMessage(errCannotOpenFile, filename)
+        rawMessage(graph.config, errCannotOpenFile, filename)
         return false
     else:
       s = stream
     while true:
-      openParsers(p, fileIdx, s, cache)
+      openParsers(p, fileIdx, s, cache, graph.config)
 
       if sfSystemModule notin module.flags:
         # XXX what about caching? no processing then? what if I change the
         # modules to include between compilation runs? we'd need to track that
         # in ROD files. I think we should enable this feature only
         # for the interactive mode.
-        processImplicits implicitImports, nkImportStmt, a, module
-        processImplicits implicitIncludes, nkIncludeStmt, a, module
+        processImplicits graph.config, graph.config.implicitImports, nkImportStmt, a, module
+        processImplicits graph.config, graph.config.implicitIncludes, nkIncludeStmt, a, module
 
       while true:
         if graph.stopCompile(): break