00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include "system.h"
00024
00025 #include "rtl.h"
00026 #include "flags.h"
00027 #include "output.h"
00028 #include "function.h"
00029 #include "hard-reg-set.h"
00030 #include "basic-block.h"
00031 #include "toplev.h"
00032 #include "graph.h"
00033
00034 static const char *const graph_ext[] =
00035 {
00036 "",
00037 ".vcg",
00038 };
00039
00040 static void start_fct PARAMS ((FILE *));
00041 static void start_bb PARAMS ((FILE *, int));
00042 static void node_data PARAMS ((FILE *, rtx));
00043 static void draw_edge PARAMS ((FILE *, int, int, int, int));
00044 static void end_fct PARAMS ((FILE *));
00045 static void end_bb PARAMS ((FILE *));
00046
00047
00048 static void
00049 start_fct (fp)
00050 FILE *fp;
00051 {
00052
00053 switch (graph_dump_format)
00054 {
00055 case vcg:
00056 fprintf (fp, "\
00057 graph: { title: \"%s\"\nfolding: 1\nhidden: 2\nnode: { title: \"%s.0\" }\n",
00058 current_function_name, current_function_name);
00059 break;
00060 case no_graph:
00061 break;
00062 }
00063 }
00064
00065 static void
00066 start_bb (fp, bb)
00067 FILE *fp;
00068 int bb;
00069 {
00070 switch (graph_dump_format)
00071 {
00072 case vcg:
00073 fprintf (fp, "\
00074 graph: {\ntitle: \"%s.BB%d\"\nfolding: 1\ncolor: lightblue\n\
00075 label: \"basic block %d",
00076 current_function_name, bb, bb);
00077 break;
00078 case no_graph:
00079 break;
00080 }
00081
00082 #if 0
00083
00084
00085
00086 fputc ('\n', fp);
00087 EXECUTE_IF_SET_IN_REG_SET (basic_block_live_at_start[bb], 0, i,
00088 {
00089 fprintf (fp, " %d", i);
00090 if (i < FIRST_PSEUDO_REGISTER)
00091 fprintf (fp, " [%s]",
00092 reg_names[i]);
00093 });
00094 #endif
00095
00096 switch (graph_dump_format)
00097 {
00098 case vcg:
00099 fputs ("\"\n\n", fp);
00100 break;
00101 case no_graph:
00102 break;
00103 }
00104 }
00105
00106 static void
00107 node_data (fp, tmp_rtx)
00108 FILE *fp;
00109 rtx tmp_rtx;
00110 {
00111
00112 if (PREV_INSN (tmp_rtx) == 0)
00113 {
00114
00115
00116 switch (graph_dump_format)
00117 {
00118 case vcg:
00119 fprintf (fp, "\
00120 edge: { sourcename: \"%s.0\" targetname: \"%s.%d\" }\n",
00121 current_function_name,
00122 current_function_name, XINT (tmp_rtx, 0));
00123 break;
00124 case no_graph:
00125 break;
00126 }
00127 }
00128
00129 switch (graph_dump_format)
00130 {
00131 case vcg:
00132 fprintf (fp, "node: {\n title: \"%s.%d\"\n color: %s\n \
00133 label: \"%s %d\n",
00134 current_function_name, XINT (tmp_rtx, 0),
00135 GET_CODE (tmp_rtx) == NOTE ? "lightgrey"
00136 : GET_CODE (tmp_rtx) == INSN ? "green"
00137 : GET_CODE (tmp_rtx) == JUMP_INSN ? "darkgreen"
00138 : GET_CODE (tmp_rtx) == CALL_INSN ? "darkgreen"
00139 : GET_CODE (tmp_rtx) == CODE_LABEL ? "\
00140 darkgrey\n shape: ellipse" : "white",
00141 GET_RTX_NAME (GET_CODE (tmp_rtx)), XINT (tmp_rtx, 0));
00142 break;
00143 case no_graph:
00144 break;
00145 }
00146
00147
00148 if (GET_CODE (tmp_rtx) == NOTE)
00149 {
00150 const char *name = "";
00151 if (NOTE_LINE_NUMBER (tmp_rtx) < 0)
00152 name = GET_NOTE_INSN_NAME (NOTE_LINE_NUMBER (tmp_rtx));
00153 fprintf (fp, " %s", name);
00154 }
00155 else if (INSN_P (tmp_rtx))
00156 print_rtl_single (fp, PATTERN (tmp_rtx));
00157 else
00158 print_rtl_single (fp, tmp_rtx);
00159
00160 switch (graph_dump_format)
00161 {
00162 case vcg:
00163 fputs ("\"\n}\n", fp);
00164 break;
00165 case no_graph:
00166 break;
00167 }
00168 }
00169
00170 static void
00171 draw_edge (fp, from, to, bb_edge, class)
00172 FILE *fp;
00173 int from;
00174 int to;
00175 int bb_edge;
00176 int class;
00177 {
00178 const char * color;
00179 switch (graph_dump_format)
00180 {
00181 case vcg:
00182 color = "";
00183 if (class == 2)
00184 color = "color: red ";
00185 else if (bb_edge)
00186 color = "color: blue ";
00187 else if (class == 3)
00188 color = "color: green ";
00189 fprintf (fp,
00190 "edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s",
00191 current_function_name, from,
00192 current_function_name, to, color);
00193 if (class)
00194 fprintf (fp, "class: %d ", class);
00195 fputs ("}\n", fp);
00196 break;
00197 case no_graph:
00198 break;
00199 }
00200 }
00201
00202 static void
00203 end_bb (fp)
00204 FILE *fp;
00205 {
00206 switch (graph_dump_format)
00207 {
00208 case vcg:
00209 fputs ("}\n", fp);
00210 break;
00211 case no_graph:
00212 break;
00213 }
00214 }
00215
00216 static void
00217 end_fct (fp)
00218 FILE *fp;
00219 {
00220 switch (graph_dump_format)
00221 {
00222 case vcg:
00223 fprintf (fp, "node: { title: \"%s.999999\" label: \"END\" }\n}\n",
00224 current_function_name);
00225 break;
00226 case no_graph:
00227 break;
00228 }
00229 }
00230
00231
00232
00233 void
00234 print_rtl_graph_with_bb (base, suffix, rtx_first)
00235 const char *base;
00236 const char *suffix;
00237 rtx rtx_first;
00238 {
00239 rtx tmp_rtx;
00240 size_t namelen = strlen (base);
00241 size_t suffixlen = strlen (suffix);
00242 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
00243 char *buf = (char *) alloca (namelen + suffixlen + extlen);
00244 FILE *fp;
00245
00246 if (basic_block_info == NULL)
00247 return;
00248
00249 memcpy (buf, base, namelen);
00250 memcpy (buf + namelen, suffix, suffixlen);
00251 memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
00252
00253 fp = fopen (buf, "a");
00254 if (fp == NULL)
00255 return;
00256
00257 if (rtx_first == 0)
00258 fprintf (fp, "(nil)\n");
00259 else
00260 {
00261 enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
00262 int max_uid = get_max_uid ();
00263 int *start = (int *) xmalloc (max_uid * sizeof (int));
00264 int *end = (int *) xmalloc (max_uid * sizeof (int));
00265 enum bb_state *in_bb_p = (enum bb_state *)
00266 xmalloc (max_uid * sizeof (enum bb_state));
00267 basic_block bb;
00268 int i;
00269
00270 for (i = 0; i < max_uid; ++i)
00271 {
00272 start[i] = end[i] = -1;
00273 in_bb_p[i] = NOT_IN_BB;
00274 }
00275
00276 FOR_EACH_BB_REVERSE (bb)
00277 {
00278 rtx x;
00279 start[INSN_UID (bb->head)] = bb->index;
00280 end[INSN_UID (bb->end)] = bb->index;
00281 for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
00282 {
00283 in_bb_p[INSN_UID (x)]
00284 = (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
00285 ? IN_ONE_BB : IN_MULTIPLE_BB;
00286 if (x == bb->end)
00287 break;
00288 }
00289 }
00290
00291
00292 dump_for_graph = 1;
00293
00294
00295 start_fct (fp);
00296
00297 for (tmp_rtx = NEXT_INSN (rtx_first); NULL != tmp_rtx;
00298 tmp_rtx = NEXT_INSN (tmp_rtx))
00299 {
00300 int edge_printed = 0;
00301 rtx next_insn;
00302
00303 if (start[INSN_UID (tmp_rtx)] < 0 && end[INSN_UID (tmp_rtx)] < 0)
00304 {
00305 if (GET_CODE (tmp_rtx) == BARRIER)
00306 continue;
00307 if (GET_CODE (tmp_rtx) == NOTE
00308 && (1 || in_bb_p[INSN_UID (tmp_rtx)] == NOT_IN_BB))
00309 continue;
00310 }
00311
00312 if ((i = start[INSN_UID (tmp_rtx)]) >= 0)
00313 {
00314
00315 start_bb (fp, i);
00316
00317 if (i == 0)
00318 draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0);
00319 }
00320
00321
00322 node_data (fp, tmp_rtx);
00323 next_insn = next_nonnote_insn (tmp_rtx);
00324
00325 if ((i = end[INSN_UID (tmp_rtx)]) >= 0)
00326 {
00327 edge e;
00328
00329 bb = BASIC_BLOCK (i);
00330
00331
00332 end_bb (fp);
00333
00334
00335
00336 for (e = bb->succ; e ; e = e->succ_next)
00337 {
00338 if (e->dest != EXIT_BLOCK_PTR)
00339 {
00340 rtx block_head = e->dest->head;
00341
00342 draw_edge (fp, INSN_UID (tmp_rtx),
00343 INSN_UID (block_head),
00344 next_insn != block_head,
00345 (e->flags & EDGE_ABNORMAL ? 2 : 0));
00346
00347 if (block_head == next_insn)
00348 edge_printed = 1;
00349 }
00350 else
00351 {
00352 draw_edge (fp, INSN_UID (tmp_rtx), 999999,
00353 next_insn != 0,
00354 (e->flags & EDGE_ABNORMAL ? 2 : 0));
00355
00356 if (next_insn == 0)
00357 edge_printed = 1;
00358 }
00359 }
00360 }
00361
00362 if (!edge_printed)
00363 {
00364
00365 if (next_insn == 0
00366 || GET_CODE (next_insn) != BARRIER)
00367 draw_edge (fp, XINT (tmp_rtx, 0),
00368 next_insn ? INSN_UID (next_insn) : 999999, 0, 0);
00369 else
00370 {
00371
00372
00373
00374 do
00375 next_insn = NEXT_INSN (next_insn);
00376 while (next_insn
00377 && (GET_CODE (next_insn) == NOTE
00378 || GET_CODE (next_insn) == BARRIER));
00379
00380 draw_edge (fp, XINT (tmp_rtx, 0),
00381 next_insn ? INSN_UID (next_insn) : 999999, 0, 3);
00382 }
00383 }
00384 }
00385
00386 dump_for_graph = 0;
00387
00388 end_fct (fp);
00389
00390
00391 free (start);
00392 free (end);
00393 free (in_bb_p);
00394 }
00395
00396 fclose (fp);
00397 }
00398
00399
00400
00401
00402 void
00403 clean_graph_dump_file (base, suffix)
00404 const char *base;
00405 const char *suffix;
00406 {
00407 size_t namelen = strlen (base);
00408 size_t suffixlen = strlen (suffix);
00409 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
00410 char *buf = (char *) alloca (namelen + extlen + suffixlen);
00411 FILE *fp;
00412
00413 memcpy (buf, base, namelen);
00414 memcpy (buf + namelen, suffix, suffixlen);
00415 memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
00416
00417 fp = fopen (buf, "w");
00418
00419 if (fp == NULL)
00420 fatal_io_error ("can't open %s", buf);
00421
00422 switch (graph_dump_format)
00423 {
00424 case vcg:
00425 fputs ("graph: {\nport_sharing: no\n", fp);
00426 break;
00427 case no_graph:
00428 abort ();
00429 }
00430
00431 fclose (fp);
00432 }
00433
00434
00435
00436 void
00437 finish_graph_dump_file (base, suffix)
00438 const char *base;
00439 const char *suffix;
00440 {
00441 size_t namelen = strlen (base);
00442 size_t suffixlen = strlen (suffix);
00443 size_t extlen = strlen (graph_ext[graph_dump_format]) + 1;
00444 char *buf = (char *) alloca (namelen + suffixlen + extlen);
00445 FILE *fp;
00446
00447 memcpy (buf, base, namelen);
00448 memcpy (buf + namelen, suffix, suffixlen);
00449 memcpy (buf + namelen + suffixlen, graph_ext[graph_dump_format], extlen);
00450
00451 fp = fopen (buf, "a");
00452 if (fp != NULL)
00453 {
00454 switch (graph_dump_format)
00455 {
00456 case vcg:
00457 fputs ("}\n", fp);
00458 break;
00459 case no_graph:
00460 abort ();
00461 }
00462
00463 fclose (fp);
00464 }
00465 }