2 * Author: Humberto Naves (hsnaves@gmail.com)
11 void print_structures (FILE *out
, struct basicblock
*block
)
13 struct ctrlstruct
*st
= block
->st
;
22 fprintf (out
, "MAIN");
25 fprintf (out
, "LOOP");
28 fprintf (out
, "SWITCH");
31 fprintf (out
, " start %d", st
->start
->node
.dfsnum
);
33 fprintf (out
, " end %d", st
->end
->node
.dfsnum
);
35 fprintf (out
, " goto");
37 fprintf (out
, " endfollow");
41 fprintf (out
, " %s", block
->blockcond
? "TRUE" : "FALSE");
48 fprintf (out
, " %d", block
->blockcond
);
53 if (++count
> 100) break;
58 void print_block_code (FILE *out
, struct basicblock
*block
)
60 if (block
->type
== BLOCK_SIMPLE
) {
62 for (loc
= block
->info
.simple
.begin
; ; loc
++) {
63 fprintf (out
, "%s\\l", allegrex_disassemble (loc
->opc
, loc
->address
, FALSE
));
64 if (loc
== block
->info
.simple
.end
) break;
70 void print_dominator (FILE *out
, struct basicblock
*block
, int reverse
, const char *color
)
72 struct basicblock
*dominator
;
75 if (list_size (block
->outrefs
) <= 1) return;
76 dominator
= element_getvalue (block
->revnode
.dominator
->blockel
);
78 if (list_size (block
->inrefs
) <= 1) return;
79 dominator
= element_getvalue (block
->node
.dominator
->blockel
);
81 fprintf (out
, " %3d -> %3d [color=%s];\n",
82 block
->node
.dfsnum
, dominator
->node
.dfsnum
, color
);
86 void print_frontier (FILE *out
, struct basicblock
*block
, list frontier
, const char *color
)
89 if (list_size (frontier
) == 0) return;
91 fprintf (out
, " %3d -> { ", block
->node
.dfsnum
);
92 ref
= list_head (frontier
);
94 struct basicblocknode
*refnode
;
95 struct basicblock
*refblock
;
97 refnode
= element_getvalue (ref
);
98 refblock
= element_getvalue (refnode
->blockel
);
100 fprintf (out
, "%3d ", refblock
->node
.dfsnum
);
101 ref
= element_next (ref
);
103 fprintf (out
, " } [color=%s];\n", color
);
107 void print_subroutine_graph (FILE *out
, struct code
*c
, struct subroutine
*sub
)
109 struct basicblock
*block
;
112 fprintf (out
, "digraph ");
113 print_subroutine_name (out
, sub
);
114 fprintf (out
, " {\n rankdir=LR;\n");
116 el
= list_head (sub
->blocks
);
119 block
= element_getvalue (el
);
121 fprintf (out
, " %3d ", block
->node
.dfsnum
);
122 fprintf (out
, "[label=\"");
124 if (g_printoptions
& OUT_PRINT_STRUCTURES
)
125 print_structures (out
, block
);
127 if (g_printoptions
& OUT_PRINT_DFS
)
128 fprintf (out
, "(%d) ", block
->node
.dfsnum
);
130 if (g_printoptions
& OUT_PRINT_RDFS
)
131 fprintf (out
, "(%d) ", block
->revnode
.dfsnum
);
133 switch (block
->type
) {
134 case BLOCK_START
: fprintf (out
, "Start"); break;
135 case BLOCK_END
: fprintf (out
, "End"); break;
136 case BLOCK_CALL
: fprintf (out
, "Call"); break;
137 case BLOCK_SIMPLE
: fprintf (out
, "0x%08X-0x%08X",
138 block
->info
.simple
.begin
->address
, block
->info
.simple
.end
->address
);
140 if (block
->status
& BLOCK_STAT_HASLABEL
) fprintf (out
, "(*)");
141 fprintf (out
, "\\l");
143 if (g_printoptions
& OUT_PRINT_CODE
)
144 print_block_code (out
, block
);
146 fprintf (out
, "\"];\n");
149 if (g_printoptions
& OUT_PRINT_DOMINATOR
)
150 print_dominator (out
, block
, FALSE
, "green");
152 if (g_printoptions
& OUT_PRINT_RDOMINATOR
)
153 print_dominator (out
, block
, TRUE
, "yellow");
155 if (g_printoptions
& OUT_PRINT_FRONTIER
)
156 print_frontier (out
, block
, block
->node
.frontier
, "orange");
158 if (g_printoptions
& OUT_PRINT_RFRONTIER
)
159 print_frontier (out
, block
, block
->revnode
.frontier
, "blue");
162 if (list_size (block
->outrefs
) != 0) {
163 ref
= list_head (block
->outrefs
);
165 struct basicedge
*edge
;
166 struct basicblock
*refblock
;
167 edge
= element_getvalue (ref
);
169 fprintf (out
, " %3d -> %3d ", block
->node
.dfsnum
, refblock
->node
.dfsnum
);
170 if (ref
!= list_head (block
->outrefs
))
171 fprintf (out
, "[arrowtail=dot]");
173 if (element_getvalue (refblock
->node
.parent
->blockel
) == block
) {
174 fprintf (out
, "[style=bold]");
175 } else if (block
->node
.dfsnum
>= refblock
->node
.dfsnum
) {
176 fprintf (out
, "[color=red]");
178 if (g_printoptions
& OUT_PRINT_EDGE_TYPES
) {
179 fprintf (out
, "[label=\"");
180 switch (edge
->type
) {
181 case EDGE_UNKNOWN
: fprintf (out
, "UNK"); break;
182 case EDGE_CONTINUE
: fprintf (out
, "CONTINUE"); break;
183 case EDGE_BREAK
: fprintf (out
, "BREAK"); break;
184 case EDGE_NEXT
: fprintf (out
, "NEXT"); break;
185 case EDGE_INVALID
: fprintf (out
, "INVALID"); break;
186 case EDGE_GOTO
: fprintf (out
, "GOTO"); break;
187 case EDGE_CASE
: fprintf (out
, "CASE"); break;
188 case EDGE_IFENTER
: fprintf (out
, "IFENTER"); break;
189 case EDGE_IFEXIT
: fprintf (out
, "IFEXIT"); break;
190 case EDGE_RETURN
: fprintf (out
, "RETURN"); break;
192 fprintf (out
, "\"]");
194 fprintf (out
, " ;\n");
195 ref
= element_next (ref
);
198 el
= element_next (el
);
200 fprintf (out
, "}\n");
204 int print_graph (struct code
*c
, char *prxname
)
212 get_base_name (prxname
, basename
, sizeof (basename
));
214 el
= list_head (c
->subroutines
);
216 struct subroutine
*sub
= element_getvalue (el
);
217 if (!sub
->haserror
&& !sub
->import
) {
219 if (sub
->export
->name
) {
220 sprintf (buffer
, "%s_%-.64s.dot", basename
, sub
->export
->name
);
222 sprintf (buffer
, "%s_nid_%08X.dot", basename
, sub
->export
->nid
);
224 sprintf (buffer
, "%s_%08X.dot", basename
, sub
->begin
->address
);
225 fp
= fopen (buffer
, "w");
227 xerror (__FILE__
": can't open file for writing `%s'", buffer
);
230 print_subroutine_graph (fp
, c
, sub
);
234 if (sub
->haserror
) report ("Skipping subroutine at 0x%08X\n", sub
->begin
->address
);
236 el
= element_next (el
);