1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
functor CFGViewer
(structure CFG : CONTROL_FLOW_GRAPH
structure GraphViewer : GRAPH_VIEWER
structure Asm : INSTRUCTION_EMITTER (* where I = CFG.I *)
where type I.addressing_mode = CFG.I.addressing_mode
and type I.ea = CFG.I.ea
and type I.instr = CFG.I.instr
and type I.instruction = CFG.I.instruction
and type I.operand = CFG.I.operand
) : sig
val view : CFG.cfg -> unit
end =
struct
structure CFG = CFG
structure L = GraphLayout
structure FMT = FormatInstruction(Asm)
structure G = Graph
val outline = MLRiscControl.getFlag "view-outline"
fun view(cfg as G.GRAPH g) = let
val CFG.INFO{annotations, ...} = #graph_info g
val toString = FMT.toString (!annotations)
fun graph _ = []
val colorScale =
Array.fromList
["#ccffff", "#99ffff", "#66ccff", "#54a9ff", "#ccff99",
"#ffff99", "#ffcc66", "#ff9966", "#cc6666", "#d14949",
"#d14949"]
fun weightRange([], min, max) = (min, max-min)
| weightRange((_,_,CFG.EDGE{w, ...})::rest, min, max) = let
val wt = !w
in
if wt > max then weightRange(rest, min, wt)
else if wt < min then weightRange(rest, wt, max)
else weightRange(rest, min, max)
end
val (loWt, range) = weightRange( #edges g (), ~1.0, ~1.0)
fun color w = let
val pos =
if range < 100.0
then floor(((w-loWt) * 10.0) / range)
else floor (Math.log10(w-loWt) * 10.0 / Math.log10 range)
in
Array.sub(colorScale, pos)
end
val ENTRY = hd(#entries g ())
val EXIT = hd(#exits g ())
val red = L.COLOR "#ff0000"
val yellow = L.COLOR "yellow"
val green = L.COLOR "green"
fun edge(i,j,CFG.EDGE{w, ...}) =
let val label = L.LABEL(Real.toString (!w))
in [label, L.COLOR(color(!w))]
end
fun title(blknum,ref freq) =
" "^Int.toString blknum ^ " freq="^Real.toString freq
fun ann(annotations) =
List.foldl(fn (a,l) => "/* "^Annotations.toString a^" */\n"^l) ""
(!annotations)
fun node(_, CFG.BLOCK{kind, labels, id, freq, insns, annotations, ...}) =
(case kind
of CFG.START =>
[L.LABEL("entry"^title(id,freq)^"\n"^ann(annotations))]
| CFG.STOP =>
[L.LABEL("exit"^title(id,freq))]
| _ =>
[L.LABEL("BLK"^title(id,freq)^"\n"^
(case !labels
of [] => ""
| labs =>
String.concatWith ":\n" (map Label.toString labs) ^ ":\n"
(*easc*)) ^
ann(annotations)^
(if !outline then "" else
List.foldl
(fn (i,t) => let val text = toString i
in if text = "" then t else text^"\n"^t
end)
""
(!insns)))]
(*esac*))
in
GraphViewer.view
(L.makeLayout{graph=graph, edge=edge, node=node} cfg)
end
end
|