Passo intermediario, ainda falta um longo caminho
[pspdecompiler.git] / outgraph.c
blob9a6219302d4ec06452cd1049a13991f7970e0e61
2 #include <stdio.h>
4 #include "output.h"
5 #include "utils.h"
7 static
8 void print_structures (FILE *out, struct basicblock *block)
10 if (block->loopst) {
11 fprintf (out, "LOOP start %d", block->loopst->start->node.dfsnum);
12 if (block->loopst->end)
13 fprintf (out, " end %d", block->loopst->end->node.dfsnum);
14 fprintf (out, "\\l");
17 if (block->st) {
18 fprintf (out, "IF");
19 if (block->st->end)
20 fprintf (out, " end %d", block->st->end->node.dfsnum);
21 fprintf (out, "\\l");
25 static
26 void print_block_code (FILE *out, struct basicblock *block)
28 if (block->type == BLOCK_SIMPLE) {
29 struct location *loc;
30 for (loc = block->info.simple.begin; ; loc++) {
31 fprintf (out, "%s\\l", allegrex_disassemble (loc->opc, loc->address, FALSE));
32 if (loc == block->info.simple.end) break;
37 static
38 void print_block_phis (FILE *out, struct basicblock *block)
40 element opsel, argel;
41 opsel = list_head (block->operations);
42 while (opsel) {
43 struct operation *op = element_getvalue (opsel);
44 int count1 = 0, count2 = 0;
46 if (op->type != OP_START && op->type != OP_END) {
47 argel = list_head (op->results);
48 while (argel) {
49 struct value *val = element_getvalue (argel);
50 if (val->type != VAL_CONSTANT) {
51 if (count1++ == 0) fprintf (out, "<");
52 print_value (out, val);
53 fprintf (out, " ");
55 argel = element_next (argel);
57 if (count1 > 0) fprintf (out, "> = ");
59 if (op->type == OP_PHI) {
60 fprintf (out, "PHI");
62 argel = list_head (op->operands);
63 while (argel) {
64 struct value *val = element_getvalue (argel);
65 if (val->type != VAL_CONSTANT) {
66 if (count2++ == 0) fprintf (out, "<");
67 print_value (out, val);
68 fprintf (out, " ");
70 argel = element_next (argel);
72 if (count2 > 0) fprintf (out, ">");
73 if (count1 || count2) fprintf (out, "\\l");
75 opsel = element_next (opsel);
79 static
80 void print_dominator (FILE *out, struct basicblock *block, int reverse, const char *color)
82 struct basicblock *dominator;
84 if (reverse) {
85 if (list_size (block->outrefs) <= 1) return;
86 dominator = element_getvalue (block->revnode.dominator->blockel);
87 } else {
88 if (list_size (block->inrefs) <= 1) return;
89 dominator = element_getvalue (block->node.dominator->blockel);
91 fprintf (out, " %3d -> %3d [color=%s];\n",
92 block->node.dfsnum, dominator->node.dfsnum, color);
95 static
96 void print_frontier (FILE *out, struct basicblock *block, list frontier, const char *color)
98 element ref;
99 if (list_size (frontier) == 0) return;
101 fprintf (out, " %3d -> { ", block->node.dfsnum);
102 ref = list_head (frontier);
103 while (ref) {
104 struct basicblocknode *refnode;
105 struct basicblock *refblock;
107 refnode = element_getvalue (ref);
108 refblock = element_getvalue (refnode->blockel);
110 fprintf (out, "%3d ", refblock->node.dfsnum);
111 ref = element_next (ref);
113 fprintf (out, " } [color=%s];\n", color);
116 static
117 void print_subroutine_graph (FILE *out, struct code *c, struct subroutine *sub, int options)
119 struct basicblock *block;
120 element el, ref;
122 fprintf (out, "digraph ");
123 print_subroutine_name (out, sub);
124 fprintf (out, " {\n rankdir=LR;\n");
126 el = list_head (sub->blocks);
128 while (el) {
129 block = element_getvalue (el);
131 fprintf (out, " %3d ", block->node.dfsnum);
132 fprintf (out, "[label=\"");
134 if (options & OUT_PRINT_STRUCTURES)
135 print_structures (out, block);
137 if (options & OUT_PRINT_DFS)
138 fprintf (out, "(%d) ", block->node.dfsnum);
140 if (options & OUT_PRINT_RDFS)
141 fprintf (out, "(%d) ", block->revnode.dfsnum);
143 switch (block->type) {
144 case BLOCK_START: fprintf (out, "Start"); break;
145 case BLOCK_END: fprintf (out, "End"); break;
146 case BLOCK_CALL: fprintf (out, "Call"); break;
147 case BLOCK_SIMPLE: fprintf (out, "0x%08X-0x%08X",
148 block->info.simple.begin->address, block->info.simple.end->address);
150 if (block->haslabel) fprintf (out, "(*)");
151 fprintf (out, "\\l");
153 if (options & OUT_PRINT_PHIS)
154 print_block_phis (out, block);
156 if (options & OUT_PRINT_CODE)
157 print_block_code (out, block);
159 fprintf (out, "\"];\n");
162 if (options & OUT_PRINT_DOMINATOR)
163 print_dominator (out, block, FALSE, "green");
165 if (options & OUT_PRINT_RDOMINATOR)
166 print_dominator (out, block, TRUE, "yellow");
168 if (options & OUT_PRINT_FRONTIER)
169 print_frontier (out, block, block->node.frontier, "orange");
171 if (options & OUT_PRINT_RFRONTIER)
172 print_frontier (out, block, block->revnode.frontier, "blue");
175 if (list_size (block->outrefs) != 0) {
176 ref = list_head (block->outrefs);
177 while (ref) {
178 struct basicedge *edge;
179 struct basicblock *refblock;
180 edge = element_getvalue (ref);
181 refblock = edge->to;
182 fprintf (out, " %3d -> %3d ", block->node.dfsnum, refblock->node.dfsnum);
183 if (ref != list_head (block->outrefs))
184 fprintf (out, "[arrowtail=dot]");
186 if (element_getvalue (refblock->node.parent->blockel) == block) {
187 fprintf (out, "[style=bold]");
188 } else if (block->node.dfsnum >= refblock->node.dfsnum) {
189 fprintf (out, "[color=red]");
191 if (options & OUT_PRINT_EDGE_TYPES) {
192 fprintf (out, "[label=\"");
193 switch (edge->type) {
194 case EDGE_UNKNOWN: fprintf (out, "UNK"); break;
195 case EDGE_CONTINUE: fprintf (out, "CONTINUE"); break;
196 case EDGE_BREAK: fprintf (out, "BREAK"); break;
197 case EDGE_FOLLOW: fprintf (out, "FOLLOW"); break;
198 case EDGE_GOTO: fprintf (out, "GOTO"); break;
199 case EDGE_IFEXIT: fprintf (out, "IFEXIT"); break;
201 fprintf (out, "\"]");
203 fprintf (out, " ;\n");
204 ref = element_next (ref);
207 el = element_next (el);
209 fprintf (out, "}\n");
213 int print_graph (struct code *c, char *prxname, int options)
215 char buffer[128];
216 char basename[32];
217 element el;
218 FILE *fp;
219 int ret = 1;
221 get_base_name (prxname, basename, sizeof (basename));
223 el = list_head (c->subroutines);
224 while (el) {
225 struct subroutine *sub = element_getvalue (el);
226 if (!sub->haserror && !sub->import) {
227 if (sub->export) {
228 if (sub->export->name) {
229 sprintf (buffer, "%s_%-.64s.dot", basename, sub->export->name);
230 } else
231 sprintf (buffer, "%s_nid_%08X.dot", basename, sub->export->nid);
232 } else
233 sprintf (buffer, "%s_%08X.dot", basename, sub->begin->address);
234 fp = fopen (buffer, "w");
235 if (!fp) {
236 xerror (__FILE__ ": can't open file for writing `%s'", buffer);
237 ret = 0;
238 } else {
239 print_subroutine_graph (fp, c, sub, options);
240 fclose (fp);
242 } else {
243 if (sub->haserror) report ("Skipping subroutine at 0x%08X\n", sub->begin->address);
245 el = element_next (el);
248 return ret;