summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2019-11-02 00:39:04 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-11-02 00:39:04 +0100
commit44a27ccfe1cd56f2e77979eba4814d94eec47b41 (patch)
treea145b167692c3572b4cf19bb2b50e2d8ec9472f7
parent7a4d066102c3fdacaebb093699024693033742b1 (diff)
downloadNim-44a27ccfe1cd56f2e77979eba4814d94eec47b41.tar.gz
--gc:destructors: simple closures work
-rw-r--r--compiler/ccgexprs.nim2
-rw-r--r--compiler/ccgtypes.nim4
-rw-r--r--compiler/injectdestructors.nim5
-rw-r--r--compiler/lambdalifting.nim22
4 files changed, 20 insertions, 13 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index f6cf799bd..1d9d0aca6 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1193,8 +1193,6 @@ proc genDefault(p: BProc; n: PNode; d: var TLoc) =
   if d.k == locNone: getTemp(p, n.typ, d, needsInit=true)
   else: resetLoc(p, d)
 
-proc trivialDestructor(s: PSym): bool {.inline.} = s.ast[bodyPos].len == 0
-
 proc rawGenNew(p: BProc, a: TLoc, sizeExpr: Rope) =
   var sizeExpr = sizeExpr
   let typ = a.t
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index de1f0e497..a867c58c1 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -1275,6 +1275,8 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope =
     it = it.sons[0]
   result = makeCString(res)
 
+proc trivialDestructor(s: PSym): bool {.inline.} = s.ast[bodyPos].len == 0
+
 proc genObjectInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo) =
   assert t.kind == tyObject
   if incompleteType(t):
@@ -1282,7 +1284,7 @@ proc genObjectInfoV2(m: BModule, t, origType: PType, name: Rope; info: TLineInfo
                       typeToString(t))
 
   var d: Rope
-  if t.destructor != nil:
+  if t.destructor != nil and not trivialDestructor(t.destructor):
     # the prototype of a destructor is ``=destroy(x: var T)`` and that of a
     # finalizer is: ``proc (x: ref T) {.nimcall.}``. We need to check the calling
     # convention at least:
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index f1823bf64..78ab2daef 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -173,6 +173,9 @@ proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
   elif op.ast[genericParamsPos].kind != nkEmpty:
     globalError(c.graph.config, dest.info, "internal error: '" & AttachedOpToStr[kind] &
       "' operator is generic")
+  dbg:
+    if kind == attachedDestructor:
+      echo "destructor is ", op.id, " ", op.ast
   if sfError in op.flags: checkForErrorPragma(c, t, ri, AttachedOpToStr[kind])
   let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
   addrExp.add(dest)
@@ -681,4 +684,4 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
     result.add body
   dbg:
     echo ">---------transformed-to--------->"
-    echo result
+    echo renderTree(result, {renderIds})
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 4a2d40ec7..9f1d29ec6 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -233,6 +233,10 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} =
   let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
   result = conf.cmd == cmdCompileToJS and not isCompileTime
 
+proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo) =
+  createTypeBoundOps(g, nil, refType.lastSon, info)
+  createTypeBoundOps(g, nil, refType, info)
+
 proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
   # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env))
   if liftingHarmful(g.config, owner): return n
@@ -257,8 +261,8 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
     result.add(v)
   # add 'new' statement:
   result.add newCall(getSysSym(g, n.info, "internalNew"), env)
-  if optOwnedRefs in g.config.globalOptions:
-    createTypeBoundOps(g, nil, env.typ, n.info)
+  if g.config.selectedGC in {gcHooks, gcDestructors}:
+    createTypeBoundOpsLL(g, env.typ, n.info)
   result.add makeClosure(g, iter, env, n.info)
 
 proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode =
@@ -586,7 +590,7 @@ proc rawClosureCreation(owner: PSym;
       let env2 = copyTree(env)
       env2.typ = unowned.typ
       result.add newAsgnStmt(unowned, env2, env.info)
-      createTypeBoundOps(d.graph, nil, unowned.typ, env.info)
+      createTypeBoundOpsLL(d.graph, unowned.typ, env.info)
 
     # add assignment statements for captured parameters:
     for i in 1..<owner.typ.n.len:
@@ -609,8 +613,8 @@ proc rawClosureCreation(owner: PSym;
       localError(d.graph.config, env.info, "internal error: cannot create up reference")
   # we are not in the sem'check phase anymore! so pass 'nil' for the PContext
   # and hope for the best:
-  if optOwnedRefs in d.graph.config.globalOptions:
-    createTypeBoundOps(d.graph, nil, env.typ, owner.info)
+  if d.graph.config.selectedGC in {gcHooks, gcDestructors}:
+    createTypeBoundOpsLL(d.graph, env.typ, owner.info)
 
 proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass;
                            info: TLineInfo; res: PNode) =
@@ -638,8 +642,8 @@ proc closureCreationForIter(iter: PNode;
     addVar(vs, vnode)
     result.add(vs)
   result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode))
-  if optOwnedRefs in d.graph.config.globalOptions:
-    createTypeBoundOps(d.graph, nil, vnode.typ, iter.info)
+  if d.graph.config.selectedGC in {gcHooks, gcDestructors}:
+    createTypeBoundOpsLL(d.graph, vnode.typ, iter.info)
 
   let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
   if upField != nil:
@@ -924,8 +928,8 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
     result.add(v)
     # add 'new' statement:
     result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode))
-    if optOwnedRefs in g.config.globalOptions:
-      createTypeBoundOps(g, nil, env.typ, body.info)
+    if g.config.selectedGC in {gcHooks, gcDestructors}:
+      createTypeBoundOpsLL(g, env.typ, body.info)
 
   elif op.kind == nkStmtListExpr:
     let closure = op.lastSon