summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/modules.nim16
-rw-r--r--compiler/passes.nim42
-rw-r--r--compiler/rod.nim2
-rw-r--r--compiler/rodimpl.nim76
-rw-r--r--compiler/sem.nim3
5 files changed, 107 insertions, 32 deletions
diff --git a/compiler/modules.nim b/compiler/modules.nim
index ab384311e..ede10a0f4 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -169,13 +169,15 @@ proc compileModule*(graph: ModuleGraph; fileIdx: int32; cache: IdentCache, flags
     if sfMainModule in result.flags:
       gMainPackageId = result.owner.id
 
-    if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
-      rd = handleSymbolFile(result, cache)
-      if result.id < 0:
-        internalError("handleSymbolFile should have set the module's ID")
-        return
-    else:
-      result.id = getModuleId(toFullPath(fileIdx))
+    when false:
+      if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}:
+        rd = handleSymbolFile(result, cache)
+        if result.id < 0:
+          internalError("handleSymbolFile should have set the module's ID")
+          return
+      else:
+        discard
+    result.id = getModuleId(toFullPath(fileIdx))
     discard processModule(graph, result,
       if sfMainModule in flags and gProjectIsStdin: stdin.llStreamOpen else: nil,
       rd, cache)
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 29b27627d..1b4cd6fec 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -7,13 +7,13 @@
 #    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
 
 
 type
@@ -29,7 +29,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,11 +42,13 @@ 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
@@ -178,7 +181,34 @@ 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
+      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
diff --git a/compiler/rod.nim b/compiler/rod.nim
index 23c816498..360466b8f 100644
--- a/compiler/rod.nim
+++ b/compiler/rod.nim
@@ -14,7 +14,7 @@ import ast, idgen
 when not defined(nimSymbolfiles):
   template setupModuleCache* = discard
   template storeNode*(module: PSym; n: PNode) = discard
-  template loadNode*(module: PSym; index: var int): PNode = discard
+  template loadNode*(module: PSym; index: var int): PNode = PNode(nil)
 
   template getModuleId*(fullpath: string): int = getID()
 
diff --git a/compiler/rodimpl.nim b/compiler/rodimpl.nim
index a6f525787..a4074e2c3 100644
--- a/compiler/rodimpl.nim
+++ b/compiler/rodimpl.nim
@@ -7,10 +7,10 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements the canonalization for the various caching mechanisms.
+## This module implements the new compilation cache.
 
 import strutils, os, intsets, tables, ropes, db_sqlite, msgs, options, types,
-  renderer, rodutils, std / sha1, idents
+  renderer, rodutils, std / sha1, idents, astalgo, magicsys
 
 var db: DbConn
 
@@ -20,7 +20,7 @@ proc getModuleId*(fullpath: string): int =
     sql"select id, fullHash from modules where fullpath = ?", fullpath)
   let currentFullhash = $secureHashFile(fullpath)
   if module[0].len == 0:
-    result = int db.insertID(sql"insert into modules(fullpath, interfHash, fullHash) values (?, ?)",
+    result = int db.insertID(sql"insert into modules(fullpath, interfHash, fullHash) values (?, ?, ?)",
       fullpath, "", currentFullhash)
   else:
     result = parseInt(module[0])
@@ -74,6 +74,19 @@ proc pushSym(w: PRodWriter, s: PSym) =
   if not containsOrIncl(w.smarks, s.id):
     w.sstack.add(s)
 
+proc toDbFileId(fullpath: string): int =
+  let id = db.getValue(sql"select id from filenames where fullpath = ?",
+    fullpath)
+  if id.len == 0:
+    result = int db.insertID(sql"insert into filenames(fullpath) values (?)", fullpath)
+  else:
+    result = parseInt(id)
+
+proc fromDbFileId(dbId: int): int32 =
+  let fullpath = db.getValue(sql"select fullpath from filenames where id = ?", dbId)
+  doAssert fullpath.len > 0, "cannot find file name for DB ID " & $dbId
+  result = fileInfoIdx(fullpath)
+
 proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
                 result: var string) =
   if n == nil:
@@ -91,7 +104,7 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode,
     result.add(',')
     encodeVInt(n.info.line, result)
     result.add(',')
-    encodeVInt(n.info.fileIndex, result)
+    encodeVInt(toDbFileId(n.info.toFullPath), result)
   elif fInfo.line != n.info.line:
     result.add('?')
     encodeVInt(n.info.col, result)
@@ -269,7 +282,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
   result.add(',')
   if s.info.line != -1'i16: encodeVInt(s.info.line, result)
   result.add(',')
-  encodeVInt(s.info.fileIndex, result)
+  encodeVInt(toDbFileId(s.info.toFullPath), result)
   if s.owner != nil:
     result.add('*')
     encodeVInt(s.owner.id, result)
@@ -331,8 +344,8 @@ proc storeSym(w: PRodWriter; s: PSym) =
   encodeSym(w, s, buf)
   # XXX only store the name for exported symbols in order to speed up lookup
   # times once we enable the skStub logic.
