From c39a6241652b19dc470bc534698629d36697f952 Mon Sep 17 00:00:00 2001 From: Araq Date: Tue, 16 Dec 2025 09:31:46 +0100 Subject: [PATCH] progress --- compiler/ast2nif.nim | 40 ++++++++++++++++++++------------------- compiler/astdef.nim | 1 + compiler/modulegraphs.nim | 16 ++++++++++++---- compiler/pipelines.nim | 2 +- 4 files changed, 35 insertions(+), 24 deletions(-) diff --git a/compiler/ast2nif.nim b/compiler/ast2nif.nim index 7a550db021..57a30a8e0d 100644 --- a/compiler/ast2nif.nim +++ b/compiler/ast2nif.nim @@ -698,8 +698,10 @@ proc writeNifModule*(config: ConfigRef; thisModule: int32; n: PNode; for action in replayActions: writeNode(w, content, action) content.addParRi() + # Only write ops that belong to this module for op in opsLog: - writeOp(w, content, op) + if op.module == thisModule.int: + writeOp(w, content, op) w.writeToplevelNode content, n @@ -1422,8 +1424,9 @@ proc resolveSym(c: var DecodeContext; symAsStr: string; alsoConsiderPrivate: boo proc resolveHookSym*(c: var DecodeContext; symId: nifstreams.SymId): PSym = ## Resolves a hook SymId to PSym. + ## Hook symbols are often private (generated =destroy, =wasMoved, etc.) let symAsStr = pool.syms[symId] - result = resolveSym(c, symAsStr, false) + result = resolveSym(c, symAsStr, true) proc tryResolveCompilerProc*(c: var DecodeContext; name: string; moduleFileIdx: FileIndex): PSym = ## Tries to resolve a compiler proc from a module by checking the NIF index. @@ -1432,7 +1435,7 @@ proc tryResolveCompilerProc*(c: var DecodeContext; name: string; moduleFileIdx: let symName = name & ".0." & suffix result = resolveSym(c, symName, true) -proc loadLogOp(c: var DecodeContext; logOps: var seq[LogEntry]; s: var Stream; kind: LogEntryKind; op: TTypeAttachedOp): PackedToken = +proc loadLogOp(c: var DecodeContext; logOps: var seq[LogEntry]; s: var Stream; kind: LogEntryKind; op: TTypeAttachedOp; module: int): PackedToken = result = next(s) var key = "" if result.kind == StringLit: @@ -1443,9 +1446,8 @@ proc loadLogOp(c: var DecodeContext; logOps: var seq[LogEntry]; s: var Stream; k if result.kind == Symbol: let sym = resolveHookSym(c, result.symId) if sym != nil: - logOps.add LogEntry(kind: kind, op: op, key: key, sym: sym) - else: - raiseAssert "symbol not found: " & pool.syms[result.symId] + logOps.add LogEntry(kind: kind, op: op, module: module, key: key, sym: sym) + # else: symbol not indexed, skip this hook entry result = next(s) if result.kind == ParRi: result = next(s) @@ -1479,7 +1481,7 @@ 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]): PNode = +proc processTopLevel(c: var DecodeContext; s: var Stream; loadFullAst: bool; suffix: string; logOps: var seq[LogEntry]; module: int): PNode = result = newNode(nkStmtList) var localSyms = initTable[string, PSym]() @@ -1504,27 +1506,27 @@ proc processTopLevel(c: var DecodeContext; s: var Stream; loadFullAst: bool; suf else: raiseAssert "expected ParRi but got " & $t.kind elif t.tagId == repConverterTag: - t = loadLogOp(c, logOps, s, ConverterEntry, attachedTrace) + t = loadLogOp(c, logOps, s, ConverterEntry, attachedTrace, module) elif t.tagId == repDestroyTag: - t = loadLogOp(c, logOps, s, HookEntry, attachedDestructor) + t = loadLogOp(c, logOps, s, HookEntry, attachedDestructor, module) elif t.tagId == repWasMovedTag: - t = loadLogOp(c, logOps, s, HookEntry, attachedWasMoved) + t = loadLogOp(c, logOps, s, HookEntry, attachedWasMoved, module) elif t.tagId == repCopyTag: - t = loadLogOp(c, logOps, s, HookEntry, attachedAsgn) + t = loadLogOp(c, logOps, s, HookEntry, attachedAsgn, module) elif t.tagId == repSinkTag: - t = loadLogOp(c, logOps, s, HookEntry, attachedSink) + t = loadLogOp(c, logOps, s, HookEntry, attachedSink, module) elif t.tagId == repDupTag: - t = loadLogOp(c, logOps, s, HookEntry, attachedDup) + t = loadLogOp(c, logOps, s, HookEntry, attachedDup, module) elif t.tagId == repTraceTag: - t = loadLogOp(c, logOps, s, HookEntry, attachedTrace) + t = loadLogOp(c, logOps, s, HookEntry, attachedTrace, module) elif t.tagId == repDeepCopyTag: - t = loadLogOp(c, logOps, s, HookEntry, attachedDeepCopy) + t = loadLogOp(c, logOps, s, HookEntry, attachedDeepCopy, module) elif t.tagId == repEnumToStrTag: - t = loadLogOp(c, logOps, s, EnumToStrEntry, attachedTrace) + t = loadLogOp(c, logOps, s, EnumToStrEntry, attachedTrace, module) elif t.tagId == repMethodTag: - t = loadLogOp(c, logOps, s, MethodEntry, attachedTrace) + t = loadLogOp(c, logOps, s, MethodEntry, attachedTrace, module) #elif t.tagId == repClassTag: - # t = loadLogOp(c, logOps, s, ClassEntry, attachedTrace) + # t = loadLogOp(c, logOps, s, ClassEntry, attachedTrace, module) elif t.tagId == includeTag or t.tagId == importTag: t = skipTree(s) elif loadFullAst: @@ -1560,7 +1562,7 @@ 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) + result = processTopLevel(c, s[], loadFullAst, suffix, logOps, f.int) else: result = newNode(nkStmtList) diff --git a/compiler/astdef.nim b/compiler/astdef.nim index 27761fd81b..411fbcd71c 100644 --- a/compiler/astdef.nim +++ b/compiler/astdef.nim @@ -1001,6 +1001,7 @@ type kind*: LogEntryKind op*: TTypeAttachedOp isGeneric*: bool + module*: int # Which module this entry belongs to key*: string sym*: PSym diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 577e3a9fa5..cac48aae55 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -369,7 +369,10 @@ proc getAttachedOp*(g: ModuleGraph; t: PType; op: TTypeAttachedOp): PSym = if g.attachedOps[op].contains(t.itemId): result = resolveAttachedOp(g, g.attachedOps[op][t.itemId]) else: - result = nil + # Fall back to key-based lookup for NIF-loaded hooks + let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback) + result = g.loadedOps[op].getOrDefault(key) + #echo "fallback ", key, " ", op, " ", result proc setAttachedOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) = ## we also need to record this to the packed module. @@ -378,7 +381,10 @@ proc setAttachedOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; # Use key-based deduplication for opsLog because different type objects # (e.g. canon vs orig) can have different itemIds but same structural key if key notin g.loadedOps[op]: - g.opsLog.add LogEntry(kind: HookEntry, op: op, key: key, sym: value) + # Hooks should be written to the module where the type is defined, + # not the module that triggered the registration + let ownerModule = if t.sym != nil: t.sym.itemId.module.int else: module + g.opsLog.add LogEntry(kind: HookEntry, op: op, module: ownerModule, key: key, sym: value) g.loadedOps[op][key] = value g.attachedOps[op][t.itemId] = LazySym(sym: value) @@ -429,7 +435,8 @@ proc getToStringProc*(g: ModuleGraph; t: PType): PSym = proc setToStringProc*(g: ModuleGraph; t: PType; value: PSym) = g.enumToStringProcs[t.itemId] = LazySym(sym: value) let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback) - g.opsLog.add LogEntry(kind: EnumToStrEntry, key: key, sym: value) + let ownerModule = if t.sym != nil: t.sym.itemId.module.int else: value.itemId.module.int + g.opsLog.add LogEntry(kind: EnumToStrEntry, module: ownerModule, key: key, sym: value) iterator methodsForGeneric*(g: ModuleGraph; t: PType): (int, PSym) = if g.methodsPerGenericType.contains(t.itemId): @@ -439,7 +446,8 @@ iterator methodsForGeneric*(g: ModuleGraph; t: PType): (int, PSym) = proc addMethodToGeneric*(g: ModuleGraph; module: int; t: PType; col: int; m: PSym) = g.methodsPerGenericType.mgetOrPut(t.itemId, @[]).add (col, LazySym(sym: m)) let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback) - g.opsLog.add LogEntry(kind: MethodEntry, key: key, sym: m) + let ownerModule = if t.sym != nil: t.sym.itemId.module.int else: module + g.opsLog.add LogEntry(kind: MethodEntry, module: ownerModule, key: key, sym: m) proc hasDisabledAsgn*(g: ModuleGraph; t: PType): bool = let op = getAttachedOp(g, t, attachedAsgn) diff --git a/compiler/pipelines.nim b/compiler/pipelines.nim index 398018cd94..7834a013c2 100644 --- a/compiler/pipelines.nim +++ b/compiler/pipelines.nim @@ -255,7 +255,7 @@ proc processPipelineModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator if m == module: replayActions.add n - writeNifModule(graph.config, module.position.int32, topLevelStmts, move(graph.opsLog), replayActions) + writeNifModule(graph.config, module.position.int32, topLevelStmts, graph.opsLog, replayActions) if graph.config.backend notin {backendC, backendCpp, backendObjc} and graph.config.cmd != cmdM: # We only write rod files here if no C-like backend is active.