ARC: solves phase ordering problems (#12654)

This commit is contained in:
Andreas Rumpf 2019-11-14 23:19:18 +01:00 • committed by GitHub
commit a14abc5708
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 65 additions and 62 deletions

View file

@ -228,7 +228,7 @@ type
TNodeKinds* = set[TNodeKind] TNodeKinds* = set[TNodeKind]
type type
TSymFlag* = enum # 39 flags! TSymFlag* = enum # 40 flags!
sfUsed, # read access of sym (for warnings) or simply used sfUsed, # read access of sym (for warnings) or simply used
sfExported, # symbol is exported from module sfExported, # symbol is exported from module
sfFromGeneric, # symbol is instantiation of a generic; this is needed sfFromGeneric, # symbol is instantiation of a generic; this is needed
@ -285,7 +285,7 @@ type
# destruction for --newruntime. # destruction for --newruntime.
sfTemplateParam # symbol is a template parameter sfTemplateParam # symbol is a template parameter
sfCursor # variable/field is a cursor, see RFC 177 for details sfCursor # variable/field is a cursor, see RFC 177 for details
sfInjectDestructors # whether the proc needs the 'injectdestructors' transformation
TSymFlags* = set[TSymFlag] TSymFlags* = set[TSymFlag]

View file

@ -14,7 +14,8 @@ import
nversion, nimsets, msgs, bitsets, idents, types, nversion, nimsets, msgs, bitsets, idents, types,
ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth, ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth,
rodutils, renderer, cgendata, ccgmerge, aliases, rodutils, renderer, cgendata, ccgmerge, aliases,
lowerings, tables, sets, ndi, lineinfos, pathutils, transf, enumtostr lowerings, tables, sets, ndi, lineinfos, pathutils, transf, enumtostr,
injectdestructors
when not defined(leanCompiler): when not defined(leanCompiler):
import spawn, semparallel import spawn, semparallel
@ -531,7 +532,7 @@ proc assignGlobalVar(p: BProc, n: PNode) =
var decl: Rope = nil var decl: Rope = nil
var td = getTypeDesc(p.module, s.loc.t) var td = getTypeDesc(p.module, s.loc.t)
if s.constraint.isNil: if s.constraint.isNil:
if s.alignment > 0: if s.kind in {skLet, skVar, skField, skForVar} and s.alignment > 0:
decl.addf "alignas($1) ", [rope(s.alignment)] decl.addf "alignas($1) ", [rope(s.alignment)]
if p.hcrOn: add(decl, "static ") if p.hcrOn: add(decl, "static ")
elif sfImportc in s.flags: add(decl, "extern ") elif sfImportc in s.flags: add(decl, "extern ")
@ -957,7 +958,10 @@ proc genProcAux(m: BModule, prc: PSym) =
var header = genProcHeader(m, prc) var header = genProcHeader(m, prc)
var returnStmt: Rope = nil var returnStmt: Rope = nil
assert(prc.ast != nil) assert(prc.ast != nil)
let procBody = transformBody(m.g.graph, prc, cache = false)
var procBody = transformBody(m.g.graph, prc, cache = false)
if sfInjectDestructors in prc.flags:
procBody = injectDestructorCalls(m.g.graph, prc, procBody)
if sfPure notin prc.flags and prc.typ.sons[0] != nil: if sfPure notin prc.flags and prc.typ.sons[0] != nil:
if resultPos >= prc.ast.len: if resultPos >= prc.ast.len:
@ -1857,7 +1861,10 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
m.initProc.options = initProcOptions(m) m.initProc.options = initProcOptions(m)
#softRnl = if optLineDir in m.config.options: noRnl else: rnl #softRnl = if optLineDir in m.config.options: noRnl else: rnl
# XXX replicate this logic! # XXX replicate this logic!
let transformedN = transformStmt(m.g.graph, m.module, n) var transformedN = transformStmt(m.g.graph, m.module, n)
if sfInjectDestructors in m.module.flags:
transformedN = injectDestructorCalls(m.g.graph, m.module, transformedN)
if m.hcrOn: if m.hcrOn:
addHcrInitGuards(m.initProc, transformedN, m.inHcrInitGuard) addHcrInitGuards(m.initProc, transformedN, m.inHcrInitGuard)
else: else:

View file

@ -33,7 +33,7 @@ import
nversion, msgs, idents, types, tables, nversion, msgs, idents, types, tables,
ropes, math, passes, ccgutils, wordrecg, renderer, ropes, math, passes, ccgutils, wordrecg, renderer,
intsets, cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils, intsets, cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
transf transf, injectdestructors
from modulegraphs import ModuleGraph, PPassContext from modulegraphs import ModuleGraph, PPassContext
@ -2259,7 +2259,10 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
else: else:
returnStmt = "return $#;$n" % [a.res] returnStmt = "return $#;$n" % [a.res]
let transformedBody = transformBody(oldProc.module.graph, prc, cache = false) var transformedBody = transformBody(oldProc.module.graph, prc, cache = false)
if sfInjectDestructors in prc.flags:
transformedBody = injectDestructorCalls(oldProc.module.graph, prc, transformedBody)
p.nested: genStmt(p, transformedBody) p.nested: genStmt(p, transformedBody)
var def: Rope var def: Rope
@ -2540,7 +2543,9 @@ proc genModule(p: PProc, n: PNode) =
add(p.body, frameCreate(p, add(p.body, frameCreate(p,
makeJSString("module " & p.module.module.name.s), makeJSString("module " & p.module.module.name.s),
makeJSString(toFilename(p.config, p.module.module.info)))) makeJSString(toFilename(p.config, p.module.module.info))))
let transformedN = transformStmt(p.module.graph, p.module.module, n) var transformedN = transformStmt(p.module.graph, p.module.module, n)
if sfInjectDestructors in p.module.module.flags:
transformedN = injectDestructorCalls(p.module.graph, p.module.module, transformedN)
if p.config.hcrOn and n.kind == nkStmtList: if p.config.hcrOn and n.kind == nkStmtList:
let moduleSym = p.module.module let moduleSym = p.module.module
var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" & var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" &

View file

@ -296,7 +296,7 @@ type
DetectionPass = object DetectionPass = object
processed, capturedVars: IntSet processed, capturedVars: IntSet
ownerToType: Table[int, PType] ownerToType: Table[int, PType]
somethingToDo, noDestructors: bool somethingToDo: bool
graph: ModuleGraph graph: ModuleGraph
proc initDetectionPass(g: ModuleGraph; fn: PSym): DetectionPass = proc initDetectionPass(g: ModuleGraph; fn: PSym): DetectionPass =
@ -423,8 +423,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
if innerProc: if innerProc:
if s.isIterator: c.somethingToDo = true if s.isIterator: c.somethingToDo = true
if not c.processed.containsOrIncl(s.id): if not c.processed.containsOrIncl(s.id):
let body = transformBody(c.graph, s, cache = true, let body = transformBody(c.graph, s, cache = true)
noDestructors = c.noDestructors)
detectCapturedVars(body, s, c) detectCapturedVars(body, s, c)
let ow = s.skipGenericOwner let ow = s.skipGenericOwner
if ow == owner: if ow == owner:
@ -714,7 +713,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
# echo renderTree(s.getBody, {renderIds}) # echo renderTree(s.getBody, {renderIds})
let oldInContainer = c.inContainer let oldInContainer = c.inContainer
c.inContainer = 0 c.inContainer = 0
var body = transformBody(d.graph, s) var body = transformBody(d.graph, s, cache = false)
body = liftCapturedVars(body, s, d, c) body = liftCapturedVars(body, s, d, c)
if c.envVars.getOrDefault(s.id).isNil: if c.envVars.getOrDefault(s.id).isNil:
s.transformedBody = body s.transformedBody = body
@ -833,8 +832,7 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
fn.kind = oldKind fn.kind = oldKind
fn.typ.callConv = oldCC fn.typ.callConv = oldCC
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool; proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
noDestructors: bool): PNode =
# XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ... # the transformation even when compiling to JS ...
@ -850,7 +848,6 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
tooEarly = true tooEarly = true
else: else:
var d = initDetectionPass(g, fn) var d = initDetectionPass(g, fn)
d.noDestructors = noDestructors
detectCapturedVars(body, fn, d) detectCapturedVars(body, fn, d)
if not d.somethingToDo and fn.isIterator: if not d.somethingToDo and fn.isIterator:
addClosureParam(d, fn, body.info) addClosureParam(d, fn, body.info)

View file

@ -671,6 +671,12 @@ proc cstringCheck(tracked: PEffects; n: PNode) =
a.typ.kind == tyString and a.kind notin {nkStrLit..nkTripleStrLit}): a.typ.kind == tyString and a.kind notin {nkStrLit..nkTripleStrLit}):
message(tracked.config, n.info, warnUnsafeCode, renderTree(n)) message(tracked.config, n.info, warnUnsafeCode, renderTree(n))
proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) =
createTypeBoundOps(tracked.graph, tracked.c, typ, info)
if (typ != nil and tfHasAsgn in typ.flags) or
optSeqDestructors in tracked.config.globalOptions:
tracked.owner.flags.incl sfInjectDestructors
proc track(tracked: PEffects, n: PNode) = proc track(tracked: PEffects, n: PNode) =
template gcsafeAndSideeffectCheck() = template gcsafeAndSideeffectCheck() =
if notGcSafe(op) and not importedFromC(a): if notGcSafe(op) and not importedFromC(a):
@ -693,7 +699,7 @@ proc track(tracked: PEffects, n: PNode) =
addEffect(tracked, n.sons[0], useLineInfo=false) addEffect(tracked, n.sons[0], useLineInfo=false)
for i in 0 ..< safeLen(n): for i in 0 ..< safeLen(n):
track(tracked, n.sons[i]) track(tracked, n.sons[i])
createTypeBoundOps(tracked.graph, tracked.c, n[0].typ, n.info) createTypeBoundOps(tracked, n[0].typ, n.info)
else: else:
# A `raise` with no arguments means we're going to re-raise the exception # A `raise` with no arguments means we're going to re-raise the exception
# being handled or, if outside of an `except` block, a `ReraiseError`. # being handled or, if outside of an `except` block, a `ReraiseError`.
@ -707,7 +713,7 @@ proc track(tracked: PEffects, n: PNode) =
return return
if n.typ != nil: if n.typ != nil:
if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray: if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray:
createTypeBoundOps(tracked.graph, tracked.c, n.typ, n.info) createTypeBoundOps(tracked, n.typ, n.info)
if a.kind == nkCast and a[1].typ.kind == tyProc: if a.kind == nkCast and a[1].typ.kind == tyProc:
a = a[1] a = a[1]
# XXX: in rare situations, templates and macros will reach here after # XXX: in rare situations, templates and macros will reach here after
@ -750,7 +756,7 @@ proc track(tracked: PEffects, n: PNode) =
message(tracked.config, arg.info, warnProveInit, $arg) message(tracked.config, arg.info, warnProveInit, $arg)
# check required for 'nim check': # check required for 'nim check':
if n[1].typ.len > 0: if n[1].typ.len > 0:
createTypeBoundOps(tracked.graph, tracked.c, n[1].typ.lastSon, n.info) createTypeBoundOps(tracked, n[1].typ.lastSon, n.info)
for i in 0 ..< safeLen(n): for i in 0 ..< safeLen(n):
track(tracked, n.sons[i]) track(tracked, n.sons[i])
of nkDotExpr: of nkDotExpr:
@ -771,18 +777,18 @@ proc track(tracked: PEffects, n: PNode) =
notNilCheck(tracked, n.sons[1], n.sons[0].typ) notNilCheck(tracked, n.sons[1], n.sons[0].typ)
when false: cstringCheck(tracked, n) when false: cstringCheck(tracked, n)
if tracked.owner.kind != skMacro: if tracked.owner.kind != skMacro:
createTypeBoundOps(tracked.graph, tracked.c, n[0].typ, n.info) createTypeBoundOps(tracked, n[0].typ, n.info)
of nkVarSection, nkLetSection: of nkVarSection, nkLetSection:
for child in n: for child in n:
let last = lastSon(child) let last = lastSon(child)
if last.kind != nkEmpty: track(tracked, last) if last.kind != nkEmpty: track(tracked, last)
if tracked.owner.kind != skMacro: if tracked.owner.kind != skMacro:
if child.kind == nkVarTuple: if child.kind == nkVarTuple:
createTypeBoundOps(tracked.graph, tracked.c, child[^1].typ, child.info) createTypeBoundOps(tracked, child[^1].typ, child.info)
for i in 0..child.len-3: for i in 0..child.len-3:
createTypeBoundOps(tracked.graph, tracked.c, child[i].typ, child.info) createTypeBoundOps(tracked, child[i].typ, child.info)
else: else:
createTypeBoundOps(tracked.graph, tracked.c, child[0].typ, child.info) createTypeBoundOps(tracked, child[0].typ, child.info)
if child.kind == nkIdentDefs and last.kind != nkEmpty: if child.kind == nkIdentDefs and last.kind != nkEmpty:
for i in 0 .. child.len-3: for i in 0 .. child.len-3:
initVar(tracked, child.sons[i], volatileCheck=false) initVar(tracked, child.sons[i], volatileCheck=false)
@ -828,15 +834,15 @@ proc track(tracked: PEffects, n: PNode) =
if tracked.owner.kind != skMacro: if tracked.owner.kind != skMacro:
if it.kind == nkVarTuple: if it.kind == nkVarTuple:
for x in it: for x in it:
createTypeBoundOps(tracked.graph, tracked.c, x.typ, x.info) createTypeBoundOps(tracked, x.typ, x.info)
else: else:
createTypeBoundOps(tracked.graph, tracked.c, it.typ, it.info) createTypeBoundOps(tracked, it.typ, it.info)
let iterCall = n[n.len-2] let iterCall = n[n.len-2]
let loopBody = n[n.len-1] let loopBody = n[n.len-1]
if tracked.owner.kind != skMacro and iterCall.safeLen > 1: if tracked.owner.kind != skMacro and iterCall.safeLen > 1:
# XXX this is a bit hacky: # XXX this is a bit hacky:
if iterCall[1].typ != nil and iterCall[1].typ.skipTypes(abstractVar).kind notin {tyVarargs, tyOpenArray}: if iterCall[1].typ != nil and iterCall[1].typ.skipTypes(abstractVar).kind notin {tyVarargs, tyOpenArray}:
createTypeBoundOps(tracked.graph, tracked.c, iterCall[1].typ, iterCall[1].info) createTypeBoundOps(tracked, iterCall[1].typ, iterCall[1].info)
track(tracked, iterCall) track(tracked, iterCall)
track(tracked, loopBody) track(tracked, loopBody)
setLen(tracked.init, oldState) setLen(tracked.init, oldState)