-  db.exec(sql"insert into syms(nimid, module, name, data) values (?, ?, ?, ?)",
-    s.id, abs(w.module.id), s.name.s, buf)
+  db.exec(sql"insert into syms(nimid, module, name, data, exported) values (?, ?, ?, ?, ?)",
+    s.id, abs(w.module.id), s.name.s, buf, ord(sfExported in s.flags))
 
 proc storeType(w: PRodWriter; t: PType) =
   var buf = newStringOfCap(160)
@@ -410,7 +423,7 @@ proc decodeLineInfo(r; b; info: var TLineInfo) =
       else: info.line = int16(decodeVInt(b.s, b.pos))
       if b.s[b.pos] == ',':
         inc(b.pos)
-        info.fileIndex = int32(decodeVInt(b.s, b.pos))
+        info.fileIndex = fromDbFileId(decodeVInt(b.s, b.pos))
 
 proc skipNode(b) =
   assert b.s[b.pos] == '('
@@ -569,7 +582,7 @@ proc loadType(r; id: int; info: TLineInfo): PType =
     inc(b.pos)
     result.size = decodeVInt(b.s, b.pos)
   else:
-    result.size = - 1
+    result.size = -1
   if b.s[b.pos] == '=':
     inc(b.pos)
     result.align = decodeVInt(b.s, b.pos).int16
@@ -642,25 +655,21 @@ proc decodeInstantiations(r; b; info: TLineInfo;
       ii.compilesId = decodeVInt(b.s, b.pos)
     s.safeAdd ii
 
-proc loadSym(r; id: int; info: TLineInfo): PSym =
-  var
-    id: int
-    ident: PIdent
-  result = r.syms.getOrDefault(id)
-  if result != nil: return result
-  var b = loadBlob(sql"select data from syms where nimid = ?", id)
+proc loadSymFromBlob(r; b; info: TLineInfo): PSym =
   if b.s[b.pos] == '{':
     inc(b.pos)
     if b.s[b.pos] == '}':
       inc(b.pos)
       return                  # nil sym
   var k = TSymKind(decodeVInt(b.s, b.pos))
+  var id: int
   if b.s[b.pos] == '+':
     inc(b.pos)
     id = decodeVInt(b.s, b.pos)
     setId(id)
   else:
     internalError(info, "decodeSym: no id")
+  var ident: PIdent
   if b.s[b.pos] == '&':
     inc(b.pos)
     ident = r.cache.getIdent(decodeStr(b.s, b.pos))
@@ -729,9 +738,34 @@ proc loadSym(r; id: int; info: TLineInfo): PSym =
     #  result.ast = decodeNodeLazyBody(b, result.info, result)
     #else:
     result.ast = decodeNode(r, b, result.info)
+  if sfCompilerProc in result.flags:
+    registerCompilerProc(result)
+
+proc loadSym(r; id: int; info: TLineInfo): PSym =
+  result = r.syms.getOrDefault(id)
+  if result != nil: return result
+  var b = loadBlob(sql"select data from syms where nimid = ?", id)
+  result = loadSymFromBlob(r, b, info)
+  doAssert id == result.id, "symbol ID is not consistent!"
+
+proc loadModuleSymTab(r; module: PSym) =
+  ## goal: fill  module.tab
+  gr.syms[module.id] = module
+  for row in db.fastRows(sql"select nimid, data from syms where module = ? and exported = 1", abs(module.id)):
+    let id = parseInt(row[0])
+    var s = r.syms.getOrDefault(id)
+    if s == nil:
+      var b = BlobReader(pos: 0)
+      shallowCopy(b.s, row[1])
+      s = loadSymFromBlob(r, b, module.info)
+    assert s != nil
+    strTableAdd(module.tab, s)
+  if sfSystemModule in module.flags:
+    magicsys.systemModule = module
 
 proc loadNode*(module: PSym; index: var int): PNode =
   if index == 0:
+    loadModuleSymTab(gr, module)
     index = parseInt db.getValue(
       sql"select min(id) from toplevelstmts where module = ?", abs module.id)
   var b = BlobReader(pos: 0)
@@ -750,6 +784,14 @@ proc createDb() =
   """)
 
   db.exec(sql"""
+    create table if not exists filenames(
+      id integer primary key,
+      fullpath varchar(8000) not null
+    );
+  """)
+  db.exec sql"create index if not exists FilenameIx on filenames(fullpath);"
+
+  db.exec(sql"""
     create table if not exists modules(
       id integer primary key,
       fullpath varchar(8000) not null,
@@ -779,6 +821,7 @@ proc createDb() =
       module integer not null,
       name varchar(256) not null,
       data blob not null,
+      exported int not null,
       foreign key (module) references module(id)
     );
   """)
@@ -798,7 +841,6 @@ proc createDb() =
   """)
   db.exec sql"create index TopLevelStmtByModuleIdx on toplevelstmts(module);"
 
-
   db.exec(sql"""
     create table if not exists statics(
       id integer primary key,
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 053e739d3..12e77affc 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -621,4 +621,5 @@ proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
   popProcCon(c)
   if c.runnableExamples != nil: testExamples(c)
 
-const semPass* = makePass(myOpen, myOpenCached, myProcess, myClose)
+const semPass* = makePass(myOpen, myOpenCached, myProcess, myClose,
+                          isFrontend = true)