summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ccgexprs.nim3
-rw-r--r--compiler/liftdestructors.nim6
-rw-r--r--compiler/lowerings.nim13
-rw-r--r--lib/system.nim25
-rw-r--r--tests/destructor/twasmoved.nim14
5 files changed, 50 insertions, 11 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index a1c81599c..ff851f924 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -2357,7 +2357,8 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
   else:
     if d.k == locNone: getTemp(p, n.typ, d)
     genAssignment(p, d, a, {})
-    resetLoc(p, a)
+    if p.config.selectedGC notin {gcArc, gcAtomicArc, gcOrc}:
+      resetLoc(p, a)
 
 proc genDestroy(p: BProc; n: PNode) =
   if optSeqDestructors in p.config.globalOptions:
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index 936d8dab0..865c18692 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -553,7 +553,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
     body.add setLenSeqCall(c, t, x, y)
     forallElements(c, t, body, x, y)
   of attachedSink:
-    let moveCall = genBuiltin(c, mMove, "move", x)
+    let moveCall = genBuiltin(c, mMove, "internalMove", x)
     moveCall.add y
     doAssert t.destructor != nil
     moveCall.add destructorCall(c, t.destructor, x)
@@ -586,7 +586,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
     body.add newHookCall(c, t.assignment, x, y)
   of attachedSink:
     # we always inline the move for better performance:
-    let moveCall = genBuiltin(c, mMove, "move", x)
+    let moveCall = genBuiltin(c, mMove, "internalMove", x)
     moveCall.add y
     doAssert t.destructor != nil
     moveCall.add destructorCall(c, t.destructor, x)
@@ -617,7 +617,7 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
   of attachedAsgn, attachedDeepCopy, attachedDup:
     body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c, x), y)
   of attachedSink:
-    let moveCall = genBuiltin(c, mMove, "move", x)
+    let moveCall = genBuiltin(c, mMove, "internalMove", x)
     moveCall.add y
     doAssert t.destructor != nil
     moveCall.add destructorCall(c, t.destructor, x)
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index d70c713a1..3f67fc168 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -66,8 +66,17 @@ proc newFastMoveStmt*(g: ModuleGraph, le, ri: PNode): PNode =
   result = newNodeI(nkFastAsgn, le.info, 2)
   result[0] = le
   result[1] = newNodeIT(nkCall, ri.info, ri.typ)
-  result[1].add newSymNode(getSysMagic(g, ri.info, "move", mMove))
-  result[1].add ri
+  if g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
+    result[1].add newSymNode(getCompilerProc(g, "internalMove"))
+    result[1].add ri
+    result = newTreeI(nkStmtList, le.info, result,
+            newTree(nkCall, newSymNode(
+              getSysMagic(g, ri.info, "=wasMoved", mWasMoved)),
+              ri
+              ))
+  else:
+    result[1].add newSymNode(getSysMagic(g, ri.info, "move", mMove))
+    result[1].add ri
 
 proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode =
   assert n.kind == nkVarTuple
diff --git a/lib/system.nim b/lib/system.nim
index 3a39da32e..949d717b0 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -147,10 +147,26 @@ proc wasMoved*[T](obj: var T) {.inline, noSideEffect.} =
   {.cast(raises: []), cast(tags: []).}:
     `=wasMoved`(obj)
 
-proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} =
-  result = x
-  {.cast(raises: []), cast(tags: []).}:
-    `=wasMoved`(x)
+const notJSnotNims = not defined(js) and not defined(nimscript)
+const arcLikeMem = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc)
+
+when notJSnotNims and arcLikeMem:
+  proc internalMove[T](x: var T): T {.magic: "Move", noSideEffect, compilerproc.} =
+    result = x
+
+  proc move*[T](x: var T): T {.noSideEffect, nodestroy.} =
+    {.cast(noSideEffect).}:
+      when nimvm:
+        result = internalMove(x)
+      else:
+        result = internalMove(x)
+        {.cast(raises: []), cast(tags: []).}:
+          `=wasMoved`(x)
+else:
+  proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} =
+    result = x
+    {.cast(raises: []), cast(tags: []).}:
+      `=wasMoved`(x)
 
 type
   range*[T]{.magic: "Range".}         ## Generic type to construct range types.
@@ -415,7 +431,6 @@ include "system/inclrtl"
 const NoFakeVars = defined(nimscript) ## `true` if the backend doesn't support \
   ## "fake variables" like `var EBADF {.importc.}: cint`.
 
-const notJSnotNims = not defined(js) and not defined(nimscript)
 
 when not defined(js) and not defined(nimSeqsV2):
   type
diff --git a/tests/destructor/twasmoved.nim b/tests/destructor/twasmoved.nim
new file mode 100644
index 000000000..566322702
--- /dev/null
+++ b/tests/destructor/twasmoved.nim
@@ -0,0 +1,14 @@
+type
+  Foo = object
+    id: int
+
+proc `=wasMoved`(x: var Foo) =
+  x.id = -1
+
+proc foo =
+  var s = Foo(id: 999)
+  var m = move s
+  doAssert s.id == -1
+  doAssert m.id == 999
+
+foo()