## machcode-controlflow-graph-viewer-g.pkg
# Compiled by:
#
src/lib/compiler/back/low/lib/visual.lib# This generic is invoked (only) from:
#
#
src/lib/compiler/back/low/main/main/backend-lowhalf-g.pkgstipulate
package f8b = eight_byte_float; # eight_byte_float is from
src/lib/std/eight-byte-float.pkg package glo = graph_layout; # graph_layout is from
src/lib/compiler/back/low/display/graph-layout.pkg package lbl = codelabel; # codelabel is from
src/lib/compiler/back/low/code/codelabel.pkg package odg = oop_digraph; # oop_digraph is from
src/lib/graph/oop-digraph.pkg package rwv = rw_vector; # rw_vector is from
src/lib/std/src/rw-vector.pkgherein
# This generic is invoked (only) in:
#
#
src/lib/compiler/back/low/main/main/backend-lowhalf-g.pkg #
generic package machcode_controlflow_graph_viewer_g (
# ==================================
#
package mcg: Machcode_Controlflow_Graph; # Machcode_Controlflow_Graph is from
src/lib/compiler/back/low/mcg/machcode-controlflow-graph.api package gv: Graph_Viewer; # Graph_Viewer is from
src/lib/compiler/back/low/display/graph-viewer.api package ae: Machcode_Codebuffer_Pp # Machcode_Codebuffer_Pp is from
src/lib/compiler/back/low/emit/machcode-codebuffer-pp.api where # "ae" == "asmcode_emitter".
mcf == mcg::mcf; # "mcf" == "machcode_form" (abstract machine code).
)
: (weak) api {
view_machcode_controlflow_graph: mcg::Machcode_Controlflow_Graph -> Void;
}
{
stipulate
package fmt = format_instruction_g( ae );
herein
view_outline
=
lowhalf_control::get_bool
"view_outline";
fun view_machcode_controlflow_graph (machcode_controlflow_graph as odg::DIGRAPH g)
=
{ g.graph_info -> mcg::GRAPH_INFO { notes, ... };
#
to_string = fmt::to_string *notes;
fun info_fn _ = [];
color_scale
=
rwv::from_list
["#ccffff", "#99ffff", "#66ccff", "#54a9ff", "#ccff99",
"#ffff99", "#ffcc66", "#ff9966", "#cc6666", "#d14949",
"#d14949"];
fun weight_range ([], min, max)
=>
(min, max-min);
weight_range((_, _, mcg::EDGE_INFO { execution_frequency, ... } ) ! rest, min, max)
=>
{ wt = *execution_frequency;
if (wt > max) weight_range (rest, min, wt);
elif (wt < min) weight_range (rest, wt, max);
else weight_range (rest, min, max);
fi;
};
end;
my (lo_wt, range)
=
weight_range( g.edges (), -1.0, -1.0);
fun color w
=
{ pos = if (range < 100.0) floor(((w-lo_wt) * 10.0) / range);
else floor (math::log10 (w-lo_wt) * 10.0 / math::log10 range);
fi;
rwv::get (color_scale, pos);
};
entry = head (g.entries ());
exit = head (g.exits ());
red = glo::COLOR "#ff0000";
yellow = glo::COLOR "yellow";
green = glo::COLOR "green";
fun edge_fn (i, j, mcg::EDGE_INFO { execution_frequency, ... } )
=
{ label = glo::LABEL (f8b::to_string *execution_frequency);
#
[ label, glo::COLOR (color *execution_frequency) ];
};
fun title (blknum, REF freq)
=
" " + int::to_string blknum + " freq=" + f8b::to_string freq;
fun ann notes
=
list::fold_forward (\\ (a, l) = "/* " + note::to_string a + " */\n" + l)
""
*notes;
fun node_fn (_, mcg::BBLOCK { kind, labels, id, execution_frequency, ops, notes, ... } )
=
case kind
#
mcg::START
=>
[glo::LABEL("entry" + title (id, execution_frequency) + "\n" + ann notes)];
mcg::STOP
=>
[glo::LABEL("exit" + title (id, execution_frequency))];
_ =>
[ glo::LABEL
( "BLK"
+ title (id, execution_frequency)
+ "\n"
+ case *labels
#
[] => "";
#
codelabels
=>
string::join
":\n"
(map lbl::codelabel_to_string codelabels) + ":\n";
esac
+ ann notes
+ if *view_outline
"";
else
list::fold_forward
(\\ (i, t) = { text = to_string i;
text == "" ?? t
:: text + "\n" + t;
}
)
""
*ops;
fi
)
];
esac;
gv::view
(glo::make_layout { info_fn, edge_fn, node_fn } machcode_controlflow_graph);
};
end;
};
end;