improve wasMoved hooks; allow reset to use the overridden wasMoved hook (#21831)

* improve `wasMoved` hooks

* Because `wasMoved` is lifted
This commit is contained in:
ringabout
2023-05-12 21:24:14 +08:00
committed by GitHub
parent 871e4af6ef
commit ddce555998
5 changed files with 43 additions and 20 deletions

View File

@@ -381,7 +381,7 @@ proc genWasMoved(c: var Con, n: PNode): PNode =
result = genOp(c, op, n)
else:
result = newNodeI(nkCall, n.info)
result.add(newSymNode(createMagic(c.graph, c.idgen, "wasMoved", mWasMoved)))
result.add(newSymNode(createMagic(c.graph, c.idgen, "`=wasMoved`", mWasMoved)))
result.add copyTree(n) #mWasMoved does not take the address
#if n.kind != nkSym:
# message(c.graph.config, n.info, warnUser, "wasMoved(" & $n & ")")

View File

@@ -89,7 +89,7 @@ proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
call.typ = t
body.add newAsgnStmt(x, call)
elif c.kind == attachedWasMoved:
body.add genBuiltin(c, mWasMoved, "wasMoved", x)
body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
proc genAddr(c: var TLiftCtx; x: PNode): PNode =
if x.kind == nkHiddenDeref:
@@ -143,7 +143,7 @@ proc destructorCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
if sfNeverRaises notin op.flags:
c.canRaise = true
if c.addMemReset:
result = newTree(nkStmtList, destroy, genBuiltin(c, mWasMoved, "wasMoved", x))
result = newTree(nkStmtList, destroy, genBuiltin(c, mWasMoved, "`=wasMoved`", x))
else:
result = destroy
@@ -262,7 +262,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
#body.add newAsgnStmt(blob, x)
var wasMovedCall = newNodeI(nkCall, c.info)
wasMovedCall.add(newSymNode(createMagic(c.g, c.idgen, "wasMoved", mWasMoved)))
wasMovedCall.add(newSymNode(createMagic(c.g, c.idgen, "`=wasMoved`", mWasMoved)))
wasMovedCall.add x # mWasMoved does not take the address
body.add wasMovedCall
@@ -548,7 +548,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if canFormAcycle(c.g, t.elemType):
# follow all elements:
forallElements(c, t, body, x, y)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -588,7 +588,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
if op == nil:
return # protect from recursion
body.add newHookCall(c, op, x, y)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -606,7 +606,7 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genBuiltin(c, mDestroy, "destroy", x)
of attachedTrace:
discard "strings are atomic and have no inner elements that are to trace"
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -707,7 +707,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# If the ref is polymorphic we have to account for this
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x, c.idgen), y)
#echo "can follow ", elemType, " static ", isFinal(elemType)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -758,7 +758,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace:
body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv, c.idgen), y)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -785,7 +785,7 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -813,7 +813,7 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, x, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -850,7 +850,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.sons.insert(des, 0)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -868,7 +868,7 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
body.add genIf(c, xx, actions)
of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: discard
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "wasMoved", x)
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
of attachedDup:
assert false, "cannot happen"
@@ -934,8 +934,14 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
defaultOp(c, t, body, x, y)
of tyObject:
if not considerUserDefinedOp(c, t, body, x, y):
if c.kind in {attachedAsgn, attachedSink} and t.sym != nil and sfImportc in t.sym.flags:
body.add newAsgnStmt(x, y)
if t.sym != nil and sfImportc in t.sym.flags:
case c.kind
of {attachedAsgn, attachedSink}:
body.add newAsgnStmt(x, y)
of attachedWasMoved:
body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
else:
fillBodyObjT(c, t, body, x, y)
else:
fillBodyObjT(c, t, body, x, y)
of tyDistinct:
@@ -1004,6 +1010,9 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
result.ast = n
incl result.flags, sfFromGeneric
incl result.flags, sfGeneratedOp
if kind == attachedWasMoved:
incl result.flags, sfNoSideEffect
incl result.typ.flags, tfNoSideEffect
proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
let xx = genBuiltin(c, mAccessTypeField, "accessTypeField", x)

View File

@@ -113,7 +113,7 @@ proc analyse(c: var Con; b: var BasicBlock; n: PNode) =
if n[0].kind == nkSym:
let s = n[0].sym
let name = s.name.s.normalize
if s.magic == mWasMoved or name == "=wasmoved":
if name == "=wasmoved":
b.wasMovedLocs.add n
special = true
elif name == "=destroy":

View File

@@ -613,6 +613,15 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
let op = getAttachedOp(c.graph, t, attachedTrace)
if op != nil:
result[0] = newSymNode(op)
of mWasMoved:
result = n
let t = n[1].typ.skipTypes(abstractVar)
let op = getAttachedOp(c.graph, t, attachedWasMoved)
if op != nil:
result[0] = newSymNode(op)
let addrExp = newNodeIT(nkHiddenAddr, result[1].info, makePtrType(c, t))
addrExp.add result[1]
result[1] = addrExp
of mUnown:
result = semUnown(c, n)
of mExists, mForall:

View File

@@ -137,15 +137,20 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
## **Note**: The `finalizer` refers to the type `T`, not to the object!
## This means that for each object of type `T` the finalizer will be called!
proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} =
proc `=wasMoved`[T](obj: var T) {.magic: "WasMoved", noSideEffect.} =
## Generic `wasMoved`:idx: implementation that can be overridden.
proc wasMoved*[T](obj: var T) {.inline, noSideEffect.} =
## Resets an object `obj` to its initial (binary zero) value to signify
## it was "moved" and to signify its destructor should do nothing and
## ideally be optimized away.
discard
{.cast(raises: []), cast(tags: []).}:
`=wasMoved`(obj)
proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} =
result = x
wasMoved(x)
{.cast(raises: []), cast(tags: []).}:
`=wasMoved`(x)
type
range*[T]{.magic: "Range".} ## Generic type to construct range types.
@@ -912,7 +917,7 @@ proc reset*[T](obj: var T) {.noSideEffect.} =
when defined(gcDestructors):
{.cast(noSideEffect), cast(raises: []), cast(tags: []).}:
`=destroy`(obj)
wasMoved(obj)
`=wasMoved`(obj)
else:
obj = default(typeof(obj))