diff --git a/compiler/icnif/icniftags.nim b/compiler/icnif/icniftags.nim index 2dc7d3fa34..f3c1fe3785 100644 --- a/compiler/icnif/icniftags.nim +++ b/compiler/icnif/icniftags.nim @@ -6,3 +6,5 @@ let typeIdTag* = registerTag("typeId") typeTag* = registerTag("t") sonsTag* = registerTag("sons") + + modIdTag* = registerTag("modId") diff --git a/compiler/icnif/nifdecoder.nim b/compiler/icnif/nifdecoder.nim index f658f4ba6a..f0a36f5441 100644 --- a/compiler/icnif/nifdecoder.nim +++ b/compiler/icnif/nifdecoder.nim @@ -8,6 +8,7 @@ type graph: ModuleGraph symbols: Table[int, PSym] types: Table[int, PType] + modules: Table[int, FileIndex] # maps module id in NIF to FileIndex of the module proc nodeKind(n: Cursor): TNodeKind {.inline.} = assert n.kind == ParLe @@ -58,6 +59,23 @@ when false: else: expectTag(n, id) +proc fromNifModuleId(c: var DecodeContext; n: var Cursor): FileIndex = + if n.kind == ParLe: + expectTag n, modIdTag + incExpect n, IntLit + let id = pool.integers[n.intId] + incExpect n, StringLit + let path = pool.strings[n.litId].AbsoluteFile + result = fileInfoIdx(c.graph.config, path) + assert id notin c.modules + c.modules[id] = result + inc n + skipParRi n + elif n.kind == IntLit: + let id = pool.integers[n.intId] + result = c.modules[id] + inc n + proc fromNifSymbol(c: var DecodeContext; n: var Cursor): PSym proc fromNifType(c: var DecodeContext; n: var Cursor): PType proc fromNif(c: var DecodeContext; n: var Cursor): PNode @@ -68,7 +86,9 @@ proc fromNifSymDef(c: var DecodeContext; n: var Cursor): PSym = let id = pool.integers[n.intId] incExpect n, Ident let ident = c.graph.cache.getIdent(pool.strings[n.litId]) - incExpect n, IntLit + inc n + let itemIdModule = c.fromNifModuleId(n).int32 + expect n, IntLit let itemId = pool.integers[n.intId].int32 incExpect n, ParLe let kind = parseSymKind(pool.tags[n.tagId]) @@ -79,17 +99,17 @@ proc fromNifSymDef(c: var DecodeContext; n: var Cursor): PSym = let flags = if n.kind == Ident: pool.strings[n.litId].parseSymFlags else: {} inc n var position = if kind == skModule: - expect n, StringLit - let path = pool.strings[n.litId].AbsoluteFile - fileInfoIdx(c.graph.config, path).int + c.fromNifModuleId(n).int else: expect n, IntLit - pool.integers[n.intId] - incExpect n, IntLit + let p = pool.integers[n.intId] + inc n + p + expect n, IntLit let disamb = pool.integers[n.intId].int32 inc n - result = PSym(itemId: ItemId(module: 0, item: itemId), + result = PSym(itemId: ItemId(module: itemIdModule, item: itemId), kind: kind, name: ident, flags: flags, @@ -116,7 +136,9 @@ proc fromNifTypeDef(c: var DecodeContext; n: var Cursor): PType = expectTag n, typeIdTag incExpect n, IntLit let id = pool.integers[n.intId] - incExpect n, IntLit + inc n + let itemIdModule = c.fromNifModuleId(n).int32 + expect n, IntLit let itemId = pool.integers[n.intId].int32 incExpect n, Ident let kind = parseTypeKind(pool.strings[n.litId]) @@ -124,7 +146,7 @@ proc fromNifTypeDef(c: var DecodeContext; n: var Cursor): PType = let flags = if n.kind == Ident: pool.strings[n.litId].parseTypeFlags else: {} inc n - result = PType(itemId: ItemId(module: 0, item: itemId), + result = PType(itemId: ItemId(module: itemIdModule, item: itemId), kind: kind, flags: flags) assert id notin c.types diff --git a/compiler/icnif/nifencoder.nim b/compiler/icnif/nifencoder.nim index c323e96541..69c16af5c7 100644 --- a/compiler/icnif/nifencoder.nim +++ b/compiler/icnif/nifencoder.nim @@ -8,6 +8,7 @@ type conf: ConfigRef decodedSyms: HashSet[PSym] decodedTypes: HashSet[PType] + decodedFileIndices: HashSet[FileIndex] dest: TokenBuf proc initEncodeContext(conf: ConfigRef): EncodeContext = @@ -30,6 +31,18 @@ proc writeFlags[E](dest: var TokenBuf; flags: set[E]) = else: dest.addDotToken +proc toNifModuleId(c: var EncodeContext; moduleId: int) = + # `ItemId.module` in PType and PSym (and `PSym.position` when it is skModule) are module's FileIndex + # but it cannot be directly encoded as the uniqueness of it can broke + # if any import/include statements are changed. + if not c.decodedFileIndices.containsOrIncl(moduleId.FileIndex): + c.dest.buildTree modIdTag: + c.dest.addIntLit moduleId + let path = toFullPath(c.conf, moduleId.FileIndex) + c.dest.addStrLit path + else: + c.dest.addIntLit moduleId + proc toNif(c: var EncodeContext; sym: PSym) proc toNif(c: var EncodeContext; typ: PType) proc toNif(c: var EncodeContext; n: PNode) @@ -38,17 +51,14 @@ proc toNifDef(c: var EncodeContext; sym: PSym) = c.dest.buildTree symIdTag: c.dest.addIntLit sym.id c.dest.addIdent sym.name.s + c.toNifModuleId sym.itemId.module c.dest.addIntLit sym.itemId.item c.dest.buildTree sym.kind.toNifTag: # TODO: add kind specific data discard c.dest.writeFlags sym.flags if sym.kind == skModule: - # position is module's FileIndex but it cannot be directly encoded - # as the uniqueness of it can broke - # if any import/include statements are changed. - let path = toFullPath(c.conf, sym.position.FileIndex) - c.dest.addStrLit path + c.toNifModuleId sym.position else: c.dest.addIntLit sym.position c.dest.addIntLit sym.disamb @@ -60,6 +70,7 @@ proc toNifDef(c: var EncodeContext; sym: PSym) = proc toNifDef(c: var EncodeContext; typ: PType) = c.dest.buildTree typeIdTag: c.dest.addIntLit typ.id + c.toNifModuleId typ.itemId.module c.dest.addIntLit typ.itemId.item c.dest.addIdent toNifTag(typ.kind) c.dest.writeFlags typ.flags @@ -75,8 +86,6 @@ proc toNifDef(c: var EncodeContext; typ: PType) = c.toNif typ.owner c.toNif typ.sym -#include nifencodertypes - proc toNif(c: var EncodeContext; sym: PSym) = if sym == nil: c.dest.addDotToken() diff --git a/tests/icnif/tencode_node2node.nim b/tests/icnif/tencode_node2node.nim index a920744404..21875c1623 100644 --- a/tests/icnif/tencode_node2node.nim +++ b/tests/icnif/tencode_node2node.nim @@ -81,21 +81,33 @@ proc eql(x, y: TLoc): bool = else: result = true +proc eqlFileIndex(x, y: int; c: EqlContext): bool = + let xpath = c.confX.toFullPath(x.FileIndex) + let ypath = c.confY.toFullPath(y.FileIndex) + if xpath != ypath: + echo "file index mismatch: ", xpath, "/", ypath + result = false + else: + result = true + proc eqlSymPos(x, y: PSym; c: EqlContext): bool = if x.kind == skModule: - let xpath = c.confX.toFullPath(x.position.FileIndex) - let ypath = c.confY.toFullPath(y.position.FileIndex) - if xpath != ypath: - echo "symbol position mismatch: ", xpath, "/", ypath - result = false - else: - result = true + result = eqlFileIndex(x.position, y.position, c) elif x.position != y.position: echo "symbol position mismatch: ", x.position, "/", y.position result = false else: result = true +proc eqlItemId(x, y: ItemId; c: EqlContext): bool = + if x.item != y.item: + echo "itemId.item mismatch: ", x.item, "/", y.item + result = false + elif not eqlFileIndex(x.module, y.module, c): + result = false + else: + result = true + proc eql(x, y: PSym; c: var EqlContext): bool = if x == nil and y == nil: result = true @@ -105,8 +117,8 @@ proc eql(x, y: PSym; c: var EqlContext): bool = elif x.name.s != y.name.s: echo "symbol name mismatch: ", x.name.s, "/", y.name.s result = false - elif x.itemId.item != y.itemId.item: - echo "symbol itemId.item mismatch: ", x.itemId.item, "/", y.itemId.item + elif not eqlItemId(x.itemId, y.itemId, c): + echo "symbol itemId mismatch" result = false elif x.kind != y.kind: echo "symbol kind mismatch: ", x.kind, "/", y.kind @@ -146,8 +158,8 @@ proc eql(x, y: PType; c: var EqlContext): bool = elif x == nil or y == nil: echo "type is missing" result = false - elif x.itemId.item != y.itemId.item: - echo "type itemId.item mismatch: ", x.itemId.item, "/", y.itemId.item + elif not eqlItemId(x.itemId, y.itemId, c): + echo "type itemId mismatch" result = false elif x.kind != y.kind: echo "type kind mismatch: ", x.kind, "/", y.kind