Posted to tcl by kbk at Wed Jan 08 23:32:55 GMT 2014view pretty
set vars [analyzeProgram $program db]
set vnames [dict keys $vars]
db relation seq st st2
db relation writes st v
db relation flowspast v st st2
db relation reaches v st st2
db relation uninitRead st v
db relation deadWrite st v
# db relation induction v st
proc reaching_defs {} [bdd::datalog::compileProgram db {
% A false entry node (node 0) sets every variable and flows
% to node 1. If any of its variables are reachable, those are
% variables possibly used uninitialized in the program.
writes(0, _).
writes(st,v) :- writes0(st,v).
seq(0, 1).
seq(st,st2) :- seq0(st,st2).
% flowspast(v,st,st2) means that control passes from the exit of st
% to the entry of st2 without altering the value of v
flowspast(_, st, st2) :- seq(st, st2).
flowspast(v, st3, st2) :- flowspast(v, st3, st),
!writes(st, v),
flowspast(v, st, st2).
% reaches(v,st,st2) means that st assigns a value to v, which
% reaches st2, which reads the value of v : that is, st is a
% reaching definition for the use of v at st2.
reaches(v, st, st2) :- writes(st, v), flowspast(v, st, st2), reads(st2, v).
% A variable read that is reachable from the entry is a read of a
% possibly uninitialized variable
uninitRead(st, v) :- reaches(v, 0, st).
% A variable write that reaches nowhere else is dead code
deadWrite(st, v) :- writes(st, v), !reaches(v, st, _).
}]
# Report which variable definitions reach statement $i
proc query1 {i} [bdd::datalog::compileProgram db {
reaches(v, st, $i)?
} d {
lappend ::flowsto [lindex $::vnames [dict get $d v]] [dict get $d st]
}]
# Report which variable uses flow from statement $i
proc query2 {i} [bdd::datalog::compileProgram db {
reaches(v, $i, st)?
} d {
lappend ::flowsfrom [lindex $::vnames [dict get $d v]] [dict get $d st]
}]
reaching_defs
puts [format {%-16s %2s %-32s %-16s} PRODUCERS {} INSTRUCTIONS CONSUMERS]
set i 0
foreach stmt $program {
set flowsto {}
query1 $i
set flowsfrom {}
query2 $i
puts [format "%-16s %2d: %-32s %-16s" \
[lsort -stride 2 -index 0 -ascii \
[lsort -stride 2 -index 1 -integer $flowsto]] \
$i \
$stmt \
[lsort -stride 2 -index 0 -ascii \
[lsort -stride 2 -index 1 -integer $flowsfrom]]]
incr i
}