Fix destructor injections for global variables (#11230)
* attach global destructors at end of mainModule * Add testcase * Minor cleanup * Inject topLevelVar temporaries' destructors early * Fix megatest
This commit is contained in:
parent
a3e27ffa2c
commit
0c869eaa47
7 changed files with 45 additions and 8 deletions
|
|
@ -1963,6 +1963,9 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
if b == nil: return
|
if b == nil: return
|
||||||
var m = BModule(b)
|
var m = BModule(b)
|
||||||
|
if sfMainModule in m.module.flags:
|
||||||
|
for destructorCall in graph.globalDestructors:
|
||||||
|
n.add destructorCall
|
||||||
if passes.skipCodegen(m.config, n): return
|
if passes.skipCodegen(m.config, n): return
|
||||||
# if the module is cached, we don't regenerate the main proc
|
# if the module is cached, we don't regenerate the main proc
|
||||||
# nor the dispatchers? But if the dispatchers changed?
|
# nor the dispatchers? But if the dispatchers changed?
|
||||||
|
|
|
||||||
|
|
@ -316,10 +316,6 @@ proc makePtrType(c: Con, baseType: PType): PType =
|
||||||
result = newType(tyPtr, c.owner)
|
result = newType(tyPtr, c.owner)
|
||||||
addSonSkipIntLit(result, baseType)
|
addSonSkipIntLit(result, baseType)
|
||||||
|
|
||||||
proc addDestroy(c: var Con; n: PNode) =
|
|
||||||
# append to front:
|
|
||||||
c.destroys = newTree(nkStmtList, n, c.destroys)
|
|
||||||
|
|
||||||
proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
|
proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
|
||||||
var op = t.attachedOps[kind]
|
var op = t.attachedOps[kind]
|
||||||
|
|
||||||
|
|
@ -738,7 +734,7 @@ proc p(n: PNode; c: var Con): PNode =
|
||||||
c.addTopVar v
|
c.addTopVar v
|
||||||
# make sure it's destroyed at the end of the proc:
|
# make sure it's destroyed at the end of the proc:
|
||||||
if not isUnpackedTuple(it[0].sym):
|
if not isUnpackedTuple(it[0].sym):
|
||||||
c.addDestroy genDestroy(c, v.typ, v)
|
c.destroys.add genDestroy(c, v.typ, v)
|
||||||
if ri.kind != nkEmpty:
|
if ri.kind != nkEmpty:
|
||||||
let r = moveOrCopy(v, ri, c)
|
let r = moveOrCopy(v, ri, c)
|
||||||
result.add r
|
result.add r
|
||||||
|
|
@ -757,7 +753,7 @@ proc p(n: PNode; c: var Con): PNode =
|
||||||
sinkExpr.add n
|
sinkExpr.add n
|
||||||
result.add sinkExpr
|
result.add sinkExpr
|
||||||
result.add tmp
|
result.add tmp
|
||||||
c.addDestroy genDestroy(c, n.typ, tmp)
|
c.destroys.add genDestroy(c, n.typ, tmp)
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
of nkAsgn, nkFastAsgn:
|
of nkAsgn, nkFastAsgn:
|
||||||
|
|
@ -799,6 +795,19 @@ proc p(n: PNode; c: var Con): PNode =
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
recurse(n, result)
|
recurse(n, result)
|
||||||
|
|
||||||
|
proc extractDestroysForTemporaries(c: Con, destroys: PNode): PNode =
|
||||||
|
result = newNodeI(nkStmtList, destroys.info)
|
||||||
|
for i in 0 ..< destroys.len:
|
||||||
|
if destroys[i][1][0].sym.kind == skTemp:
|
||||||
|
result.add destroys[i]
|
||||||
|
destroys[i] = c.emptyNode
|
||||||
|
|
||||||
|
proc reverseDestroys(destroys: PNode) =
|
||||||
|
var reversed: seq[PNode]
|
||||||
|
for i in countdown(destroys.len - 1, 0):
|
||||||
|
reversed.add(destroys[i])
|
||||||
|
destroys.sons = reversed
|
||||||
|
|
||||||
proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||||
if sfGeneratedOp in owner.flags or isInlineIterator(owner): return n
|
if sfGeneratedOp in owner.flags or isInlineIterator(owner): return n
|
||||||
var c: Con
|
var c: Con
|
||||||
|
|
@ -821,7 +830,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||||
for i in 1 ..< params.len:
|
for i in 1 ..< params.len:
|
||||||
let param = params[i].sym
|
let param = params[i].sym
|
||||||
if isSinkTypeForParam(param.typ) and hasDestructor(param.typ.skipTypes({tySink})):
|
if isSinkTypeForParam(param.typ) and hasDestructor(param.typ.skipTypes({tySink})):
|
||||||
c.addDestroy genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i])
|
c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i])
|
||||||
|
|
||||||
#if optNimV2 in c.graph.config.globalOptions:
|
#if optNimV2 in c.graph.config.globalOptions:
|
||||||
# injectDefaultCalls(n, c)
|
# injectDefaultCalls(n, c)
|
||||||
|
|
@ -830,6 +839,11 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||||
if c.topLevelVars.len > 0:
|
if c.topLevelVars.len > 0:
|
||||||
result.add c.topLevelVars
|
result.add c.topLevelVars
|
||||||
if c.destroys.len > 0:
|
if c.destroys.len > 0:
|
||||||
|
reverseDestroys(c.destroys)
|
||||||
|
if owner.kind == skModule:
|
||||||
|
result.add newTryFinally(body, extractDestroysForTemporaries(c, c.destroys))
|
||||||
|
g.globalDestructors.add c.destroys
|
||||||
|
else:
|
||||||
result.add newTryFinally(body, c.destroys)
|
result.add newTryFinally(body, c.destroys)
|
||||||
else:
|
else:
|
||||||
result.add body
|
result.add body
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ type
|
||||||
onDefinition*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
|
onDefinition*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
|
||||||
onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
|
onDefinitionResolveForward*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
|
||||||
onUsage*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
|
onUsage*: proc (graph: ModuleGraph; s: PSym; info: TLineInfo) {.nimcall.}
|
||||||
|
globalDestructors*: seq[PNode]
|
||||||
|
|
||||||
TPassContext* = object of RootObj # the pass's context
|
TPassContext* = object of RootObj # the pass's context
|
||||||
PPassContext* = ref TPassContext
|
PPassContext* = ref TPassContext
|
||||||
|
|
|
||||||
8
tests/destructor/objFile.nim
Normal file
8
tests/destructor/objFile.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
type Obj* = object
|
||||||
|
v*: int
|
||||||
|
|
||||||
|
proc `=destroy`(this: var Obj) =
|
||||||
|
echo "igotdestroyed"
|
||||||
|
this.v = -1
|
||||||
|
|
||||||
|
var test* = Obj(v: 42)
|
||||||
|
|
@ -6,6 +6,7 @@ discard """
|
||||||
10
|
10
|
||||||
destroyed!
|
destroyed!
|
||||||
'''
|
'''
|
||||||
|
joinable: false
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
||||||
9
tests/destructor/tglobaldestructor.nim
Normal file
9
tests/destructor/tglobaldestructor.nim
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
discard """
|
||||||
|
cmd: '''nim c --newruntime $file'''
|
||||||
|
output: '''(v: 42)
|
||||||
|
igotdestroyed'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import objFile
|
||||||
|
|
||||||
|
echo test
|
||||||
|
|
@ -3,6 +3,7 @@ discard """
|
||||||
output: '''5
|
output: '''5
|
||||||
vseq destroy
|
vseq destroy
|
||||||
'''
|
'''
|
||||||
|
joinable: false
|
||||||
"""
|
"""
|
||||||
type
|
type
|
||||||
opt*[T] = object
|
opt*[T] = object
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue