DFA: implement exception handling properly
This commit is contained in:
parent
a30ba8cc37
commit
b39302b0d2
3 changed files with 55 additions and 16 deletions
|
|
@ -216,6 +216,7 @@ proc isLastRead(n: PNode; c: var Con): bool =
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
var pcs: seq[int] = @[instr+1]
|
var pcs: seq[int] = @[instr+1]
|
||||||
var takenGotos: IntSet
|
var takenGotos: IntSet
|
||||||
|
var takenForks = initIntSet()
|
||||||
while pcs.len > 0:
|
while pcs.len > 0:
|
||||||
var pc = pcs.pop
|
var pc = pcs.pop
|
||||||
|
|
||||||
|
|
@ -251,7 +252,7 @@ proc isLastRead(n: PNode; c: var Con): bool =
|
||||||
inc pc
|
inc pc
|
||||||
of fork:
|
of fork:
|
||||||
# we follow the next instruction but push the dest onto our "work" stack:
|
# 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
|
pcs.add pc + c.g[pc].dest
|
||||||
inc pc
|
inc pc
|
||||||
#echo c.graph.config $ n.info, " last read here!"
|
#echo c.graph.config $ n.info, " last read here!"
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,9 @@ type
|
||||||
|
|
||||||
Con = object
|
Con = object
|
||||||
code: ControlFlowGraph
|
code: ControlFlowGraph
|
||||||
inCall: int
|
inCall, inTryStmt: int
|
||||||
blocks: seq[TBlock]
|
blocks: seq[TBlock]
|
||||||
|
tryStmtFixups: seq[TPosition]
|
||||||
|
|
||||||
proc debugInfo(info: TLineInfo): string =
|
proc debugInfo(info: TLineInfo): string =
|
||||||
result = $info.line #info.toFilename & ":" & $info.line
|
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) =
|
proc genTry(c: var Con; n: PNode) =
|
||||||
var endings: seq[TPosition] = @[]
|
var endings: seq[TPosition] = @[]
|
||||||
|
inc c.inTryStmt
|
||||||
|
var newFixups: seq[TPosition]
|
||||||
|
swap(newFixups, c.tryStmtFixups)
|
||||||
|
|
||||||
let elsePos = c.forkI(n)
|
let elsePos = c.forkI(n)
|
||||||
c.gen(n.sons[0])
|
c.gen(n.sons[0])
|
||||||
|
dec c.inTryStmt
|
||||||
|
for f in newFixups:
|
||||||
|
c.patch(f)
|
||||||
|
swap(newFixups, c.tryStmtFixups)
|
||||||
|
|
||||||
c.patch(elsePos)
|
c.patch(elsePos)
|
||||||
for i in 1 ..< n.len:
|
for i in 1 ..< n.len:
|
||||||
let it = n.sons[i]
|
let it = n.sons[i]
|
||||||
|
|
@ -244,7 +254,10 @@ proc genTry(c: var Con; n: PNode) =
|
||||||
|
|
||||||
proc genRaise(c: var Con; n: PNode) =
|
proc genRaise(c: var Con; n: PNode) =
|
||||||
gen(c, n.sons[0])
|
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) =
|
proc genReturn(c: var Con; n: PNode) =
|
||||||
if n.sons[0].kind != nkEmpty: gen(c, n.sons[0])
|
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])
|
gen(c, n[i])
|
||||||
if t != nil and i < t.len and t.sons[i].kind == tyVar:
|
if t != nil and i < t.len and t.sons[i].kind == tyVar:
|
||||||
genDef(c, n[i])
|
genDef(c, n[i])
|
||||||
|
# every call can potentially raise:
|
||||||
|
if c.inTryStmt > 0:
|
||||||
|
c.tryStmtFixups.add c.forkI(n)
|
||||||
dec c.inCall
|
dec c.inCall
|
||||||
|
|
||||||
proc genMagic(c: var Con; n: PNode; m: TMagic) =
|
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])
|
gen(c, n.sons[1])
|
||||||
of nkObjDownConv, nkStringToCString, nkCStringToString: gen(c, n.sons[0])
|
of nkObjDownConv, nkStringToCString, nkCStringToString: gen(c, n.sons[0])
|
||||||
of nkVarSection, nkLetSection: genVarSection(c, n)
|
of nkVarSection, nkLetSection: genVarSection(c, n)
|
||||||
|
of nkDefer:
|
||||||
|
doAssert false, "dfa construction pass requires the elimination of 'defer'"
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc dfa(code: seq[Instr]; conf: ConfigRef) =
|
proc dfa(code: seq[Instr]; conf: ConfigRef) =
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
discard """
|
discard """
|
||||||
errormsg: "'=' is not available for type <Foo>; requires a copy because it's not the last read of 'otherTree'"
|
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
|
type
|
||||||
|
|
@ -19,18 +25,21 @@ proc take2(a, b: sink Foo) =
|
||||||
|
|
||||||
proc allowThis() =
|
proc allowThis() =
|
||||||
var otherTree: Foo
|
var otherTree: Foo
|
||||||
for i in 0..3:
|
try:
|
||||||
while true:
|
for i in 0..3:
|
||||||
#if i == 0:
|
while true:
|
||||||
otherTree = createTree(44)
|
#if i == 0:
|
||||||
case i
|
otherTree = createTree(44)
|
||||||
of 0:
|
case i
|
||||||
echo otherTree
|
of 0:
|
||||||
take2(createTree(34), otherTree)
|
echo otherTree
|
||||||
of 1:
|
take2(createTree(34), otherTree)
|
||||||
take2(createTree(34), otherTree)
|
of 1:
|
||||||
else:
|
take2(createTree(34), otherTree)
|
||||||
discard
|
else:
|
||||||
|
discard
|
||||||
|
finally:
|
||||||
|
discard
|
||||||
|
|
||||||
proc preventThis() =
|
proc preventThis() =
|
||||||
var otherTree: Foo
|
var otherTree: Foo
|
||||||
|
|
@ -46,3 +55,14 @@ proc preventThis() =
|
||||||
take2(createTree(34), otherTree)
|
take2(createTree(34), otherTree)
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
proc preventThis2() =
|
||||||
|
var otherTree: Foo
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
otherTree = createTree(44)
|
||||||
|
echo otherTree
|
||||||
|
finally:
|
||||||
|
take2(createTree(34), otherTree)
|
||||||
|
finally:
|
||||||
|
echo otherTree
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue