summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2023-07-06 17:14:42 +0800
committerGitHub <noreply@github.com>2023-07-06 11:14:42 +0200
commitdfa0d2569e772d6fc4568796db03f65dc2e94771 (patch)
tree02bae53201fd7c0531b888c9695376877a0261b3
parent7616e6ee2b48a3c3504684f3324a42e95bd73790 (diff)
downloadNim-dfa0d2569e772d6fc4568796db03f65dc2e94771.tar.gz
alternative to #22219; adds a pointer wrapper for T destructor (#22225)
* alternative to #22219; adds a pointer wrapper for T destructor

* clean up and add comments

* Update compiler/ccgtypes.nim

* tidy up

* fixes comments

* fixes cpp

* fixes cpp
-rw-r--r--compiler/ccgexprs.nim4
-rw-r--r--compiler/ccgtypes.nim55
2 files changed, 53 insertions, 6 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index e2498b57b..c585290cd 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1919,10 +1919,6 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
     else: putIntoDest(p, d, e, rope(lengthOrd(p.config, typ)))
   else: internalError(p.config, e.info, "genArrayLen()")
 
-proc makePtrType(baseType: PType; idgen: IdGenerator): PType =
-  result = newType(tyPtr, nextTypeId idgen, baseType.owner)
-  addSonSkipIntLit(result, baseType, idgen)
-
 proc makeAddr(n: PNode; idgen: IdGenerator): PNode =
   if n.kind == nkHiddenAddr:
     result = n
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index f808fa93e..9f4b7aa7c 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -1517,6 +1517,51 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope =
 
 proc isTrivialProc(g: ModuleGraph; s: PSym): bool {.inline.} = getBody(g, s).len == 0
 
+proc makePtrType(baseType: PType; idgen: IdGenerator): PType =
+  result = newType(tyPtr, nextTypeId idgen, baseType.owner)
+  addSonSkipIntLit(result, baseType, idgen)
+
+proc generateRttiDestructor(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
+              info: TLineInfo; idgen: IdGenerator; theProc: PSym): PSym =
+  # the wrapper is roughly like:
+  # proc rttiDestroy(x: pointer) =
+  #   `=destroy`(cast[ptr T](x)[])
+  let procname = getIdent(g.cache, "rttiDestroy")
+  result = newSym(skProc, procname, idgen, owner, info)
+  let dest = newSym(skParam, getIdent(g.cache, "dest"), idgen, result, info)
+
+  dest.typ = getSysType(g, info, tyPointer)
+
+  result.typ = newProcType(info, nextTypeId(idgen), owner)
+  result.typ.addParam dest
+
+  var n = newNodeI(nkProcDef, info, bodyPos+1)
+  for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
+  n[namePos] = newSymNode(result)
+  n[paramsPos] = result.typ.n
+  let body = newNodeI(nkStmtList, info)
+  let castType = makePtrType(typ, idgen)
+  if theProc.typ[1].kind != tyVar:
+    body.add newTreeI(nkCall, info, newSymNode(theProc), newDeref(newTreeIT(
+      nkCast, info, castType, newNodeIT(nkType, info, castType),
+      newSymNode(dest)
+    ))
+    )
+  else:
+    let addrOf = newNodeIT(nkAddr, info, theProc.typ[1])
+    addrOf.add newDeref(newTreeIT(
+      nkCast, info, castType, newNodeIT(nkType, info, castType),
+      newSymNode(dest)
+    ))
+    body.add newTreeI(nkCall, info, newSymNode(theProc),
+      addrOf
+    )
+  n[bodyPos] = body
+  result.ast = n
+
+  incl result.flags, sfFromGeneric
+  incl result.flags, sfGeneratedOp
+
 proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp; result: var Rope) =
   let theProc = getAttachedOp(m.g.graph, t, op)
   if theProc != nil and not isTrivialProc(m.g.graph, theProc):
@@ -1527,8 +1572,14 @@ proc genHook(m: BModule; t: PType; info: TLineInfo; op: TTypeAttachedOp; result:
       localError(m.config, info,
         theProc.name.s & " needs to have the 'nimcall' calling convention")
 
-    genProc(m, theProc)
-    result.add theProc.loc.r
+    if op == attachedDestructor:
+      let wrapper = generateRttiDestructor(m.g.graph, t, theProc.owner, attachedDestructor,
+                theProc.info, m.idgen, theProc)
+      genProc(m, wrapper)
+      result.add wrapper.loc.r
+    else:
+      genProc(m, theProc)
+      result.add theProc.loc.r
 
     when false:
       if not canFormAcycle(m.g.graph, t) and op == attachedTrace: