This commit is contained in:
araq
2025-12-14 11:02:29 +01:00
parent a78dd184ec
commit 1f3899ca29
6 changed files with 120 additions and 113 deletions

View File

@@ -46,6 +46,12 @@ template loadType(t: PType) =
when not defined(nimKochBootstrap):
ast2nif.loadType(program, t)
proc loadSymCallback*(s: PSym) {.nimcall.} =
loadSym(s)
proc loadTypeCallback*(t: PType) {.nimcall.} =
loadType(t)
proc ensureMutable*(s: PSym) {.inline.} =
assert s.state != Sealed
if s.state == Partial: loadSym(s)

View File

@@ -667,7 +667,7 @@ proc buildExportBuf(w: var Writer): TokenBuf =
proc translateOpsLog(w: var Writer; opsLog: seq[LogEntry]): IndexSections =
result = IndexSections(hooks: default array[AttachedOp, seq[HookIndexEntry]], converters: @[], classes: @[])
for entry in opsLog:
let key = pool.syms.getOrIncl(entry.typ.typeKey(w.infos.config))
let key = pool.syms.getOrIncl(entry.key)
let sym = pool.syms.getOrIncl(w.toNifSymName(entry.sym))
case entry.kind
of HookEntry:
@@ -1393,24 +1393,6 @@ proc toNifIndexFilename*(conf: ConfigRef; f: FileIndex): string =
let suffix = moduleSuffix(conf, f)
result = toGeneratedFile(conf, AbsoluteFile(suffix), ".s.idx.nif").string
proc parseTypeSymIdToItemId*(c: var DecodeContext; symId: nifstreams.SymId): ItemId =
## Parses a type SymId (format: `"`tN.modulesuffix"`) to extract ItemId.
let s = pool.syms[symId]
if not s.startsWith("`t"):
return ItemId(module: -1, item: 0)
var i = 2 # skip "`t"
var item = 0'i32
while i < s.len and s[i] in {'0'..'9'}:
item = item * 10 + int32(ord(s[i]) - ord('0'))
inc i
if i < s.len and s[i] == '.':
inc i
let suffix = s.substr(i)
let module = moduleId(c, suffix)
result = ItemId(module: int32(module), item: item)
else:
result = ItemId(module: -1, item: item)
proc resolveSym(c: var DecodeContext; symAsStr: string; alsoConsiderPrivate: bool): PSym =
result = c.syms.getOrDefault(symAsStr)[0]
if result != nil:
@@ -1463,9 +1445,22 @@ proc loadNifModule*(c: var DecodeContext; f: FileIndex; interf, interfHidden: va
populateInterfaceTablesFromIndex(c, module, interf, interfHidden, suffix)
# Return hooks from the index
hooks = move c.mods[module].index.hooks
let hooks = move c.mods[module].index.hooks
for typeKey, h in hooks:
for op in AttachedOp:
let (hookSymId, isGeneric) = h.a[op]
let hookSym = resolveHookSym(c, hookSymId)
if hookSym != nil:
logOps.add LogEntry(kind: HookEntry, op: toTTypeAttachedOp(op),
isGeneric: isGeneric, key: pool.syms[typeKey], sym: hookSym)
# Return converters from the index
converters = move c.mods[module].index.converters
let converters = move c.mods[module].index.converters
for (destType, convSym) in converters:
let symId = pool.syms.getOrIncl(convSym)
let convPSym = resolveHookSym(c, symId) # reuse hook resolution
if convPSym != nil:
logOps.add LogEntry(kind: ConverterEntry,
isGeneric: false, key: destType, sym: convPSym)
# Return classes/methods from the index
classes = move c.mods[module].index.classes

View File

@@ -1001,7 +1001,7 @@ type
kind*: LogEntryKind
op*: TTypeAttachedOp
isGeneric*: bool
typ*: PType
key*: string
sym*: PSym

View File

@@ -20,6 +20,8 @@ when not defined(nimKochBootstrap):
import ast2nif
import "../dist/nimony/src/lib" / [nifstreams, bitabs]
import typekeys
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -79,6 +81,7 @@ type
typeInstCache*: Table[ItemId, seq[LazyType]] # A symbol's ItemId.
procInstCache*: Table[ItemId, seq[LazyInstantiation]] # A symbol's ItemId.
attachedOps*: array[TTypeAttachedOp, Table[ItemId, LazySym]] # Type ID, destructors, etc.
loadedOps: array[TTypeAttachedOp, Table[string, PSym]] # This can later by unified with `attachedOps` once it's stable
opsLog*: seq[LogEntry]
methodsPerGenericType*: Table[ItemId, seq[(int, LazySym)]] # Type ID, attached methods
memberProcsPerType*: Table[ItemId, seq[PSym]] # Type ID, attached member procs (only c++, virtual,member and ctor so far).
@@ -368,7 +371,8 @@ proc getAttachedOp*(g: ModuleGraph; t: PType; op: TTypeAttachedOp): PSym =
proc setAttachedOp*(g: ModuleGraph; module: int; t: PType; op: TTypeAttachedOp; value: PSym) =
## we also need to record this to the packed module.
if not g.attachedOps[op].contains(t.itemId):
g.opsLog.add LogEntry(kind: HookEntry, op: op, typ: t, sym: value)
let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback)
g.opsLog.add LogEntry(kind: HookEntry, op: op, key: key, sym: value)
g.attachedOps[op][t.itemId] = LazySym(sym: value)
proc setAttachedOp*(g: ModuleGraph; module: int; typeId: ItemId; op: TTypeAttachedOp; value: PSym) =
@@ -417,7 +421,8 @@ proc getToStringProc*(g: ModuleGraph; t: PType): PSym =
proc setToStringProc*(g: ModuleGraph; t: PType; value: PSym) =
g.enumToStringProcs[t.itemId] = LazySym(sym: value)
g.opsLog.add LogEntry(kind: EnumToStrEntry, typ: t, sym: value)
let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback)
g.opsLog.add LogEntry(kind: EnumToStrEntry, key: key, sym: value)
iterator methodsForGeneric*(g: ModuleGraph; t: PType): (int, PSym) =
if g.methodsPerGenericType.contains(t.itemId):
@@ -426,7 +431,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))
g.opsLog.add LogEntry(kind: MethodEntry, typ: t, sym: m)
let key = typeKey(t, g.config, loadTypeCallback, loadSymCallback)
g.opsLog.add LogEntry(kind: MethodEntry, key: key, sym: m)
proc hasDisabledAsgn*(g: ModuleGraph; t: PType): bool =
let op = getAttachedOp(g, t, attachedAsgn)
@@ -809,38 +815,23 @@ when not defined(nimKochBootstrap):
# Register module in graph
registerModule(g, result)
var hooks = initTable[nifstreams.SymId, HooksPerType]()
var converters: seq[(string, string)] = @[]
var opsLog: seq[LogEntry] = @[]
var classes: seq[ClassIndexEntry] = @[]
result.astImpl = loadNifModule(ast.program, fileIdx, g.ifaces[fileIdx.int].interf,
g.ifaces[fileIdx.int].interfHidden, hooks, converters, classes, loadFullAst)
g.ifaces[fileIdx.int].interfHidden, opsLog, classes, loadFullAst)
# Register hooks from NIF index with the module graph
for typSymId, hooksPerType in hooks:
let typeItemId = parseTypeSymIdToItemId(ast.program, typSymId)
if typeItemId.module >= 0:
for op in AttachedOp:
let (hookSymId, isGeneric) = hooksPerType.a[op]
if hookSymId != nifstreams.SymId(0):
let hookSym = resolveHookSym(ast.program, hookSymId)
if hookSym != nil:
setAttachedOp(g, int(fileIdx), typeItemId, toTTypeAttachedOp(op), hookSym)
# Register converters from NIF index with the module's interface
for (destType, convSym) in converters:
let symId = pool.syms.getOrIncl(convSym)
let convPSym = resolveHookSym(ast.program, symId) # reuse hook resolution
if convPSym != nil:
g.ifaces[fileIdx.int].converters.add LazySym(sym: convPSym)
for x in opsLog:
case x.kind
of HookEntry:
g.loadedOps[x.op][x.key] = x.sym
of ConverterEntry:
g.ifaces[fileIdx.int].converters.add LazySym(sym: x.sym)
of MethodEntry:
discard "todo"
of EnumToStrEntry:
discard "todo"
# Register methods per type from NIF index
for classEntry in classes:
let typeItemId = parseTypeSymIdToItemId(ast.program, classEntry.cls)
if typeItemId.module >= 0:
var methodSyms: seq[LazySym] = @[]
for methodEntry in classEntry.methods:
let methodSym = resolveHookSym(ast.program, methodEntry.fn)
if methodSym != nil:
methodSyms.add LazySym(sym: methodSym)
if methodSyms.len > 0:
setMethodsPerType(g, typeItemId, methodSyms)
discard "todo"
cachedModules.add fileIdx
proc configComplete*(g: ModuleGraph) =

