11package de .mirkosertic .metair .ir ;
22
3- import java . io . OutputStream ;
3+
44import java .io .PrintStream ;
5+ import java .lang .classfile .CodeElement ;
6+ import java .lang .classfile .CodeModel ;
7+ import java .lang .classfile .MethodModel ;
8+ import java .lang .classfile .instruction .LabelTarget ;
59import java .util .ArrayDeque ;
610import java .util .ArrayList ;
711import java .util .Deque ;
812import java .util .HashMap ;
913import java .util .HashSet ;
1014import java .util .List ;
1115import java .util .Map ;
16+ import java .util .Optional ;
1217import java .util .Set ;
1318
1419public final class DOTExporter {
@@ -139,7 +144,7 @@ public static void writeTo(final Method method, final PrintStream ps) {
139144 d7 [style = invis];
140145 }
141146 c0 -> c1 [label="Control flow", style=solid, color=red]
142- c1 -> c2 [label="Control flow back edge", style=dashed, color=red]
147+ c2 -> c3 [label="Control flow back edge", style=dashed, color=red]
143148 d0 -> d1 [label="Data flow"]
144149 d2 -> d3 [label="Declaration", style=dotted]
145150 d4 -> d5 [label="PHI Data flow", color=blue]
@@ -166,9 +171,7 @@ private static void printNode(final int index, final Node node, final PrintStrea
166171 }
167172 }
168173
169- public static void writeTo (final DominatorTree tree , final OutputStream fileOutputStream ) {
170- final PrintStream ps = new PrintStream (fileOutputStream );
171-
174+ public static void writeTo (final DominatorTree tree , final PrintStream ps ) {
172175 ps .println ("digraph debugoutput {" );
173176 for (final Node n : tree .preOrder ) {
174177 ps .print (" node" + tree .preOrder .indexOf (n ) + "[" );
@@ -236,7 +239,7 @@ public static void writeTo(final DominatorTree tree, final OutputStream fileOutp
236239 d7 [style = invis];
237240 }
238241 c0 -> c1 [label="Control flow", style=solid, color=red]
239- c1 -> c2 [label="Control flow back edge", style=dashed, color=red]
242+ c2 -> c3 [label="Control flow back edge", style=dashed, color=red]
240243 d0 -> d1 [label="Data flow"]
241244 d2 -> d3 [label="Declaration", style=dotted]
242245 d4 -> d5 [label="PHI Data flow", color=blue]
@@ -246,4 +249,73 @@ public static void writeTo(final DominatorTree tree, final OutputStream fileOutp
246249 ps .println ("}" );
247250 ps .flush ();
248251 }
252+
253+ public static void writeBytecodeCFGTo (final MethodAnalyzer analyzer , final PrintStream ps ) {
254+ ps .println ("digraph {" );
255+
256+ final MethodModel method = analyzer .getMethod ();
257+ final Optional <CodeModel > optCode = method .code ();
258+ if (optCode .isPresent ()) {
259+ final CodeModel code = optCode .get ();
260+
261+ final MethodAnalyzer .Frame [] frames = analyzer .getFrames ();
262+ final List <MethodAnalyzer .Frame > topologicalOrder = analyzer .getCodeModelTopologicalOrder ();
263+
264+ final List <CodeElement > elements = code .elementList ();
265+ for (int i = 0 ; i < elements .size (); i ++) {
266+ if (i == elements .size () - 1 && elements .get (i ) instanceof LabelTarget ) {
267+ // Ignore last label
268+ continue ;
269+ }
270+ ps .print (" node" + i );
271+ ps .print ("[" );
272+ ps .print ("label=\" " );
273+ ps .print ("#" );
274+ ps .print (i );
275+ ps .print (" " );
276+ ps .print (elements .get (i ));
277+ if (topologicalOrder != null && topologicalOrder .size () > i ) {
278+ ps .print (" Order: " + topologicalOrder .indexOf (frames [i ]));
279+ }
280+ ps .print ("\" " );
281+ ps .println (", shape=box, fillcolor=lightgrey, style=filled];" );
282+ }
283+
284+ for (int elementIndex = 0 ; elementIndex < frames .length - 1 ; elementIndex ++) {
285+ final MethodAnalyzer .Frame frame = frames [elementIndex ];
286+ if (frame != null ) {
287+ for (final MethodAnalyzer .CFGEdge edge : frame .predecessors ) {
288+ ps .print (" node" );
289+ ps .print (edge .fromIndex ());
290+ ps .print (" -> node" );
291+ ps .print (elementIndex );
292+ ps .print ("[color=red" );
293+ if (edge .controlType () == ControlType .BACKWARD ) {
294+ ps .print (", style=dotted" );
295+ }
296+ ps .println ("];" );
297+ }
298+ }
299+ }
300+ }
301+
302+ ps .println ("""
303+ subgraph cluster_000 {
304+ label = "Legend";
305+ node [shape=point]
306+ {
307+ rank=same;
308+ c0 [style = invis];
309+ c1 [style = invis];
310+ c2 [style = invis];
311+ c3 [style = invis];
312+ }
313+ c0 -> c1 [label="Control flow", style=solid, color=red]
314+ c2 -> c3 [label="Control flow back edge", style=dashed, color=red]
315+ }
316+ """ );
317+
318+ ps .println ("}" );
319+
320+ }
249321}
0 commit comments