incremental compilation: implemented basic replay logic
This commit is contained in:
parent
cae1973856
commit
826c1e2d78
25 changed files with 295 additions and 271 deletions
|
|
@ -18,19 +18,15 @@ import
|
|||
|
||||
|
||||
type
|
||||
PRodReader* = ref object
|
||||
TPassContext* = object of RootObj # the pass's context
|
||||
|
||||
PPassContext* = ref TPassContext
|
||||
|
||||
TPassOpen* = proc (graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext {.nimcall.}
|
||||
TPassOpenCached* =
|
||||
proc (graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext {.nimcall.}
|
||||
TPassOpen* = proc (graph: ModuleGraph; module: PSym): PPassContext {.nimcall.}
|
||||
TPassClose* = proc (graph: ModuleGraph; p: PPassContext, n: PNode): PNode {.nimcall.}
|
||||
TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}
|
||||
|
||||
TPass* = tuple[open: TPassOpen, openCached: TPassOpenCached,
|
||||
process: TPassProcess, close: TPassClose,
|
||||
TPass* = tuple[open: TPassOpen, process: TPassProcess, close: TPassClose,
|
||||
isFrontend: bool]
|
||||
|
||||
TPassData* = tuple[input: PNode, closeOutput: PNode]
|
||||
|
|
@ -41,23 +37,14 @@ type
|
|||
# This mechanism used to be used for the instantiation of generics.
|
||||
|
||||
proc makePass*(open: TPassOpen = nil,
|
||||
openCached: TPassOpenCached = nil,
|
||||
process: TPassProcess = nil,
|
||||
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: FileIndex; cache: IdentCache): PSym {.nimcall.}
|
||||
gIncludeFile*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex; cache: IdentCache): PNode {.nimcall.}
|
||||
|
||||
# implementation
|
||||
|
||||
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
|
||||
|
|
@ -81,35 +68,27 @@ proc registerPass*(g: ModuleGraph; p: TPass) =
|
|||
gPasses[gPassesLen] = p
|
||||
inc(gPassesLen)
|
||||
|
||||
proc carryPass*(g: ModuleGraph; p: TPass, module: PSym; cache: IdentCache;
|
||||
proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
|
||||
m: TPassData): TPassData =
|
||||
var c = p.open(g, module, cache)
|
||||
var c = p.open(g, module)
|
||||
result.input = p.process(c, m.input)
|
||||
result.closeOutput = if p.close != nil: p.close(g, c, m.closeOutput)
|
||||
else: m.closeOutput
|
||||
|
||||
proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
|
||||
cache: IdentCache; passes: TPasses) =
|
||||
passes: TPasses) =
|
||||
var passdata: TPassData
|
||||
passdata.input = nodes
|
||||
for pass in passes:
|
||||
passdata = carryPass(g, pass, module, cache, passdata)
|
||||
passdata = carryPass(g, pass, module, passdata)
|
||||
|
||||
proc openPasses(g: ModuleGraph; a: var TPassContextArray;
|
||||
module: PSym; cache: IdentCache) =
|
||||
module: PSym) =
|
||||
for i in countup(0, gPassesLen - 1):
|
||||
if not isNil(gPasses[i].open):
|
||||
a[i] = gPasses[i].open(g, module, cache)
|
||||
a[i] = gPasses[i].open(g, module)
|
||||
else: a[i] = nil
|
||||
|
||||
proc openPassesCached(g: ModuleGraph; a: var TPassContextArray, module: PSym,
|
||||
rd: PRodReader) =
|
||||
for i in countup(0, gPassesLen - 1):
|
||||
if not isNil(gPasses[i].openCached):
|
||||
a[i] = gPasses[i].openCached(g, module, rd)
|
||||
else:
|
||||
a[i] = nil
|
||||
|
||||
proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
|
||||
var m: PNode = nil
|
||||
for i in countup(0, gPassesLen - 1):
|
||||
|
|
@ -125,19 +104,6 @@ proc processTopLevelStmt(n: PNode, a: var TPassContextArray): bool =
|
|||
if isNil(m): return false
|
||||
result = true
|
||||
|
||||
proc processTopLevelStmtCached(n: PNode, a: var TPassContextArray) =
|
||||
# this implements the code transformation pipeline
|
||||
var m = n
|
||||
for i in countup(0, gPassesLen - 1):
|
||||
if not isNil(gPasses[i].openCached): m = gPasses[i].process(a[i], m)
|
||||
|
||||
proc closePassesCached(graph: ModuleGraph; a: var TPassContextArray) =
|
||||
var m: PNode = nil
|
||||
for i in countup(0, gPassesLen - 1):
|
||||
if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close):
|
||||
m = gPasses[i].close(graph, a[i], m)
|
||||
a[i] = nil # free the memory here
|
||||
|
||||
proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
|
||||
let fullPath = findModule(conf, module, relativeTo)
|
||||
if fullPath.len == 0:
|
||||
|
|
@ -159,8 +125,7 @@ proc processImplicits(conf: ConfigRef; implicits: seq[string], nodeKind: TNodeKi
|
|||
importStmt.addSon str
|
||||
if not processTopLevelStmt(importStmt, a): break
|
||||
|
||||
proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
|
||||
rd: PRodReader; cache: IdentCache): bool {.discardable.} =
|
||||
proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {.discardable.} =
|
||||
if graph.stopCompile(): return true
|
||||
var
|
||||
p: TParsers
|
||||
|
|
@ -171,24 +136,17 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
|
|||
# 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)
|
||||
a[i] = gPasses[i].open(graph, module)
|
||||
else:
|
||||
a[i] = nil
|
||||
|
||||
var stmtIndex = 0
|
||||
var doContinue = true
|
||||
while doContinue:
|
||||
let n = loadNode(graph, module, stmtIndex)
|
||||
if n == nil or graph.stopCompile(): break
|
||||
#if n.kind == nkImportStmt:
|
||||
# echo "yes and it's ", n
|
||||
inc stmtIndex
|
||||
if not graph.stopCompile():
|
||||
let n = loadNode(graph, module)
|
||||
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
|
||||
|
|
@ -197,7 +155,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
|
|||
m = gPasses[i].close(graph, a[i], m)
|
||||
a[i] = nil
|
||||
else:
|
||||
openPasses(graph, a, module, cache)
|
||||
openPasses(graph, a, module)
|
||||
if stream == nil:
|
||||
let filename = toFullPathConsiderDirty(graph.config, fileIdx)
|
||||
s = llStreamOpen(filename, fmRead)
|
||||
|
|
@ -207,7 +165,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
|
|||
else:
|
||||
s = stream
|
||||
while true:
|
||||
openParsers(p, fileIdx, s, cache, graph.config)
|
||||
openParsers(p, fileIdx, s, graph.cache, graph.config)
|
||||
|
||||
if sfSystemModule notin module.flags:
|
||||
# XXX what about caching? no processing then? what if I change the
|
||||
|
|
@ -230,7 +188,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
|
|||
if n.kind == nkEmpty: break
|
||||
sl.add n
|
||||
if sfReorder in module.flags:
|
||||
sl = reorder(graph, sl, module, cache)
|
||||
sl = reorder(graph, sl, module)
|
||||
discard processTopLevelStmt(sl, a)
|
||||
break
|
||||
elif not processTopLevelStmt(n, a): break
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue