mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-30 09:54:49 +00:00
IC: code generation progress (#25379)
This commit is contained in:
@@ -164,7 +164,7 @@ type
|
||||
|
||||
const
|
||||
# Symbol kinds that are always local to a proc and should never have module suffix
|
||||
skLocalSymKinds = {skParam, skGenericParam, skForVar, skResult, skTemp}
|
||||
skLocalSymKinds = {skParam, skForVar, skResult, skTemp}
|
||||
|
||||
proc isLocalSym(sym: PSym): bool {.inline.} =
|
||||
sym.kindImpl in skLocalSymKinds or
|
||||
@@ -362,10 +362,7 @@ proc writeSymDef(w: var Writer; dest: var TokenBuf; sym: PSym) =
|
||||
writeSym(w, dest, sym.ownerFieldImpl)
|
||||
# Store the AST for routine symbols and constants
|
||||
# Constants need their AST for astdef() to return the constant's value
|
||||
if sym.kindImpl in routineKinds + {skConst}:
|
||||
writeNode(w, dest, sym.astImpl, forAst = true)
|
||||
else:
|
||||
dest.addDotToken
|
||||
writeNode(w, dest, sym.astImpl, forAst = true)
|
||||
writeLoc w, dest, sym.locImpl
|
||||
writeNode(w, dest, sym.constraintImpl)
|
||||
writeSym(w, dest, sym.instantiatedFromImpl)
|
||||
@@ -438,14 +435,20 @@ proc addLocalSym(w: var Writer; n: PNode) =
|
||||
w.locals.incl(n.sym.itemId)
|
||||
|
||||
proc addLocalSyms(w: var Writer; n: PNode) =
|
||||
if n.kind in {nkIdentDefs, nkVarTuple}:
|
||||
case n.kind
|
||||
of nkIdentDefs, nkVarTuple:
|
||||
# nkIdentDefs: [ident1, ident2, ..., type, default]
|
||||
# All children except the last two are identifiers
|
||||
for i in 0 ..< max(0, n.len - 2):
|
||||
addLocalSyms(w, n[i])
|
||||
elif n.kind == nkSym:
|
||||
of nkPostfix:
|
||||
addLocalSyms(w, n[1])
|
||||
of nkPragmaExpr:
|
||||
addLocalSyms(w, n[0])
|
||||
of nkSym:
|
||||
addLocalSym(w, n)
|
||||
|
||||
else:
|
||||
discard
|
||||
|
||||
proc trInclude(w: var Writer; n: PNode) =
|
||||
w.deps.addParLe pool.tags.getOrIncl(toNifTag(n.kind)), trLineInfo(w, n.info)
|
||||
@@ -456,6 +459,9 @@ proc trInclude(w: var Writer; n: PNode) =
|
||||
w.deps.addStrLit child.strVal # raw string literal, no wrapper needed
|
||||
w.deps.addParRi
|
||||
|
||||
proc moduleSuffix(conf: ConfigRef; f: FileIndex): string =
|
||||
cachedModuleSuffix(conf, f)
|
||||
|
||||
proc trImport(w: var Writer; n: PNode) =
|
||||
for child in n:
|
||||
if child.kind == nkSym:
|
||||
@@ -464,7 +470,7 @@ proc trImport(w: var Writer; n: PNode) =
|
||||
w.deps.addDotToken # type
|
||||
let s = child.sym
|
||||
assert s.kindImpl == skModule
|
||||
let fp = toFullPath(w.infos.config, s.positionImpl.FileIndex)
|
||||
let fp = moduleSuffix(w.infos.config, s.positionImpl.FileIndex)
|
||||
w.deps.addStrLit fp # raw string literal, no wrapper needed
|
||||
w.deps.addParRi
|
||||
|
||||
@@ -512,14 +518,14 @@ proc writeNode(w: var Writer; dest: var TokenBuf; n: PNode; forAst = false) =
|
||||
of nkNilLit:
|
||||
w.withNode dest, n:
|
||||
discard
|
||||
of nkLetSection, nkVarSection, nkConstSection, nkGenericParams:
|
||||
of nkLetSection, nkVarSection, nkConstSection:
|
||||
# Track local variables declared in let/var sections
|
||||
w.withNode dest, n:
|
||||
for child in n:
|
||||
addLocalSyms w, child
|
||||
# Process the child node
|
||||
writeNode(w, dest, child, forAst)
|
||||
of nkForStmt, nkTypeDef:
|
||||
of nkForStmt:
|
||||
# Track for loop variable (first child is the loop variable)
|
||||
w.withNode dest, n:
|
||||
if n.len > 0:
|
||||
@@ -535,7 +541,7 @@ proc writeNode(w: var Writer; dest: var TokenBuf; n: PNode; forAst = false) =
|
||||
addLocalSyms(w, n[i])
|
||||
writeNode(w, dest, n[i], forAst)
|
||||
dec w.inProc
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef, nkMacroDef:
|
||||
of nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef, nkMacroDef, nkTemplateDef:
|
||||
# For top-level named routines (not forAst), just write the symbol.
|
||||
# The full AST will be stored in the symbol's sdef.
|
||||
if not forAst and n[namePos].kind == nkSym:
|
||||
@@ -602,16 +608,53 @@ proc writeNode(w: var Writer; dest: var TokenBuf; n: PNode; forAst = false) =
|
||||
# Write the export statement as a regular node
|
||||
w.withNode dest, n:
|
||||
for i in 0 ..< n.len:
|
||||
writeNode(w, dest, n[i], forAst)
|
||||
if n[i].kind == nkSym and n[i].sym.kindImpl == skModule:
|
||||
discard "do not write module syms here"
|
||||
else:
|
||||
writeNode(w, dest, n[i], forAst)
|
||||
else:
|
||||
w.withNode dest, n:
|
||||
for i in 0 ..< n.len:
|
||||
writeNode(w, dest, n[i], forAst)
|
||||
|
||||
proc writeToplevelNode(w: var Writer; dest: var TokenBuf; n: PNode) =
|
||||
proc writeGlobal(w: var Writer; dest: var TokenBuf; n: PNode) =
|
||||
case n.kind
|
||||
of nkVarTuple:
|
||||
writeNode(w, dest, n)
|
||||
of nkIdentDefs, nkConstDef:
|
||||
# nkIdentDefs: [ident1, ident2, ..., type, default]
|
||||
# All children except the last two are identifiers
|
||||
for i in 0 ..< max(0, n.len - 2):
|
||||
writeGlobal(w, dest, n[i])
|
||||
of nkPostfix:
|
||||
writeGlobal(w, dest, n[1])
|
||||
of nkPragmaExpr:
|
||||
writeGlobal(w, dest, n[0])
|
||||
of nkSym:
|
||||
writeSym(w, dest, n.sym)
|
||||
else:
|
||||
discard
|
||||
|
||||
proc writeGlobals(w: var Writer; dest: var TokenBuf; n: PNode) =
|
||||
w.withNode dest, n:
|
||||
for child in n:
|
||||
writeGlobal(w, dest, child)
|
||||
|
||||
proc writeToplevelNode(w: var Writer; dest, bottom: var TokenBuf; n: PNode) =
|
||||
case n.kind
|
||||
of nkStmtList, nkStmtListExpr:
|
||||
for son in n: writeToplevelNode(w, dest, son)
|
||||
for son in n: writeToplevelNode(w, dest, bottom, son)
|
||||
of nkEmpty:
|
||||
discard "ignore"
|
||||
of nkTypeSection, nkCommentStmt, nkMixinStmt, nkBindStmt, nkUsingStmt,
|
||||
nkPragma,
|
||||
nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef, nkMacroDef, nkTemplateDef:
|
||||
# We write purely declarative nodes at the bottom of the file
|
||||
writeNode(w, bottom, n)
|
||||
of nkConstSection:
|
||||
writeGlobals(w, bottom, n)
|
||||
of nkLetSection, nkVarSection:
|
||||
writeGlobals(w, dest, n)
|
||||
else:
|
||||
writeNode w, dest, n
|
||||
|
||||
@@ -652,6 +695,7 @@ let repMethodTag = registerTag("repmethod")
|
||||
#let repClassTag = registerTag("repclass")
|
||||
let includeTag = registerTag("include")
|
||||
let importTag = registerTag("import")
|
||||
let implTag = registerTag("implementation")
|
||||
|
||||
proc writeOp(w: var Writer; content: var TokenBuf; op: LogEntry) =
|
||||
case op.kind
|
||||
@@ -706,8 +750,14 @@ proc writeNifModule*(config: ConfigRef; thisModule: int32; n: PNode;
|
||||
if op.module == thisModule.int:
|
||||
writeOp(w, content, op)
|
||||
|
||||
w.writeToplevelNode content, n
|
||||
var bottom = createTokenBuf(300)
|
||||
w.writeToplevelNode content, bottom, n
|
||||
|
||||
# the implTag is used to tell the loader that the
|
||||
# bottom of the file is the implementation of the module:
|
||||
content.addParLe implTag, NoLineInfo
|
||||
content.addParRi()
|
||||
content.add bottom
|
||||
content.addParRi()
|
||||
|
||||
let m = modname(w.currentModule, w.infos.config)
|
||||
@@ -817,10 +867,14 @@ proc cursorFromIndexEntry(c: var DecodeContext; module: FileIndex; entry: NifInd
|
||||
nifcursors.parse(s[], buf, entry.info)
|
||||
result = cursorAt(buf, 0)
|
||||
|
||||
proc moduleId(c: var DecodeContext; suffix: string): FileIndex =
|
||||
type
|
||||
LoadFlag* = enum
|
||||
LoadFullAst, AlwaysLoadInterface
|
||||
|
||||
proc moduleId(c: var DecodeContext; suffix: string; flags: set[LoadFlag] = {}): FileIndex =
|
||||
var isKnownFile = false
|
||||
result = c.infos.config.registerNifSuffix(suffix, isKnownFile)
|
||||
if not isKnownFile:
|
||||
if not isKnownFile or AlwaysLoadInterface in flags:
|
||||
let modFile = (getNimcacheDir(c.infos.config) / RelativeFile(suffix & ".nif")).string
|
||||
let idxFile = (getNimcacheDir(c.infos.config) / RelativeFile(suffix & ".s.idx.nif")).string
|
||||
if not fileExists(modFile):
|
||||
@@ -1099,6 +1153,8 @@ proc loadSymFromCursor(c: var DecodeContext; s: PSym; n: var Cursor; thisModule:
|
||||
inc n
|
||||
var isKnownFile = false
|
||||
s.positionImpl = int c.infos.config.registerNifSuffix(thisModule, isKnownFile)
|
||||
# do to the precompiled mechanism things end up as main modules which are not!
|
||||
excl s.flagsImpl, sfMainModule
|
||||
else:
|
||||
loadField s.positionImpl
|
||||
|
||||
@@ -1110,12 +1166,7 @@ proc loadSymFromCursor(c: var DecodeContext; s: PSym; n: var Cursor; thisModule:
|
||||
s.ownerFieldImpl = loadSymStub(c, n, thisModule, localSyms)
|
||||
# Load the AST for routine symbols and constants
|
||||
# Constants need their AST for astdef() to return the constant's value
|
||||
if s.kindImpl in routineKinds + {skConst}:
|
||||
s.astImpl = loadNode(c, n, thisModule, localSyms)
|
||||
elif n.kind == DotToken:
|
||||
inc n
|
||||
else:
|
||||
raiseAssert "expected '.' for non-routine symbol AST but got " & $n.kind
|
||||
s.astImpl = loadNode(c, n, thisModule, localSyms)
|
||||
loadLoc c, n, s.locImpl
|
||||
s.constraintImpl = loadNode(c, n, thisModule, localSyms)
|
||||
s.instantiatedFromImpl = loadSymStub(c, n, thisModule, localSyms)
|
||||
@@ -1303,9 +1354,6 @@ proc loadNode(c: var DecodeContext; n: var Cursor; thisModule: string;
|
||||
else:
|
||||
raiseAssert "expected string literal but got " & $n.kind
|
||||
|
||||
proc moduleSuffix(conf: ConfigRef; f: FileIndex): string =
|
||||
cachedModuleSuffix(conf, f)
|
||||
|
||||
proc loadSymFromIndexEntry(c: var DecodeContext; module: FileIndex;
|
||||
nifName: string; entry: NifIndexEntry; thisModule: string): PSym =
|
||||
## Loads a symbol from the NIF index entry using the entry directly.
|
||||
@@ -1494,8 +1542,32 @@ proc nextSubtree(r: var Stream; dest: var TokenBuf; tok: var PackedToken) =
|
||||
dec nested
|
||||
if nested == 0: break
|
||||
|
||||
proc processTopLevel(c: var DecodeContext; s: var Stream; loadFullAst: bool; suffix: string; logOps: var seq[LogEntry]; module: int): PNode =
|
||||
result = newNode(nkStmtList)
|
||||
type
|
||||
ModuleSuffix* = distinct string
|
||||
PrecompiledModule* = object
|
||||
topLevel*: PNode # top level statements of the main module
|
||||
deps*: seq[ModuleSuffix] # other modules we need to process the top level statements of
|
||||
logOps*: seq[LogEntry]
|
||||
module*: PSym # set by modulegraphs.nim!
|
||||
|
||||
proc loadImport(c: var DecodeContext; s: var Stream; deps: var seq[ModuleSuffix]; tok: var PackedToken) =
|
||||
tok = next(s) # skip `(import`
|
||||
if tok.kind == DotToken:
|
||||
tok = next(s) # skip dot
|
||||
if tok.kind == DotToken:
|
||||
tok = next(s) # skip dot
|
||||
if tok.kind == StringLit:
|
||||
deps.add ModuleSuffix(pool.strings[tok.litId])
|
||||
tok = next(s)
|
||||
else:
|
||||
raiseAssert "expected StringLit but got " & $tok.kind
|
||||
if tok.kind == ParRi:
|
||||
tok = next(s) # skip )
|
||||
else:
|
||||
raiseAssert "expected ParRi but got " & $tok.kind
|
||||
|
||||
proc processTopLevel(c: var DecodeContext; s: var Stream; flags: set[LoadFlag] = {}; suffix: string; module: int): PrecompiledModule =
|
||||
result = PrecompiledModule(topLevel: newNode(nkStmtList))
|
||||
var localSyms = initTable[string, PSym]()
|
||||
|
||||
var t = next(s) # skip dot
|
||||
@@ -1512,60 +1584,62 @@ proc processTopLevel(c: var DecodeContext; s: var Stream; loadFullAst: bool; suf
|
||||
var cursor = cursorAt(buf, 0)
|
||||
let replayNode = loadNode(c, cursor, suffix, localSyms)
|
||||
if replayNode != nil:
|
||||
result.sons.add replayNode
|
||||
result.topLevel.sons.add replayNode
|
||||
t = next(s)
|
||||
if t.kind == ParRi:
|
||||
t = next(s)
|
||||
else:
|
||||
raiseAssert "expected ParRi but got " & $t.kind
|
||||
elif t.tagId == repConverterTag:
|
||||
t = loadLogOp(c, logOps, s, ConverterEntry, attachedTrace, module)
|
||||
t = loadLogOp(c, result.logOps, s, ConverterEntry, attachedTrace, module)
|
||||
elif t.tagId == repDestroyTag:
|
||||
t = loadLogOp(c, logOps, s, HookEntry, attachedDestructor, module)
|
||||
t = loadLogOp(c, result.logOps, s, HookEntry, attachedDestructor, module)
|
||||
elif t.tagId == repWasMovedTag:
|
||||
t = loadLogOp(c, logOps, s, HookEntry, attachedWasMoved, module)
|
||||
t = loadLogOp(c, result.logOps, s, HookEntry, attachedWasMoved, module)
|
||||
elif t.tagId == repCopyTag:
|
||||
t = loadLogOp(c, logOps, s, HookEntry, attachedAsgn, module)
|
||||
t = loadLogOp(c, result.logOps, s, HookEntry, attachedAsgn, module)
|
||||
elif t.tagId == repSinkTag:
|
||||
t = loadLogOp(c, logOps, s, HookEntry, attachedSink, module)
|
||||
t = loadLogOp(c, result.logOps, s, HookEntry, attachedSink, module)
|
||||
elif t.tagId == repDupTag:
|
||||
t = loadLogOp(c, logOps, s, HookEntry, attachedDup, module)
|
||||
t = loadLogOp(c, result.logOps, s, HookEntry, attachedDup, module)
|
||||
elif t.tagId == repTraceTag:
|
||||
t = loadLogOp(c, logOps, s, HookEntry, attachedTrace, module)
|
||||
t = loadLogOp(c, result.logOps, s, HookEntry, attachedTrace, module)
|
||||
elif t.tagId == repDeepCopyTag:
|
||||
t = loadLogOp(c, logOps, s, HookEntry, attachedDeepCopy, module)
|
||||
t = loadLogOp(c, result.logOps, s, HookEntry, attachedDeepCopy, module)
|
||||
elif t.tagId == repEnumToStrTag:
|
||||
t = loadLogOp(c, logOps, s, EnumToStrEntry, attachedTrace, module)
|
||||
t = loadLogOp(c, result.logOps, s, EnumToStrEntry, attachedTrace, module)
|
||||
elif t.tagId == repMethodTag:
|
||||
t = loadLogOp(c, logOps, s, MethodEntry, attachedTrace, module)
|
||||
t = loadLogOp(c, result.logOps, s, MethodEntry, attachedTrace, module)
|
||||
#elif t.tagId == repClassTag:
|
||||
# t = loadLogOp(c, logOps, s, ClassEntry, attachedTrace, module)
|
||||
elif t.tagId == includeTag or t.tagId == importTag:
|
||||
elif t.tagId == includeTag:
|
||||
t = skipTree(s)
|
||||
elif loadFullAst:
|
||||
elif t.tagId == importTag:
|
||||
loadImport(c, s, result.deps, t)
|
||||
elif t.tagId == implTag:
|
||||
cont = false
|
||||
elif LoadFullAst in flags:
|
||||
# Parse the full statement
|
||||
var buf = createTokenBuf(50)
|
||||
nextSubtree(s, buf, t)
|
||||
t = next(s) # skip ParRi
|
||||
var cursor = cursorAt(buf, 0)
|
||||
let stmtNode = loadNode(c, cursor, suffix, localSyms)
|
||||
if stmtNode != nil:
|
||||
result.sons.add stmtNode
|
||||
result.topLevel.sons.add stmtNode
|
||||
else:
|
||||
cont = false
|
||||
else:
|
||||
cont = false
|
||||
|
||||
proc loadNifModule*(c: var DecodeContext; f: FileIndex; interf, interfHidden: var TStrTable;
|
||||
logOps: var seq[LogEntry];
|
||||
loadFullAst: bool = false): PNode =
|
||||
let suffix = moduleSuffix(c.infos.config, f)
|
||||
|
||||
# Ensure module index is loaded - moduleId returns the FileIndex for this suffix
|
||||
let module = moduleId(c, suffix)
|
||||
proc loadNifModule*(c: var DecodeContext; suffix: ModuleSuffix; interf, interfHidden: var TStrTable;
|
||||
flags: set[LoadFlag] = {}): PrecompiledModule =
|
||||
# Ensure module index is loaded - moduleId returns the FileIndex for this suffix
|
||||
let module = moduleId(c, string(suffix), flags)
|
||||
|
||||
# Populate interface tables from the NIF index structure
|
||||
# Symbols are created as stubs (Partial state) and will be loaded lazily via loadSym
|
||||
populateInterfaceTablesFromIndex(c, module, interf, interfHidden, suffix)
|
||||
populateInterfaceTablesFromIndex(c, module, interf, interfHidden, string(suffix))
|
||||
|
||||
# Load the module AST (or just replay actions if loadFullAst is false)
|
||||
let s = addr c.mods[module].stream
|
||||
@@ -1575,10 +1649,14 @@ proc loadNifModule*(c: var DecodeContext; f: FileIndex; interf, interfHidden: va
|
||||
if t.kind == ParLe and pool.tags[t.tagId] == toNifTag(nkStmtList):
|
||||
t = next(s[]) # skip (stmts
|
||||
t = next(s[]) # skip flags
|
||||
result = processTopLevel(c, s[], loadFullAst, suffix, logOps, f.int)
|
||||
result = processTopLevel(c, s[], flags, string(suffix), module.int)
|
||||
else:
|
||||
result = newNode(nkStmtList)
|
||||
result = PrecompiledModule(topLevel: newNode(nkStmtList))
|
||||
|
||||
proc loadNifModule*(c: var DecodeContext; f: FileIndex; interf, interfHidden: var TStrTable;
|
||||
flags: set[LoadFlag] = {}): PrecompiledModule =
|
||||
let suffix = ModuleSuffix(moduleSuffix(c.infos.config, f))
|
||||
result = loadNifModule(c, suffix, interf, interfHidden, flags)
|
||||
|
||||
when isMainModule:
|
||||
import std / syncio
|
||||
|
||||
@@ -126,7 +126,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
let vn = n[i]
|
||||
let v = vn.sym
|
||||
if sfCompileTime in v.flags: continue
|
||||
ensureMutable v
|
||||
backendEnsureMutable v
|
||||
if sfGlobal in v.flags:
|
||||
assignGlobalVar(p, vn, "")
|
||||
genObjectInit(p, cpsInit, v.typ, v.locImpl, constructObj)
|
||||
@@ -136,7 +136,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
initLocalVar(p, v, immediateAsgn=isAssignedImmediately(p.config, n[^1]))
|
||||
var field = initLoc(locExpr, vn, tup.storage)
|
||||
let rtup = rdLoc(tup)
|
||||
let fieldName =
|
||||
let fieldName =
|
||||
if t.kind == tyTuple:
|
||||
"Field" & $i
|
||||
else:
|
||||
@@ -490,14 +490,17 @@ proc genClosureVar(p: BProc, a: PNode) =
|
||||
constructLoc(p, v)
|
||||
|
||||
proc genVarStmt(p: BProc, n: PNode) =
|
||||
for it in n.sons:
|
||||
if it.kind == nkCommentStmt: continue
|
||||
if it.kind == nkIdentDefs:
|
||||
for it in n:
|
||||
case it.kind
|
||||
of nkCommentStmt: discard
|
||||
of nkIdentDefs:
|
||||
# can be a lifted var nowadays ...
|
||||
if it[0].kind == nkSym:
|
||||
genSingleVar(p, it)
|
||||
else:
|
||||
genClosureVar(p, it)
|
||||
of nkSym:
|
||||
genSingleVar(p, it.sym, newSymNode(it.sym), it.sym.astdef)
|
||||
else:
|
||||
genVarTuple(p, it)
|
||||
|
||||
@@ -740,9 +743,10 @@ proc genBlock(p: BProc, n: PNode, d: var TLoc) =
|
||||
# named block?
|
||||
assert(n[0].kind == nkSym)
|
||||
var sym = n[0].sym
|
||||
ensureMutable sym
|
||||
backendEnsureMutable sym
|
||||
sym.locImpl.k = locOther
|
||||
sym.position = p.breakIdx+1
|
||||
sym.positionImpl = p.breakIdx+1
|
||||
# ^ IC: review this
|
||||
expr(p, n[1], d)
|
||||
endSimpleBlock(p, scope)
|
||||
|
||||
@@ -1255,7 +1259,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
initElifBranch(p.s(cpsStmts), ifStmt, orExpr)
|
||||
if exvar != nil:
|
||||
fillLocalName(p, exvar.sym)
|
||||
ensureMutable exvar.sym
|
||||
backendEnsureMutable exvar.sym
|
||||
fillLoc(exvar.sym.locImpl, locTemp, exvar, OnStack)
|
||||
linefmt(p, cpsStmts, "$1 $2 = T$3_;$n", [getTypeDesc(p.module, exvar.sym.typ),
|
||||
rdLoc(exvar.sym.loc), rope(etmp+1)])
|
||||
@@ -1304,7 +1308,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
if isImportedException(typeNode.typ, p.config):
|
||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||
fillLocalName(p, exvar.sym)
|
||||
ensureMutable exvar.sym
|
||||
backendEnsureMutable exvar.sym
|
||||
fillLoc(exvar.sym.locImpl, locTemp, exvar, OnStack)
|
||||
startBlockWith(p):
|
||||
lineCg(p, cpsStmts, "catch ($1& $2) {$n", [getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc)])
|
||||
@@ -1396,7 +1400,7 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||
if t[i][j].isInfixAs():
|
||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||
fillLocalName(p, exvar.sym)
|
||||
ensureMutable exvar.sym
|
||||
backendEnsureMutable exvar.sym
|
||||
fillLoc(exvar.sym.locImpl, locTemp, exvar, OnUnknown)
|
||||
startBlockWith(p):
|
||||
lineCg(p, cpsStmts, "catch ($1& $2) {$n", [getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc)])
|
||||
|
||||
@@ -1864,7 +1864,7 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
|
||||
|
||||
proc myModuleOpenForCodegen(m: BModule; idx: FileIndex): bool {.inline.} =
|
||||
if moduleOpenForCodegen(m.g.graph, idx):
|
||||
result = idx.int < m.g.modules.len and m.g.modules[idx.int] != nil
|
||||
result = idx.int < m.g.mods.len and m.g.mods[idx.int] != nil
|
||||
else:
|
||||
result = false
|
||||
|
||||
@@ -1898,7 +1898,7 @@ proc genTypeInfoV2(m: BModule; t: PType; info: TLineInfo): Rope =
|
||||
let owner = t.skipTypes(typedescPtrs).itemId.module
|
||||
if owner != m.module.position and myModuleOpenForCodegen(m, FileIndex owner):
|
||||
# make sure the type info is created in the owner module
|
||||
discard genTypeInfoV2(m.g.modules[owner], origType, info)
|
||||
discard genTypeInfoV2(m.g.mods[owner], origType, info)
|
||||
# reference the type info as extern here
|
||||
cgsym(m, "TNimTypeV2")
|
||||
declareNimType(m, "TNimTypeV2", result, owner)
|
||||
@@ -1983,7 +1983,7 @@ proc genTypeInfoV1(m: BModule; t: PType; info: TLineInfo): Rope =
|
||||
var owner = t.skipTypes(typedescPtrs).itemId.module
|
||||
if owner != m.module.position and myModuleOpenForCodegen(m, FileIndex owner):
|
||||
# make sure the type info is created in the owner module
|
||||
discard genTypeInfoV1(m.g.modules[owner], origType, info)
|
||||
discard genTypeInfoV1(m.g.mods[owner], origType, info)
|
||||
# reference the type info as extern here
|
||||
cgsym(m, "TNimType")
|
||||
cgsym(m, "TNimNode")
|
||||
|
||||
@@ -67,19 +67,19 @@ proc findPendingModule(m: BModule, s: PSym): BModule =
|
||||
# TODO fixme
|
||||
if m.config.symbolFiles == v2Sf or optCompress in m.config.globalOptions:
|
||||
let ms = s.itemId.module #getModule(s)
|
||||
result = m.g.modules[ms]
|
||||
result = m.g.mods[ms]
|
||||
elif m.config.cmd in {cmdNifC, cmdM}:
|
||||
var ms = getModule(s)
|
||||
registerModule m.g.graph, ms
|
||||
if ms.position >= m.g.modules.len:
|
||||
if ms.position >= m.g.mods.len:
|
||||
result = newModule(m.g, ms, m.config, idGeneratorFromModule(ms))
|
||||
else:
|
||||
result = m.g.modules[ms.position]
|
||||
result = m.g.mods[ms.position]
|
||||
if result == nil:
|
||||
result = newModule(m.g, ms, m.config, idGeneratorFromModule(ms))
|
||||
else:
|
||||
var ms = getModule(s)
|
||||
result = m.g.modules[ms.position]
|
||||
result = m.g.mods[ms.position]
|
||||
|
||||
proc initLoc(k: TLocKind, lode: PNode, s: TStorageLoc, flags: TLocFlags = {}): TLoc =
|
||||
result = TLoc(k: k, storage: s, lode: lode,
|
||||
@@ -133,10 +133,10 @@ proc getModuleDllPath(m: BModule): Rope =
|
||||
result = makeCString(dir.string & "/" & filename)
|
||||
|
||||
proc getModuleDllPath(m: BModule, module: int): Rope =
|
||||
result = getModuleDllPath(m.g.modules[module])
|
||||
result = getModuleDllPath(m.g.mods[module])
|
||||
|
||||
proc getModuleDllPath(m: BModule, s: PSym): Rope =
|
||||
result = getModuleDllPath(m.g.modules[s.itemId.module])
|
||||
result = getModuleDllPath(m.g.mods[s.itemId.module])
|
||||
|
||||
import std/macros
|
||||
|
||||
@@ -1720,9 +1720,12 @@ proc genMainProcs(m: BModule) =
|
||||
|
||||
proc genMainProcsWithResult(m: BModule) =
|
||||
genMainProcs(m)
|
||||
var res = "nim_program_result"
|
||||
if m.hcrOn: res = cDeref(res)
|
||||
m.s[cfsProcs].addReturn(res)
|
||||
if m.config.cmd != cmdNifC:
|
||||
var res = "nim_program_result"
|
||||
if m.hcrOn: res = cDeref(res)
|
||||
m.s[cfsProcs].addReturn(res)
|
||||
else:
|
||||
m.s[cfsProcs].addReturn(cIntValue(0))
|
||||
|
||||
proc genNimMainInner(m: BModule) =
|
||||
m.s[cfsProcs].addDeclWithVisibility(Private):
|
||||
@@ -1960,7 +1963,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
|
||||
if m.hcrOn:
|
||||
var hcrModuleMeta = newBuilder("")
|
||||
let systemModulePath = getModuleDllPath(m, g.modules[g.graph.config.m.systemFileIdx.int].module)
|
||||
let systemModulePath = getModuleDllPath(m, g.mods[g.graph.config.m.systemFileIdx.int].module)
|
||||
let mainModulePath = getModuleDllPath(m, m.module)
|
||||
hcrModuleMeta.addDeclWithVisibility(Private):
|
||||
hcrModuleMeta.addArrayVarWithInitializer(kind = Local,
|
||||
@@ -1977,7 +1980,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
|
||||
g.graph.importDeps.withValue(FileIndex(m.module.position), deps):
|
||||
for curr in deps[]:
|
||||
hcrModuleMeta.addField(modules, ""):
|
||||
hcrModuleMeta.add(getModuleDllPath(m, g.modules[curr.int].module))
|
||||
hcrModuleMeta.add(getModuleDllPath(m, g.mods[curr.int].module))
|
||||
hcrModuleMeta.addField(modules, ""):
|
||||
hcrModuleMeta.add("\"\"")
|
||||
hcrModuleMeta.addDeclWithVisibility(ExportLib):
|
||||
@@ -2170,6 +2173,8 @@ proc genInitCode(m: BModule) =
|
||||
else:
|
||||
prcBody.add(extract(m.thing.s(section)))
|
||||
|
||||
#echo "PRE INIT PROC ", m.module.name.s, " ", m.s[cfsVars].buf.len
|
||||
|
||||
if m.preInitProc.s(cpsInit).buf.len > 0 or m.preInitProc.s(cpsStmts).buf.len > 0:
|
||||
# Give this small function its own scope
|
||||
prcBody.addScope():
|
||||
@@ -2386,10 +2391,10 @@ proc newModule(g: BModuleList; module: PSym; conf: ConfigRef; idgen: IdGenerator
|
||||
# we should create only one cgen module for each module sym
|
||||
result = rawNewModule(g, module, conf)
|
||||
result.idgen = idgen
|
||||
if module.position >= g.modules.len:
|
||||
setLen(g.modules, module.position + 1)
|
||||
if module.position >= g.mods.len:
|
||||
setLen(g.mods, module.position + 1)
|
||||
#growCache g.modules, module.position
|
||||
g.modules[module.position] = result
|
||||
g.mods[module.position] = result
|
||||
|
||||
template injectG() {.dirty.} =
|
||||
if graph.backend == nil:
|
||||
@@ -2523,13 +2528,7 @@ proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool =
|
||||
rawMessage(m.config, errCannotOpenFile, cfile.cname.string)
|
||||
result = true
|
||||
|
||||
# We need 2 different logics here: pending modules (including
|
||||
# 'nim__dat') may require file merging for the combination of dead code
|
||||
# elimination and incremental compilation! Non pending modules need no
|
||||
# such logic and in fact the logic hurts for the main module at least;
|
||||
# it would generate multiple 'main' procs, for instance.
|
||||
|
||||
proc writeModule(m: BModule, pending: bool) =
|
||||
proc writeModule(m: BModule) =
|
||||
let cfile = getCFile(m)
|
||||
if moduleHasChanged(m.g.graph, m.module):
|
||||
genInitCode(m)
|
||||
@@ -2658,7 +2657,7 @@ proc genForwardedProcs(g: BModuleList) =
|
||||
while g.forwardedProcs.len > 0:
|
||||
let
|
||||
prc = g.forwardedProcs.pop()
|
||||
m = g.modules[prc.itemId.module]
|
||||
m = g.mods[prc.itemId.module]
|
||||
if sfForward in prc.flags:
|
||||
internalError(m.config, prc.info, "still forwarded: " & prc.name.s)
|
||||
|
||||
@@ -2674,6 +2673,6 @@ proc cgenWriteModules*(backend: RootRef, config: ConfigRef) =
|
||||
genForwardedProcs(g)
|
||||
|
||||
for m in cgenModules(g):
|
||||
m.writeModule(pending=true)
|
||||
m.writeModule()
|
||||
writeMapping(config, g.mapping)
|
||||
if g.generatedHeader != nil: writeHeader(g.generatedHeader)
|
||||
|
||||
@@ -117,7 +117,7 @@ type
|
||||
BModuleList* = ref object of RootObj
|
||||
mainModProcs*, mainModInit*, otherModsInit*, mainDatInit*: Builder
|
||||
mapping*: Rope # the generated mapping file (if requested)
|
||||
modules*: seq[BModule] # list of all compiled modules
|
||||
mods*: seq[BModule] # list of all compiled modules
|
||||
modulesClosed*: seq[BModule] # list of the same compiled modules, but in the order they were closed
|
||||
forwardedProcs*: seq[PSym] # procs that did not yet have a body
|
||||
generatedHeader*: BModule
|
||||
|
||||
@@ -40,7 +40,7 @@ proc setupBackendModule(g: ModuleGraph; m: var LoadedModule) =
|
||||
var bmod = cgen.newModule(BModuleList(g.backend), m.module, g.config, idgenFromLoadedModule(m))
|
||||
|
||||
proc generateCodeForModule(g: ModuleGraph; m: var LoadedModule; alive: var AliveSyms) =
|
||||
var bmod = BModuleList(g.backend).modules[m.module.position]
|
||||
var bmod = BModuleList(g.backend).mods[m.module.position]
|
||||
assert bmod != nil
|
||||
bmod.flags.incl useAliveDataFromDce
|
||||
bmod.alive = move alive[m.module.position]
|
||||
|
||||
@@ -404,140 +404,140 @@ proc parse*(t: typedesc[TSymKind]; s: string): TSymKind =
|
||||
|
||||
proc toNifTag*(s: TTypeKind): string =
|
||||
case s
|
||||
of tyNone: "none"
|
||||
of tyBool: "bool"
|
||||
of tyChar: "char"
|
||||
of tyEmpty: "empty"
|
||||
of tyAlias: "alias"
|
||||
of tyNil: "nil"
|
||||
of tyUntyped: "untyped"
|
||||
of tyTyped: "typed"
|
||||
of tyTypeDesc: "typedesc"
|
||||
of tyGenericInvocation: "ginvoke"
|
||||
of tyGenericBody: "gbody"
|
||||
of tyGenericInst: "ginst"
|
||||
of tyGenericParam: "gparam"
|
||||
of tyDistinct: "distinct"
|
||||
of tyEnum: "enum"
|
||||
of tyOrdinal: "ordinal"
|
||||
of tyArray: "array"
|
||||
of tyObject: "object"
|
||||
of tyTuple: "tuple"
|
||||
of tySet: "set"
|
||||
of tyRange: "range"
|
||||
of tyPtr: "ptr"
|
||||
of tyRef: "ref"
|
||||
of tyVar: "mut"
|
||||
of tySequence: "seq"
|
||||
of tyProc: "proctype"
|
||||
of tyPointer: "pointer"
|
||||
of tyOpenArray: "openarray"
|
||||
of tyString: "string"
|
||||
of tyCstring: "cstring"
|
||||
of tyForward: "forward"
|
||||
of tyInt: "int"
|
||||
of tyInt8: "int8"
|
||||
of tyInt16: "int16"
|
||||
of tyInt32: "int32"
|
||||
of tyInt64: "int64"
|
||||
of tyFloat: "float"
|
||||
of tyFloat32: "float32"
|
||||
of tyFloat64: "float64"
|
||||
of tyFloat128: "float128"
|
||||
of tyUInt: "uint"
|
||||
of tyUInt8: "uint8"
|
||||
of tyUInt16: "uint16"
|
||||
of tyUInt32: "uint32"
|
||||
of tyUInt64: "uint64"
|
||||
of tyOwned: "owned"
|
||||
of tySink: "sink"
|
||||
of tyLent: "lent"
|
||||
of tyVarargs: "varargs"
|
||||
of tyUncheckedArray: "uarray"
|
||||
of tyError: "error"
|
||||
of tyBuiltInTypeClass: "bconcept"
|
||||
of tyUserTypeClass: "uconcept"
|
||||
of tyUserTypeClassInst: "uconceptinst"
|
||||
of tyCompositeTypeClass: "cconcept"
|
||||
of tyInferred: "inferred"
|
||||
of tyAnd: "and"
|
||||
of tyOr: "or"
|
||||
of tyNot: "not"
|
||||
of tyAnything: "anything"
|
||||
of tyStatic: "static"
|
||||
of tyFromExpr: "fromx"
|
||||
of tyConcept: "concept"
|
||||
of tyVoid: "void"
|
||||
of tyIterable: "iterable"
|
||||
of tyNone: "n0"
|
||||
of tyBool: "b0"
|
||||
of tyChar: "c0"
|
||||
of tyEmpty: "e0"
|
||||
of tyAlias: "a0"
|
||||
of tyNil: "n1"
|
||||
of tyUntyped: "U0"
|
||||
of tyTyped: "t0"
|
||||
of tyTypeDesc: "t1"
|
||||
of tyGenericInvocation: "g0"
|
||||
of tyGenericBody: "g1"
|
||||
of tyGenericInst: "g2"
|
||||
of tyGenericParam: "g4"
|
||||
of tyDistinct: "d0"
|
||||
of tyEnum: "e1"
|
||||
of tyOrdinal: "o0"
|
||||
of tyArray: "a1"
|
||||
of tyObject: "o1"
|
||||
of tyTuple: "t2"
|
||||
of tySet: "s0"
|
||||
of tyRange: "r0"
|
||||
of tyPtr: "p0"
|
||||
of tyRef: "r1"
|
||||
of tyVar: "v0"
|
||||
of tySequence: "s1"
|
||||
of tyProc: "p1"
|
||||
of tyPointer: "p2"
|
||||
of tyOpenArray: "o3"
|
||||
of tyString: "s2"
|
||||
of tyCstring: "c1"
|
||||
of tyForward: "F0"
|
||||
of tyInt: "i0"
|
||||
of tyInt8: "i1"
|
||||
of tyInt16: "i2"
|
||||
of tyInt32: "i3"
|
||||
of tyInt64: "i4"
|
||||
of tyFloat: "f0"
|
||||
of tyFloat32: "f1"
|
||||
of tyFloat64: "f2"
|
||||
of tyFloat128: "f3"
|
||||
of tyUInt: "u0"
|
||||
of tyUInt8: "u1"
|
||||
of tyUInt16: "u2"
|
||||
of tyUInt32: "u3"
|
||||
of tyUInt64: "u4"
|
||||
of tyOwned: "o2"
|
||||
of tySink: "s3"
|
||||
of tyLent: "L0"
|
||||
of tyVarargs: "v1"
|
||||
of tyUncheckedArray: "U1"
|
||||
of tyError: "e2"
|
||||
of tyBuiltInTypeClass: "b1"
|
||||
of tyUserTypeClass: "U2"
|
||||
of tyUserTypeClassInst: "U3"
|
||||
of tyCompositeTypeClass: "c2"
|
||||
of tyInferred: "I0"
|
||||
of tyAnd: "a2"
|
||||
of tyOr: "o4"
|
||||
of tyNot: "n2"
|
||||
of tyAnything: "a3"
|
||||
of tyStatic: "s4"
|
||||
of tyFromExpr: "F1"
|
||||
of tyConcept: "c3"
|
||||
of tyVoid: "v2"
|
||||
of tyIterable: "I1"
|
||||
|
||||
|
||||
proc parse*(t: typedesc[TTypeKind]; s: string): TTypeKind =
|
||||
case s
|
||||
of "none": tyNone
|
||||
of "bool": tyBool
|
||||
of "char": tyChar
|
||||
of "empty": tyEmpty
|
||||
of "alias": tyAlias
|
||||
of "nil": tyNil
|
||||
of "untyped": tyUntyped
|
||||
of "typed": tyTyped
|
||||
of "typedesc": tyTypeDesc
|
||||
of "ginvoke": tyGenericInvocation
|
||||
of "gbody": tyGenericBody
|
||||
of "ginst": tyGenericInst
|
||||
of "gparam": tyGenericParam
|
||||
of "distinct": tyDistinct
|
||||
of "enum": tyEnum
|
||||
of "ordinal": tyOrdinal
|
||||
of "array": tyArray
|
||||
of "object": tyObject
|
||||
of "tuple": tyTuple
|
||||
of "set": tySet
|
||||
of "range": tyRange
|
||||
of "ptr": tyPtr
|
||||
of "ref": tyRef
|
||||
of "mut": tyVar
|
||||
of "seq": tySequence
|
||||
of "proctype": tyProc
|
||||
of "pointer": tyPointer
|
||||
of "openarray": tyOpenArray
|
||||
of "string": tyString
|
||||
of "cstring": tyCstring
|
||||
of "forward": tyForward
|
||||
of "int": tyInt
|
||||
of "int8": tyInt8
|
||||
of "int16": tyInt16
|
||||
of "int32": tyInt32
|
||||
of "int64": tyInt64
|
||||
of "float": tyFloat
|
||||
of "float32": tyFloat32
|
||||
of "float64": tyFloat64
|
||||
of "float128": tyFloat128
|
||||
of "uint": tyUInt
|
||||
of "uint8": tyUInt8
|
||||
of "uint16": tyUInt16
|
||||
of "uint32": tyUInt32
|
||||
of "uint64": tyUInt64
|
||||
of "owned": tyOwned
|
||||
of "sink": tySink
|
||||
of "lent": tyLent
|
||||
of "varargs": tyVarargs
|
||||
of "uarray": tyUncheckedArray
|
||||
of "error": tyError
|
||||
of "bconcept": tyBuiltInTypeClass
|
||||
of "uconcept": tyUserTypeClass
|
||||
of "uconceptinst": tyUserTypeClassInst
|
||||
of "cconcept": tyCompositeTypeClass
|
||||
of "inferred": tyInferred
|
||||
of "and": tyAnd
|
||||
of "or": tyOr
|
||||
of "not": tyNot
|
||||
of "anything": tyAnything
|
||||
of "static": tyStatic
|
||||
of "fromx": tyFromExpr
|
||||
of "concept": tyConcept
|
||||
of "void": tyVoid
|
||||
of "iterable": tyIterable
|
||||
of "n0": tyNone
|
||||
of "b0": tyBool
|
||||
of "c0": tyChar
|
||||
of "e0": tyEmpty
|
||||
of "a0": tyAlias
|
||||
of "n1": tyNil
|
||||
of "U0": tyUntyped
|
||||
of "t0": tyTyped
|
||||
of "t1": tyTypeDesc
|
||||
of "g0": tyGenericInvocation
|
||||
of "g1": tyGenericBody
|
||||
of "g2": tyGenericInst
|
||||
of "g4": tyGenericParam
|
||||
of "d0": tyDistinct
|
||||
of "e1": tyEnum
|
||||
of "o0": tyOrdinal
|
||||
of "a1": tyArray
|
||||
of "o1": tyObject
|
||||
of "t2": tyTuple
|
||||
of "s0": tySet
|
||||
of "r0": tyRange
|
||||
of "p0": tyPtr
|
||||
of "r1": tyRef
|
||||
of "v0": tyVar
|
||||
of "s1": tySequence
|
||||
of "p1": tyProc
|
||||
of "p2": tyPointer
|
||||
of "o3": tyOpenArray
|
||||
of "s2": tyString
|
||||
of "c1": tyCstring
|
||||
of "F0": tyForward
|
||||
of "i0": tyInt
|
||||
of "i1": tyInt8
|
||||
of "i2": tyInt16
|
||||
of "i3": tyInt32
|
||||
of "i4": tyInt64
|
||||
of "f0": tyFloat
|
||||
of "f1": tyFloat32
|
||||
of "f2": tyFloat64
|
||||
of "f3": tyFloat128
|
||||
of "u0": tyUInt
|
||||
of "u1": tyUInt8
|
||||
of "u2": tyUInt16
|
||||
of "u3": tyUInt32
|
||||
of "u4": tyUInt64
|
||||
of "o2": tyOwned
|
||||
of "s3": tySink
|
||||
of "L0": tyLent
|
||||
of "v1": tyVarargs
|
||||
of "U1": tyUncheckedArray
|
||||
of "e2": tyError
|
||||
of "b1": tyBuiltInTypeClass
|
||||
of "U2": tyUserTypeClass
|
||||
of "U3": tyUserTypeClassInst
|
||||
of "c2": tyCompositeTypeClass
|
||||
of "I0": tyInferred
|
||||
of "a2": tyAnd
|
||||
of "o4": tyOr
|
||||
of "n2": tyNot
|
||||
of "a3": tyAnything
|
||||
of "s4": tyStatic
|
||||
of "F1": tyFromExpr
|
||||
of "c3": tyConcept
|
||||
of "v2": tyVoid
|
||||
of "I1": tyIterable
|
||||
else: tyNone
|
||||
|
||||
|
||||
|
||||
@@ -471,7 +471,7 @@ proc copyTypeProps*(g: ModuleGraph; module: int; dest, src: PType) =
|
||||
|
||||
proc loadCompilerProc*(g: ModuleGraph; name: string): PSym =
|
||||
result = nil
|
||||
if g.config.symbolFiles == disabledSf:
|
||||
if g.config.symbolFiles == disabledSf and optWithinConfigSystem notin g.config.globalOptions:
|
||||
# For NIF-based compilation, search in loaded NIF modules
|
||||
when not defined(nimKochBootstrap):
|
||||
# Only try to resolve from NIF if we're actually using NIF files (cmdNifC)
|
||||
@@ -599,9 +599,10 @@ proc registerModule*(g: ModuleGraph; m: PSym) =
|
||||
if m.position >= g.packed.len:
|
||||
setLen(g.packed.pm, m.position + 1)
|
||||
|
||||
g.ifaces[m.position] = Iface(module: m, converters: @[], patterns: @[],
|
||||
uniqueName: rope(uniqueModuleName(g.config, m)))
|
||||
initStrTables(g, m)
|
||||
if g.ifaces[m.position].module == nil:
|
||||
g.ifaces[m.position] = Iface(module: m, converters: @[], patterns: @[],
|
||||
uniqueName: rope(uniqueModuleName(g.config, m)))
|
||||
initStrTables(g, m)
|
||||
|
||||
proc registerModuleById*(g: ModuleGraph; m: FileIndex) =
|
||||
registerModule(g, g.packed[int m].module)
|
||||
@@ -814,31 +815,33 @@ proc moduleFromRodFile*(g: ModuleGraph; fileIdx: FileIndex;
|
||||
|
||||
when not defined(nimKochBootstrap):
|
||||
proc moduleFromNifFile*(g: ModuleGraph; fileIdx: FileIndex;
|
||||
cachedModules: var seq[FileIndex];
|
||||
loadFullAst: bool = false): PSym =
|
||||
flags: set[LoadFlag] = {}): PrecompiledModule =
|
||||
## Returns 'nil' if the module needs to be recompiled.
|
||||
## Loads module from NIF file when optCompress is enabled.
|
||||
## When loadFullAst is true, loads the complete module AST for code generation.
|
||||
if not fileExists(toNifFilename(g.config, fileIdx)):
|
||||
return nil
|
||||
return PrecompiledModule(module: nil)
|
||||
|
||||
# Create module symbol
|
||||
let filename = AbsoluteFile toFullPath(g.config, fileIdx)
|
||||
result = PSym(
|
||||
|
||||
let m = PSym(
|
||||
kindImpl: skModule,
|
||||
itemId: ItemId(module: int32(fileIdx), item: 0'i32),
|
||||
name: getIdent(g.cache, splitFile(filename).name),
|
||||
infoImpl: newLineInfo(fileIdx, 1, 1),
|
||||
positionImpl: int(fileIdx))
|
||||
setOwner(result, getPackage(g.config, g.cache, fileIdx))
|
||||
|
||||
setOwner(m, getPackage(g.config, g.cache, fileIdx))
|
||||
# Register module in graph
|
||||
registerModule(g, result)
|
||||
var opsLog: seq[LogEntry] = @[]
|
||||
result.astImpl = loadNifModule(ast.program, fileIdx, g.ifaces[fileIdx.int].interf,
|
||||
g.ifaces[fileIdx.int].interfHidden, opsLog, loadFullAst)
|
||||
registerModule(g, m)
|
||||
|
||||
result = loadNifModule(ast.program, fileIdx,
|
||||
g.ifaces[fileIdx.int].interf,
|
||||
g.ifaces[fileIdx.int].interfHidden, flags)
|
||||
result.module = m
|
||||
|
||||
# Register hooks from NIF index with the module graph
|
||||
for x in opsLog:
|
||||
for x in result.logOps:
|
||||
case x.kind
|
||||
of HookEntry:
|
||||
g.loadedOps[x.op][x.key] = x.sym
|
||||
@@ -852,7 +855,6 @@ when not defined(nimKochBootstrap):
|
||||
raiseAssert "GenericInstEntry should not be in the NIF index"
|
||||
# Register methods per type from NIF index
|
||||
discard "todo"
|
||||
cachedModules.add fileIdx
|
||||
|
||||
proc configComplete*(g: ModuleGraph) =
|
||||
rememberStartupConfig(g.startupPackedConfig, g.config)
|
||||
|
||||
@@ -25,30 +25,36 @@ when defined(nimPreviewSlimSystem):
|
||||
import ast, options, lineinfos, modulegraphs, cgendata, cgen,
|
||||
pathutils, extccomp, msgs, modulepaths, idents, types, ast2nif
|
||||
|
||||
proc loadModuleDependencies(g: ModuleGraph; mainFileIdx: FileIndex): seq[PSym] =
|
||||
proc loadModuleDependencies(g: ModuleGraph; mainFileIdx: FileIndex): seq[PrecompiledModule] =
|
||||
## Traverse the module dependency graph using a stack.
|
||||
## Returns all modules that need code generation, in dependency order.
|
||||
var visited = initIntSet()
|
||||
var stack: seq[FileIndex] = @[mainFileIdx]
|
||||
let mainModule = moduleFromNifFile(g, mainFileIdx, {LoadFullAst})
|
||||
|
||||
var stack: seq[ModuleSuffix] = @[]
|
||||
result = @[]
|
||||
var cachedModules: seq[FileIndex] = @[]
|
||||
|
||||
if mainModule.module != nil:
|
||||
incl mainModule.module.flagsImpl, sfMainModule
|
||||
for dep in mainModule.deps:
|
||||
stack.add dep
|
||||
|
||||
var visited = initHashSet[string]()
|
||||
|
||||
while stack.len > 0:
|
||||
let fileIdx = stack.pop()
|
||||
let suffix = stack.pop()
|
||||
|
||||
if not visited.containsOrIncl(int(fileIdx)):
|
||||
# Only load full AST for main module; others are loaded lazily by codegen
|
||||
let isMainModule = fileIdx == mainFileIdx
|
||||
let module = moduleFromNifFile(g, fileIdx, cachedModules, loadFullAst=isMainModule)
|
||||
if module != nil:
|
||||
result.add module
|
||||
if isMainModule:
|
||||
incl module.flagsImpl, sfMainModule
|
||||
# Add dependencies to stack (they come from cachedModules)
|
||||
for dep in cachedModules:
|
||||
if not visited.contains(int(dep)):
|
||||
if not visited.containsOrIncl(suffix.string):
|
||||
let nifFile = toGeneratedFile(g.config, AbsoluteFile(suffix.string), ".nif")
|
||||
let fileIdx = msgs.fileInfoIdx(g.config, nifFile)
|
||||
let precomp = moduleFromNifFile(g, fileIdx, {LoadFullAst})
|
||||
if precomp.module != nil:
|
||||
result.add precomp
|
||||
for dep in precomp.deps:
|
||||
if not visited.contains(dep.string):
|
||||
stack.add dep
|
||||
cachedModules.setLen(0)
|
||||
|
||||
if mainModule.module != nil:
|
||||
result.add mainModule
|
||||
|
||||
proc setupNifBackendModule(g: ModuleGraph; module: PSym): BModule =
|
||||
## Set up a BModule for code generation from a NIF module.
|
||||
@@ -56,38 +62,44 @@ proc setupNifBackendModule(g: ModuleGraph; module: PSym): BModule =
|
||||
g.backend = cgendata.newModuleList(g)
|
||||
result = cgen.newModule(BModuleList(g.backend), module, g.config, idGeneratorFromModule(module))
|
||||
|
||||
proc generateCodeForModule(g: ModuleGraph; module: PSym) =
|
||||
## Generate C code for a single module.
|
||||
let moduleId = module.position
|
||||
var bmod = BModuleList(g.backend).modules[moduleId]
|
||||
if bmod == nil:
|
||||
bmod = setupNifBackendModule(g, module)
|
||||
|
||||
# Generate code for the module's top-level statements
|
||||
if module.ast != nil:
|
||||
cgen.genTopLevelStmt(bmod, module.ast)
|
||||
|
||||
proc finishModule(g: ModuleGraph; bmod: BModule) =
|
||||
# Finalize the module (this adds it to modulesClosed)
|
||||
# Create an empty stmt list as the init body - genInitCode in writeModule will set it up properly
|
||||
let initStmt = newNodeI(nkStmtList, module.info)
|
||||
let initStmt = newNode(nkStmtList)
|
||||
finalCodegenActions(g, bmod, initStmt)
|
||||
|
||||
# Generate dispatcher methods
|
||||
for disp in getDispatchers(g):
|
||||
genProcLvl3(bmod, disp)
|
||||
|
||||
proc generateCodeForModule(g: ModuleGraph; precomp: PrecompiledModule) =
|
||||
## Generate C code for a single module.
|
||||
let moduleId = precomp.module.position
|
||||
var bmod = BModuleList(g.backend).mods[moduleId]
|
||||
if bmod == nil:
|
||||
bmod = setupNifBackendModule(g, precomp.module)
|
||||
|
||||
# Generate code for the module's top-level statements
|
||||
if precomp.topLevel != nil:
|
||||
cgen.genTopLevelStmt(bmod, precomp.topLevel)
|
||||
|
||||
proc generateCode*(g: ModuleGraph; mainFileIdx: FileIndex) =
|
||||
## Main entry point for NIF-based C code generation.
|
||||
## Traverses the module dependency graph and generates C code.
|
||||
|
||||
# Reset backend state
|
||||
resetForBackend(g)
|
||||
let mainModule = g.getModule(mainFileIdx)
|
||||
|
||||
var isKnownFile = false
|
||||
let systemFileIdx = registerNifSuffix(g.config, "sysma2dyk", isKnownFile)
|
||||
g.config.m.systemFileIdx = systemFileIdx
|
||||
#msgs.fileInfoIdx(g.config,
|
||||
# g.config.libpath / RelativeFile"system.nim")
|
||||
|
||||
# Load system module first - it's always needed and contains essential hooks
|
||||
var cachedModules: seq[FileIndex] = @[]
|
||||
if g.config.m.systemFileIdx != InvalidFileIdx:
|
||||
g.systemModule = moduleFromNifFile(g, g.config.m.systemFileIdx, cachedModules)
|
||||
var precompSys = PrecompiledModule(module: nil)
|
||||
precompSys = moduleFromNifFile(g, systemFileIdx, {LoadFullAst, AlwaysLoadInterface})
|
||||
g.systemModule = precompSys.module
|
||||
|
||||
# Load all modules in dependency order using stack traversal
|
||||
# This must happen BEFORE any code generation so that hooks are loaded into loadedOps
|
||||
@@ -98,29 +110,35 @@ proc generateCode*(g: ModuleGraph; mainFileIdx: FileIndex) =
|
||||
return
|
||||
|
||||
# Set up backend modules for all modules that need code generation
|
||||
for module in modules:
|
||||
discard setupNifBackendModule(g, module)
|
||||
for m in modules:
|
||||
discard setupNifBackendModule(g, m.module)
|
||||
|
||||
# Also ensure system module is set up and generated first if it exists
|
||||
if g.systemModule != nil and g.systemModule != mainModule:
|
||||
let systemBmod = BModuleList(g.backend).modules[g.systemModule.position]
|
||||
if systemBmod == nil:
|
||||
discard setupNifBackendModule(g, g.systemModule)
|
||||
generateCodeForModule(g, g.systemModule)
|
||||
if precompSys.module != nil:
|
||||
discard setupNifBackendModule(g, precompSys.module)
|
||||
generateCodeForModule(g, precompSys)
|
||||
|
||||
# Generate code for all modules except main (main goes last)
|
||||
# This ensures all modules are added to modulesClosed
|
||||
for module in modules:
|
||||
if module != mainModule and module != g.systemModule:
|
||||
generateCodeForModule(g, module)
|
||||
# Track which modules have been processed to avoid duplicates
|
||||
var processed = initIntSet()
|
||||
if precompSys.module != nil:
|
||||
processed.incl precompSys.module.position
|
||||
|
||||
# Generate main module last (so all init procs are registered)
|
||||
if mainModule != nil:
|
||||
generateCodeForModule(g, mainModule)
|
||||
# Generate code for all modules (skip system since it's already processed)
|
||||
for m in modules:
|
||||
if not processed.containsOrIncl(m.module.position):
|
||||
generateCodeForModule(g, m)
|
||||
|
||||
# during code generation of `main.nim` we can trigger the code generation
|
||||
# of symbols in different modules so we need to finish these modules
|
||||
# here later, after the above loop!
|
||||
for m in BModuleList(g.backend).mods:
|
||||
if m != nil:
|
||||
assert m.module != nil
|
||||
#if sfMainModule notin m.module.flags:
|
||||
finishModule g, m
|
||||
|
||||
# Write C files
|
||||
if g.backend != nil:
|
||||
cgenWriteModules(g.backend, g.config)
|
||||
cgenWriteModules(g.backend, g.config)
|
||||
|
||||
# Run C compiler
|
||||
if g.config.cmd != cmdTcc:
|
||||
|
||||
@@ -112,6 +112,7 @@ type # please make sure we have under 32 options
|
||||
optJsBigInt64 # use bigints for 64-bit integers in JS
|
||||
optItaniumMangle # mangling follows the Itanium spec
|
||||
optCompress # turn on AST compression by converting it to NIF
|
||||
optWithinConfigSystem # we still compile within the configuration system
|
||||
|
||||
TGlobalOptions* = set[TGlobalOption]
|
||||
|
||||
|
||||
@@ -286,8 +286,8 @@ proc compilePipelineModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymF
|
||||
sfMainModule notin flags and
|
||||
not graph.withinSystem and
|
||||
not graph.config.isDefined("nimscript"):
|
||||
result = moduleFromNifFile(graph, fileIdx, cachedModules)
|
||||
if result == nil:
|
||||
let precomp = moduleFromNifFile(graph, fileIdx)
|
||||
if precomp.module == nil:
|
||||
let nifPath = toNifFilename(graph.config, fileIdx)
|
||||
localError(graph.config, unknownLineInfo,
|
||||
"nim m requires precompiled NIF for import: " & toFullPath(graph.config, fileIdx) &
|
||||
@@ -385,7 +385,8 @@ proc compilePipelineProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx
|
||||
graph.config.libpath / RelativeFile"system.nim")
|
||||
var cachedModules: seq[FileIndex] = @[]
|
||||
when not defined(nimKochBootstrap):
|
||||
graph.systemModule = moduleFromNifFile(graph, graph.config.m.systemFileIdx, cachedModules)
|
||||
let precomp = moduleFromNifFile(graph, graph.config.m.systemFileIdx)
|
||||
graph.systemModule = precomp.module
|
||||
if graph.systemModule == nil:
|
||||
let nifPath = toNifFilename(graph.config, graph.config.m.systemFileIdx)
|
||||
localError(graph.config, unknownLineInfo,
|
||||
|
||||
@@ -1836,6 +1836,9 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
putWithSpace(g, tkSymbol, "error")
|
||||
#gcomma(g, n, c)
|
||||
gsub(g, n[0], c)
|
||||
of nkReplayAction:
|
||||
put(g, tkSymbol, "replayaction")
|
||||
#gsons(g, n, c, 0)
|
||||
else:
|
||||
#nkNone, nkExplicitTypeListCall:
|
||||
internalError(g.config, n.info, "renderer.gsub(" & $n.kind & ')')
|
||||
|
||||
@@ -213,6 +213,7 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
||||
unregisterArcOrc(conf)
|
||||
conf.globalOptions.excl optOwnedRefs
|
||||
conf.selectedGC = gcUnselected
|
||||
conf.globalOptions.incl optWithinConfigSystem
|
||||
|
||||
var m = graph.makeModule(scriptName)
|
||||
incl(m, sfMainModule)
|
||||
@@ -251,4 +252,5 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
|
||||
#initDefines()
|
||||
undefSymbol(conf.symbols, "nimscript")
|
||||
undefSymbol(conf.symbols, "nimconfig")
|
||||
conf.globalOptions.excl optWithinConfigSystem
|
||||
conf.symbolFiles = oldSymbolFiles
|
||||
|
||||
@@ -28,10 +28,6 @@ const
|
||||
("nkError", "err"),
|
||||
("nkType", "onlytype"),
|
||||
("nkTypeSection", "type"),
|
||||
("tySequence", "seq"),
|
||||
("tyVar", "mut"),
|
||||
("tyProc", "proctype"),
|
||||
("tyUncheckedArray", "uarray"),
|
||||
("nkExprEqExpr", "vv"),
|
||||
("nkExprColonExpr", "kv"),
|
||||
("nkDerefExpr", "deref"),
|
||||
@@ -55,17 +51,75 @@ const
|
||||
("mVar", "varm"),
|
||||
("mInSet", "contains"),
|
||||
("mNil", "nilm"),
|
||||
("tyBuiltInTypeClass", "bconcept"),
|
||||
("tyUserTypeClass", "uconcept"),
|
||||
("tyUserTypeClassInst", "uconceptinst"),
|
||||
("tyCompositeTypeClass", "cconcept"),
|
||||
("tyGenericInvocation", "ginvoke"),
|
||||
("tyGenericBody", "gbody"),
|
||||
("tyGenericInst", "ginst"),
|
||||
("tyGenericParam", "gparam"),
|
||||
("nkStmtList", "stmts"),
|
||||
("nkDotExpr", "dot"),
|
||||
("nkBracketExpr", "at")
|
||||
("nkBracketExpr", "at"),
|
||||
|
||||
("tyNone", "n0"), # we always use a digit for type kinds so there can be no overlap with node kinds
|
||||
("tyBool", "b0"),
|
||||
("tyChar", "c0"),
|
||||
("tyEmpty", "e0"),
|
||||
("tyAlias", "a0"),
|
||||
("tyNil", "n1"),
|
||||
("tyUntyped", "U0"),
|
||||
("tyTyped", "t0"),
|
||||
("tyTypeDesc", "t1"),
|
||||
("tyGenericInvocation", "g0"),
|
||||
("tyGenericBody", "g1"),
|
||||
("tyGenericInst", "g2"),
|
||||
("tyGenericParam", "g4"),
|
||||
("tyDistinct", "d0"),
|
||||
("tyEnum", "e1"),
|
||||
("tyOrdinal", "o0"),
|
||||
("tyArray", "a1"),
|
||||
("tyObject", "o1"),
|
||||
("tyTuple", "t2"),
|
||||
("tySet", "s0"),
|
||||
("tyRange", "r0"),
|
||||
("tyPtr", "p0"),
|
||||
("tyRef", "r1"),
|
||||
("tyVar", "v0"),
|
||||
("tySequence", "s1"),
|
||||
("tyProc", "p1"),
|
||||
("tyPointer", "p2"),
|
||||
("tyOpenArray", "o3"),
|
||||
("tyString", "s2"),
|
||||
("tyCstring", "c1"),
|
||||
("tyForward", "F0"),
|
||||
("tyInt", "i0"),
|
||||
("tyInt8", "i1"),
|
||||
("tyInt16", "i2"),
|
||||
("tyInt32", "i3"),
|
||||
("tyInt64", "i4"),
|
||||
("tyFloat", "f0"),
|
||||
("tyFloat32", "f1"),
|
||||
("tyFloat64", "f2"),
|
||||
("tyFloat128", "f3"),
|
||||
("tyUInt", "u0"),
|
||||
("tyUInt8", "u1"),
|
||||
("tyUInt16", "u2"),
|
||||
("tyUInt32", "u3"),
|
||||
("tyUInt64", "u4"),
|
||||
("tyOwned", "o2"),
|
||||
("tySink", "s3"),
|
||||
("tyLent", "L0"),
|
||||
("tyVarargs", "v1"),
|
||||
("tyUncheckedArray", "U1"),
|
||||
("tyError", "e2"),
|
||||
("tyBuiltInTypeClass", "b1"),
|
||||
("tyUserTypeClass", "U2"),
|
||||
("tyUserTypeClassInst", "U3"),
|
||||
("tyCompositeTypeClass", "c2"),
|
||||
("tyInferred", "I0"),
|
||||
("tyAnd", "a2"),
|
||||
("tyOr", "o4"),
|
||||
("tyNot", "n2"),
|
||||
("tyAnything", "a3"),
|
||||
("tyStatic", "s4"),
|
||||
("tyFromExpr", "F1"),
|
||||
("tyConcept", "c3"),
|
||||
("tyVoid", "v2"),
|
||||
("tyIterable", "I1")
|
||||
]
|
||||
SuffixesToReplace = [
|
||||
("Section", ""), ("Branch", ""), ("Stmt", ""), ("I", ""),
|
||||
|
||||
Reference in New Issue
Block a user