View File

@@ -48,10 +48,20 @@ type
CoDistinct
CoHashTypeInsideNode
proc typeKey(c: var Mangler, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef)
proc symKey(c: var Mangler, s: PSym; conf: ConfigRef) =
TypeLoader* = proc (t: PType) {.nimcall.}
SymLoader* = proc (s: PSym) {.nimcall.}
Context = object
m: Mangler
tl: TypeLoader
sl: SymLoader
proc typeKey(c: var Context; t: PType; flags: set[ConsiderFlag]; conf: ConfigRef)
proc symKey(c: var Context; s: PSym; conf: ConfigRef) =
if s.state == Partial:
assert c.sl != nil
c.sl(s)
if sfAnon in s.flagsImpl or s.kindImpl == skGenericParam:
c.addIdent("´anon")
c.m.addIdent("´anon")
else:
var name = s.name.s
name.add '.'
@@ -67,32 +77,32 @@ proc symKey(c: var Mangler, s: PSym; conf: ConfigRef) =
if it.kindImpl == skModule:
name.add '.'
name.add modname(it, conf)
c.addSymbol(name)
c.m.addSymbol(name)
proc treeKey(c: var Mangler, n: PNode; flags: set[ConsiderFlag]; conf: ConfigRef) =
proc treeKey(c: var Context; n: PNode; flags: set[ConsiderFlag]; conf: ConfigRef) =
if n == nil:
c.addEmpty()
c.m.addEmpty()
return
let k = n.kind
case k
of nkEmpty, nkNilLit, nkType: discard
of nkIdent:
c.addIdent(n.ident.s)
c.m.addIdent(n.ident.s)
of nkSym:
symKey(c, n.sym, conf)
if CoHashTypeInsideNode in flags and n.sym.typImpl != nil:
typeKey(c, n.sym.typImpl, flags, conf)
of nkCharLit..nkUInt64Lit:
let v = n.intVal
c.addIntLit v
c.m.addIntLit v
of nkFloatLit..nkFloat64Lit:
let v = n.floatVal
c.addFloatLit v
c.m.addFloatLit v
of nkStrLit..nkTripleStrLit:
c.addStrLit n.strVal
c.m.addStrLit n.strVal
else:
withTree c, toNifTag(k):
withTree c.m, toNifTag(k):
for i in 0..<n.len: treeKey(c, n[i], flags, conf)
proc skipModifierB(n: PType): PType {.inline.} =
@@ -110,15 +120,19 @@ proc skipGenericAlias(t: PType): PType =
if result.isGenericAlias:
result = result.skipModifierB.skipTypesB({tyAlias})
proc maybeImported(c: var Mangler, s: PSym; conf: ConfigRef) {.inline.} =
proc maybeImported(c: var Context; s: PSym; conf: ConfigRef) {.inline.} =
if s != nil and {sfImportc, sfExportc} * s.flagsImpl != {}:
c.symKey(s, conf)
proc typeKey(c: var Mangler, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef) =
proc typeKey(c: var Context; t: PType; flags: set[ConsiderFlag]; conf: ConfigRef) =
if t == nil:
c.addEmpty()
c.m.addEmpty()
return
if t.state == Partial:
assert c.tl != nil
c.tl(t)
case t.kind
of tyGenericInvocation:
for a in t.sonsImpl:
@@ -147,56 +161,56 @@ proc typeKey(c: var Mangler, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef
c.typeKey t.skipModifierB, flags, conf
of tyOwned:
if CoConsiderOwned in flags:
withTree c, toNifTag(t.kind):
withTree c.m, toNifTag(t.kind):
c.typeKey t.skipModifierB, flags, conf
else:
c.typeKey t.skipModifierB, flags, conf
of tyBool:
withTree c, "bool":
withTree c.m, "bool":
maybeImported(c, t.symImpl, conf)
of tyChar:
withTree c, "c":
c.addIntLit 8 # char is always 8 bits
withTree c.m, "c":
c.m.addIntLit 8 # char is always 8 bits
maybeImported(c, t.symImpl, conf)
of tyInt:
withTree c, "i":
c.addIntLit -1
withTree c.m, "i":
c.m.addIntLit -1
maybeImported(c, t.symImpl, conf)
of tyInt8:
withTree c, "i":
c.addIntLit 8
withTree c.m, "i":
c.m.addIntLit 8
maybeImported(c, t.symImpl, conf)
of tyInt16:
withTree c, "i":
c.addIntLit 16
withTree c.m, "i":
c.m.addIntLit 16
maybeImported(c, t.symImpl, conf)
of tyInt32:
withTree c, "i":
c.addIntLit 32
withTree c.m, "i":
c.m.addIntLit 32
maybeImported(c, t.symImpl, conf)
of tyInt64:
withTree c, "i":
c.addIntLit 64
withTree c.m, "i":
c.m.addIntLit 64
maybeImported(c, t.symImpl, conf)
of tyUInt:
withTree c, "u":
c.addIntLit -1
withTree c.m, "u":
c.m.addIntLit -1
maybeImported(c, t.symImpl, conf)
of tyUInt8:
withTree c, "u":
c.addIntLit 8
withTree c.m, "u":
c.m.addIntLit 8
maybeImported(c, t.symImpl, conf)
of tyUInt16:
withTree c, "u":
c.addIntLit 16
withTree c.m, "u":
c.m.addIntLit 16
maybeImported(c, t.symImpl, conf)
of tyUInt32:
withTree c, "u":
c.addIntLit 32
withTree c.m, "u":
c.m.addIntLit 32
maybeImported(c, t.symImpl, conf)
of tyUInt64:
withTree c, "u":
c.addIntLit 64
withTree c.m, "u":
c.m.addIntLit 64
maybeImported(c, t.symImpl, conf)
of tyObject, tyEnum:
if t.typeInstImpl != nil:
@@ -211,15 +225,15 @@ proc typeKey(c: var Mangler, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef
elif t.symImpl != nil:
c.symKey(t.symImpl, conf)
else:
c.addIdent "`bug"
c.m.addIdent "`bug"
of tyFromExpr:
withTree c, toNifTag(t.kind):
withTree c.m, toNifTag(t.kind):
c.treeKey(t.nImpl, flags, conf)
of tyTuple:
withTree c, toNifTag(t.kind):
withTree c.m, toNifTag(t.kind):
if t.nImpl != nil and CoType notin flags:
for i in 0..<t.nImpl.len:
withTree c, "kv":
withTree c.m, "kv":
assert(t.nImpl[i].kind == nkSym)
c.symKey(t.nImpl[i].sym, conf)
c.typeKey(t.nImpl[i].sym.typImpl, flags+{CoIgnoreRange}, conf)
@@ -228,17 +242,17 @@ proc typeKey(c: var Mangler, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef
c.typeKey t.sonsImpl[i], flags+{CoIgnoreRange}, conf
of tyRange:
if CoIgnoreRange notin flags:
withTree c, toNifTag(t.kind):
withTree c.m, toNifTag(t.kind):
c.treeKey(t.nImpl, {}, conf)
c.typeKey(t.sonsImpl[^1], flags, conf)
else:
c.typeKey(t.sonsImpl[^1], flags, conf)
of tyStatic:
withTree c, toNifTag(t.kind):
withTree c.m, toNifTag(t.kind):
c.treeKey(t.nImpl, {}, conf)
c.typeKey(t.skipModifierB, flags, conf)
of tyProc:
withTree c, (if tfIterator in t.flagsImpl: "itertype" else: "proctype"):
withTree c.m, (if tfIterator in t.flagsImpl: "itertype" else: "proctype"):
if CoProc in flags and t.nImpl != nil:
let params = t.nImpl
for i in 1..<params.len:
@@ -251,19 +265,20 @@ proc typeKey(c: var Mangler, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef
if t.sonsImpl.len > 0:
c.typeKey(t.sonsImpl[0], flags, conf)
c.addIdent toNifTag(t.callConvImpl)
if tfVarargs in t.flagsImpl: c.addIdent "´varargs"
c.m.addIdent toNifTag(t.callConvImpl)
if tfVarargs in t.flagsImpl: c.m.addIdent "´varargs"
of tyArray:
withTree c, toNifTag(t.kind):
withTree c.m, toNifTag(t.kind):
c.typeKey(t.sonsImpl[^1], flags-{CoIgnoreRange}, conf)
c.typeKey(t.sonsImpl[0], flags-{CoIgnoreRange}, conf)
else:
withTree c, toNifTag(t.kind):
withTree c.m, toNifTag(t.kind):
for i in 1..<t.sonsImpl.len:
c.typeKey t.sonsImpl[i], flags, conf
if tfNotNil in t.flagsImpl and CoType notin flags: c.addIdent "´notnil"
if tfNotNil in t.flagsImpl and CoType notin flags:
c.m.addIdent "´notnil"
proc typeKey*(t: PType; conf: ConfigRef): string =
var c = createMangler(30, -1)
proc typeKey*(t: PType; conf: ConfigRef; tl: TypeLoader; sl: SymLoader): string =
var c: Context = Context(m: createMangler(30, -1), tl: tl, sl: sl)
typeKey(c, t, {}, conf)
result = c.extract()
result = c.m.extract()

View File

@@ -390,15 +390,15 @@ else:
## Generic `destructor`:idx: implementation that can be overridden.
discard
when defined(nimAllowNonVarDestructor) and arcLikeMem:
proc `=destroy`*(x: string) {.inline, magic: "Destroy", enforceNoRaises.} =
discard
when defined(nimAllowNonVarDestructor) and arcLikeMem:
proc `=destroy`*(x: string) {.inline, magic: "Destroy", enforceNoRaises.} =
discard
proc `=destroy`*[T](x: seq[T]) {.inline, magic: "Destroy".} =
discard
proc `=destroy`*[T](x: seq[T]) {.inline, magic: "Destroy".} =
discard
proc `=destroy`*[T](x: ref T) {.inline, magic: "Destroy".} =
discard
proc `=destroy`*[T](x: ref T) {.inline, magic: "Destroy".} =
discard
when defined(nimHasDup):
proc `=dup`*[T](x: T): T {.inline, magic: "Dup".} =