diff options
-rw-r--r-- | compiler/ccgexprs.nim | 3 | ||||
-rw-r--r-- | compiler/liftdestructors.nim | 6 | ||||
-rw-r--r-- | compiler/lowerings.nim | 13 | ||||
-rw-r--r-- | lib/system.nim | 25 | ||||
-rw-r--r-- | tests/destructor/twasmoved.nim | 14 |
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() |