View file

@ -21,11 +21,10 @@
import import
options, ast, astalgo, trees, msgs, options, ast, astalgo, trees, msgs,
idents, renderer, types, semfold, magicsys, cgmeth, idents, renderer, types, semfold, magicsys, cgmeth,
lowerings, injectdestructors, liftlocals, lowerings, liftlocals,
modulegraphs, lineinfos modulegraphs, lineinfos
proc transformBody*(g: ModuleGraph, prc: PSym, cache = true; proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode
noDestructors = false): PNode
import closureiters, lambdalifting import closureiters, lambdalifting
@ -49,7 +48,7 @@ type
inlining: int # > 0 if we are in inlining context (copy vars) inlining: int # > 0 if we are in inlining context (copy vars)
nestedProcs: int # > 0 if we are in a nested proc nestedProcs: int # > 0 if we are in a nested proc
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
deferDetected, tooEarly, needsDestroyPass, noDestructors: bool deferDetected, tooEarly: bool
graph: ModuleGraph graph: ModuleGraph
PTransf = ref TTransfContext PTransf = ref TTransfContext
@ -131,7 +130,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
let s = n.sym let s = n.sym
if s.typ != nil and s.typ.callConv == ccClosure: if s.typ != nil and s.typ.callConv == ccClosure:
if s.kind in routineKinds: if s.kind in routineKinds:
discard transformBody(c.graph, s, true, c.noDestructors) discard transformBody(c.graph, s, true)
if s.kind == skIterator: if s.kind == skIterator:
if c.tooEarly: return n if c.tooEarly: return n
else: return liftIterSym(c.graph, n, getCurrOwner(c)) else: return liftIterSym(c.graph, n, getCurrOwner(c))
@ -678,7 +677,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode)) add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode))
idNodeTablePut(newC.mapping, formal, temp) idNodeTablePut(newC.mapping, formal, temp)
let body = transformBody(c.graph, iter, true, c.noDestructors) let body = transformBody(c.graph, iter, true)
pushInfoContext(c.graph.config, n.info) pushInfoContext(c.graph.config, n.info)
inc(c.inlining) inc(c.inlining)
add(stmtList, transform(c, body)) add(stmtList, transform(c, body))
@ -913,9 +912,6 @@ proc transform(c: PTransf, n: PNode): PTransNode =
nkBlockStmt, nkBlockExpr}: nkBlockStmt, nkBlockExpr}:
oldDeferAnchor = c.deferAnchor oldDeferAnchor = c.deferAnchor
c.deferAnchor = n c.deferAnchor = n
if (n.typ != nil and tfHasAsgn in n.typ.flags) or
optSeqDestructors in c.graph.config.globalOptions:
c.needsDestroyPass = true
case n.kind case n.kind
of nkSym: of nkSym:
result = transformSym(c, n) result = transformSym(c, n)
@ -1113,8 +1109,7 @@ template liftDefer(c, root) =
if c.deferDetected: if c.deferDetected:
liftDeferAux(root) liftDeferAux(root)
proc transformBody*(g: ModuleGraph, prc: PSym, cache = true; proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode =
noDestructors = false): PNode =
assert prc.kind in routineKinds assert prc.kind in routineKinds
if prc.transformedBody != nil: if prc.transformedBody != nil:
@ -1124,13 +1119,10 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache = true;
else: else:
prc.transformedBody = newNode(nkEmpty) # protects from recursion prc.transformedBody = newNode(nkEmpty) # protects from recursion
var c = openTransf(g, prc.getModule, "") var c = openTransf(g, prc.getModule, "")
c.noDestructors = noDestructors result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly)
result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly, noDestructors)
result = processTransf(c, result, prc) result = processTransf(c, result, prc)
liftDefer(c, result) liftDefer(c, result)
result = liftLocalsIfRequested(prc, result, g.cache, g.config) result = liftLocalsIfRequested(prc, result, g.cache, g.config)
if c.needsDestroyPass and not noDestructors:
result = injectDestructorCalls(g, prc, result)
if prc.isIterator: if prc.isIterator:
result = g.transformClosureIterator(prc, result) result = g.transformClosureIterator(prc, result)
@ -1152,12 +1144,9 @@ proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode =
result = processTransf(c, n, module) result = processTransf(c, n, module)
liftDefer(c, result) liftDefer(c, result)
#result = liftLambdasForTopLevel(module, result) #result = liftLambdasForTopLevel(module, result)
if c.needsDestroyPass:
result = injectDestructorCalls(g, module, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode; proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
noDestructors = false): PNode =
if nfTransf in n.flags: if nfTransf in n.flags:
result = n result = n
else: else:
@ -1166,6 +1155,4 @@ proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode;
liftDefer(c, result) liftDefer(c, result)
# expressions are not to be injected with destructor calls as that # expressions are not to be injected with destructor calls as that
# the list of top level statements needs to be collected before. # the list of top level statements needs to be collected before.
if c.needsDestroyPass and not noDestructors:
result = injectDestructorCalls(g, module, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)

