Make the registered passes local to the ModuleGraph (#9259)
Closes #9068
This commit is contained in:
parent
85187d4ba3
commit
b97a7dbf3d
12 changed files with 60 additions and 64 deletions
|
|
@ -18,7 +18,7 @@ import
|
||||||
|
|
||||||
import strutils except `%` # collides with ropes.`%`
|
import strutils except `%` # collides with ropes.`%`
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
from lineinfos import
|
from lineinfos import
|
||||||
warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile
|
warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile
|
||||||
import dynlib
|
import dynlib
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import
|
||||||
ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
|
ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
|
||||||
tables, ndi, lineinfos, pathutils
|
tables, ndi, lineinfos, pathutils
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
|
|
||||||
type
|
type
|
||||||
TLabel* = Rope # for the C generator a label is just a rope
|
TLabel* = Rope # for the C generator a label is just a rope
|
||||||
|
|
@ -132,7 +132,7 @@ type
|
||||||
# nimtvDeps is VERY hard to cache because it's
|
# nimtvDeps is VERY hard to cache because it's
|
||||||
# not a list of IDs nor can it be made to be one.
|
# not a list of IDs nor can it be made to be one.
|
||||||
|
|
||||||
TCGen = object of TPassContext # represents a C source file
|
TCGen = object of PPassContext # represents a C source file
|
||||||
s*: TCFileSections # sections of the C file
|
s*: TCFileSections # sections of the C file
|
||||||
flags*: set[Codegenflag]
|
flags*: set[Codegenflag]
|
||||||
module*: PSym
|
module*: PSym
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,10 @@ import
|
||||||
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
|
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
|
||||||
pathutils
|
pathutils
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
|
|
||||||
type
|
type
|
||||||
TGen = object of TPassContext
|
TGen = object of PPassContext
|
||||||
module: PSym
|
module: PSym
|
||||||
config: ConfigRef
|
config: ConfigRef
|
||||||
graph: ModuleGraph
|
graph: ModuleGraph
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ import
|
||||||
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
|
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
|
||||||
pathutils
|
pathutils
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
|
|
||||||
type
|
type
|
||||||
TGen = object of TPassContext
|
TGen = object of PPassContext
|
||||||
doc: PDoc
|
doc: PDoc
|
||||||
module: PSym
|
module: PSym
|
||||||
PGen = ref TGen
|
PGen = ref TGen
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,10 @@ import
|
||||||
times, ropes, math, passes, ccgutils, wordrecg, renderer,
|
times, ropes, math, passes, ccgutils, wordrecg, renderer,
|
||||||
intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils, pathutils
|
intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils, pathutils
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
|
|
||||||
type
|
type
|
||||||
TJSGen = object of TPassContext
|
TJSGen = object of PPassContext
|
||||||
module: PSym
|
module: PSym
|
||||||
graph: ModuleGraph
|
graph: ModuleGraph
|
||||||
config: ConfigRef
|
config: ConfigRef
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,19 @@ type
|
||||||
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
|
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
|
||||||
cacheCounters*: Table[string, BiggestInt]
|
cacheCounters*: Table[string, BiggestInt]
|
||||||
cacheTables*: Table[string, BTree[string, PNode]]
|
cacheTables*: Table[string, BTree[string, PNode]]
|
||||||
|
passes*: seq[TPass]
|
||||||
|
|
||||||
|
TPassContext* = object of RootObj # the pass's context
|
||||||
|
PPassContext* = ref TPassContext
|
||||||
|
|
||||||
|
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,
|
||||||
|
process: TPassProcess,
|
||||||
|
close: TPassClose,
|
||||||
|
isFrontend: bool]
|
||||||
|
|
||||||
proc hash*(x: FileIndex): Hash {.borrow.}
|
proc hash*(x: FileIndex): Hash {.borrow.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@
|
||||||
import
|
import
|
||||||
strutils, ast, astalgo, passes, idents, msgs, options, idgen, lineinfos
|
strutils, ast, astalgo, passes, idents, msgs, options, idgen, lineinfos
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
|
|
||||||
type
|
type
|
||||||
VerboseRef = ref object of TPassContext
|
VerboseRef = ref object of PPassContext
|
||||||
config: ConfigRef
|
config: ConfigRef
|
||||||
|
|
||||||
proc verboseOpen(graph: ModuleGraph; s: PSym): PPassContext =
|
proc verboseOpen(graph: ModuleGraph; s: PSym): PPassContext =
|
||||||
|
|
|
||||||
|
|
@ -16,21 +16,8 @@ import
|
||||||
nimsets, syntaxes, times, idgen, modulegraphs, reorder, rod,
|
nimsets, syntaxes, times, idgen, modulegraphs, reorder, rod,
|
||||||
lineinfos, pathutils
|
lineinfos, pathutils
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TPassContext* = object of RootObj # the pass's context
|
|
||||||
|
|
||||||
PPassContext* = ref TPassContext
|
|
||||||
|
|
||||||
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, process: TPassProcess, close: TPassClose,
|
|
||||||
isFrontend: bool]
|
|
||||||
|
|
||||||
TPassData* = tuple[input: PNode, closeOutput: PNode]
|
TPassData* = tuple[input: PNode, closeOutput: PNode]
|
||||||
TPasses* = openArray[TPass]
|
|
||||||
|
|
||||||
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
|
# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
|
||||||
# nodes. These are passed to the other close procedures.
|
# nodes. These are passed to the other close procedures.
|
||||||
|
|
@ -57,16 +44,12 @@ const
|
||||||
type
|
type
|
||||||
TPassContextArray = array[0..maxPasses - 1, PPassContext]
|
TPassContextArray = array[0..maxPasses - 1, PPassContext]
|
||||||
|
|
||||||
var
|
|
||||||
gPasses: array[0..maxPasses - 1, TPass]
|
|
||||||
gPassesLen*: int
|
|
||||||
|
|
||||||
proc clearPasses*(g: ModuleGraph) =
|
proc clearPasses*(g: ModuleGraph) =
|
||||||
gPassesLen = 0
|
g.passes.setLen(0)
|
||||||
|
|
||||||
proc registerPass*(g: ModuleGraph; p: TPass) =
|
proc registerPass*(g: ModuleGraph; p: TPass) =
|
||||||
gPasses[gPassesLen] = p
|
internalAssert g.config, g.passes.len < maxPasses
|
||||||
inc(gPassesLen)
|
g.passes.add(p)
|
||||||
|
|
||||||
proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
|
proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
|
||||||
m: TPassData): TPassData =
|
m: TPassData): TPassData =
|
||||||
|
|
@ -76,7 +59,7 @@ proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
|
||||||
else: m.closeOutput
|
else: m.closeOutput
|
||||||
|
|
||||||
proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
|
proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
|
||||||
passes: TPasses) =
|
passes: openArray[TPass]) =
|
||||||
var passdata: TPassData
|
var passdata: TPassData
|
||||||
passdata.input = nodes
|
passdata.input = nodes
|
||||||
for pass in passes:
|
for pass in passes:
|
||||||
|
|
@ -84,23 +67,23 @@ proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
|
||||||
|
|
||||||
proc openPasses(g: ModuleGraph; a: var TPassContextArray;
|
proc openPasses(g: ModuleGraph; a: var TPassContextArray;
|
||||||
module: PSym) =
|
module: PSym) =
|
||||||
for i in countup(0, gPassesLen - 1):
|
for i in countup(0, g.passes.len - 1):
|
||||||
if not isNil(gPasses[i].open):
|
if not isNil(g.passes[i].open):
|
||||||
a[i] = gPasses[i].open(g, module)
|
a[i] = g.passes[i].open(g, module)
|
||||||
else: a[i] = nil
|
else: a[i] = nil
|
||||||
|
|
||||||
proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
|
proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
|
||||||
var m: PNode = nil
|
var m: PNode = nil
|
||||||
for i in countup(0, gPassesLen - 1):
|
for i in countup(0, graph.passes.len - 1):
|
||||||
if not isNil(gPasses[i].close): m = gPasses[i].close(graph, a[i], m)
|
if not isNil(graph.passes[i].close): m = graph.passes[i].close(graph, a[i], m)
|
||||||
a[i] = nil # free the memory here
|
a[i] = nil # free the memory here
|
||||||
|
|
||||||
proc processTopLevelStmt(n: PNode, a: var TPassContextArray): bool =
|
proc processTopLevelStmt(graph: ModuleGraph, n: PNode, a: var TPassContextArray): bool =
|
||||||
# this implements the code transformation pipeline
|
# this implements the code transformation pipeline
|
||||||
var m = n
|
var m = n
|
||||||
for i in countup(0, gPassesLen - 1):
|
for i in countup(0, graph.passes.len - 1):
|
||||||
if not isNil(gPasses[i].process):
|
if not isNil(graph.passes[i].process):
|
||||||
m = gPasses[i].process(a[i], m)
|
m = graph.passes[i].process(a[i], m)
|
||||||
if isNil(m): return false
|
if isNil(m): return false
|
||||||
result = true
|
result = true
|
||||||
|
|
||||||
|
|
@ -111,19 +94,19 @@ proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
|
||||||
else:
|
else:
|
||||||
result = fileInfoIdx(conf, fullPath)
|
result = fileInfoIdx(conf, fullPath)
|
||||||
|
|
||||||
proc processImplicits(conf: ConfigRef; implicits: seq[string], nodeKind: TNodeKind,
|
proc processImplicits(graph: ModuleGraph; implicits: seq[string], nodeKind: TNodeKind,
|
||||||
a: var TPassContextArray; m: PSym) =
|
a: var TPassContextArray; m: PSym) =
|
||||||
# XXX fixme this should actually be relative to the config file!
|
# XXX fixme this should actually be relative to the config file!
|
||||||
let gCmdLineInfo = newLineInfo(FileIndex(0), 1, 1)
|
let gCmdLineInfo = newLineInfo(FileIndex(0), 1, 1)
|
||||||
let relativeTo = toFullPath(conf, m.info)
|
let relativeTo = toFullPath(graph.config, m.info)
|
||||||
for module in items(implicits):
|
for module in items(implicits):
|
||||||
# implicit imports should not lead to a module importing itself
|
# implicit imports should not lead to a module importing itself
|
||||||
if m.position != resolveMod(conf, module, relativeTo).int32:
|
if m.position != resolveMod(graph.config, module, relativeTo).int32:
|
||||||
var importStmt = newNodeI(nodeKind, gCmdLineInfo)
|
var importStmt = newNodeI(nodeKind, gCmdLineInfo)
|
||||||
var str = newStrNode(nkStrLit, module)
|
var str = newStrNode(nkStrLit, module)
|
||||||
str.info = gCmdLineInfo
|
str.info = gCmdLineInfo
|
||||||
importStmt.addSon str
|
importStmt.addSon str
|
||||||
if not processTopLevelStmt(importStmt, a): break
|
if not processTopLevelStmt(graph, importStmt, a): break
|
||||||
|
|
||||||
const
|
const
|
||||||
imperativeCode = {low(TNodeKind)..high(TNodeKind)} - {nkTemplateDef, nkProcDef, nkMethodDef,
|
imperativeCode = {low(TNodeKind)..high(TNodeKind)} - {nkTemplateDef, nkProcDef, nkMethodDef,
|
||||||
|
|
@ -139,25 +122,25 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
|
||||||
fileIdx = module.fileIdx
|
fileIdx = module.fileIdx
|
||||||
if module.id < 0:
|
if module.id < 0:
|
||||||
# new module caching mechanism:
|
# new module caching mechanism:
|
||||||
for i in 0..<gPassesLen:
|
for i in 0 ..< graph.passes.len:
|
||||||
if not isNil(gPasses[i].open) and not gPasses[i].isFrontend:
|
if not isNil(graph.passes[i].open) and not graph.passes[i].isFrontend:
|
||||||
a[i] = gPasses[i].open(graph, module)
|
a[i] = graph.passes[i].open(graph, module)
|
||||||
else:
|
else:
|
||||||
a[i] = nil
|
a[i] = nil
|
||||||
|
|
||||||
if not graph.stopCompile():
|
if not graph.stopCompile():
|
||||||
let n = loadNode(graph, module)
|
let n = loadNode(graph, module)
|
||||||
var m = n
|
var m = n
|
||||||
for i in 0..<gPassesLen:
|
for i in 0 ..< graph.passes.len:
|
||||||
if not isNil(gPasses[i].process) and not gPasses[i].isFrontend:
|
if not isNil(graph.passes[i].process) and not graph.passes[i].isFrontend:
|
||||||
m = gPasses[i].process(a[i], m)
|
m = graph.passes[i].process(a[i], m)
|
||||||
if isNil(m):
|
if isNil(m):
|
||||||
break
|
break
|
||||||
|
|
||||||
var m: PNode = nil
|
var m: PNode = nil
|
||||||
for i in 0..<gPassesLen:
|
for i in 0 ..< graph.passes.len:
|
||||||
if not isNil(gPasses[i].close) and not gPasses[i].isFrontend:
|
if not isNil(graph.passes[i].close) and not graph.passes[i].isFrontend:
|
||||||
m = gPasses[i].close(graph, a[i], m)
|
m = graph.passes[i].close(graph, a[i], m)
|
||||||
a[i] = nil
|
a[i] = nil
|
||||||
else:
|
else:
|
||||||
openPasses(graph, a, module)
|
openPasses(graph, a, module)
|
||||||
|
|
@ -177,8 +160,8 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
|
||||||
# modules to include between compilation runs? we'd need to track that
|
# modules to include between compilation runs? we'd need to track that
|
||||||
# in ROD files. I think we should enable this feature only
|
# in ROD files. I think we should enable this feature only
|
||||||
# for the interactive mode.
|
# for the interactive mode.
|
||||||
processImplicits graph.config, graph.config.implicitImports, nkImportStmt, a, module
|
processImplicits graph, graph.config.implicitImports, nkImportStmt, a, module
|
||||||
processImplicits graph.config, graph.config.implicitIncludes, nkIncludeStmt, a, module
|
processImplicits graph, graph.config.implicitIncludes, nkIncludeStmt, a, module
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
if graph.stopCompile(): break
|
if graph.stopCompile(): break
|
||||||
|
|
@ -194,7 +177,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
|
||||||
sl.add n
|
sl.add n
|
||||||
if sfReorder in module.flags:
|
if sfReorder in module.flags:
|
||||||
sl = reorder(graph, sl, module)
|
sl = reorder(graph, sl, module)
|
||||||
discard processTopLevelStmt(sl, a)
|
discard processTopLevelStmt(graph, sl, a)
|
||||||
break
|
break
|
||||||
elif n.kind in imperativeCode:
|
elif n.kind in imperativeCode:
|
||||||
# read everything until the next proc declaration etc.
|
# read everything until the next proc declaration etc.
|
||||||
|
|
@ -208,13 +191,13 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
|
||||||
break
|
break
|
||||||
sl.add n
|
sl.add n
|
||||||
#echo "-----\n", sl
|
#echo "-----\n", sl
|
||||||
if not processTopLevelStmt(sl, a): break
|
if not processTopLevelStmt(graph, sl, a): break
|
||||||
if rest != nil:
|
if rest != nil:
|
||||||
#echo "-----\n", rest
|
#echo "-----\n", rest
|
||||||
if not processTopLevelStmt(rest, a): break
|
if not processTopLevelStmt(graph, rest, a): break
|
||||||
else:
|
else:
|
||||||
#echo "----- single\n", n
|
#echo "----- single\n", n
|
||||||
if not processTopLevelStmt(n, a): break
|
if not processTopLevelStmt(graph, n, a): break
|
||||||
closeParsers(p)
|
closeParsers(p)
|
||||||
if s.kind != llsStdIn: break
|
if s.kind != llsStdIn: break
|
||||||
closePasses(graph, a)
|
closePasses(graph, a)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import
|
||||||
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
|
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
|
||||||
semparallel, lowerings, pluginsupport, plugins/active, rod, lineinfos
|
semparallel, lowerings, pluginsupport, plugins/active, rod, lineinfos
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
|
|
||||||
when defined(nimfix):
|
when defined(nimfix):
|
||||||
import nimfix/prettybase
|
import nimfix/prettybase
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ type
|
||||||
# if we encounter the 2nd yield statement
|
# if we encounter the 2nd yield statement
|
||||||
next: PTransCon # for stacking
|
next: PTransCon # for stacking
|
||||||
|
|
||||||
TTransfContext = object of passes.TPassContext
|
TTransfContext = object of TPassContext
|
||||||
module: PSym
|
module: PSym
|
||||||
transCon: PTransCon # top of a TransCon stack
|
transCon: PTransCon # top of a TransCon stack
|
||||||
inlining: int # > 0 if we are in inlining context (copy vars)
|
inlining: int # > 0 if we are in inlining context (copy vars)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import
|
||||||
from semfold import leValueConv, ordinalValToString
|
from semfold import leValueConv, ordinalValToString
|
||||||
from evaltempl import evalTemplate
|
from evaltempl import evalTemplate
|
||||||
|
|
||||||
from modulegraphs import ModuleGraph
|
from modulegraphs import ModuleGraph, PPassContext
|
||||||
|
|
||||||
when hasFFI:
|
when hasFFI:
|
||||||
import evalffi
|
import evalffi
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,7 @@ type
|
||||||
VmCallback* = proc (args: VmArgs) {.closure.}
|
VmCallback* = proc (args: VmArgs) {.closure.}
|
||||||
|
|
||||||
PCtx* = ref TCtx
|
PCtx* = ref TCtx
|
||||||
TCtx* = object of passes.TPassContext # code gen context
|
TCtx* = object of TPassContext # code gen context
|
||||||
code*: seq[TInstr]
|
code*: seq[TInstr]
|
||||||
debug*: seq[TLineInfo] # line info for every instruction; kept separate
|
debug*: seq[TLineInfo] # line info for every instruction; kept separate
|
||||||
# to not slow down interpretation
|
# to not slow down interpretation
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue