Mercurial > hg > CbC > CbC_gcc
annotate gcc/graph.c @ 81:dbfc0d2dde36
minor fix
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 24 Sep 2011 02:43:04 +0900 |
parents | f6334be47118 |
children | 04ced10e8804 |
rev | line source |
---|---|
0 | 1 /* Output routines for graphical representation. |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2 Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007, 2008, 2010 |
0 | 3 Free Software Foundation, Inc. |
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998. | |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
22 #include "config.h" |
0 | 23 #include "system.h" |
24 #include "coretypes.h" | |
25 #include "tm.h" | |
26 #include "rtl.h" | |
27 #include "flags.h" | |
28 #include "output.h" | |
29 #include "function.h" | |
30 #include "hard-reg-set.h" | |
31 #include "obstack.h" | |
32 #include "basic-block.h" | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
33 #include "diagnostic-core.h" |
0 | 34 #include "graph.h" |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
35 #include "emit-rtl.h" |
0 | 36 |
37 static const char *const graph_ext[] = | |
38 { | |
39 /* no_graph */ "", | |
40 /* vcg */ ".vcg", | |
41 }; | |
42 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
43 /* The flag to indicate if output is inside of a building block. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
44 static int inbb = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
45 |
0 | 46 static void start_fct (FILE *); |
47 static void start_bb (FILE *, int); | |
48 static void node_data (FILE *, rtx); | |
49 static void draw_edge (FILE *, int, int, int, int); | |
50 static void end_fct (FILE *); | |
51 static void end_bb (FILE *); | |
52 | |
53 /* Output text for new basic block. */ | |
54 static void | |
55 start_fct (FILE *fp) | |
56 { | |
57 switch (graph_dump_format) | |
58 { | |
59 case vcg: | |
60 fprintf (fp, "\ | |
61 graph: { title: \"%s\"\nfolding: 1\nhidden: 2\nnode: { title: \"%s.0\" }\n", | |
62 current_function_name (), current_function_name ()); | |
63 break; | |
64 case no_graph: | |
65 break; | |
66 } | |
67 } | |
68 | |
69 static void | |
70 start_bb (FILE *fp, int bb) | |
71 { | |
72 #if 0 | |
73 reg_set_iterator rsi; | |
74 #endif | |
75 | |
76 switch (graph_dump_format) | |
77 { | |
78 case vcg: | |
79 fprintf (fp, "\ | |
80 graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\ | |
81 label: \"basic block %d", | |
82 current_function_name (), bb, bb); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
83 inbb = 1; /* Now We are inside of a building block. */ |
0 | 84 break; |
85 case no_graph: | |
86 break; | |
87 } | |
88 | |
89 #if 0 | |
90 /* FIXME Should this be printed? It makes the graph significantly larger. */ | |
91 | |
92 /* Print the live-at-start register list. */ | |
93 fputc ('\n', fp); | |
94 EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[bb], 0, i, rsi) | |
95 { | |
96 fprintf (fp, " %d", i); | |
97 if (i < FIRST_PSEUDO_REGISTER) | |
98 fprintf (fp, " [%s]", reg_names[i]); | |
99 } | |
100 #endif | |
101 | |
102 switch (graph_dump_format) | |
103 { | |
104 case vcg: | |
105 fputs ("\"\n\n", fp); | |
106 break; | |
107 case no_graph: | |
108 break; | |
109 } | |
110 } | |
111 | |
112 static void | |
113 node_data (FILE *fp, rtx tmp_rtx) | |
114 { | |
115 if (PREV_INSN (tmp_rtx) == 0) | |
116 { | |
117 /* This is the first instruction. Add an edge from the starting | |
118 block. */ | |
119 switch (graph_dump_format) | |
120 { | |
121 case vcg: | |
122 fprintf (fp, "\ | |
123 edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n", | |
124 current_function_name (), | |
125 current_function_name (), XINT (tmp_rtx, 0)); | |
126 break; | |
127 case no_graph: | |
128 break; | |
129 } | |
130 } | |
131 | |
132 switch (graph_dump_format) | |
133 { | |
134 case vcg: | |
135 fprintf (fp, "node: {\n title: \"%s.%d\"\n color: %s\n \ | |
136 label: \"%s %d\n", | |
137 current_function_name (), XINT (tmp_rtx, 0), | |
138 NOTE_P (tmp_rtx) ? "lightgrey" | |
139 : NONJUMP_INSN_P (tmp_rtx) ? "green" | |
140 : JUMP_P (tmp_rtx) ? "darkgreen" | |
141 : CALL_P (tmp_rtx) ? "darkgreen" | |
142 : LABEL_P (tmp_rtx) ? "\ | |
143 darkgrey\n shape: ellipse" : "white", | |
144 GET_RTX_NAME (GET_CODE (tmp_rtx)), XINT (tmp_rtx, 0)); | |
145 break; | |
146 case no_graph: | |
147 break; | |
148 } | |
149 | |
150 /* Print the RTL. */ | |
151 if (NOTE_P (tmp_rtx)) | |
152 { | |
153 const char *name; | |
154 name = GET_NOTE_INSN_NAME (NOTE_KIND (tmp_rtx)); | |
155 fprintf (fp, " %s", name); | |
156 } | |
157 else if (INSN_P (tmp_rtx)) | |
158 print_rtl_single (fp, PATTERN (tmp_rtx)); | |
159 else | |
160 print_rtl_single (fp, tmp_rtx); | |
161 | |
162 switch (graph_dump_format) | |
163 { | |
164 case vcg: | |
165 fputs ("\"\n}\n", fp); | |
166 break; | |
167 case no_graph: | |
168 break; | |
169 } | |
170 } | |
171 | |
172 static void | |
173 draw_edge (FILE *fp, int from, int to, int bb_edge, int color_class) | |
174 { | |
175 const char * color; | |
176 switch (graph_dump_format) | |
177 { | |
178 case vcg: | |
179 color = ""; | |
180 if (color_class == 2) | |
181 color = "color: red "; | |
182 else if (bb_edge) | |
183 color = "color: blue "; | |
184 else if (color_class == 3) | |
185 color = "color: green "; | |
186 fprintf (fp, | |
187 "edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s", | |
188 current_function_name (), from, | |
189 current_function_name (), to, color); | |
190 if (color_class) | |
191 fprintf (fp, "class: %d ", color_class); | |
192 fputs ("}\n", fp); | |
193 break; | |
194 case no_graph: | |
195 break; | |
196 } | |
197 } | |
198 | |
199 static void | |
200 end_bb (FILE *fp) | |
201 { | |
202 switch (graph_dump_format) | |
203 { | |
204 case vcg: | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
205 /* Check if we are inside of a building block. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
206 if (inbb != 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
207 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
208 fputs ("}\n", fp); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
209 inbb = 0; /* Now we are outside of a building block. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
210 } |
0 | 211 break; |
212 case no_graph: | |
213 break; | |
214 } | |
215 } | |
216 | |
217 static void | |
218 end_fct (FILE *fp) | |
219 { | |
220 switch (graph_dump_format) | |
221 { | |
222 case vcg: | |
223 fprintf (fp, "node: { title: \"%s.999999\" label: \"END\" }\n}\n", | |
224 current_function_name ()); | |
225 break; | |
226 case no_graph: | |
227 break; | |
228 } | |
229 } | |
230 | |
231 /* Like print_rtl, but also print out live information for the start of each | |
232 basic block. */ | |
233 void | |
234 print_rtl_graph_with_bb (const char *base, rtx rtx_first) | |
235 { | |
236 rtx tmp_rtx; | |
237 size_t namelen = strlen (base); | |
238 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1; | |
239 char *buf = XALLOCAVEC (char, namelen + extlen); | |
240 FILE *fp; | |
241 | |
242 if (basic_block_info == NULL) | |
243 return; | |
244 | |
245 memcpy (buf, base, namelen); | |
246 memcpy (buf + namelen, graph_ext[graph_dump_format], extlen); | |
247 | |
248 fp = fopen (buf, "a"); | |
249 if (fp == NULL) | |
250 return; | |
251 | |
252 if (rtx_first == 0) | |
253 fprintf (fp, "(nil)\n"); | |
254 else | |
255 { | |
256 enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB }; | |
257 int max_uid = get_max_uid (); | |
258 int *start = XNEWVEC (int, max_uid); | |
259 int *end = XNEWVEC (int, max_uid); | |
260 enum bb_state *in_bb_p = XNEWVEC (enum bb_state, max_uid); | |
261 basic_block bb; | |
262 int i; | |
263 | |
264 for (i = 0; i < max_uid; ++i) | |
265 { | |
266 start[i] = end[i] = -1; | |
267 in_bb_p[i] = NOT_IN_BB; | |
268 } | |
269 | |
270 FOR_EACH_BB_REVERSE (bb) | |
271 { | |
272 rtx x; | |
273 start[INSN_UID (BB_HEAD (bb))] = bb->index; | |
274 end[INSN_UID (BB_END (bb))] = bb->index; | |
275 for (x = BB_HEAD (bb); x != NULL_RTX; x = NEXT_INSN (x)) | |
276 { | |
277 in_bb_p[INSN_UID (x)] | |
278 = (in_bb_p[INSN_UID (x)] == NOT_IN_BB) | |
279 ? IN_ONE_BB : IN_MULTIPLE_BB; | |
280 if (x == BB_END (bb)) | |
281 break; | |
282 } | |
283 } | |
284 | |
285 /* Tell print-rtl that we want graph output. */ | |
286 dump_for_graph = 1; | |
287 | |
288 /* Start new function. */ | |
289 start_fct (fp); | |
290 | |
291 for (tmp_rtx = NEXT_INSN (rtx_first); NULL != tmp_rtx; | |
292 tmp_rtx = NEXT_INSN (tmp_rtx)) | |
293 { | |
294 int edge_printed = 0; | |
295 rtx next_insn; | |
296 | |
297 if (start[INSN_UID (tmp_rtx)] < 0 && end[INSN_UID (tmp_rtx)] < 0) | |
298 { | |
299 if (BARRIER_P (tmp_rtx)) | |
300 continue; | |
301 if (NOTE_P (tmp_rtx) | |
302 && (1 || in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB)) | |
303 continue; | |
304 } | |
305 | |
306 if ((i = start[INSN_UID (tmp_rtx)]) >= 0) | |
307 { | |
308 /* We start a subgraph for each basic block. */ | |
309 start_bb (fp, i); | |
310 | |
311 if (i == 0) | |
312 draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0); | |
313 } | |
314 | |
315 /* Print the data for this node. */ | |
316 node_data (fp, tmp_rtx); | |
317 next_insn = next_nonnote_insn (tmp_rtx); | |
318 | |
319 if ((i = end[INSN_UID (tmp_rtx)]) >= 0) | |
320 { | |
321 edge e; | |
322 edge_iterator ei; | |
323 | |
324 bb = BASIC_BLOCK (i); | |
325 | |
326 /* End of the basic block. */ | |
327 end_bb (fp); | |
328 | |
329 /* Now specify the edges to all the successors of this | |
330 basic block. */ | |
331 FOR_EACH_EDGE (e, ei, bb->succs) | |
332 { | |
333 if (e->dest != EXIT_BLOCK_PTR) | |
334 { | |
335 rtx block_head = BB_HEAD (e->dest); | |
336 | |
337 draw_edge (fp, INSN_UID (tmp_rtx), | |
338 INSN_UID (block_head), | |
339 next_insn != block_head, | |
340 (e->flags & EDGE_ABNORMAL ? 2 : 0)); | |
341 | |
342 if (block_head == next_insn) | |
343 edge_printed = 1; | |
344 } | |
345 else | |
346 { | |
347 draw_edge (fp, INSN_UID (tmp_rtx), 999999, | |
348 next_insn != 0, | |
349 (e->flags & EDGE_ABNORMAL ? 2 : 0)); | |
350 | |
351 if (next_insn == 0) | |
352 edge_printed = 1; | |
353 } | |
354 } | |
355 } | |
356 | |
357 if (!edge_printed) | |
358 { | |
359 /* Don't print edges to barriers. */ | |
360 if (next_insn == 0 | |
361 || !BARRIER_P (next_insn)) | |
362 draw_edge (fp, XINT (tmp_rtx, 0), | |
363 next_insn ? INSN_UID (next_insn) : 999999, 0, 0); | |
364 else | |
365 { | |
366 /* We draw the remaining edges in class 3. We have | |
367 to skip over the barrier since these nodes are | |
368 not printed at all. */ | |
369 do | |
370 next_insn = NEXT_INSN (next_insn); | |
371 while (next_insn | |
372 && (NOTE_P (next_insn) | |
373 || BARRIER_P (next_insn))); | |
374 | |
375 draw_edge (fp, XINT (tmp_rtx, 0), | |
376 next_insn ? INSN_UID (next_insn) : 999999, 0, 3); | |
377 } | |
378 } | |
379 } | |
380 | |
381 dump_for_graph = 0; | |
382 | |
383 end_fct (fp); | |
384 | |
385 /* Clean up. */ | |
386 free (start); | |
387 free (end); | |
388 free (in_bb_p); | |
389 } | |
390 | |
391 fclose (fp); | |
392 } | |
393 | |
394 | |
395 /* Similar as clean_dump_file, but this time for graph output files. */ | |
396 | |
397 void | |
398 clean_graph_dump_file (const char *base) | |
399 { | |
400 size_t namelen = strlen (base); | |
401 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1; | |
402 char *buf = XALLOCAVEC (char, namelen + extlen); | |
403 FILE *fp; | |
404 | |
405 memcpy (buf, base, namelen); | |
406 memcpy (buf + namelen, graph_ext[graph_dump_format], extlen); | |
407 | |
408 fp = fopen (buf, "w"); | |
409 | |
410 if (fp == NULL) | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
411 fatal_error ("can%'t open %s: %m", buf); |
0 | 412 |
413 gcc_assert (graph_dump_format == vcg); | |
414 fputs ("graph: {\nport_sharing: no\n", fp); | |
415 | |
416 fclose (fp); | |
417 } | |
418 | |
419 | |
420 /* Do final work on the graph output file. */ | |
421 void | |
422 finish_graph_dump_file (const char *base) | |
423 { | |
424 size_t namelen = strlen (base); | |
425 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1; | |
426 char *buf = XALLOCAVEC (char, namelen + extlen); | |
427 FILE *fp; | |
428 | |
429 memcpy (buf, base, namelen); | |
430 memcpy (buf + namelen, graph_ext[graph_dump_format], extlen); | |
431 | |
432 fp = fopen (buf, "a"); | |
433 if (fp != NULL) | |
434 { | |
435 gcc_assert (graph_dump_format == vcg); | |
436 fputs ("}\n", fp); | |
437 fclose (fp); | |
438 } | |
439 } |