View file

@ -1005,13 +1005,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
decodeB(rkNode) decodeB(rkNode)
let a = regs[rb].node let a = regs[rb].node
if a.kind == nkSym: if a.kind == nkSym:
regs[ra].node = if a.sym.ast.isNil: newNode(nkNilLit) regs[ra].node =
else: if a.sym.ast.isNil:
let ast = a.sym.ast.shallowCopy newNode(nkNilLit)
for i in 0..<a.sym.ast.len: else:
ast[i] = a.sym.ast[i] let ast = a.sym.ast.shallowCopy
ast[bodyPos] = transformBody(c.graph, a.sym) for i in 0..<a.sym.ast.len:
ast.copyTree() ast[i] = a.sym.ast[i]
ast[bodyPos] = transformBody(c.graph, a.sym, cache=true)
ast.copyTree()
of opcSymOwner: of opcSymOwner:
decodeB(rkNode) decodeB(rkNode)
let a = regs[rb].node let a = regs[rb].node
@ -1983,7 +1985,7 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
"NimScript: attempt to call non-routine: " & sym.name.s) "NimScript: attempt to call non-routine: " & sym.name.s)
proc evalStmt*(c: PCtx, n: PNode) = proc evalStmt*(c: PCtx, n: PNode) =
let n = transformExpr(c.graph, c.module, n, noDestructors = true) let n = transformExpr(c.graph, c.module, n)
let start = genStmt(c, n) let start = genStmt(c, n)
# execute new instructions; this redundant opcEof check saves us lots # execute new instructions; this redundant opcEof check saves us lots
# of allocations in 'execute': # of allocations in 'execute':
@ -1991,7 +1993,7 @@ proc evalStmt*(c: PCtx, n: PNode) =
discard execute(c, start) discard execute(c, start)
proc evalExpr*(c: PCtx, n: PNode): PNode = proc evalExpr*(c: PCtx, n: PNode): PNode =
let n = transformExpr(c.graph, c.module, n, noDestructors = true) let n = transformExpr(c.graph, c.module, n)
let start = genExpr(c, n) let start = genExpr(c, n)
assert c.code[start].opcode != opcEof assert c.code[start].opcode != opcEof
result = execute(c, start) result = execute(c, start)
@ -2037,7 +2039,7 @@ proc evalConstExprAux(module: PSym;
g: ModuleGraph; prc: PSym, n: PNode, g: ModuleGraph; prc: PSym, n: PNode,
mode: TEvalMode): PNode = mode: TEvalMode): PNode =
if g.config.errorCounter > 0: return n if g.config.errorCounter > 0: return n
let n = transformExpr(g, module, n, noDestructors = true) let n = transformExpr(g, module, n)
setupGlobalCtx(module, g) setupGlobalCtx(module, g)
var c = PCtx g.vm var c = PCtx g.vm
let oldMode = c.mode let oldMode = c.mode

View file

@ -2243,8 +2243,7 @@ proc genProc(c: PCtx; s: PSym): int =
s.ast.sons[miscPos] = x s.ast.sons[miscPos] = x
# thanks to the jmp we can add top level statements easily and also nest # thanks to the jmp we can add top level statements easily and also nest
# procs easily: # procs easily:
let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s), let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s))
noDestructors = true)
let procStart = c.xjmp(body, opcJmp, 0) let procStart = c.xjmp(body, opcJmp, 0)
var p = PProc(blocks: @[], sym: s) var p = PProc(blocks: @[], sym: s)
let oldPrc = c.prc let oldPrc = c.prc

View file

@ -58,9 +58,9 @@ iterator items(p: Pony): int =
for x in getPony(): for x in getPony():
echo x echo x
# XXX this needs to be enabled once top level statements
# produce destructor calls again.
#echo "Pony is dying!"
#------------------------------------------------------------ #------------------------------------------------------------