mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 13:30:33 +00:00
DFA: implement exception handling properly
This commit is contained in:
@@ -216,6 +216,7 @@ proc isLastRead(n: PNode; c: var Con): bool =
|
||||
let s = n.sym
|
||||
var pcs: seq[int] = @[instr+1]
|
||||
var takenGotos: IntSet
|
||||
var takenForks = initIntSet()
|
||||
while pcs.len > 0:
|
||||
var pc = pcs.pop
|
||||
|
||||
@@ -251,7 +252,7 @@ proc isLastRead(n: PNode; c: var Con): bool =
|
||||
inc pc
|
||||
of fork:
|
||||
# we follow the next instruction but push the dest onto our "work" stack:
|
||||
if not takenGotos.containsOrIncl(pc):
|
||||
if not takenForks.containsOrIncl(pc):
|
||||
pcs.add pc + c.g[pc].dest
|
||||
inc pc
|
||||
#echo c.graph.config $ n.info, " last read here!"
|
||||
|
||||
@@ -53,8 +53,9 @@ type
|
||||
|
||||
Con = object
|
||||
code: ControlFlowGraph
|
||||
inCall: int
|
||||
inCall, inTryStmt: int
|
||||
blocks: seq[TBlock]
|
||||
tryStmtFixups: seq[TPosition]
|
||||
|
||||
proc debugInfo(info: TLineInfo): string =
|
||||
result = $info.line #info.toFilename & ":" & $info.line
|
||||
@@ -225,8 +226,17 @@ proc genCase(c: var Con; n: PNode) =
|
||||
|
||||
proc genTry(c: var Con; n: PNode) =
|
||||
var endings: seq[TPosition] = @[]
|
||||
inc c.inTryStmt
|
||||
var newFixups: seq[TPosition]
|
||||
swap(newFixups, c.tryStmtFixups)
|
||||
|
||||
let elsePos = c.forkI(n)
|
||||
c.gen(n.sons[0])
|
||||
dec c.inTryStmt
|
||||
for f in newFixups:
|
||||
c.patch(f)
|
||||
swap(newFixups, c.tryStmtFixups)
|
||||
|
||||
c.patch(elsePos)
|
||||
for i in 1 ..< n.len:
|
||||
let it = n.sons[i]
|
||||
@@ -244,7 +254,10 @@ proc genTry(c: var Con; n: PNode) =
|
||||
|
||||
proc genRaise(c: var Con; n: PNode) =
|
||||
gen(c, n.sons[0])
|
||||
c.code.add Instr(n: n, kind: goto, dest: high(int) - c.code.len)
|
||||
if c.inTryStmt > 0:
|
||||
c.tryStmtFixups.add c.gotoI(n)
|
||||
else:
|
||||
c.code.add Instr(n: n, kind: goto, dest: high(int) - c.code.len)
|
||||
|
||||
proc genReturn(c: var Con; n: PNode) =
|
||||
if n.sons[0].kind != nkEmpty: gen(c, n.sons[0])
|
||||
@@ -275,6 +288,9 @@ proc genCall(c: var Con; n: PNode) =
|
||||
gen(c, n[i])
|
||||
if t != nil and i < t.len and t.sons[i].kind == tyVar:
|
||||
genDef(c, n[i])
|
||||
# every call can potentially raise:
|
||||
if c.inTryStmt > 0:
|
||||
c.tryStmtFixups.add c.forkI(n)
|
||||
dec c.inCall
|
||||
|
||||
proc genMagic(c: var Con; n: PNode; m: TMagic) =
|
||||
@@ -340,6 +356,8 @@ proc gen(c: var Con; n: PNode) =
|
||||
gen(c, n.sons[1])
|
||||
of nkObjDownConv, nkStringToCString, nkCStringToString: gen(c, n.sons[0])
|
||||
of nkVarSection, nkLetSection: genVarSection(c, n)
|
||||
of nkDefer:
|
||||
doAssert false, "dfa construction pass requires the elimination of 'defer'"
|
||||
else: discard
|
||||
|
||||
proc dfa(code: seq[Instr]; conf: ConfigRef) =
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
discard """
|
||||
errormsg: "'=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
|
||||
line: 44
|
||||
|
||||
cmd: "nim check --hint[Performance]:off $file"
|
||||
nimout: '''
|
||||
tprevent_assign2.nim(53, 31) Error: '=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'; another read is done here: tprevent_assign2.nim(52, 13)
|
||||
tprevent_assign2.nim(55, 31) Error: '=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'; another read is done here: tprevent_assign2.nim(52, 13)
|
||||
tprevent_assign2.nim(66, 29) Error: '=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'; another read is done here: tprevent_assign2.nim(68, 9)
|
||||
'''
|
||||
"""
|
||||
|
||||
type
|
||||
@@ -19,18 +25,21 @@ proc take2(a, b: sink Foo) =
|
||||
|
||||
proc allowThis() =
|
||||
var otherTree: Foo
|
||||
for i in 0..3:
|
||||
while true:
|
||||
#if i == 0:
|
||||
otherTree = createTree(44)
|
||||
case i
|
||||
of 0:
|
||||
echo otherTree
|
||||
take2(createTree(34), otherTree)
|
||||
of 1:
|
||||
take2(createTree(34), otherTree)
|
||||
else:
|
||||
discard
|
||||
try:
|
||||
for i in 0..3:
|
||||
while true:
|
||||
#if i == 0:
|
||||
otherTree = createTree(44)
|
||||
case i
|
||||
of 0:
|
||||
echo otherTree
|
||||
take2(createTree(34), otherTree)
|
||||
of 1:
|
||||
take2(createTree(34), otherTree)
|
||||
else:
|
||||
discard
|
||||
finally:
|
||||
discard
|
||||
|
||||
proc preventThis() =
|
||||
var otherTree: Foo
|
||||
@@ -46,3 +55,14 @@ proc preventThis() =
|
||||
take2(createTree(34), otherTree)
|
||||
else:
|
||||
discard
|
||||
|
||||
proc preventThis2() =
|
||||
var otherTree: Foo
|
||||
try:
|
||||
try:
|
||||
otherTree = createTree(44)
|
||||
echo otherTree
|
||||
finally:
|
||||
take2(createTree(34), otherTree)
|
||||
finally:
|
||||
echo otherTree
|
||||
|
||||
Reference in New Issue
Block a user