DFA works for simple examples
This commit is contained in:
parent
6b321d0650
commit
c2d91771bc
1 changed files with 17 additions and 9 deletions
|
|
@ -344,20 +344,20 @@ proc dfa(code: seq[Instr]) =
|
||||||
case code[i].kind
|
case code[i].kind
|
||||||
of use, useWithinCall: u[i].incl(code[i].sym.id)
|
of use, useWithinCall: u[i].incl(code[i].sym.id)
|
||||||
of def: d[i].incl(code[i].sym.id)
|
of def: d[i].incl(code[i].sym.id)
|
||||||
of fork:
|
of fork, goto:
|
||||||
let d = i+code[i].dest
|
let d = i+code[i].dest
|
||||||
backrefs.add(d, i)
|
backrefs.add(d, i)
|
||||||
of goto: discard
|
|
||||||
|
|
||||||
var w = @[0]
|
var w = @[0]
|
||||||
var maxIters = 50
|
var maxIters = 50
|
||||||
var someChange = true
|
var someChange = true
|
||||||
while w.len > 0 and maxIters > 0 and someChange:
|
var takenGotos = initIntSet()
|
||||||
|
while w.len > 0 and maxIters > 0: # and someChange:
|
||||||
dec maxIters
|
dec maxIters
|
||||||
var pc = w.pop() # w[^1]
|
var pc = w.pop() # w[^1]
|
||||||
var prevPc = -1
|
var prevPc = -1
|
||||||
# this simulates a single linear control flow execution:
|
# this simulates a single linear control flow execution:
|
||||||
while pc < code.len and someChange:
|
while pc < code.len:
|
||||||
# according to the paper, it is better to shrink the working set here
|
# according to the paper, it is better to shrink the working set here
|
||||||
# in this inner loop:
|
# in this inner loop:
|
||||||
#let widx = w.find(pc)
|
#let widx = w.find(pc)
|
||||||
|
|
@ -386,17 +386,21 @@ proc dfa(code: seq[Instr]) =
|
||||||
if def notin d[prevPc]:
|
if def notin d[prevPc]:
|
||||||
excl(intersect, def)
|
excl(intersect, def)
|
||||||
someChange = true
|
someChange = true
|
||||||
|
when defined(debugDfa):
|
||||||
|
echo "Excluding ", pc, " prev ", prevPc
|
||||||
assign d[pc], intersect
|
assign d[pc], intersect
|
||||||
|
|
||||||
# our interpretation ![I!]:
|
# our interpretation ![I!]:
|
||||||
prevPc = pc
|
prevPc = pc
|
||||||
|
when defined(debugDfa):
|
||||||
|
echo "looking at ", pc
|
||||||
case code[pc].kind
|
case code[pc].kind
|
||||||
of goto:
|
of goto:
|
||||||
# we must leave endless loops eventually:
|
# we must leave endless loops eventually:
|
||||||
#if someChange:
|
if not takenGotos.containsOrIncl(pc) or someChange:
|
||||||
pc = pc + code[pc].dest
|
pc = pc + code[pc].dest
|
||||||
#else:
|
else:
|
||||||
# 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 someChange:
|
#if someChange:
|
||||||
|
|
@ -405,6 +409,10 @@ proc dfa(code: seq[Instr]) =
|
||||||
of use, useWithinCall, def:
|
of use, useWithinCall, def:
|
||||||
inc pc
|
inc pc
|
||||||
|
|
||||||
|
when defined(useDfa) and defined(debugDfa):
|
||||||
|
for i in 0..<code.len:
|
||||||
|
echo "PC ", i, ": defs: ", d[i], "; uses ", u[i]
|
||||||
|
|
||||||
# now check the condition we're interested in:
|
# now check the condition we're interested in:
|
||||||
for i in 0..<code.len:
|
for i in 0..<code.len:
|
||||||
case code[i].kind
|
case code[i].kind
|
||||||
|
|
@ -508,7 +516,7 @@ proc dfaUnused(code: seq[Instr]) =
|
||||||
proc dataflowAnalysis*(s: PSym; body: PNode) =
|
proc dataflowAnalysis*(s: PSym; body: PNode) =
|
||||||
var c = Con(code: @[], blocks: @[])
|
var c = Con(code: @[], blocks: @[])
|
||||||
gen(c, body)
|
gen(c, body)
|
||||||
#echoCfg(c.code)
|
when defined(useDfa) and defined(debugDfa): echoCfg(c.code)
|
||||||
dfa(c.code)
|
dfa(c.code)
|
||||||
|
|
||||||
proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =
|
proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue