Skip to content

Commit

Permalink
Make the registered passes local to the ModuleGraph (nim-lang#9259)
Browse files Browse the repository at this point in the history
  • Loading branch information
LemonBoy authored and krux02 committed Oct 15, 2018
1 parent 83d0ef2 commit fb2a97b
Show file tree
Hide file tree
Showing 12 changed files with 60 additions and 64 deletions.
2 changes: 1 addition & 1 deletion compiler/cgen.nim
Expand Up @@ -18,7 +18,7 @@ import

import strutils except `%` # collides with ropes.`%`

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext
from lineinfos import
warnGcMem, errXMustBeCompileTime, hintDependency, errGenerated, errCannotOpenFile
import dynlib
Expand Down
4 changes: 2 additions & 2 deletions compiler/cgendata.nim
Expand Up @@ -13,7 +13,7 @@ import
ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
tables, ndi, lineinfos, pathutils

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext

type
TLabel* = Rope # for the C generator a label is just a rope
Expand Down Expand Up @@ -132,7 +132,7 @@ type
# nimtvDeps is VERY hard to cache because it's
# 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
flags*: set[Codegenflag]
module*: PSym
Expand Down
4 changes: 2 additions & 2 deletions compiler/depends.nim
Expand Up @@ -13,10 +13,10 @@ import
os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
pathutils

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext

type
TGen = object of TPassContext
TGen = object of PPassContext
module: PSym
config: ConfigRef
graph: ModuleGraph
Expand Down
4 changes: 2 additions & 2 deletions compiler/docgen2.nim
Expand Up @@ -14,10 +14,10 @@ import
os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
pathutils

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext

type
TGen = object of TPassContext
TGen = object of PPassContext
doc: PDoc
module: PSym
PGen = ref TGen
Expand Down
4 changes: 2 additions & 2 deletions compiler/jsgen.nim
Expand Up @@ -34,10 +34,10 @@ import
times, ropes, math, passes, ccgutils, wordrecg, renderer,
intsets, cgmeth, lowerings, sighashes, lineinfos, rodutils, pathutils

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext

type
TJSGen = object of TPassContext
TJSGen = object of PPassContext
module: PSym
graph: ModuleGraph
config: ConfigRef
Expand Down
13 changes: 13 additions & 0 deletions compiler/modulegraphs.nim
Expand Up @@ -62,6 +62,19 @@ type
cacheSeqs*: Table[string, PNode] # state that is shared to suppor the 'macrocache' API
cacheCounters*: Table[string, BiggestInt]
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.}

Expand Down
4 changes: 2 additions & 2 deletions compiler/passaux.nim
Expand Up @@ -12,10 +12,10 @@
import
strutils, ast, astalgo, passes, idents, msgs, options, idgen, lineinfos

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext

type
VerboseRef = ref object of TPassContext
VerboseRef = ref object of PPassContext
config: ConfigRef

proc verboseOpen(graph: ModuleGraph; s: PSym): PPassContext =
Expand Down
81 changes: 32 additions & 49 deletions compiler/passes.nim
Expand Up @@ -16,21 +16,8 @@ import
nimsets, syntaxes, times, idgen, modulegraphs, reorder, rod,
lineinfos, pathutils


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]
TPasses* = openArray[TPass]

# a pass is a tuple of procedure vars ``TPass.close`` may produce additional
# nodes. These are passed to the other close procedures.
Expand All @@ -57,16 +44,12 @@ const
type
TPassContextArray = array[0..maxPasses - 1, PPassContext]

var
gPasses: array[0..maxPasses - 1, TPass]
gPassesLen*: int

proc clearPasses*(g: ModuleGraph) =
gPassesLen = 0
g.passes.setLen(0)

proc registerPass*(g: ModuleGraph; p: TPass) =
gPasses[gPassesLen] = p
inc(gPassesLen)
internalAssert g.config, g.passes.len < maxPasses
g.passes.add(p)

proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
m: TPassData): TPassData =
Expand All @@ -76,31 +59,31 @@ proc carryPass*(g: ModuleGraph; p: TPass, module: PSym;
else: m.closeOutput

proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
passes: TPasses) =
passes: openArray[TPass]) =
var passdata: TPassData
passdata.input = nodes
for pass in passes:
passdata = carryPass(g, pass, module, passdata)

proc openPasses(g: ModuleGraph; a: var TPassContextArray;
module: PSym) =
for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].open):
a[i] = gPasses[i].open(g, module)
for i in countup(0, g.passes.len - 1):
if not isNil(g.passes[i].open):
a[i] = g.passes[i].open(g, module)
else: a[i] = nil

proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
var m: PNode = nil
for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].close): m = gPasses[i].close(graph, a[i], m)
for i in countup(0, graph.passes.len - 1):
if not isNil(graph.passes[i].close): m = graph.passes[i].close(graph, a[i], m)
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
var m = n
for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].process):
m = gPasses[i].process(a[i], m)
for i in countup(0, graph.passes.len - 1):
if not isNil(graph.passes[i].process):
m = graph.passes[i].process(a[i], m)
if isNil(m): return false
result = true

Expand All @@ -111,19 +94,19 @@ proc resolveMod(conf: ConfigRef; module, relativeTo: string): FileIndex =
else:
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) =
# XXX fixme this should actually be relative to the config file!
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):
# 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 str = newStrNode(nkStrLit, module)
str.info = gCmdLineInfo
importStmt.addSon str
if not processTopLevelStmt(importStmt, a): break
if not processTopLevelStmt(graph, importStmt, a): break

const
imperativeCode = {low(TNodeKind)..high(TNodeKind)} - {nkTemplateDef, nkProcDef, nkMethodDef,
Expand All @@ -139,25 +122,25 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
fileIdx = module.fileIdx
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)
for i in 0 ..< graph.passes.len:
if not isNil(graph.passes[i].open) and not graph.passes[i].isFrontend:
a[i] = graph.passes[i].open(graph, module)
else:
a[i] = nil

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)
for i in 0 ..< graph.passes.len:
if not isNil(graph.passes[i].process) and not graph.passes[i].isFrontend:
m = graph.passes[i].process(a[i], m)
if isNil(m):
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)
for i in 0 ..< graph.passes.len:
if not isNil(graph.passes[i].close) and not graph.passes[i].isFrontend:
m = graph.passes[i].close(graph, a[i], m)
a[i] = nil
else:
openPasses(graph, a, module)
Expand All @@ -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
# in ROD files. I think we should enable this feature only
# for the interactive mode.
processImplicits graph.config, graph.config.implicitImports, nkImportStmt, a, module
processImplicits graph.config, graph.config.implicitIncludes, nkIncludeStmt, a, module
processImplicits graph, graph.config.implicitImports, nkImportStmt, a, module
processImplicits graph, graph.config.implicitIncludes, nkIncludeStmt, a, module

while true:
if graph.stopCompile(): break
Expand All @@ -194,7 +177,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
sl.add n
if sfReorder in module.flags:
sl = reorder(graph, sl, module)
discard processTopLevelStmt(sl, a)
discard processTopLevelStmt(graph, sl, a)
break
elif n.kind in imperativeCode:
# read everything until the next proc declaration etc.
Expand All @@ -208,13 +191,13 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
break
sl.add n
#echo "-----\n", sl
if not processTopLevelStmt(sl, a): break
if not processTopLevelStmt(graph, sl, a): break
if rest != nil:
#echo "-----\n", rest
if not processTopLevelStmt(rest, a): break
if not processTopLevelStmt(graph, rest, a): break
else:
#echo "----- single\n", n
if not processTopLevelStmt(n, a): break
if not processTopLevelStmt(graph, n, a): break
closeParsers(p)
if s.kind != llsStdIn: break
closePasses(graph, a)
Expand Down
2 changes: 1 addition & 1 deletion compiler/sem.nim
Expand Up @@ -18,7 +18,7 @@ import
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
semparallel, lowerings, pluginsupport, plugins/active, rod, lineinfos

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext

when defined(nimfix):
import nimfix/prettybase
Expand Down
2 changes: 1 addition & 1 deletion compiler/transf.nim
Expand Up @@ -38,7 +38,7 @@ type
# if we encounter the 2nd yield statement
next: PTransCon # for stacking

TTransfContext = object of passes.TPassContext
TTransfContext = object of TPassContext
module: PSym
transCon: PTransCon # top of a TransCon stack
inlining: int # > 0 if we are in inlining context (copy vars)
Expand Down
2 changes: 1 addition & 1 deletion compiler/vm.nim
Expand Up @@ -24,7 +24,7 @@ import
from semfold import leValueConv, ordinalValToString
from evaltempl import evalTemplate

from modulegraphs import ModuleGraph
from modulegraphs import ModuleGraph, PPassContext

when hasFFI:
import evalffi
Expand Down
2 changes: 1 addition & 1 deletion compiler/vmdef.nim
Expand Up @@ -191,7 +191,7 @@ type
VmCallback* = proc (args: VmArgs) {.closure.}

PCtx* = ref TCtx
TCtx* = object of passes.TPassContext # code gen context
TCtx* = object of TPassContext # code gen context
code*: seq[TInstr]
debug*: seq[TLineInfo] # line info for every instruction; kept separate
# to not slow down interpretation
Expand Down

0 comments on commit fb2a97b

Please sign in to comment.