From cf6dd57efeb3f4dba21102b75fd91c5a84224eaf Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 12 Jan 2021 09:36:51 +0100 Subject: IC: next steps (#16632) * removed dead code * beginnings of a rodfile reader * IC: record global VM state changes and pragma state changes * IC: replay pragmas and VM state changes * implemented rod load file simuation for easier, extensive testing * critical bugfix * IC: stress test logic; should also help with recursive module dependencies; WIP * IC: loading from .rod files begins to work reliably * removed ugly hacks * yet another silly mistake --- compiler/ast.nim | 5 + compiler/canonicalizer_unused.nim | 421 --------------------------------- compiler/commands.nim | 6 +- compiler/ic/design.rst | 21 +- compiler/ic/packed_ast.nim | 70 +----- compiler/ic/replayer.nim | 89 +++++++ compiler/ic/rodfiles.nim | 7 +- compiler/ic/to_packed_ast.nim | 473 ++++++++++++++++++++++---------------- compiler/lineinfos.nim | 1 + compiler/macrocacheimpl.nim | 59 +---- compiler/main.nim | 12 +- compiler/modulegraphs.nim | 19 +- compiler/modules.nim | 4 +- compiler/options.nim | 4 +- compiler/passes.nim | 3 +- compiler/pragmas.nim | 6 +- compiler/semdata.nim | 45 +++- compiler/vmdef.nim | 1 + 18 files changed, 475 insertions(+), 771 deletions(-) delete mode 100644 compiler/canonicalizer_unused.nim create mode 100644 compiler/ic/replayer.nim (limited to 'compiler') diff --git a/compiler/ast.nim b/compiler/ast.nim index de4ab5b77..f8e8f1d3b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -221,6 +221,8 @@ type nkBreakState, # special break statement for easier code generation nkFuncDef, # a func nkTupleConstr # a tuple constructor + nkModuleRef # for .rod file support: A (moduleId, itemId) pair + nkReplayAction # for .rod file support: A replay action TNodeKinds* = set[TNodeKind] @@ -1139,6 +1141,9 @@ proc add*(father, son: Indexable) = if isNil(father.sons): father.sons = @[] father.sons.add(son) +proc addAllowNil*(father, son: Indexable) {.inline.} = + father.sons.add(son) + template `[]`*(n: Indexable, i: int): Indexable = n.sons[i] template `[]=`*(n: Indexable, i: int; x: Indexable) = n.sons[i] = x diff --git a/compiler/canonicalizer_unused.nim b/compiler/canonicalizer_unused.nim deleted file mode 100644 index de0d0f30e..000000000 --- a/compiler/canonicalizer_unused.nim +++ /dev/null @@ -1,421 +0,0 @@ -# -# -# The Nim Compiler -# (c) Copyright 2015 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module implements the canonalization for the various caching mechanisms. - -import strutils, db_sqlite, md5 - -var db: DbConn - -# We *hash* the relevant information into 128 bit hashes. This should be good -# enough to prevent any collisions. - -type - TUid = distinct MD5Digest - -# For name mangling we encode these hashes via a variant of base64 (called -# 'base64a') and prepend the *primary* identifier to ease the debugging pain. -# So a signature like: -# -# proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) -# -# is mangled into: -# gABI_MTdmOWY5MTQ1MDcyNGQ3ZA -# -# This is a good compromise between correctness and brevity. ;-) - -const - cb64 = [ - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", - "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", - "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "_A", "_B"] - -proc toBase64a(s: cstring, len: int): string = - ## encodes `s` into base64 representation. After `lineLen` characters, a - ## `newline` is added. - result = newStringOfCap(((len + 2) div 3) * 4) - var i = 0 - while i < s.len - 2: - let a = ord(s[i]) - let b = ord(s[i+1]) - let c = ord(s[i+2]) - result.add cb64[a shr 2] - result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)] - result.add cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)] - result.add cb64[c and 0x3F] - inc(i, 3) - if i < s.len-1: - let a = ord(s[i]) - let b = ord(s[i+1]) - result.add cb64[a shr 2] - result.add cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)] - result.add cb64[((b and 0x0F) shl 2)] - elif i < s.len: - let a = ord(s[i]) - result.add cb64[a shr 2] - result.add cb64[(a and 3) shl 4] - -proc toBase64a(u: TUid): string = toBase64a(cast[cstring](u), sizeof(u)) - -proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len) - -proc hashSym(c: var MD5Context, s: PSym) = - if sfAnon in s.flags or s.kind == skGenericParam: - c &= ":anon" - else: - var it = s.owner - while it != nil: - hashSym(c, it) - c &= "." - it = s.owner - c &= s.name.s - -proc hashTree(c: var MD5Context, n: PNode) = - if n == nil: - c &= "\255" - return - var k = n.kind - md5Update(c, cast[cstring](addr(k)), 1) - # we really must not hash line information. 'n.typ' is debatable but - # shouldn't be necessary for now and avoids potential infinite recursions. - case n.kind - of nkEmpty, nkNilLit, nkType: discard - of nkIdent: - c &= n.ident.s - of nkSym: - hashSym(c, n.sym) - of nkCharLit..nkUInt64Lit: - var v = n.intVal - md5Update(c, cast[cstring](addr(v)), sizeof(v)) - of nkFloatLit..nkFloat64Lit: - var v = n.floatVal - md5Update(c, cast[cstring](addr(v)), sizeof(v)) - of nkStrLit..nkTripleStrLit: - c &= n.strVal - else: - for i in 0..') - -proc encodeType(w: PRodWriter, t: PType, result: var string) = - if t == nil: - # nil nodes have to be stored too: - result.add("[]") - return - # we need no surrounding [] here because the type is in a line of its own - if t.kind == tyForward: internalError("encodeType: tyForward") - # for the new rodfile viewer we use a preceding [ so that the data section - # can easily be disambiguated: - result.add('[') - encodeVInt(ord(t.kind), result) - result.add('+') - encodeVInt(t.id, result) - if t.n != nil: - encodeNode(w, unknownLineInfo, t.n, result) - if t.flags != {}: - result.add('$') - encodeVInt(cast[int32](t.flags), result) - if t.callConv != low(t.callConv): - result.add('?') - encodeVInt(ord(t.callConv), result) - if t.owner != nil: - result.add('*') - encodeVInt(t.owner.id, result) - pushSym(w, t.owner) - if t.sym != nil: - result.add('&') - encodeVInt(t.sym.id, result) - pushSym(w, t.sym) - if t.size != - 1: - result.add('/') - encodeVBiggestInt(t.size, result) - if t.align != - 1: - result.add('=') - encodeVInt(t.align, result) - encodeLoc(w, t.loc, result) - for i in 0..= 2: + internalAssert g.config, n[0].kind == nkStrLit and n[1].kind == nkStrLit + case n[0].strVal + of "hint": message(g.config, n.info, hintUser, n[1].strVal) + of "warning": message(g.config, n.info, warnUser, n[1].strVal) + of "error": localError(g.config, n.info, errUser, n[1].strVal) + of "compile": + internalAssert g.config, n.len == 4 and n[2].kind == nkStrLit + let cname = AbsoluteFile n[1].strVal + var cf = Cfile(nimname: splitFile(cname).name, cname: cname, + obj: AbsoluteFile n[2].strVal, + flags: {CfileFlag.External}, + customArgs: n[3].strVal) + extccomp.addExternalFileToCompile(g.config, cf) + of "link": + extccomp.addExternalFileToLink(g.config, AbsoluteFile n[1].strVal) + of "passl": + extccomp.addLinkOption(g.config, n[1].strVal) + of "passc": + extccomp.addCompileOption(g.config, n[1].strVal) + of "localpassc": + extccomp.addLocalCompileOption(g.config, n[1].strVal, toFullPathConsiderDirty(g.config, module.info.fileIndex)) + of "cppdefine": + options.cppDefine(g.config, n[1].strVal) + of "inc": + let destKey = n[1].strVal + let by = n[2].intVal + let v = getOrDefault(g.cacheCounters, destKey) + g.cacheCounters[destKey] = v+by + of "put": + let destKey = n[1].strVal + let key = n[2].strVal + let val = n[3] + if not contains(g.cacheTables, destKey): + g.cacheTables[destKey] = initBTree[string, PNode]() + if not contains(g.cacheTables[destKey], key): + g.cacheTables[destKey].add(key, val) + else: + internalError(g.config, n.info, "key already exists: " & key) + of "incl": + let destKey = n[1].strVal + let val = n[2] + if not contains(g.cacheSeqs, destKey): + g.cacheSeqs[destKey] = newTree(nkStmtList, val) + else: + block search: + for existing in g.cacheSeqs[destKey]: + if exprStructuralEquivalent(existing, val, strictSymEquality=true): + break search + g.cacheSeqs[destKey].add val + of "add": + let destKey = n[1].strVal + let val = n[2] + if not contains(g.cacheSeqs, destKey): + g.cacheSeqs[destKey] = newTree(nkStmtList, val) + else: + g.cacheSeqs[destKey].add val + else: + internalAssert g.config, false + +# of nkMethodDef: +# methodDef(g, n[namePos].sym, fromCache=true) + diff --git a/compiler/ic/rodfiles.nim b/compiler/ic/rodfiles.nim index 725262120..fe71f2441 100644 --- a/compiler/ic/rodfiles.nim +++ b/compiler/ic/rodfiles.nim @@ -26,13 +26,14 @@ type methodsSection pureEnumsSection macroUsagesSection + toReplaySection topLevelSection bodiesSection symsSection typesSection RodFileError* = enum - ok, tooBig, ioFailure, wrongHeader, wrongSection, configMismatch, + ok, tooBig, cannotOpen, ioFailure, wrongHeader, wrongSection, configMismatch, includeFileChanged RodFile* = object @@ -146,10 +147,10 @@ proc loadSection*(f: var RodFile; expected: RodSection) = proc create*(filename: string): RodFile = if not open(result.f, filename, fmWrite): - setError result, ioFailure + setError result, cannotOpen proc close*(f: var RodFile) = close(f.f) proc open*(filename: string): RodFile = if not open(result.f, filename, fmRead): - setError result, ioFailure + setError result, cannotOpen diff --git a/compiler/ic/to_packed_ast.nim b/compiler/ic/to_packed_ast.nim index fe7a60c28..aa3b447b8 100644 --- a/compiler/ic/to_packed_ast.nim +++ b/compiler/ic/to_packed_ast.nim @@ -26,9 +26,9 @@ type definedSymbols: string includes: seq[(LitId, string)] # first entry is the module filename itself imports: seq[LitId] # the modules this module depends on + toReplay: PackedTree # pragmas and VM specific state to replay. topLevel*: PackedTree # top level statements bodies*: PackedTree # other trees. Referenced from typ.n and sym.ast by their position. - hidden*: PackedTree # instantiated generics and other trees not directly in the source code. #producedGenerics*: Table[GenericKey, SymId] exports*: seq[(LitId, int32)] reexports*: seq[(LitId, PackedItemId)] @@ -39,7 +39,7 @@ type cfg: PackedConfig PackedEncoder* = object - m: PackedModule + #m*: PackedModule thisModule*: int32 lastFile*: FileIndex # remember the last lookup entry. lastLit*: LitId @@ -64,12 +64,12 @@ proc definedSymbolsAsString(config: ConfigRef): string = result.add ' ' result.add d -proc rememberConfig(c: var PackedEncoder; config: ConfigRef; pc: PackedConfig) = - c.m.definedSymbols = definedSymbolsAsString(config) +proc rememberConfig(c: var PackedEncoder; m: var PackedModule; config: ConfigRef; pc: PackedConfig) = + m.definedSymbols = definedSymbolsAsString(config) #template rem(x) = # c.m.cfg.x = config.x #primConfigFields rem - c.m.cfg = pc + m.cfg = pc proc configIdentical(m: PackedModule; config: ConfigRef): bool = result = m.definedSymbols == definedSymbolsAsString(config) @@ -93,7 +93,7 @@ proc hashFileCached(conf: ConfigRef; fileIdx: FileIndex): string = result = $secureHashFile(fullpath) msgs.setHash(conf, fileIdx, result) -proc toLitId(x: FileIndex; c: var PackedEncoder): LitId = +proc toLitId(x: FileIndex; c: var PackedEncoder; m: var PackedModule): LitId = ## store a file index as a literal if x == c.lastFile: result = c.lastLit @@ -101,7 +101,7 @@ proc toLitId(x: FileIndex; c: var PackedEncoder): LitId = result = c.filenames.getOrDefault(x) if result == LitId(0): let p = msgs.toFullPath(c.config, x) - result = getOrIncl(c.m.sh.strings, p) + result = getOrIncl(m.sh.strings, p) c.filenames[x] = result c.lastFile = x c.lastLit = result @@ -116,13 +116,13 @@ proc includesIdentical(m: var PackedModule; config: ConfigRef): bool = return false result = true -proc initEncoder*(c: var PackedEncoder; m: PSym; config: ConfigRef; pc: PackedConfig) = +proc initEncoder*(c: var PackedEncoder; m: var PackedModule; moduleSym: PSym; config: ConfigRef; pc: PackedConfig) = ## setup a context for serializing to packed ast - c.m.sh = Shared() - c.thisModule = m.itemId.module + m.sh = Shared() + c.thisModule = moduleSym.itemId.module c.config = config - c.m.bodies = newTreeFrom(c.m.topLevel) - c.m.hidden = newTreeFrom(c.m.topLevel) + m.bodies = newTreeFrom(m.topLevel) + m.toReplay = newTreeFrom(m.topLevel) let thisNimFile = FileIndex c.thisModule var h = msgs.getHash(config, thisNimFile) @@ -132,90 +132,91 @@ proc initEncoder*(c: var PackedEncoder; m: PSym; config: ConfigRef; pc: PackedCo # For NimScript compiler API support the main Nim file might be from a stream. h = $secureHashFile(fullpath) msgs.setHash(config, thisNimFile, h) - c.m.includes.add((toLitId(thisNimFile, c), h)) # the module itself + m.includes.add((toLitId(thisNimFile, c, m), h)) # the module itself - rememberConfig(c, config, pc) + rememberConfig(c, m, config, pc) -proc addIncludeFileDep*(c: var PackedEncoder; f: FileIndex) = - c.m.includes.add((toLitId(f, c), hashFileCached(c.config, f))) +proc addIncludeFileDep*(c: var PackedEncoder; m: var PackedModule; f: FileIndex) = + m.includes.add((toLitId(f, c, m), hashFileCached(c.config, f))) -proc addImportFileDep*(c: var PackedEncoder; f: FileIndex) = - c.m.imports.add toLitId(f, c) +proc addImportFileDep*(c: var PackedEncoder; m: var PackedModule; f: FileIndex) = + m.imports.add toLitId(f, c, m) -proc addExported*(c: var PackedEncoder; s: PSym) = - let nameId = getOrIncl(c.m.sh.strings, s.name.s) - c.m.exports.add((nameId, s.itemId.item)) +proc addExported*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + let nameId = getOrIncl(m.sh.strings, s.name.s) + m.exports.add((nameId, s.itemId.item)) -proc addConverter*(c: var PackedEncoder; s: PSym) = - let nameId = getOrIncl(c.m.sh.strings, s.name.s) - c.m.converters.add((nameId, s.itemId.item)) +proc addConverter*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + let nameId = getOrIncl(m.sh.strings, s.name.s) + m.converters.add((nameId, s.itemId.item)) -proc addTrmacro*(c: var PackedEncoder; s: PSym) = - let nameId = getOrIncl(c.m.sh.strings, s.name.s) - c.m.trmacros.add((nameId, s.itemId.item)) +proc addTrmacro*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + let nameId = getOrIncl(m.sh.strings, s.name.s) + m.trmacros.add((nameId, s.itemId.item)) -proc addPureEnum*(c: var PackedEncoder; s: PSym) = - let nameId = getOrIncl(c.m.sh.strings, s.name.s) +proc addPureEnum*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + let nameId = getOrIncl(m.sh.strings, s.name.s) assert s.kind == skType - c.m.pureEnums.add((nameId, s.itemId.item)) + m.pureEnums.add((nameId, s.itemId.item)) -proc addMethod*(c: var PackedEncoder; s: PSym) = - let nameId = getOrIncl(c.m.sh.strings, s.name.s) +proc addMethod*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + let nameId = getOrIncl(m.sh.strings, s.name.s) discard "to do" # c.m.methods.add((nameId, s.itemId.item)) -proc addReexport*(c: var PackedEncoder; s: PSym) = - let nameId = getOrIncl(c.m.sh.strings, s.name.s) - c.m.reexports.add((nameId, PackedItemId(module: toLitId(s.itemId.module.FileIndex, c), - item: s.itemId.item))) +proc addReexport*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + let nameId = getOrIncl(m.sh.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; s: PSym) = - let nameId = getOrIncl(c.m.sh.strings, s.name.s) - c.m.compilerProcs.add((nameId, s.itemId.item)) +proc addCompilerProc*(c: var PackedEncoder; m: var PackedModule; s: PSym) = + let nameId = getOrIncl(m.sh.strings, s.name.s) + m.compilerProcs.add((nameId, s.itemId.item)) -proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder) -proc toPackedSym*(s: PSym; c: var PackedEncoder): PackedItemId -proc toPackedType(t: PType; c: var PackedEncoder): PackedItemId +proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) +proc toPackedSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId +proc toPackedType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemId -proc flush(c: var PackedEncoder) = +proc flush(c: var PackedEncoder; m: var PackedModule) = ## serialize any pending types or symbols from the context while true: if c.pendingTypes.len > 0: - discard toPackedType(c.pendingTypes.pop, c) + discard toPackedType(c.pendingTypes.pop, c, m) elif c.pendingSyms.len > 0: - discard toPackedSym(c.pendingSyms.pop, c) + discard toPackedSym(c.pendingSyms.pop, c, m) else: break -proc toLitId(x: string; c: var PackedEncoder): LitId = +proc toLitId(x: string; m: var PackedModule): LitId = ## store a string as a literal - result = getOrIncl(c.m.sh.strings, x) + result = getOrIncl(m.sh.strings, x) -proc toLitId(x: BiggestInt; c: var PackedEncoder): LitId = +proc toLitId(x: BiggestInt; m: var PackedModule): LitId = ## store an integer as a literal - result = getOrIncl(c.m.sh.integers, x) + result = getOrIncl(m.sh.integers, x) -proc toPackedInfo(x: TLineInfo; c: var PackedEncoder): PackedLineInfo = - PackedLineInfo(line: x.line, col: x.col, file: toLitId(x.fileIndex, c)) +proc toPackedInfo(x: TLineInfo; c: var PackedEncoder; m: var PackedModule): PackedLineInfo = + PackedLineInfo(line: x.line, col: x.col, file: toLitId(x.fileIndex, c, m)) -proc safeItemId(s: PSym; c: var PackedEncoder): PackedItemId {.inline.} = +proc safeItemId(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId {.inline.} = ## given a symbol, produce an ItemId with the correct properties ## for local or remote symbols, packing the symbol as necessary - if s == nil: + if s == nil or s.kind == skPackage: result = nilItemId - elif s.itemId.module == c.thisModule: - result = PackedItemId(module: LitId(0), item: s.itemId.item) + #elif s.itemId.module == c.thisModule: + # result = PackedItemId(module: LitId(0), item: s.itemId.item) else: - result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c), + assert int(s.itemId.module) >= 0 + result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) -proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder) = +proc addModuleRef(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = ## add a remote symbol reference to the tree - let info = n.info.toPackedInfo(c) - ir.nodes.add PackedNode(kind: nkModuleRef, operand: 2.int32, # 2 kids... - typeId: toPackedType(n.typ, c), info: info) + let info = n.info.toPackedInfo(c, m) + ir.nodes.add PackedNode(kind: nkModuleRef, operand: 3.int32, # spans 3 nodes in total + typeId: toPackedType(n.typ, c, m), info: info) ir.nodes.add PackedNode(kind: nkInt32Lit, info: info, - operand: toLitId(n.sym.itemId.module.FileIndex, c).int32) + operand: toLitId(n.sym.itemId.module.FileIndex, c, m).int32) ir.nodes.add PackedNode(kind: nkInt32Lit, info: info, operand: n.sym.itemId.item) @@ -234,24 +235,25 @@ proc addMissing(c: var PackedEncoder; p: PType) = template storeNode(dest, src, field) = var nodeId: NodeId if src.field != nil: - nodeId = getNodeId(c.m.bodies) - toPackedNode(src.field, c.m.bodies, c) + nodeId = getNodeId(m.bodies) + toPackedNode(src.field, m.bodies, c, m) else: nodeId = emptyNodeId dest.field = nodeId -proc toPackedType(t: PType; c: var PackedEncoder): PackedItemId = +proc toPackedType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemId = ## serialize a ptype if t.isNil: return nilItemId if t.uniqueId.module != c.thisModule: # XXX Assert here that it already was serialized in the foreign module! # it is a foreign type: - return PackedItemId(module: toLitId(t.uniqueId.module.FileIndex, c), item: t.uniqueId.item) + assert t.uniqueId.module >= 0 + return PackedItemId(module: toLitId(t.uniqueId.module.FileIndex, c, m), item: t.uniqueId.item) if not c.typeMarker.containsOrIncl(t.uniqueId.item): - if t.uniqueId.item >= c.m.sh.types.len: - setLen c.m.sh.types, t.uniqueId.item+1 + if t.uniqueId.item >= m.sh.types.len: + setLen m.sh.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, @@ -260,140 +262,148 @@ proc toPackedType(t: PType; c: var PackedEncoder): PackedItemId = for op, s in pairs t.attachedOps: c.addMissing s - p.attachedOps[op] = s.safeItemId(c) + p.attachedOps[op] = s.safeItemId(c, m) - p.typeInst = t.typeInst.toPackedType(c) + p.typeInst = t.typeInst.toPackedType(c, m) for kid in items t.sons: - p.types.add kid.toPackedType(c) + p.types.add kid.toPackedType(c, m) for i, s in items t.methods: c.addMissing s - p.methods.add (i, s.safeItemId(c)) + p.methods.add (i, s.safeItemId(c, m)) c.addMissing t.sym - p.sym = t.sym.safeItemId(c) + p.sym = t.sym.safeItemId(c, m) c.addMissing t.owner - p.owner = t.owner.safeItemId(c) + p.owner = t.owner.safeItemId(c, m) # fill the reserved slot, nothing else: - c.m.sh.types[t.uniqueId.item] = p + m.sh.types[t.uniqueId.item] = p - result = PackedItemId(module: LitId(0), item: t.uniqueId.item) + assert t.itemId.module >= 0 + result = PackedItemId(module: toLitId(t.itemId.module.FileIndex, c, m), item: t.uniqueId.item) -proc toPackedLib(l: PLib; c: var PackedEncoder): PackedLib = +proc toPackedLib(l: PLib; c: var PackedEncoder; m: var PackedModule): PackedLib = ## the plib hangs off the psym via the .annex field if l.isNil: return result.kind = l.kind result.generated = l.generated result.isOverriden = l.isOverriden - result.name = toLitId($l.name, c) + result.name = toLitId($l.name, m) storeNode(result, l, path) -proc toPackedSym*(s: PSym; c: var PackedEncoder): PackedItemId = +proc toPackedSym*(s: PSym; c: var PackedEncoder; m: var PackedModule): PackedItemId = ## serialize a psym if s.isNil: return nilItemId + assert s.itemId.module >= 0 + if s.itemId.module != c.thisModule: # XXX Assert here that it already was serialized in the foreign module! # it is a foreign symbol: - return PackedItemId(module: toLitId(s.itemId.module.FileIndex, c), item: s.itemId.item) + assert s.itemId.module >= 0 + return PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) if not c.symMarker.containsOrIncl(s.itemId.item): - if s.itemId.item >= c.m.sh.syms.len: - setLen c.m.sh.syms, s.itemId.item+1 + if s.itemId.item >= m.sh.syms.len: + setLen m.sh.syms, s.itemId.item+1 - var p = PackedSym(kind: s.kind, flags: s.flags, info: s.info.toPackedInfo(c), magic: s.magic, + var p = PackedSym(kind: s.kind, flags: s.flags, info: s.info.toPackedInfo(c, m), magic: s.magic, position: s.position, offset: s.offset, options: s.options, - name: s.name.s.toLitId(c)) + name: s.name.s.toLitId(m)) storeNode(p, s, ast) storeNode(p, s, constraint) if s.kind in {skLet, skVar, skField, skForVar}: c.addMissing s.guard - p.guard = s.guard.safeItemId(c) + p.guard = s.guard.safeItemId(c, m) p.bitsize = s.bitsize p.alignment = s.alignment - p.externalName = toLitId(if s.loc.r.isNil: "" else: $s.loc.r, c) + p.externalName = toLitId(if s.loc.r.isNil: "" else: $s.loc.r, m) c.addMissing s.typ - p.typ = s.typ.toPackedType(c) + p.typ = s.typ.toPackedType(c, m) c.addMissing s.owner - p.owner = s.owner.safeItemId(c) - p.annex = toPackedLib(s.annex, c) + p.owner = s.owner.safeItemId(c, m) + p.annex = toPackedLib(s.annex, c, m) when hasFFI: - p.cname = toLitId(s.cname, c) + p.cname = toLitId(s.cname, m) # fill the reserved slot, nothing else: - c.m.sh.syms[s.itemId.item] = p + m.sh.syms[s.itemId.item] = p - result = PackedItemId(module: LitId(0), item: s.itemId.item) + assert s.itemId.module >= 0 + result = PackedItemId(module: toLitId(s.itemId.module.FileIndex, c, m), item: s.itemId.item) -proc toSymNode(n: PNode; ir: var PackedTree; c: var PackedEncoder) = +proc toSymNode(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = ## store a local or remote psym reference in the tree assert n.kind == nkSym template s: PSym = n.sym - let id = s.toPackedSym(c).item + let id = s.toPackedSym(c, m).item if s.itemId.module == c.thisModule: # it is a symbol that belongs to the module we're currently # packing: - ir.addSym(id, toPackedInfo(n.info, c)) + ir.addSym(id, toPackedInfo(n.info, c, m)) else: # store it as an external module reference: - addModuleRef(n, ir, c) + addModuleRef(n, ir, c, m) -proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder) = +proc toPackedNode*(n: PNode; ir: var PackedTree; c: var PackedEncoder; m: var PackedModule) = ## serialize a node into the tree if n.isNil: return - let info = toPackedInfo(n.info, c) + let info = toPackedInfo(n.info, c, m) case n.kind of nkNone, nkEmpty, nkNilLit, nkType: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: 0, - typeId: toPackedType(n.typ, c), info: info) + typeId: toPackedType(n.typ, c, m), info: info) of nkIdent: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, - operand: int32 getOrIncl(c.m.sh.strings, n.ident.s), - typeId: toPackedType(n.typ, c), info: info) + operand: int32 getOrIncl(m.sh.strings, n.ident.s), + typeId: toPackedType(n.typ, c, m), info: info) of nkSym: - toSymNode(n, ir, c) + toSymNode(n, ir, c, m) of directIntLit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, operand: int32(n.intVal), - typeId: toPackedType(n.typ, c), info: info) + typeId: toPackedType(n.typ, c, m), info: info) of externIntLit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, - operand: int32 getOrIncl(c.m.sh.integers, n.intVal), - typeId: toPackedType(n.typ, c), info: info) + operand: int32 getOrIncl(m.sh.integers, n.intVal), + typeId: toPackedType(n.typ, c, m), info: info) of nkStrLit..nkTripleStrLit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, - operand: int32 getOrIncl(c.m.sh.strings, n.strVal), - typeId: toPackedType(n.typ, c), info: info) + operand: int32 getOrIncl(m.sh.strings, n.strVal), + typeId: toPackedType(n.typ, c, m), info: info) of nkFloatLit..nkFloat128Lit: ir.nodes.add PackedNode(kind: n.kind, flags: n.flags, - operand: int32 getOrIncl(c.m.sh.floats, n.floatVal), - typeId: toPackedType(n.typ, c), info: info) + operand: int32 getOrIncl(m.sh.floats, n.floatVal), + typeId: toPackedType(n.typ, c, m), info: info) else: let patchPos = ir.prepare(n.kind, n.flags, - toPackedType(n.typ, c), info) + toPackedType(n.typ, c, m), info) for i in 0.. 0: + var decoder = PackedDecoder( + lastModule: int32(-1), + lastLit: LitId(0), + lastFile: FileIndex(-1), + config: conf, + cache: cache) + var p = 0 + while p < m.fromDisk.toReplay.len: + m.module.ast.add loadNodes(decoder, g, int(fileIdx), m.fromDisk.toReplay, NodePos p) + let s = span(m.fromDisk.toReplay, p) + inc p, s proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; fileIdx: FileIndex): bool = @@ -783,7 +815,7 @@ proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache result = true if not result: - setupLookupTables(g[m], conf, cache, fileIdx) + setupLookupTables(g, conf, cache, fileIdx, g[m]) g[m].status = if result: outdated else: loaded else: loadError(err, rod) @@ -791,7 +823,7 @@ proc needsRecompile(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache result = true of loading, loaded: result = false - of outdated: + of outdated, storing: result = true proc moduleFromRodFile*(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; @@ -802,10 +834,11 @@ proc moduleFromRodFile*(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentC else: result = g[int fileIdx].module assert result != nil + loadToReplayNodes(g, conf, cache, fileIdx, g[int fileIdx]) template setupDecoder() {.dirty.} = var decoder = PackedDecoder( - thisModule: int32(module), + lastModule: int32(-1), lastLit: LitId(0), lastFile: FileIndex(-1), config: config, @@ -815,55 +848,70 @@ proc loadProcBody*(config: ConfigRef, cache: IdentCache; g: var PackedModuleGraph; s: PSym): PNode = let mId = s.itemId.module var decoder = PackedDecoder( - thisModule: mId, + lastModule: int32(-1), lastLit: LitId(0), lastFile: FileIndex(-1), config: config, cache: cache) let pos = g[mId].fromDisk.sh.syms[s.itemId.item].ast assert pos != emptyNodeId - result = loadProcBody(decoder, g, g[mId].fromDisk.bodies, NodePos pos) + result = loadProcBody(decoder, g, mId, g[mId].fromDisk.bodies, NodePos pos) + +proc simulateLoadedModule*(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache; + moduleSym: PSym; m: PackedModule) = + # For now only used for heavy debugging. In the future we could use this to reduce the + # compiler's memory consumption. + let idx = moduleSym.position + assert g[idx].status in {storing} + g[idx].status = loaded + assert g[idx].module == moduleSym + setupLookupTables(g, conf, cache, FileIndex(idx), g[idx]) + loadToReplayNodes(g, conf, cache, FileIndex(idx), g[idx]) + +# ---------------- symbol table handling ---------------- type RodIter* = object decoder: PackedDecoder values: seq[PackedItemId] - i: int + i, module: int proc initRodIter*(it: var RodIter; config: ConfigRef, cache: IdentCache; g: var PackedModuleGraph; module: FileIndex; name: PIdent): PSym = it.decoder = PackedDecoder( - thisModule: int32(module), + lastModule: int32(-1), lastLit: LitId(0), lastFile: FileIndex(-1), config: config, cache: cache) it.values = g[int module].iface.getOrDefault(name) it.i = 0 + it.module = int(module) if it.i < it.values.len: - result = loadSym(it.decoder, g, it.values[it.i]) + result = loadSym(it.decoder, g, int(module), it.values[it.i]) inc it.i proc initRodIterAllSyms*(it: var RodIter; config: ConfigRef, cache: IdentCache; g: var PackedModuleGraph; module: FileIndex): PSym = it.decoder = PackedDecoder( - thisModule: int32(module), + lastModule: int32(-1), lastLit: LitId(0), lastFile: FileIndex(-1), config: config, cache: cache) it.values = @[] + it.module = int(module) for v in g[int module].iface.values: it.values.add v it.i = 0 if it.i < it.values.len: - result = loadSym(it.decoder, g, it.values[it.i]) + result = loadSym(it.decoder, g, int(module), it.values[it.i]) inc it.i proc nextRodIter*(it: var RodIter; g: var PackedModuleGraph): PSym = if it.i < it.values.len: - result = loadSym(it.decoder, g, it.values[it.i]) + result = loadSym(it.decoder, g, it.module, it.values[it.i]) inc it.i iterator interfaceSymbols*(config: ConfigRef, cache: IdentCache; @@ -872,7 +920,7 @@ iterator interfaceSymbols*(config: ConfigRef, cache: IdentCache; setupDecoder() let values = g[int module].iface.getOrDefault(name) for pid in values: - let s = loadSym(decoder, g, pid) + let s = loadSym(decoder, g, int(module), pid) assert s != nil yield s @@ -881,5 +929,28 @@ proc interfaceSymbol*(config: ConfigRef, cache: IdentCache; name: PIdent): PSym = setupDecoder() let values = g[int module].iface.getOrDefault(name) - result = loadSym(decoder, g, values[0]) - + result = loadSym(decoder, g, int(module), values[0]) + +# ------------------------- .rod file viewer --------------------------------- + +proc rodViewer*(rodfile: AbsoluteFile; config: ConfigRef, cache: IdentCache) = + var m: PackedModule + if loadRodFile(rodfile, m, config) != ok: + echo "Error: could not load: ", rodfile.string + quit 1 + + when true: + echo "exports:" + for ex in m.exports: + echo " ", m.sh.strings[ex[0]] + assert ex[0] == m.sh.syms[ex[1]].name + # ex[1] int32 + + echo "reexports:" + for ex in m.reexports: + echo " ", m.sh.strings[ex[0]] + # reexports*: seq[(LitId, PackedItemId)] + echo "symbols: ", m.sh.syms.len, " types: ", m.sh.types.len, + " top level nodes: ", m.topLevel.nodes.len, " other nodes: ", m.bodies.nodes.len, + " strings: ", m.sh.strings.len, " integers: ", m.sh.integers.len, + " floats: ", m.sh.floats.len diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim index 9e0fe68fc..c4546b7ed 100644 --- a/compiler/lineinfos.nim +++ b/compiler/lineinfos.nim @@ -279,3 +279,4 @@ proc initMsgConfig*(): MsgConfig = result.filenameToIndexTbl = initTable[string, FileIndex]() result.fileInfos = @[] result.errorOutputs = {eStdOut, eStdErr} + result.filenameToIndexTbl["???"] = FileIndex(-1) diff --git a/compiler/macrocacheimpl.nim b/compiler/macrocacheimpl.nim index 365497e31..c869c2289 100644 --- a/compiler/macrocacheimpl.nim +++ b/compiler/macrocacheimpl.nim @@ -9,71 +9,36 @@ ## This module implements helpers for the macro cache. -import lineinfos, ast, modulegraphs, vmdef +import lineinfos, ast, vmdef + +proc append(c: PCtx; n: PNode) = + c.vmstateDiff.add((c.module, n)) proc recordInc*(c: PCtx; info: TLineInfo; key: string; by: BiggestInt) = - var recorded = newNodeI(nkCommentStmt, info) + var recorded = newNodeI(nkReplayAction, info) recorded.add newStrNode("inc", info) recorded.add newStrNode(key, info) recorded.add newIntNode(nkIntLit, by) - c.graph.recordStmt(c.graph, c.module, recorded) + c.append(recorded) proc recordPut*(c: PCtx; info: TLineInfo; key: string; k: string; val: PNode) = - var recorded = newNodeI(nkCommentStmt, info) + var recorded = newNodeI(nkReplayAction, info) recorded.add newStrNode("put", info) recorded.add newStrNode(key, info) recorded.add newStrNode(k, info) recorded.add copyTree(val) - c.graph.recordStmt(c.graph, c.module, recorded) + c.append(recorded) proc recordAdd*(c: PCtx; info: TLineInfo; key: string; val: PNode) = - var recorded = newNodeI(nkCommentStmt, info) + var recorded = newNodeI(nkReplayAction, info) recorded.add newStrNode("add", info) recorded.add newStrNode(key, info) recorded.add copyTree(val) - c.graph.recordStmt(c.graph, c.module, recorded) + c.append(recorded) proc recordIncl*(c: PCtx; info: TLineInfo; key: string; val: PNode) = - var recorded = newNodeI(nkCommentStmt, info) + var recorded = newNodeI(nkReplayAction, info) recorded.add newStrNode("incl", info) recorded.add newStrNode(key, info) recorded.add copyTree(val) - c.graph.recordStmt(c.graph, c.module, recorded) - -when false: - proc genCall3(g: ModuleGraph; m: TMagic; s: string; a, b, c: PNode): PNode = - newTree(nkStaticStmt, newTree(nkCall, createMagic(g, s, m).newSymNode, a, b, c)) - - proc genCall2(g: ModuleGraph; m: TMagic; s: string; a, b: PNode): PNode = - newTree(nkStaticStmt, newTree(nkCall, createMagic(g, s, m).newSymNode, a, b)) - - template nodeFrom(s: string): PNode = - var res = newStrNode(s, info) - res.typ = getSysType(g, info, tyString) - res - - template nodeFrom(i: BiggestInt): PNode = - var res = newIntNode(i, info) - res.typ = getSysType(g, info, tyInt) - res - - template nodeFrom(n: PNode): PNode = copyTree(n) - - template record(call) = - g.recordStmt(g, c.module, call) - - proc recordInc*(c: PCtx; info: TLineInfo; key: string; by: BiggestInt) = - let g = c.graph - record genCall2(mNccInc, "inc", nodeFrom key, nodeFrom by) - - proc recordPut*(c: PCtx; info: TLineInfo; key: string; k: string; val: PNode) = - let g = c.graph - record genCall3(mNctPut, "[]=", nodeFrom key, nodeFrom k, nodeFrom val) - - proc recordAdd*(c: PCtx; info: TLineInfo; key: string; val: PNode) = - let g = c.graph - record genCall2(mNcsAdd, "add", nodeFrom key, nodeFrom val) - - proc recordIncl*(c: PCtx; info: TLineInfo; key: string; val: PNode) = - let g = c.graph - record genCall2(mNcsIncl, "incl", nodeFrom key, nodeFrom val) + c.append(recorded) diff --git a/compiler/main.nim b/compiler/main.nim index 438f90ba6..184998738 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -21,6 +21,8 @@ import modules, modulegraphs, tables, lineinfos, pathutils, vmprofiler +from ic / to_packed_ast import rodViewer + when not defined(leanCompiler): import jsgen, docgen, docgen2 @@ -158,6 +160,10 @@ proc commandScan(cache: IdentCache, config: ConfigRef) = else: rawMessage(config, errGenerated, "cannot open file: " & f.string) +proc commandView(graph: ModuleGraph) = + let f = toAbsolute(mainCommandArg(graph.config), AbsoluteDir getCurrentDir()).addFileExt(RodExt) + rodViewer(f, graph.config, graph.cache) + const PrintRopeCacheStats = false @@ -311,10 +317,10 @@ proc mainCommand*(graph: ModuleGraph) = of cmdParse: wantMainModule(conf) discard parseFile(conf.projectMainIdx, cache, conf) - of cmdScan: + of cmdRod: wantMainModule(conf) - commandScan(cache, conf) - msgWriteln(conf, "Beware: Indentation tokens depend on the parser's state!") + commandView(graph) + #msgWriteln(conf, "Beware: Indentation tokens depend on the parser's state!") of cmdInteractive: commandInteractive(graph) of cmdNimscript: if conf.projectIsCmd or conf.projectIsStdin: discard diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index ab3ef5ab8..9b174d281 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -29,13 +29,14 @@ type ModuleGraph* = ref object ifaces*: seq[Iface] ## indexed by int32 fileIdx - packed: PackedModuleGraph + packed*: PackedModuleGraph startupPackedConfig*: PackedConfig packageSyms*: TStrTable deps*: IntSet # the dependency graph or potentially its transitive closure. importDeps*: Table[FileIndex, seq[FileIndex]] # explicit import module dependencies suggestMode*: bool # whether we are in nimsuggest mode or not. invalidTransitiveClosure: bool + systemModuleComplete*: bool inclToMod*: Table[FileIndex, FileIndex] # mapping of include file to the # first module that included it importStack*: seq[FileIndex] # The current import stack. Used for detecting recursive @@ -61,7 +62,6 @@ type symBodyHashes*: Table[int, SigHash] # symId to digest mapping importModuleCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PSym {.nimcall.} includeFileCallback*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex): PNode {.nimcall.} - recordStmt*: proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.} cacheSeqs*: Table[string, PNode] # state that is shared to support the 'macrocache' API cacheCounters*: Table[string, BiggestInt] cacheTables*: Table[string, BTree[string, PNode]] @@ -128,6 +128,11 @@ template semtab*(m: PSym; g: ModuleGraph): TStrTable = proc cachedModule(g: ModuleGraph; m: PSym): bool {.inline.} = m.position < g.packed.len and g.packed[m.position].status == loaded +proc simulateCachedModule*(g: ModuleGraph; moduleSym: PSym; m: PackedModule) = + when false: + echo "simulating ", moduleSym.name.s, " ", moduleSym.position + simulateLoadedModule(g.packed, g.config, g.cache, moduleSym, m) + type ModuleIter* = object fromRod: bool @@ -231,6 +236,10 @@ proc registerModule*(g: ModuleGraph; m: PSym) = if m.position >= g.ifaces.len: setLen(g.ifaces, m.position + 1) + + if m.position >= g.packed.len: + setLen(g.packed, m.position + 1) + g.ifaces[m.position] = Iface(module: m, converters: @[], patterns: @[]) initStrTable(g.ifaces[m.position].interf) @@ -253,8 +262,6 @@ proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph = result.opNot = createMagic(result, "not", mNot) result.opContains = createMagic(result, "contains", mInSet) result.emptyNode = newNode(nkEmpty) - result.recordStmt = proc (graph: ModuleGraph; m: PSym; n: PNode) {.nimcall.} = - discard result.cacheSeqs = initTable[string, PNode]() result.cacheCounters = initTable[string, BiggestInt]() result.cacheTables = initTable[string, BTree[string, PNode]]() @@ -334,14 +341,14 @@ proc isDirty*(g: ModuleGraph; m: PSym): bool = proc getBody*(g: ModuleGraph; s: PSym): PNode {.inline.} = result = s.ast[bodyPos] - if result == nil and g.config.symbolFiles in {readOnlySf, v2Sf}: + if result == nil and g.config.symbolFiles in {readOnlySf, v2Sf, stressTest}: result = loadProcBody(g.config, g.cache, g.packed, s) s.ast[bodyPos] = result assert result != nil proc moduleFromRodFile*(g: ModuleGraph; fileIdx: FileIndex): PSym = ## Returns 'nil' if the module needs to be recompiled. - if g.config.symbolFiles in {readOnlySf, v2Sf}: + if g.config.symbolFiles in {readOnlySf, v2Sf, stressTest}: result = moduleFromRodFile(g.packed, g.config, g.cache, fileIdx) proc configComplete*(g: ModuleGraph) = diff --git a/compiler/modules.nim b/compiler/modules.nim index deb0174b5..aa7e56119 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -14,6 +14,8 @@ import idents, lexer, passes, syntaxes, llstream, modulegraphs, lineinfos, pathutils, tables +import ic / replayer + proc resetSystemArtifacts*(g: ModuleGraph) = magicsys.resetSysTypes(g) @@ -108,7 +110,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P processModuleAux() else: partialInitModule(result, graph, fileIdx, filename) - # XXX replay the pragmas here! + replayStateChanges(result, graph) elif graph.isDirty(result): result.flags.excl sfDirty # reset module fields: diff --git a/compiler/options.nim b/compiler/options.nim index 6cdb5db63..4861defeb 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -124,7 +124,7 @@ type cmdTcc # run the project via TCC backend cmdCheck # semantic checking for whole project cmdParse # parse a single file (for debugging) - cmdScan # scan a single file (for debugging) + cmdRod # .rod to some text representation (for debugging) cmdIdeTools # ide tools (e.g. nimsuggest) cmdNimscript # evaluate nimscript cmdDoc0 @@ -190,7 +190,7 @@ type ## are not anymore. SymbolFilesOption* = enum - disabledSf, writeOnlySf, readOnlySf, v2Sf + disabledSf, writeOnlySf, readOnlySf, v2Sf, stressTest TSystemCC* = enum ccNone, ccGcc, ccNintendoSwitch, ccLLVM_Gcc, ccCLang, ccBcc, ccVcc, diff --git a/compiler/passes.nim b/compiler/passes.nim index e3885540e..11799b122 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -108,7 +108,8 @@ proc prepareConfigNotes(graph: ModuleGraph; module: PSym) = graph.config.notes = graph.config.foreignPackageNotes proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} = - result = module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange") + result = true + #module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange") proc partOfStdlib(x: PSym): bool = var it = x.owner diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index c1627fe0c..1404959c6 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -96,10 +96,10 @@ proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords; isStatement: bool = false) proc recordPragma(c: PContext; n: PNode; args: varargs[string]) = - var recorded = newNodeI(nkCommentStmt, n.info) + var recorded = newNodeI(nkReplayAction, n.info) for i in 0..args.high: recorded.add newStrNode(args[i], n.info) - c.graph.recordStmt(c.graph, c.module, recorded) + addPragmaComputation(c, recorded) const errStringLiteralExpected = "string literal expected" @@ -705,7 +705,7 @@ proc markCompilerProc(c: PContext; s: PSym) = incl(s.flags, sfUsed) registerCompilerProc(c.graph, s) if c.config.symbolFiles != disabledSf: - addCompilerProc(c.encoder, s) + addCompilerProc(c.encoder, c.packedRepr, s) proc deprecatedStmt(c: PContext; outerPragma: PNode) = let pragma = outerPragma[1] diff --git a/compiler/semdata.nim b/compiler/semdata.nim index f2f074447..583077fbf 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -268,15 +268,25 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext = result.typesWithOps = @[] result.features = graph.config.features if graph.config.symbolFiles != disabledSf: - initEncoder result.encoder, module, graph.config, graph.startupPackedConfig + let id = module.position + assert graph.packed[id].status in {undefined, outdated} + graph.packed[id].status = storing + graph.packed[id].module = module + initEncoder result.encoder, graph.packed[id].fromDisk, module, graph.config, graph.startupPackedConfig + +template packedRepr*(c): untyped = c.graph.packed[c.module.position].fromDisk proc addIncludeFileDep*(c: PContext; f: FileIndex) = if c.config.symbolFiles != disabledSf: - addIncludeFileDep(c.encoder, f) + addIncludeFileDep(c.encoder, c.packedRepr, f) proc addImportFileDep*(c: PContext; f: FileIndex) = if c.config.symbolFiles != disabledSf: - addImportFileDep(c.encoder, f) + addImportFileDep(c.encoder, c.packedRepr, f) + +proc addPragmaComputation*(c: PContext; n: PNode) = + if c.config.symbolFiles != disabledSf: + addPragmaComputation(c.encoder, c.packedRepr, n) proc inclSym(sq: var seq[PSym], s: PSym) = for i in 0..