ic refactoring (#17778)

* minor IC documentation update

* IC: refactoring: removed the 'shared' type and fields, these were a leftover from an earlier design
This commit is contained in:
Andreas Rumpf
2021-04-19 11:48:06 +02:00
committed by GitHub
parent 83fa0fc843
commit 4b0b536419
7 changed files with 146 additions and 159 deletions

View File

@@ -27,7 +27,7 @@ type
proc isExportedToC(c: var AliveContext; g: PackedModuleGraph; symId: int32): bool =
## "Exported to C" procs are special (these are marked with '.exportc') because these
## must not be optimized away!
let symPtr = addr g[c.thisModule].fromDisk.sh.syms[symId]
let symPtr = unsafeAddr g[c.thisModule].fromDisk.syms[symId]
let flags = symPtr.flags
# due to a bug/limitation in the lambda lifting, unused inner procs
# are not transformed correctly; issue (#411). However, the whole purpose here
@@ -39,7 +39,7 @@ proc isExportedToC(c: var AliveContext; g: PackedModuleGraph; symId: int32): boo
# XXX: This used to be a condition to:
# (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
if sfCompilerProc in flags:
c.compilerProcs[g[c.thisModule].fromDisk.sh.strings[symPtr.name]] = (c.thisModule, symId)
c.compilerProcs[g[c.thisModule].fromDisk.strings[symPtr.name]] = (c.thisModule, symId)
template isNotGeneric(n: NodePos): bool = ithSon(tree, n, genericParamsPos).kind == nkEmpty
@@ -47,17 +47,17 @@ proc followLater(c: var AliveContext; g: PackedModuleGraph; module: int; item: i
## Marks a symbol 'item' as used and later in 'followNow' the symbol's body will
## be analysed.
if not c.alive[module].containsOrIncl(item):
var body = g[module].fromDisk.sh.syms[item].ast
var body = g[module].fromDisk.syms[item].ast
if body != emptyNodeId:
let opt = g[module].fromDisk.sh.syms[item].options
if g[module].fromDisk.sh.syms[item].kind in routineKinds:
let opt = g[module].fromDisk.syms[item].options
if g[module].fromDisk.syms[item].kind in routineKinds:
body = NodeId ithSon(g[module].fromDisk.bodies, NodePos body, bodyPos)
c.stack.add((module, opt, NodePos(body)))
when false:
let nid = g[module].fromDisk.sh.syms[item].name
let nid = g[module].fromDisk.syms[item].name
if nid != LitId(0):
let name = g[module].fromDisk.sh.strings[nid]
let name = g[module].fromDisk.strings[nid]
if name in ["nimFrame", "callDepthLimitReached"]:
echo "I was called! ", name, " body exists: ", body != emptyNodeId, " ", module, " ", item
@@ -66,12 +66,12 @@ proc requestCompilerProc(c: var AliveContext; g: PackedModuleGraph; name: string
followLater(c, g, module, item)
proc loadTypeKind(t: PackedItemId; c: AliveContext; g: PackedModuleGraph; toSkip: set[TTypeKind]): TTypeKind =
template kind(t: ItemId): TTypeKind = g[t.module].fromDisk.sh.types[t.item].kind
template kind(t: ItemId): TTypeKind = g[t.module].fromDisk.types[t.item].kind
var t2 = translateId(t, g, c.thisModule, c.decoder.config)
result = t2.kind
while result in toSkip:
t2 = translateId(g[t2.module].fromDisk.sh.types[t2.item].types[^1], g, t2.module, c.decoder.config)
t2 = translateId(g[t2.module].fromDisk.types[t2.item].types[^1], g, t2.module, c.decoder.config)
result = t2.kind
proc rangeCheckAnalysis(c: var AliveContext; g: PackedModuleGraph; tree: PackedTree; n: NodePos) =

View File

@@ -7,12 +7,8 @@ The frontend produces a set of `.rod` files. Every `.nim` module
produces its own `.rod` file.
- The IR must be a faithful representation of the AST in memory.
- The backend can do its own caching but doesn't have to.
- We know by comparing 'nim check compiler/nim' against 'nim c compiler/nim'
that 2/3 of the compiler's runtime is spent in the frontend. Hence we
implement IC for the frontend first and only later for the backend. The
backend will recompile everything until we implement its own caching
mechanisms.
- The backend can do its own caching but doesn't have to. In the
current implementation the backend also caches its results.
Advantage of the "set of files" vs the previous global database:
- By construction, we either read from the `.rod` file or from the

View File

@@ -51,7 +51,12 @@ type
emittedTypeInfo*: seq[string]
backendFlags*: set[ModuleBackendFlag]
sh*: Shared
syms*: seq[PackedSym]
types*: seq[PackedType]
strings*: BiTable[string] # we could share these between modules.
numbers*: BiTable[BiggestInt] # we also store floats in here so
# that we can assure that every bit is kept
cfg: PackedConfig
PackedEncoder* = object
@@ -66,6 +71,50 @@ type
symMarker*: IntSet #Table[ItemId, SymId] # ItemId.item -> SymId
config*: ConfigRef
proc toString*(tree: PackedTree; n: NodePos; m: PackedModule; nesting: int;
result: var string) =
let pos = n.int
if result.len > 0 and result[^1] notin {' ', '\n'}:
result.add ' '
result.add $tree[pos].kind
case tree.nodes[pos].kind
of nkNone, nkEmpty, nkNilLit, nkType: discard
of nkIdent, nkStrLit..nkTripleStrLit:
result.add " "
result.add m.strings[LitId tree.nodes[pos].operand]
of nkSym:
result.add " "
result.add m.strings[m.syms[tree.nodes[pos].operand].name]
of directIntLit:
result.add " "
result.addInt tree.nodes[pos].operand
of externSIntLit:
result.add " "
result.addInt m.numbers[LitId tree.nodes[pos].operand]
of externUIntLit:
result.add " "
result.add $cast[uint64](m.numbers[LitId tree.nodes[pos].operand])
of nkFloatLit..nkFloat128Lit:
result.add " "
result.add $cast[BiggestFloat](m.numbers[LitId tree.nodes[pos].operand])
else:
result.add "(\n"
for i in 1..(nesting+1)*2: result.add ' '
for child in sonsReadonly(tree, n):
toString(tree, child, m, nesting + 1, result)
result.add "\n"
for i in 1..nesting*2: result.add ' '
result.add ")"
#for i in 1..nesting*2: result.add ' '
proc toString*(tree: PackedTree; n: NodePos; m: PackedModule): string =
result = ""
toString(tree, n, m, 0, result)
proc debug*(tree: PackedTree; m: PackedModule) =
stdout.write toString(tree, NodePos 0, m)
proc isActive*(e: PackedEncoder): bool = e.config != nil
proc disable(e: var PackedEncoder) = e.config = nil
@@ -134,14 +183,14 @@ proc toLitId(x: FileIndex; c: var PackedEncoder; m: var PackedModule): LitId =
result = c.filenames.getOrDefault(x)
if result == LitId(0):
let p = msgs.toFullPath(c.config, x)
result = getOrIncl(m.sh.strings, p)
result = getOrIncl(m.strings, p)
c.filenames[x] = result
c.lastFile = x
c.lastLit = result
assert result != LitId(0)
proc toFileIndex*(x: LitId; m: PackedModule; config: ConfigRef): FileIndex =
result = msgs.fileInfoIdx(config, AbsoluteFile m.sh.strings[x])
result = msgs.fileInfoIdx(config, AbsoluteFile m.strings[x])
proc includesIdentical(m: var PackedModule; config: ConfigRef): bool =
for it in mitems(m.includes):
@@ -151,7 +200,6 @@ proc includesIdentical(m: var PackedModule; config: ConfigRef): bool =
proc initEncoder*(c: var PackedEncoder; m: var PackedModule; moduleSym: PSym; config: ConfigRef; pc: PackedConfig) =
## setup a context for serializing to packed ast
m.sh = Shared()
c.thisModule = moduleSym.itemId.module
c.config = config
m.moduleFlags = moduleSym.flags
@@ -179,11 +227,11 @@ proc addImportFileDep*(c: var PackedEncoder; m: var PackedModule; f: FileIndex)
m.imports.add toLitId(f, c, m)
proc addHidden*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
let nameId = getOrIncl(m.sh.strings, s.name.s)
let nameId = getOrIncl(m.strings, s.name.s)
m.hidden.add((nameId, s.itemId.item))
proc addExported*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
let nameId = getOrIncl(m.sh.strings, s.name.s)
let nameId = getOrIncl(m.strings, s.name.s)
m.exports.add((nameId, s.itemId.item))
proc addConverter*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
@@ -201,12 +249,12 @@ proc addMethod*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
m.methods.add s.itemId.item
proc addReexport*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
let nameId = getOrIncl(m.sh.strings, s.name.s)
let nameId = getOrIncl(m.strings, s.name.s)
m.reexports.add((nameId, PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m),
item: s.itemId.item)))
proc addCompilerProc*(c: var PackedEncoder; m: var PackedModule; s: PSym) =
let nameId = getOrIncl(m.sh.strings, s.name.s)
let nameId = getOrIncl(m.strings, s.name.s)
m.compilerProcs.add((nameId, s.itemId.item))
proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule)
@@ -225,11 +273,11 @@ proc flush(c: var PackedEncoder; m: var PackedModule) =
proc toLitId(x: string; m: var PackedModule): LitId =
## store a string as a literal
result = getOrIncl(m.sh.strings, x)
result = getOrIncl(m.strings, x)
proc toLitId(x: BiggestInt; m: var PackedModule): LitId =
## store an integer as a literal
result = getOrIncl(m.sh.numbers, x)
result = getOrIncl(m.numbers, x)
proc toPackedInfo(x: TLineInfo; c: var PackedEncoder; m: var PackedModule): PackedLineInfo =
PackedLineInfo(line: x.line, col: x.col, file: toLitId(x.fileIndex, c, m))
@@ -299,8 +347,8 @@ proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemI
result = PackedItemId(module: toLitId(t.uniqueId.module.FileIndex, c, m), item: t.uniqueId.item)
if t.uniqueId.module == c.thisModule and not c.typeMarker.containsOrIncl(t.uniqueId.item):
if t.uniqueId.item >= m.sh.types.len:
setLen m.sh.types, t.uniqueId.item+1
if t.uniqueId.item >= m.types.len:
setLen m.types, t.uniqueId.item+1
var p = PackedType(kind: t.kind, flags: t.flags, callConv: t.callConv,
size: t.size, align: t.align, nonUniqueId: t.itemId.item,
@@ -315,7 +363,7 @@ proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemI
p.owner = t.owner.safeItemId(c, m)
# fill the reserved slot, nothing else:
m.sh.types[t.uniqueId.item] = p
m.types[t.uniqueId.item] = p
proc toPackedLib(l: PLib; c: var PackedEncoder; m: var PackedModule): PackedLib =
## the plib hangs off the psym via the .annex field
@@ -334,8 +382,8 @@ proc storeSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId
result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item)
if s.itemId.module == c.thisModule and not c.symMarker.containsOrIncl(s.itemId.item):
if s.itemId.item >= m.sh.syms.len:
setLen m.sh.syms, s.itemId.item+1
if s.itemId.item >= m.syms.len:
setLen m.syms, s.itemId.item+1
assert sfForward notin s.flags
@@ -363,7 +411,7 @@ proc storeSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId
p.cname = toLitId(s.cname, m)
# fill the reserved slot, nothing else:
m.sh.syms[s.itemId.item] = p
m.syms[s.itemId.item] = p
proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) =
## add a remote symbol reference to the tree
@@ -387,7 +435,7 @@ proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var Pa
typeId: storeTypeLater(n.typ, c, m), info: info)
of nkIdent:
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
operand: int32 getOrIncl(m.sh.strings, n.ident.s),
operand: int32 getOrIncl(m.strings, n.ident.s),
typeId: storeTypeLater(n.typ, c, m), info: info)
of nkSym:
if n.sym.itemId.module == c.thisModule:
@@ -405,15 +453,15 @@ proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var Pa
typeId: storeTypeLater(n.typ, c, m), info: info)
of externIntLit:
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
operand: int32 getOrIncl(m.sh.numbers, n.intVal),
operand: int32 getOrIncl(m.numbers, n.intVal),
typeId: storeTypeLater(n.typ, c, m), info: info)
of nkStrLit..nkTripleStrLit:
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
operand: int32 getOrIncl(m.sh.strings, n.strVal),
operand: int32 getOrIncl(m.strings, n.strVal),
typeId: storeTypeLater(n.typ, c, m), info: info)
of nkFloatLit..nkFloat128Lit:
ir.nodes.add PackedNode(kind: n.kind, flags: n.flags,
operand: int32 getOrIncl(m.sh.numbers, cast[BiggestInt](n.floatVal)),
operand: int32 getOrIncl(m.numbers, cast[BiggestInt](n.floatVal)),
typeId: storeTypeLater(n.typ, c, m), info: info)
else:
let patchPos = ir.prepare(n.kind, n.flags,
@@ -499,7 +547,6 @@ proc loadError(err: RodFileError; filename: AbsoluteFile; config: ConfigRef;) =
proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef;
ignoreConfig = false): RodFileError =
m.sh = Shared()
var f = rodfiles.open(filename.string)
f.loadHeader()
f.loadSection configSection
@@ -519,7 +566,7 @@ proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef
f.loadSection section
f.load data
loadTabSection stringsSection, m.sh.strings
loadTabSection stringsSection, m.strings
loadSeqSection checkSumsSection, m.includes
if not includesIdentical(m, config):
@@ -527,7 +574,7 @@ proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef
loadSeqSection depsSection, m.imports
loadTabSection numbersSection, m.sh.numbers
loadTabSection numbersSection, m.numbers
loadSeqSection exportsSection, m.exports
loadSeqSection hiddenSection, m.hidden
@@ -545,8 +592,8 @@ proc loadRodFile*(filename: AbsoluteFile; m: var PackedModule; config: ConfigRef
loadSeqSection toReplaySection, m.toReplay.nodes
loadSeqSection topLevelSection, m.topLevel.nodes
loadSeqSection bodiesSection, m.bodies.nodes
loadSeqSection symsSection, m.sh.syms
loadSeqSection typesSection, m.sh.types
loadSeqSection symsSection, m.syms
loadSeqSection typesSection, m.types
loadSeqSection typeInstCacheSection, m.typeInstCache
loadSeqSection procInstCacheSection, m.procInstCache
@@ -586,13 +633,13 @@ proc saveRodFile*(filename: AbsoluteFile; encoder: var PackedEncoder; m: var Pac
f.storeSection section
f.store data
storeTabSection stringsSection, m.sh.strings
storeTabSection stringsSection, m.strings
storeSeqSection checkSumsSection, m.includes
storeSeqSection depsSection, m.imports
storeTabSection numbersSection, m.sh.numbers
storeTabSection numbersSection, m.numbers
storeSeqSection exportsSection, m.exports
storeSeqSection hiddenSection, m.hidden
@@ -610,9 +657,9 @@ proc saveRodFile*(filename: AbsoluteFile; encoder: var PackedEncoder; m: var Pac
storeSeqSection topLevelSection, m.topLevel.nodes
storeSeqSection bodiesSection, m.bodies.nodes
storeSeqSection symsSection, m.sh.syms
storeSeqSection symsSection, m.syms
storeSeqSection typesSection, m.sh.types
storeSeqSection typesSection, m.types
storeSeqSection typeInstCacheSection, m.typeInstCache
storeSeqSection procInstCacheSection, m.procInstCache
@@ -700,17 +747,17 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int;
of nkEmpty, nkNilLit, nkType:
discard
of nkIdent:
result.ident = getIdent(c.cache, g[thisModule].fromDisk.sh.strings[n.litId])
result.ident = getIdent(c.cache, g[thisModule].fromDisk.strings[n.litId])
of nkSym:
result.sym = loadSym(c, g, thisModule, PackedItemId(module: LitId(0), item: tree.nodes[n.int].operand))
of directIntLit:
result.intVal = tree.nodes[n.int].operand
of externIntLit:
result.intVal = g[thisModule].fromDisk.sh.numbers[n.litId]
result.intVal = g[thisModule].fromDisk.numbers[n.litId]
of nkStrLit..nkTripleStrLit:
result.strVal = g[thisModule].fromDisk.sh.strings[n.litId]
result.strVal = g[thisModule].fromDisk.strings[n.litId]
of nkFloatLit..nkFloat128Lit:
result.floatVal = cast[BiggestFloat](g[thisModule].fromDisk.sh.numbers[n.litId])
result.floatVal = cast[BiggestFloat](g[thisModule].fromDisk.numbers[n.litId])
of nkModuleRef:
let (n1, n2) = sons2(tree, n)
assert n1.kind == nkInt32Lit
@@ -767,7 +814,7 @@ proc symHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
options: s.options,
position: if s.kind in {skForVar, skVar, skLet, skTemp}: 0 else: s.position,
offset: if s.kind in routineKinds: defaultOffset else: s.offset,
name: getIdent(c.cache, g[si].fromDisk.sh.strings[s.name])
name: getIdent(c.cache, g[si].fromDisk.strings[s.name])
)
template loadAstBody(p, field) =
@@ -785,7 +832,7 @@ proc loadLib(c: var PackedDecoder; g: var PackedModuleGraph;
result = nil
else:
result = PLib(generated: l.generated, isOverriden: l.isOverriden,
kind: l.kind, name: rope g[si].fromDisk.sh.strings[l.name])
kind: l.kind, name: rope g[si].fromDisk.strings[l.name])
loadAstBody(l, path)
proc symBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
@@ -798,14 +845,14 @@ proc symBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
loadAstBody(s, ast)
result.annex = loadLib(c, g, si, item, s.annex)
when hasFFI:
result.cname = g[si].fromDisk.sh.strings[s.cname]
result.cname = g[si].fromDisk.strings[s.cname]
if s.kind in {skLet, skVar, skField, skForVar}:
result.guard = loadSym(c, g, si, s.guard)
result.bitsize = s.bitsize
result.alignment = s.alignment
result.owner = loadSym(c, g, si, s.owner)
let externalName = g[si].fromDisk.sh.strings[s.externalName]
let externalName = g[si].fromDisk.strings[s.externalName]
if externalName != "":
result.loc.r = rope externalName
result.loc.flags = s.locFlags
@@ -818,14 +865,14 @@ proc loadSym(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; s:
assert g[si].status in {loaded, storing, stored}
if not g[si].symsInit:
g[si].symsInit = true
setLen g[si].syms, g[si].fromDisk.sh.syms.len
setLen g[si].syms, g[si].fromDisk.syms.len
if g[si].syms[s.item] == nil:
if g[si].fromDisk.sh.syms[s.item].kind != skModule:
result = symHeaderFromPacked(c, g, g[si].fromDisk.sh.syms[s.item], si, s.item)
if g[si].fromDisk.syms[s.item].kind != skModule:
result = symHeaderFromPacked(c, g, g[si].fromDisk.syms[s.item], si, s.item)
# store it here early on, so that recursions work properly:
g[si].syms[s.item] = result
symBodyFromPacked(c, g, g[si].fromDisk.sh.syms[s.item], si, s.item, result)
symBodyFromPacked(c, g, g[si].fromDisk.syms[s.item], si, s.item, result)
else:
result = g[si].module
assert result != nil
@@ -866,13 +913,13 @@ proc loadType(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int; t
if not g[si].typesInit:
g[si].typesInit = true
setLen g[si].types, g[si].fromDisk.sh.types.len
setLen g[si].types, g[si].fromDisk.types.len
if g[si].types[t.item] == nil:
result = typeHeaderFromPacked(c, g, g[si].fromDisk.sh.types[t.item], si, t.item)
result = typeHeaderFromPacked(c, g, g[si].fromDisk.types[t.item], si, t.item)
# store it here early on, so that recursions work properly:
g[si].types[t.item] = result
typeBodyFromPacked(c, g, g[si].fromDisk.sh.types[t.item], si, t.item, result)
typeBodyFromPacked(c, g, g[si].fromDisk.types[t.item], si, t.item, result)
else:
result = g[si].types[t.item]
assert result.itemId.item > 0
@@ -897,7 +944,7 @@ proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCa
let e2 =
when e[1] is PackedItemId: e[1]
else: PackedItemId(module: LitId(0), item: e[1])
iface.mgetOrPut(cache.getIdent(m.fromDisk.sh.strings[nameLit]), @[]).add(e2)
iface.mgetOrPut(cache.getIdent(m.fromDisk.strings[nameLit]), @[]).add(e2)
for e in m.fromDisk.exports:
m.iface.impl(e)
@@ -1000,7 +1047,7 @@ proc loadProcBody*(config: ConfigRef, cache: IdentCache;
lastFile: FileIndex(-1),
config: config,
cache: cache)
let pos = g[mId].fromDisk.sh.syms[s.itemId.item].ast
let pos = g[mId].fromDisk.syms[s.itemId.item].ast
assert pos != emptyNodeId
result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos)
@@ -1042,15 +1089,15 @@ proc translateId*(id: PackedItemId; g: PackedModuleGraph; thisModule: int; confi
proc checkForHoles(m: PackedModule; config: ConfigRef; moduleId: int) =
var bugs = 0
for i in 1 .. high(m.sh.syms):
if m.sh.syms[i].kind == skUnknown:
for i in 1 .. high(m.syms):
if m.syms[i].kind == skUnknown:
echo "EMPTY ID ", i, " module ", moduleId, " ", toFullPath(config, FileIndex(moduleId))
inc bugs
assert bugs == 0
when false:
var nones = 0
for i in 1 .. high(m.sh.types):
inc nones, m.sh.types[i].kind == tyNone
for i in 1 .. high(m.types):
inc nones, m.types[i].kind == tyNone
assert nones < 1
proc simulateLoadedModule*(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache;
@@ -1133,13 +1180,13 @@ proc interfaceSymbol*(config: ConfigRef, cache: IdentCache;
result = loadSym(decoder, g, int(module), values[0])
proc idgenFromLoadedModule*(m: LoadedModule): IdGenerator =
IdGenerator(module: m.module.itemId.module, symId: int32 m.fromDisk.sh.syms.len,
typeId: int32 m.fromDisk.sh.types.len)
IdGenerator(module: m.module.itemId.module, symId: int32 m.fromDisk.syms.len,
typeId: int32 m.fromDisk.types.len)
proc searchForCompilerproc*(m: LoadedModule; name: string): int32 =
# slow, linear search, but the results are cached:
for it in items(m.fromDisk.compilerProcs):
if m.fromDisk.sh.strings[it[0]] == name:
if m.fromDisk.strings[it[0]] == name:
return it[1]
return -1
@@ -1149,31 +1196,31 @@ proc rodViewer*(rodfile: AbsoluteFile; config: ConfigRef, cache: IdentCache) =
var m: PackedModule
let err = loadRodFile(rodfile, m, config, ignoreConfig=true)
if err != ok:
config.quitOrRaise "Error: could not load: " & $rodfile.string & " reason: " & $err
config.quitOrRaise "Error: could not load: " & $rodfile.string & " reason: " & $err
when true:
echo "exports:"
for ex in m.exports:
echo " ", m.sh.strings[ex[0]], " local ID: ", ex[1]
assert ex[0] == m.sh.syms[ex[1]].name
echo " ", m.strings[ex[0]], " local ID: ", ex[1]
assert ex[0] == m.syms[ex[1]].name
# ex[1] int32
echo "reexports:"
for ex in m.reexports:
echo " ", m.sh.strings[ex[0]]
echo " ", m.strings[ex[0]]
# reexports*: seq[(LitId, PackedItemId)]
echo "hidden: " & $m.hidden.len
for ex in m.hidden:
echo " ", m.sh.strings[ex[0]], " local ID: ", ex[1]
echo " ", m.strings[ex[0]], " local ID: ", ex[1]
echo "all symbols"
for i in 0..high(m.sh.syms):
if m.sh.syms[i].name != LitId(0):
echo " ", m.sh.strings[m.sh.syms[i].name], " local ID: ", i, " kind ", m.sh.syms[i].kind
for i in 0..high(m.syms):
if m.syms[i].name != LitId(0):
echo " ", m.strings[m.syms[i].name], " local ID: ", i, " kind ", m.syms[i].kind
else:
echo " <anon symbol?> local ID: ", i, " kind ", m.sh.syms[i].kind
echo " <anon symbol?> local ID: ", i, " kind ", m.syms[i].kind
echo "symbols: ", m.sh.syms.len, " types: ", m.sh.types.len,
echo "symbols: ", m.syms.len, " types: ", m.types.len,
" top level nodes: ", m.topLevel.nodes.len, " other nodes: ", m.bodies.nodes.len,
" strings: ", m.sh.strings.len, " numbers: ", m.sh.numbers.len
" strings: ", m.strings.len, " numbers: ", m.numbers.len

View File

@@ -42,12 +42,12 @@ proc checkType(c: var CheckedContext; typeId: PackedItemId) =
if not c.checkedTypes.containsOrIncl(itemId):
let oldThisModule = c.thisModule
c.thisModule = itemId.module
checkTypeObj c, c.g.packed[itemId.module].fromDisk.sh.types[itemId.item]
checkTypeObj c, c.g.packed[itemId.module].fromDisk.types[itemId.item]
c.thisModule = oldThisModule
proc checkSym(c: var CheckedContext; s: PackedSym) =
if s.name != LitId(0):
assert c.g.packed[c.thisModule].fromDisk.sh.strings.hasLitId s.name
assert c.g.packed[c.thisModule].fromDisk.strings.hasLitId s.name
checkType c, s.typ
if s.ast != emptyNodeId:
checkNode(c, c.g.packed[c.thisModule].fromDisk.bodies, NodePos s.ast)
@@ -57,14 +57,14 @@ proc checkSym(c: var CheckedContext; s: PackedSym) =
proc checkLocalSym(c: var CheckedContext; item: int32) =
let itemId = ItemId(module: c.thisModule, item: item)
if not c.checkedSyms.containsOrIncl(itemId):
checkSym c, c.g.packed[c.thisModule].fromDisk.sh.syms[item]
checkSym c, c.g.packed[c.thisModule].fromDisk.syms[item]
proc checkForeignSym(c: var CheckedContext; symId: PackedItemId) =
let itemId = translateId(symId, c.g.packed, c.thisModule, c.g.config)
if not c.checkedSyms.containsOrIncl(itemId):
let oldThisModule = c.thisModule
c.thisModule = itemId.module
checkSym c, c.g.packed[itemId.module].fromDisk.sh.syms[itemId.item]
checkSym c, c.g.packed[itemId.module].fromDisk.syms[itemId.item]
c.thisModule = oldThisModule
proc checkNode(c: var CheckedContext; tree: PackedTree; n: NodePos) =
@@ -74,15 +74,15 @@ proc checkNode(c: var CheckedContext; tree: PackedTree; n: NodePos) =
of nkEmpty, nkNilLit, nkType, nkNilRodNode:
discard
of nkIdent:
assert c.g.packed[c.thisModule].fromDisk.sh.strings.hasLitId n.litId
assert c.g.packed[c.thisModule].fromDisk.strings.hasLitId n.litId
of nkSym:
checkLocalSym(c, tree.nodes[n.int].operand)
of directIntLit:
discard
of externIntLit, nkFloatLit..nkFloat128Lit:
assert c.g.packed[c.thisModule].fromDisk.sh.numbers.hasLitId n.litId
assert c.g.packed[c.thisModule].fromDisk.numbers.hasLitId n.litId
of nkStrLit..nkTripleStrLit:
assert c.g.packed[c.thisModule].fromDisk.sh.strings.hasLitId n.litId
assert c.g.packed[c.thisModule].fromDisk.strings.hasLitId n.litId
of nkModuleRef:
let (n1, n2) = sons2(tree, n)
assert n1.kind == nkInt32Lit
@@ -97,25 +97,25 @@ proc checkTree(c: var CheckedContext; t: PackedTree) =
proc checkLocalSymIds(c: var CheckedContext; m: PackedModule; symIds: seq[int32]) =
for symId in symIds:
assert symId >= 0 and symId < m.sh.syms.len, $symId & " " & $m.sh.syms.len
assert symId >= 0 and symId < m.syms.len, $symId & " " & $m.syms.len
proc checkModule(c: var CheckedContext; m: PackedModule) =
# We check that:
# - Every symbol references existing types and symbols.
# - Every tree node references existing types and symbols.
for i in 0..high(m.sh.syms):
for i in 0..high(m.syms):
checkLocalSym c, int32(i)
checkTree c, m.toReplay
checkTree c, m.topLevel
for e in m.exports:
assert e[1] >= 0 and e[1] < m.sh.syms.len
assert e[0] == m.sh.syms[e[1]].name
assert e[1] >= 0 and e[1] < m.syms.len
assert e[0] == m.syms[e[1]].name
for e in m.compilerProcs:
assert e[1] >= 0 and e[1] < m.sh.syms.len
assert e[0] == m.sh.syms[e[1]].name
assert e[1] >= 0 and e[1] < m.syms.len
assert e[0] == m.syms[e[1]].name
checkLocalSymIds c, m, m.converters
checkLocalSymIds c, m, m.methods

View File

@@ -35,12 +35,12 @@ proc isTracked(current, trackPos: PackedLineInfo, tokenLen: int): bool =
proc searchLocalSym(c: var NavContext; s: PackedSym; info: PackedLineInfo): bool =
result = s.name != LitId(0) and
isTracked(info, c.trackPos, c.g.packed[c.thisModule].fromDisk.sh.strings[s.name].len)
isTracked(info, c.trackPos, c.g.packed[c.thisModule].fromDisk.strings[s.name].len)
proc searchForeignSym(c: var NavContext; s: ItemId; info: PackedLineInfo): bool =
let name = c.g.packed[s.module].fromDisk.sh.syms[s.item].name
let name = c.g.packed[s.module].fromDisk.syms[s.item].name
result = name != LitId(0) and
isTracked(info, c.trackPos, c.g.packed[s.module].fromDisk.sh.strings[name].len)
isTracked(info, c.trackPos, c.g.packed[s.module].fromDisk.strings[name].len)
const
EmptyItemId = ItemId(module: -1'i32, item: -1'i32)
@@ -51,7 +51,7 @@ proc search(c: var NavContext; tree: PackedTree): ItemId =
case tree.nodes[i].kind
of nkSym:
let item = tree.nodes[i].operand
if searchLocalSym(c, c.g.packed[c.thisModule].fromDisk.sh.syms[item], tree.nodes[i].info):
if searchLocalSym(c, c.g.packed[c.thisModule].fromDisk.syms[item], tree.nodes[i].info):
return ItemId(module: c.thisModule, item: item)
of nkModuleRef:
if tree.nodes[i].info.line == c.trackPos.line and tree.nodes[i].info.file == c.trackPos.file:
@@ -74,7 +74,7 @@ proc isDecl(tree: PackedTree; n: NodePos): bool =
proc usage(c: var NavContext; info: PackedLineInfo; isDecl: bool) =
var m = ""
var file = c.g.packed[c.thisModule].fromDisk.sh.strings[info.file]
var file = c.g.packed[c.thisModule].fromDisk.strings[info.file]
if c.outputSep == ' ':
file = os.extractFilename file
toLocation(m, file, info.line.int, info.col.int + ColOffset)
@@ -102,7 +102,7 @@ proc nav(g: ModuleGraph) =
# translate the track position to a packed position:
let unpacked = g.config.m.trackPos
let mid = unpacked.fileIndex
let fileId = g.packed[int32 mid].fromDisk.sh.strings.getKeyId(toFullPath(g.config, mid))
let fileId = g.packed[int32 mid].fromDisk.strings.getKeyId(toFullPath(g.config, mid))
if fileId == LitId(0):
internalError(g.config, unpacked, "cannot find a valid file ID")

View File

@@ -98,17 +98,6 @@ type
PackedTree* = object ## usually represents a full Nim module
nodes*: seq[PackedNode]
#sh*: Shared
Shared* = ref object # shared between different versions of 'Module'.
# (though there is always exactly one valid
# version of a module)
syms*: seq[PackedSym]
types*: seq[PackedType]
strings*: BiTable[string] # we could share these between modules.
numbers*: BiTable[BiggestInt] # we also store floats in here so
# that we can assure that every bit is kept
#config*: ConfigRef
PackedInstantiation* = object
key*, sym*: PackedItemId
@@ -374,51 +363,6 @@ const
externUIntLit* = {nkUIntLit, nkUInt8Lit, nkUInt16Lit, nkUInt32Lit, nkUInt64Lit}
directIntLit* = nkInt32Lit
proc toString*(tree: PackedTree; n: NodePos; sh: Shared; nesting: int;
result: var string) =
let pos = n.int
if result.len > 0 and result[^1] notin {' ', '\n'}:
result.add ' '
result.add $tree[pos].kind
case tree.nodes[pos].kind
of nkNone, nkEmpty, nkNilLit, nkType: discard
of nkIdent, nkStrLit..nkTripleStrLit:
result.add " "
result.add sh.strings[LitId tree.nodes[pos].operand]
of nkSym:
result.add " "
result.add sh.strings[sh.syms[tree.nodes[pos].operand].name]
of directIntLit:
result.add " "
result.addInt tree.nodes[pos].operand
of externSIntLit:
result.add " "
result.addInt sh.numbers[LitId tree.nodes[pos].operand]
of externUIntLit:
result.add " "
result.add $cast[uint64](sh.numbers[LitId tree.nodes[pos].operand])
of nkFloatLit..nkFloat128Lit:
result.add " "
result.add $cast[BiggestFloat](sh.numbers[LitId tree.nodes[pos].operand])
else:
result.add "(\n"
for i in 1..(nesting+1)*2: result.add ' '
for child in sonsReadonly(tree, n):
toString(tree, child, sh, nesting + 1, result)
result.add "\n"
for i in 1..nesting*2: result.add ' '
result.add ")"
#for i in 1..nesting*2: result.add ' '
proc toString*(tree: PackedTree; n: NodePos; sh: Shared): string =
result = ""
toString(tree, n, sh, 0, result)
proc debug*(tree: PackedTree; sh: Shared) =
stdout.write toString(tree, NodePos 0, sh)
when false:
proc identIdImpl(tree: PackedTree; n: NodePos): LitId =
if n.kind == nkIdent:

View File

@@ -23,8 +23,8 @@ from typetraits import supportsCopyMem
## (`RodFileError`). The file format broken up into sections (`RodSection`)
## and preceeded by a header (see: `cookie`). The precise layout, section
## ordering and data following the section are determined by the user. See
## `ic.loadRoadFile`.
##
## `ic.loadRodFile`.
##
## A basic but "wrong" example of the lifecycle:
## ---------------------------------------------
## 1. `create` or `open` - create a new one or open an existing
@@ -45,10 +45,10 @@ from typetraits import supportsCopyMem
## The API is centered around IO and prone to error, each operation checks or
## sets the `RodFile.err` field. A user of this API needs to handle these
## appropriately.
##
##
## API Notes
## =========
##
##
## Valid inputs for Rod files
## --------------------------
## ASTs, hopes, dreams, and anything as long as it and any children it may have
@@ -61,7 +61,7 @@ from typetraits import supportsCopyMem
## ----------------------------
## A flag based approach is used where operations no-op in case of a
## preexisting error and set the flag if they encounter one.
##
##
## Misc
## ----
## * 'Prim' is short for 'primitive', as in a non-sequence type