mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
lift the =dup hook (#21903)
* fixes tests again * remove helper functions * fixes closures, owned refs * final cleanup
This commit is contained in:
@@ -944,10 +944,10 @@ type
|
||||
attachedWasMoved,
|
||||
attachedDestructor,
|
||||
attachedAsgn,
|
||||
attachedDup,
|
||||
attachedSink,
|
||||
attachedTrace,
|
||||
attachedDeepCopy,
|
||||
attachedDup
|
||||
attachedDeepCopy
|
||||
|
||||
TType* {.acyclic.} = object of TIdObj # \
|
||||
# types are identical iff they have the
|
||||
@@ -1518,7 +1518,7 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
|
||||
|
||||
const
|
||||
AttachedOpToStr*: array[TTypeAttachedOp, string] = [
|
||||
"=wasMoved", "=destroy", "=copy", "=sink", "=trace", "=deepcopy", "=dup"]
|
||||
"=wasMoved", "=destroy", "=copy", "=dup", "=sink", "=trace", "=deepcopy"]
|
||||
|
||||
proc `$`*(s: PSym): string =
|
||||
if s != nil:
|
||||
|
||||
@@ -2359,11 +2359,6 @@ proc genMove(p: BProc; n: PNode; d: var TLoc) =
|
||||
genAssignment(p, d, a, {})
|
||||
resetLoc(p, a)
|
||||
|
||||
proc genDup(p: BProc; src: TLoc; d: var TLoc; n: PNode) =
|
||||
if d.k == locNone: getTemp(p, n.typ, d)
|
||||
linefmt(p, cpsStmts, "#nimDupRef((void**)$1, (void*)$2);$n",
|
||||
[addrLoc(p.config, d), rdLoc(src)])
|
||||
|
||||
proc genDestroy(p: BProc; n: PNode) =
|
||||
if optSeqDestructors in p.config.globalOptions:
|
||||
let arg = n[1].skipAddr
|
||||
@@ -2615,11 +2610,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mAccessTypeField: genAccessTypeField(p, e, d)
|
||||
of mSlice: genSlice(p, e, d)
|
||||
of mTrace: discard "no code to generate"
|
||||
of mDup:
|
||||
var a: TLoc
|
||||
let x = if e[1].kind in {nkAddr, nkHiddenAddr}: e[1][0] else: e[1]
|
||||
initLocExpr(p, x, a)
|
||||
genDup(p, a, d, e)
|
||||
else:
|
||||
when defined(debugMagics):
|
||||
echo p.prc.name.s, " ", p.prc.id, " ", p.prc.flags, " ", p.prc.ast[genericParamsPos].kind
|
||||
|
||||
@@ -188,7 +188,7 @@ template isUnpackedTuple(n: PNode): bool =
|
||||
|
||||
proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
|
||||
var m = "'" & opname & "' is not available for type <" & typeToString(t) & ">"
|
||||
if (opname == "=" or opname == "=copy") and ri != nil:
|
||||
if (opname == "=" or opname == "=copy" or opname == "=dup") and ri != nil:
|
||||
m.add "; requires a copy because it's not the last read of '"
|
||||
m.add renderTree(ri)
|
||||
m.add '\''
|
||||
@@ -427,21 +427,17 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
|
||||
if hasDestructor(c, n.typ):
|
||||
let typ = n.typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
let op = getAttachedOp(c.graph, typ, attachedDup)
|
||||
if op != nil:
|
||||
if op != nil and tfHasOwned notin typ.flags:
|
||||
if sfError in op.flags:
|
||||
c.checkForErrorPragma(n.typ, n, "=dup")
|
||||
let src = p(n, c, s, normal)
|
||||
result.add newTreeI(nkFastAsgn,
|
||||
src.info, tmp,
|
||||
newTreeIT(nkCall, src.info, src.typ,
|
||||
var newCall = newTreeIT(nkCall, src.info, src.typ,
|
||||
newSymNode(op),
|
||||
src)
|
||||
)
|
||||
elif typ.kind == tyRef:
|
||||
let src = p(n, c, s, normal)
|
||||
c.finishCopy(newCall, n, isFromSink = true)
|
||||
result.add newTreeI(nkFastAsgn,
|
||||
src.info, tmp,
|
||||
newTreeIT(nkCall, src.info, src.typ,
|
||||
newSymNode(createMagic(c.graph, c.idgen, "`=dup`", mDup)),
|
||||
src)
|
||||
newCall
|
||||
)
|
||||
else:
|
||||
result.add c.genWasMoved(tmp)
|
||||
|
||||
@@ -34,6 +34,7 @@ type
|
||||
|
||||
template destructor*(t: PType): PSym = getAttachedOp(c.g, t, attachedDestructor)
|
||||
template assignment*(t: PType): PSym = getAttachedOp(c.g, t, attachedAsgn)
|
||||
template dup*(t: PType): PSym = getAttachedOp(c.g, t, attachedDup)
|
||||
template asink*(t: PType): PSym = getAttachedOp(c.g, t, attachedSink)
|
||||
|
||||
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
|
||||
@@ -82,7 +83,7 @@ proc genBuiltin(c: var TLiftCtx; magic: TMagic; name: string; i: PNode): PNode =
|
||||
result = genBuiltin(c.g, c.idgen, magic, name, i)
|
||||
|
||||
proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink}:
|
||||
if c.kind in {attachedAsgn, attachedDeepCopy, attachedSink, attachedDup}:
|
||||
body.add newAsgnStmt(x, y)
|
||||
elif c.kind == attachedDestructor and c.addMemReset:
|
||||
let call = genBuiltin(c, mDefault, "default", x)
|
||||
@@ -283,7 +284,7 @@ proc boolLit*(g: ModuleGraph; info: TLineInfo; value: bool): PNode =
|
||||
result.typ = getSysType(g, info, tyBool)
|
||||
|
||||
proc getCycleParam(c: TLiftCtx): PNode =
|
||||
assert c.kind == attachedAsgn
|
||||
assert c.kind in {attachedAsgn, attachedDup}
|
||||
if c.fn.typ.len == 4:
|
||||
result = c.fn.typ.n.lastSon
|
||||
assert result.kind == nkSym
|
||||
@@ -322,6 +323,9 @@ proc newOpCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
|
||||
proc newDeepCopyCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
|
||||
result = newAsgnStmt(x, newOpCall(c, op, y))
|
||||
|
||||
proc newDupCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode =
|
||||
result = newAsgnStmt(x, newOpCall(c, op, y))
|
||||
|
||||
proc usesBuiltinArc(t: PType): bool =
|
||||
proc wrap(t: PType): bool {.nimcall.} = ast.isGCedMem(t)
|
||||
result = types.searchTypeFor(t, wrap)
|
||||
@@ -464,7 +468,18 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
|
||||
result = true
|
||||
|
||||
of attachedDup:
|
||||
assert false, "cannot happen"
|
||||
var op = getAttachedOp(c.g, t, attachedDup)
|
||||
if op != nil and sfOverriden in op.flags:
|
||||
|
||||
if op.ast.isGenericRoutine:
|
||||
# patch generic destructor:
|
||||
op = instantiateGeneric(c, op, t, t.typeInst)
|
||||
setAttachedOp(c.g, c.idgen.module, t, attachedDup, op)
|
||||
|
||||
#markUsed(c.g.config, c.info, op, c.g.usageSym)
|
||||
onUse(c.info, op)
|
||||
body.add newDupCall(c, op, x, y)
|
||||
result = true
|
||||
|
||||
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode =
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
|
||||
@@ -526,6 +541,9 @@ proc forallElements(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
|
||||
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
case c.kind
|
||||
of attachedDup:
|
||||
body.add setLenSeqCall(c, t, x, y)
|
||||
forallElements(c, t, body, x, y)
|
||||
of attachedAsgn, attachedDeepCopy:
|
||||
# we generate:
|
||||
# setLen(dest, y.len)
|
||||
@@ -549,15 +567,13 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
# follow all elements:
|
||||
forallElements(c, t, body, x, y)
|
||||
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
|
||||
of attachedDup:
|
||||
assert false, "cannot happen"
|
||||
|
||||
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
createTypeBoundOps(c.g, c.c, t, body.info, c.idgen)
|
||||
# recursions are tricky, so we might need to forward the generated
|
||||
# operation here:
|
||||
var t = t
|
||||
if t.assignment == nil or t.destructor == nil:
|
||||
if t.assignment == nil or t.destructor == nil or t.dup == nil:
|
||||
let h = sighashes.hashType(t,c.g.config, {CoType, CoConsiderOwned, CoDistinct})
|
||||
let canon = c.g.canonTypes.getOrDefault(h)
|
||||
if canon != nil: t = canon
|
||||
@@ -590,11 +606,15 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newHookCall(c, op, x, y)
|
||||
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
|
||||
of attachedDup:
|
||||
assert false, "cannot happen"
|
||||
# XXX: replace these with assertions.
|
||||
let op = getAttachedOp(c.g, t, c.kind)
|
||||
if op == nil:
|
||||
return # protect from recursion
|
||||
body.add newDupCall(c, op, x, y)
|
||||
|
||||
proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
case c.kind
|
||||
of attachedAsgn, attachedDeepCopy:
|
||||
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)
|
||||
@@ -607,8 +627,6 @@ proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
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 attachedDup:
|
||||
assert false, "cannot happen"
|
||||
|
||||
proc cyclicType*(g: ModuleGraph, t: PType): bool =
|
||||
case t.kind
|
||||
@@ -648,7 +666,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
# dynamic Acyclic refs need to use dyn decRef
|
||||
|
||||
let tmp =
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink, attachedDup}:
|
||||
declareTempOf(c, body, x)
|
||||
else:
|
||||
x
|
||||
@@ -709,7 +727,14 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
#echo "can follow ", elemType, " static ", isFinal(elemType)
|
||||
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
|
||||
of attachedDup:
|
||||
assert false, "cannot happen"
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, y, callCodegenProc(c.g,
|
||||
"nimIncRefCyclic", c.info, y, getCycleParam(c)))
|
||||
else:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, y, callCodegenProc(c.g,
|
||||
"nimIncRef", c.info, y))
|
||||
|
||||
proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
## Closures are really like refs except they always use a virtual destructor
|
||||
@@ -719,7 +744,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc
|
||||
let tmp =
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink}:
|
||||
if isCyclic and c.kind in {attachedAsgn, attachedSink, attachedDup}:
|
||||
declareTempOf(c, body, xenv)
|
||||
else:
|
||||
xenv
|
||||
@@ -753,14 +778,21 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
|
||||
body.add genIf(c, cond, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
let yenv = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRefCyclic", c.info, yenv, getCycleParam(c)))
|
||||
else:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRef", c.info, yenv))
|
||||
of attachedDestructor:
|
||||
body.add genIf(c, cond, actions)
|
||||
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 attachedDup:
|
||||
assert false, "cannot happen"
|
||||
|
||||
proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
case c.kind
|
||||
@@ -773,6 +805,9 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y))
|
||||
body.add genIf(c, x, callCodegenProc(c.g, "nimDecWeakRef", c.info, x))
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, y, callCodegenProc(c.g, "nimIncRef", c.info, y))
|
||||
of attachedDestructor:
|
||||
# it's better to prepend the destruction of weak refs in order to
|
||||
# prevent wrong "dangling refs exist" problems:
|
||||
@@ -786,8 +821,6 @@ proc weakrefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
of attachedDeepCopy: assert(false, "cannot happen")
|
||||
of attachedTrace: discard
|
||||
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
|
||||
of attachedDup:
|
||||
assert false, "cannot happen"
|
||||
|
||||
proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
var actions = newNodeI(nkStmtList, c.info)
|
||||
@@ -809,13 +842,13 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
of attachedSink, attachedAsgn:
|
||||
body.add genIf(c, x, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDestructor:
|
||||
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 attachedDup:
|
||||
assert false, "cannot happen"
|
||||
|
||||
proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if c.kind == attachedDeepCopy:
|
||||
@@ -842,6 +875,11 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
|
||||
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
let yy = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yy.typ = getSysType(c.g, c.info, tyPointer)
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
|
||||
of attachedDestructor:
|
||||
let des = genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||
if body.len == 0:
|
||||
@@ -851,8 +889,6 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
of attachedDeepCopy: assert(false, "cannot happen")
|
||||
of attachedTrace: discard
|
||||
of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
|
||||
of attachedDup:
|
||||
assert false, "cannot happen"
|
||||
|
||||
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let xx = genBuiltin(c, mAccessEnv, "accessEnv", x)
|
||||
@@ -864,13 +900,13 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
of attachedSink, attachedAsgn:
|
||||
body.add genIf(c, xx, actions)
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDestructor:
|
||||
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 attachedDup:
|
||||
assert false, "cannot happen"
|
||||
|
||||
proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
case t.kind
|
||||
@@ -936,7 +972,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if not considerUserDefinedOp(c, t, body, x, y):
|
||||
if t.sym != nil and sfImportc in t.sym.flags:
|
||||
case c.kind
|
||||
of {attachedAsgn, attachedSink}:
|
||||
of {attachedAsgn, attachedSink, attachedDup}:
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedWasMoved:
|
||||
body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
|
||||
@@ -976,8 +1012,44 @@ proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
|
||||
result = getAttachedOp(g, baseType, kind)
|
||||
setAttachedOp(g, idgen.module, typ, kind, result)
|
||||
|
||||
proc symDupPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
|
||||
info: TLineInfo; idgen: IdGenerator): PSym =
|
||||
let procname = getIdent(g.cache, AttachedOpToStr[kind])
|
||||
result = newSym(skProc, procname, idgen, owner, info)
|
||||
let res = newSym(skResult, getIdent(g.cache, "result"), idgen, result, info)
|
||||
let src = newSym(skParam, getIdent(g.cache, "src"),
|
||||
idgen, result, info)
|
||||
res.typ = typ
|
||||
src.typ = typ
|
||||
|
||||
result.typ = newType(tyProc, nextTypeId idgen, owner)
|
||||
result.typ.n = newNodeI(nkFormalParams, info)
|
||||
rawAddSon(result.typ, res.typ)
|
||||
result.typ.n.add newNodeI(nkEffectList, info)
|
||||
|
||||
result.typ.addParam src
|
||||
|
||||
if g.config.selectedGC == gcOrc and
|
||||
cyclicType(g, typ.skipTypes(abstractInst)):
|
||||
let cycleParam = newSym(skParam, getIdent(g.cache, "cyclic"),
|
||||
idgen, result, info)
|
||||
cycleParam.typ = getSysType(g, info, tyBool)
|
||||
result.typ.addParam cycleParam
|
||||
|
||||
var n = newNodeI(nkProcDef, info, bodyPos+2)
|
||||
for i in 0..<n.len: n[i] = newNodeI(nkEmpty, info)
|
||||
n[namePos] = newSymNode(result)
|
||||
n[paramsPos] = result.typ.n
|
||||
n[bodyPos] = newNodeI(nkStmtList, info)
|
||||
n[resultPos] = newSymNode(res)
|
||||
result.ast = n
|
||||
incl result.flags, sfFromGeneric
|
||||
incl result.flags, sfGeneratedOp
|
||||
|
||||
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp;
|
||||
info: TLineInfo; idgen: IdGenerator): PSym =
|
||||
if kind == attachedDup:
|
||||
return symDupPrototype(g, typ, owner, kind, info, idgen)
|
||||
|
||||
let procname = getIdent(g.cache, AttachedOpToStr[kind])
|
||||
result = newSym(skProc, procname, idgen, owner, info)
|
||||
@@ -992,7 +1064,7 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
|
||||
result.typ = newProcType(info, nextTypeId(idgen), owner)
|
||||
result.typ.addParam dest
|
||||
if kind notin {attachedDestructor, attachedWasMoved, attachedDup}:
|
||||
if kind notin {attachedDestructor, attachedWasMoved}:
|
||||
result.typ.addParam src
|
||||
|
||||
if kind == attachedAsgn and g.config.selectedGC == gcOrc and
|
||||
@@ -1033,9 +1105,11 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType: typ, idgen: idgen,
|
||||
fn: result)
|
||||
|
||||
let dest = result.typ.n[1].sym
|
||||
let d = newDeref(newSymNode(dest))
|
||||
let src = if kind in {attachedDestructor, attachedWasMoved, attachedDup}: newNodeIT(nkSym, info, getSysType(g, info, tyPointer))
|
||||
let dest = if kind == attachedDup: result.ast[resultPos].sym else: result.typ.n[1].sym
|
||||
let d = if kind == attachedDup: newSymNode(dest) else: newDeref(newSymNode(dest))
|
||||
let src = case kind
|
||||
of {attachedDestructor, attachedWasMoved}: newNodeIT(nkSym, info, getSysType(g, info, tyPointer))
|
||||
of attachedDup: newSymNode(result.typ.n[1].sym)
|
||||
else: newSymNode(result.typ.n[2].sym)
|
||||
|
||||
# register this operation already:
|
||||
@@ -1059,7 +1133,7 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
fillStrOp(a, typ, result.ast[bodyPos], d, src)
|
||||
else:
|
||||
fillBody(a, typ, result.ast[bodyPos], d, src)
|
||||
if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy} and not lacksMTypeField(typ):
|
||||
if tk == tyObject and a.kind in {attachedAsgn, attachedSink, attachedDeepCopy, attachedDup} and not lacksMTypeField(typ):
|
||||
# bug #19205: Do not forget to also copy the hidden type field:
|
||||
genTypeFieldCopy(a, typ, result.ast[bodyPos], d, src)
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ 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.} =
|
||||
@@ -354,7 +354,7 @@ proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} =
|
||||
discard
|
||||
|
||||
when defined(nimHasDup):
|
||||
proc `=dup`*[T](x: ref T): ref T {.inline, magic: "Dup".} =
|
||||
proc `=dup`*[T](x: T): T {.inline, magic: "Dup".} =
|
||||
## Generic `dup`:idx: implementation that can be overridden.
|
||||
discard
|
||||
|
||||
|
||||
@@ -200,10 +200,6 @@ proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} =
|
||||
when traceCollector:
|
||||
cprintf("[DECREF] %p\n", cell)
|
||||
|
||||
proc nimDupRef(dest: ptr pointer, src: pointer) {.compilerRtl, inl.} =
|
||||
dest[] = src
|
||||
if src != nil: nimIncRef src
|
||||
|
||||
proc GC_unref*[T](x: ref T) =
|
||||
## New runtime only supports this operation for 'ref T'.
|
||||
var y {.cursor.} = x
|
||||
|
||||
@@ -87,7 +87,7 @@ pkg "kdtree", "nimble test -d:nimLegacyRandomInitRand", "https://github.com/jbli
|
||||
pkg "loopfusion"
|
||||
pkg "lockfreequeues"
|
||||
pkg "macroutils"
|
||||
pkg "manu"
|
||||
pkg "manu", url = "https://github.com/nim-lang/manu"
|
||||
pkg "markdown"
|
||||
pkg "measuremancer", "nimble testDeps; nimble -y test"
|
||||
pkg "memo"
|
||||
|
||||
@@ -18,7 +18,7 @@ inc:
|
||||
var id_1 = 777
|
||||
s = RefCustom(id_2: addr(id_1))
|
||||
inc_1 :
|
||||
:tmpD_1 = `=dup`(s)
|
||||
:tmpD_1 = `=dup_1`(s)
|
||||
:tmpD_1
|
||||
inc_1 :
|
||||
let blitTmp_1 = s
|
||||
@@ -34,14 +34,15 @@ type
|
||||
RefCustom = object
|
||||
id: ptr int
|
||||
|
||||
proc `=dup`(x: RefCustom): RefCustom =
|
||||
result.id = x.id
|
||||
|
||||
proc inc(x: sink Ref) =
|
||||
inc x.id
|
||||
|
||||
proc inc(x: sink RefCustom) =
|
||||
inc x.id[]
|
||||
|
||||
proc `=dup`(x: RefCustom): RefCustom =
|
||||
result.id = x.id
|
||||
|
||||
proc foo =
|
||||
var x = Ref(id: 8)
|
||||
|
||||
@@ -61,11 +61,9 @@ var
|
||||
try:
|
||||
it_cursor = x
|
||||
a = (
|
||||
`=wasMoved`(:tmpD)
|
||||
`=copy`(:tmpD, it_cursor.key)
|
||||
:tmpD = `=dup`(it_cursor.key)
|
||||
:tmpD,
|
||||
`=wasMoved`(:tmpD_1)
|
||||
`=copy`(:tmpD_1, it_cursor.val)
|
||||
:tmpD_1 = `=dup`(it_cursor.val)
|
||||
:tmpD_1)
|
||||
echo [
|
||||
:tmpD_2 = `$$`(a)
|
||||
@@ -125,19 +123,16 @@ this.isValid = fileExists(this.value)
|
||||
if dirExists(this.value):
|
||||
var :tmpD
|
||||
par = (dir:
|
||||
`=wasMoved`(:tmpD)
|
||||
`=copy`(:tmpD, this.value)
|
||||
:tmpD = `=dup`(this.value)
|
||||
:tmpD, front: "") else:
|
||||
var
|
||||
:tmpD_1
|
||||
:tmpD_2
|
||||
:tmpD_3
|
||||
par = (dir_1: parentDir(this.value), front_1:
|
||||
`=wasMoved`(:tmpD_1)
|
||||
`=copy`(:tmpD_1,
|
||||
:tmpD_1 = `=dup`(
|
||||
:tmpD_3 = splitDrive do:
|
||||
`=wasMoved`(:tmpD_2)
|
||||
`=copy`(:tmpD_2, this.value)
|
||||
:tmpD_2 = `=dup`(this.value)
|
||||
:tmpD_2
|
||||
:tmpD_3.path)
|
||||
:tmpD_1)
|
||||
|
||||
@@ -39,8 +39,7 @@ try:
|
||||
if i_cursor == 2:
|
||||
return
|
||||
add(a):
|
||||
`=wasMoved`(:tmpD)
|
||||
`=copy`(:tmpD, x)
|
||||
:tmpD = `=dup`(x)
|
||||
:tmpD
|
||||
inc i_1, 1
|
||||
if cond:
|
||||
|
||||
@@ -39,7 +39,7 @@ proc `=destroy`*[T](dest: var SharedPtr[T]) =
|
||||
echo "deallocating"
|
||||
dest.x = nil
|
||||
|
||||
proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
|
||||
proc `=copy`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
|
||||
var s = src.x
|
||||
if s != nil: incRef(s)
|
||||
#atomicSwap(dest, s)
|
||||
@@ -50,6 +50,9 @@ proc `=`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
|
||||
deallocShared(s)
|
||||
echo "deallocating"
|
||||
|
||||
proc `=dup`*[T](src: SharedPtr[T]): SharedPtr[T] =
|
||||
`=copy`(result, src)
|
||||
|
||||
proc `=sink`*[T](dest: var SharedPtr[T]; src: SharedPtr[T]) =
|
||||
## XXX make this an atomic store:
|
||||
if dest.x != src.x:
|
||||
@@ -120,7 +123,7 @@ proc `=destroy`*[T](m: var MySeq[T]) {.inline.} =
|
||||
deallocShared(m.data)
|
||||
m.data = nil
|
||||
|
||||
proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) =
|
||||
proc `=copy`*[T](m: var MySeq[T], m2: MySeq[T]) =
|
||||
if m.data == m2.data: return
|
||||
if m.data != nil:
|
||||
`=destroy`(m)
|
||||
@@ -131,6 +134,9 @@ proc `=`*[T](m: var MySeq[T], m2: MySeq[T]) =
|
||||
m.data = cast[ptr UncheckedArray[T]](allocShared(bytes))
|
||||
copyMem(m.data, m2.data, bytes)
|
||||
|
||||
proc `=dup`*[T](m: MySeq[T]): MySeq[T] =
|
||||
`=copy`[T](result, m)
|
||||
|
||||
proc `=sink`*[T](m: var MySeq[T], m2: MySeq[T]) {.inline.} =
|
||||
if m.data != m2.data:
|
||||
if m.data != nil:
|
||||
|
||||
@@ -31,7 +31,7 @@ proc `=sink`*(a: var Matrix; b: Matrix) =
|
||||
a.m = b.m
|
||||
a.n = b.n
|
||||
|
||||
proc `=`*(a: var Matrix; b: Matrix) =
|
||||
proc `=copy`*(a: var Matrix; b: Matrix) =
|
||||
if a.data != nil and a.data != b.data:
|
||||
dealloc(a.data)
|
||||
deallocCount.inc
|
||||
@@ -43,6 +43,9 @@ proc `=`*(a: var Matrix; b: Matrix) =
|
||||
allocCount.inc
|
||||
copyMem(a.data, b.data, b.m * b.n * sizeof(float))
|
||||
|
||||
proc `=dup`*(a: Matrix): Matrix =
|
||||
`=copy`(result, a)
|
||||
|
||||
proc matrix*(m, n: int, s: float): Matrix =
|
||||
## Construct an m-by-n constant matrix.
|
||||
result.m = m
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
discard """
|
||||
errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
|
||||
errormsg: "'=dup' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
|
||||
file: "tprevent_assign2.nim"
|
||||
line: 48
|
||||
line: 49
|
||||
"""
|
||||
|
||||
type
|
||||
@@ -9,7 +9,8 @@ type
|
||||
x: int
|
||||
|
||||
proc `=destroy`(f: var Foo) = f.x = 0
|
||||
proc `=`(a: var Foo; b: Foo) {.error.} # = a.x = b.x
|
||||
proc `=copy`(a: var Foo; b: Foo) {.error.} # = a.x = b.x
|
||||
proc `=dup`(a: Foo): Foo {.error.}
|
||||
proc `=sink`(a: var Foo; b: Foo) = a.x = b.x
|
||||
|
||||
proc createTree(x: int): Foo =
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
discard """
|
||||
errormsg: "'=copy' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
|
||||
errormsg: "'=dup' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
|
||||
file: "tprevent_assign3.nim"
|
||||
line: 46
|
||||
line: 47
|
||||
"""
|
||||
|
||||
type
|
||||
@@ -9,7 +9,8 @@ type
|
||||
x: int
|
||||
|
||||
proc `=destroy`(f: var Foo) = f.x = 0
|
||||
proc `=`(a: var Foo; b: Foo) {.error.} # = a.x = b.x
|
||||
proc `=copy`(a: var Foo; b: Foo) {.error.} # = a.x = b.x
|
||||
proc `=dup`(a: Foo): Foo {.error.}
|
||||
proc `=sink`(a: var Foo; b: Foo) = a.x = b.x
|
||||
|
||||
proc createTree(x: int): Foo =
|
||||
|
||||
@@ -3,7 +3,7 @@ discard """
|
||||
@[116, 101, 115, 116]
|
||||
@[1953719668, 875770417]
|
||||
destroying O1'''
|
||||
cmd: '''nim c --gc:arc --expandArc:main --expandArc:main1 --expandArc:main2 --expandArc:main3 --hints:off --assertions:off $file'''
|
||||
cmd: '''nim c --mm:arc --expandArc:main --expandArc:main1 --expandArc:main2 --expandArc:main3 --hints:off --assertions:off $file'''
|
||||
nimout: '''
|
||||
--expandArc: main
|
||||
|
||||
@@ -13,8 +13,7 @@ var
|
||||
:tmpD_1
|
||||
:tmpD_2
|
||||
data =
|
||||
`=wasMoved`(:tmpD)
|
||||
`=copy`(:tmpD, cast[string](
|
||||
:tmpD = `=dup`(cast[string](
|
||||
:tmpD_2 = encode(cast[seq[byte]](
|
||||
:tmpD_1 = newString(100)
|
||||
:tmpD_1))
|
||||
@@ -33,8 +32,7 @@ var
|
||||
:tmpD_1
|
||||
s = newString(100)
|
||||
data =
|
||||
`=wasMoved`(:tmpD)
|
||||
`=copy`(:tmpD, cast[string](
|
||||
:tmpD = `=dup`(cast[string](
|
||||
:tmpD_1 = encode(toOpenArrayByte(s, 0, len(s) - 1))
|
||||
:tmpD_1))
|
||||
:tmpD
|
||||
@@ -51,8 +49,7 @@ var
|
||||
:tmpD_1
|
||||
s = newSeq(100)
|
||||
data =
|
||||
`=wasMoved`(:tmpD)
|
||||
`=copy`(:tmpD, cast[string](
|
||||
:tmpD = `=dup`(cast[string](
|
||||
:tmpD_1 = encode(s)
|
||||
:tmpD_1))
|
||||
:tmpD
|
||||
@@ -68,8 +65,7 @@ var
|
||||
:tmpD_1
|
||||
:tmpD_2
|
||||
data =
|
||||
`=wasMoved`(:tmpD)
|
||||
`=copy`(:tmpD, cast[string](
|
||||
:tmpD = `=dup`(cast[string](
|
||||
:tmpD_2 = encode do:
|
||||
:tmpD_1 = newSeq(100)
|
||||
:tmpD_1
|
||||
|
||||
Reference in New Issue
Block a user