From ae24b872191bead0ed2ba456fb78903b9717f107 Mon Sep 17 00:00:00 2001 From: Andrii Riabushenko Date: Sat, 8 Dec 2018 23:04:38 +0000 Subject: [PATCH] Double sink checks --- compiler/destroyer.nim | 66 ++++++++++++++++++++++++++++++++---- tests/destructor/tmatrix.nim | 12 +++---- 2 files changed, 65 insertions(+), 13 deletions(-) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index c5f49984e..bed60a3e0 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -116,7 +116,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, - strutils, options, dfa, lowerings, tables, modulegraphs, + strutils, options, dfa, lowerings, tables, modulegraphs, msgs, lineinfos, parampatterns const @@ -128,6 +128,8 @@ type g: ControlFlowGraph jumpTargets: IntSet destroys, topLevelVars: PNode + tracingSinkedParams: bool # we aren't checking double sink for proc args in if, case, loops since they possibly not taken + alreadySinkedParams: Table[int, TLineInfo] graph: ModuleGraph emptyNode: PNode otherRead: PNode @@ -365,6 +367,16 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode = result.add genWasMoved(n, c) result.add tempAsNode +proc sinkParamConsumed(c: var Con, s: PNode, tracing = true) = + assert s.kind == nkSym + let isConsumed = + if c.tracingSinkedParams and tracing: + c.alreadySinkedParams.hasKeyOrPut(s.sym.id, s.info) + else: c.alreadySinkedParams.hasKey(s.sym.id) + if isConsumed: + localError(c.graph.config, s.info, "sink parameter `" & $s.sym.name.s & + "` is already consumed at " & toFileLineCol(c. graph.config, c.alreadySinkedParams[s.sym.id])) + proc passCopyToSink(n: PNode; c: var Con): PNode = result = newNodeIT(nkStmtListExpr, n.info, n.typ) let tmp = getTemp(c, n.typ, n.info) @@ -399,10 +411,14 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkFloat128Lit}: discard "object construction to sink parameter: nothing to do" result = arg - elif arg.kind == nkSym and (isSinkParam(arg.sym) or - arg.sym.kind in InterestingSyms and isLastRead(arg, c)): - # it is the last read be final consumption. We need to reset the memory - # to disable the destructor which we have not elided: + elif arg.kind == nkSym and isSinkParam(arg.sym): + # Sinked params can be consumed only once. We need to reset the memory + # to disable the destructor which we have not elided + result = destructiveMoveVar(arg, c) + sinkParamConsumed(c, arg) + elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c): + # it is the last read, can be sinked. We need to reset the memory + # to disable the destructor which we have not elided result = destructiveMoveVar(arg, c) elif arg.kind in {nkBlockExpr, nkBlockStmt}: result = copyNode(arg) @@ -415,6 +431,7 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode = result.add pArg(arg[^1], c, isSink) elif arg.kind in {nkIfExpr, nkIfStmt}: result = copyNode(arg) + c.tracingSinkedParams = false for i in 0..