DFA: implement exception handling properly

This commit is contained in:
Andreas Rumpf
2018-10-14 13:19:33 +02:00
parent a30ba8cc37
commit b39302b0d2
3 changed files with 55 additions and 16 deletions

View File

@@ -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!"

View File

@@ -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) =

View File

@@ -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