diff options
Diffstat (limited to 'gcc/graph.c')
-rw-r--r-- | gcc/graph.c | 124 |
1 files changed, 58 insertions, 66 deletions
diff --git a/gcc/graph.c b/gcc/graph.c index bb1bb7b..a908e60 100644 --- a/gcc/graph.c +++ b/gcc/graph.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "rtl.h" #include "tree.h" #include "graph.h" +#include "pretty-print.h" /* DOT files with the .dot extension are recognized as document templates by a well-known piece of word processing software out of Redmond, WA. @@ -56,45 +57,30 @@ open_graph_file (const char *base, const char *mode) return fp; } -/* Print the output from print_insn or print_pattern with GraphViz-special - characters escaped as necessary. */ -void -print_escaped_line (FILE *fp, const char *buf) +/* Return a pretty-print buffer for output to file FP. */ + +static pretty_printer * +init_graph_slim_pretty_print (FILE *fp) { - const char *p = buf; + static bool initialized = false; + static pretty_printer graph_slim_pp; - while (*p) + if (! initialized) { - switch (*p) - { - case '\n': - /* Print newlines as a left-aligned newline. */ - fputs ("\\l\\\n", fp); - break; - - case '{': - case '}': - case '<': - case '>': - case '|': - case '"': - case ' ': - /* These characters have to be escaped to work with record-shape nodes. */ - fputc ('\\', fp); - /* fall through */ - default: - fputc (*p, fp); - break; - } - p++; + pp_construct (&graph_slim_pp, /*prefix=*/NULL, /*linewidth=*/0); + initialized = true; } - fputs ("\\l\\\n", fp); + else + gcc_assert (! pp_last_position_in_text (&graph_slim_pp)); + + graph_slim_pp.buffer->stream = fp; + return &graph_slim_pp; } /* Draw a basic block BB belonging to the function with FNDECL_UID as its unique number. */ static void -draw_cfg_node (FILE *fp, int fndecl_uid, basic_block bb) +draw_cfg_node (pretty_printer *pp, int fndecl_uid, basic_block bb) { rtx insn; bool first = true; @@ -115,48 +101,53 @@ draw_cfg_node (FILE *fp, int fndecl_uid, basic_block bb) : "lightgrey"; } - fprintf (fp, - "\tfn_%d_basic_block_%d [shape=%s,style=filled,fillcolor=%s,label=\"", - fndecl_uid, bb->index, shape, fillcolor); + pp_printf (pp, + "\tfn_%d_basic_block_%d " + "[shape=%s,style=filled,fillcolor=%s,label=\"", + fndecl_uid, bb->index, shape, fillcolor); if (bb->index == ENTRY_BLOCK) - fputs ("ENTRY", fp); + pp_string (pp, "ENTRY"); else if (bb->index == EXIT_BLOCK) - fputs ("EXIT", fp); + pp_string (pp, "EXIT"); else { - fputc ('{', fp); + pp_character (pp, '{'); + pp_write_text_to_stream (pp); + /* TODO: inter-bb stuff. */ FOR_BB_INSNS (bb, insn) { - char buf[2048]; - if (! first) - fputc ('|', fp); + { + pp_character (pp, '|'); + pp_write_text_to_stream (pp); + } + first = false; - print_insn (buf, insn, 1); - print_escaped_line (fp, buf); + print_insn (pp, insn, 1); + pp_newline (pp); if (INSN_P (insn) && REG_NOTES (insn)) for (rtx note = REG_NOTES (insn); note; note = XEXP (note, 1)) { - fprintf (fp, " %s: ", - GET_REG_NOTE_NAME (REG_NOTE_KIND (note))); - print_pattern (buf, XEXP (note, 0), 1); - print_escaped_line (fp, buf); + pp_printf (pp, " %s: ", + GET_REG_NOTE_NAME (REG_NOTE_KIND (note))); + print_pattern (pp, XEXP (note, 0), 1); + pp_newline (pp); } - - first = false; + pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true); } - fputc ('}', fp); + pp_character (pp, '}'); } - fputs ("\"];\n\n", fp); + pp_string (pp, "\"];\n\n"); + pp_flush (pp); } /* Draw all successor edges of a basic block BB belonging to the function with FNDECL_UID as its unique number. */ static void -draw_cfg_node_succ_edges (FILE *fp, int fndecl_uid, basic_block bb) +draw_cfg_node_succ_edges (pretty_printer *pp, int fndecl_uid, basic_block bb) { edge e; edge_iterator ei; @@ -187,14 +178,15 @@ draw_cfg_node_succ_edges (FILE *fp, int fndecl_uid, basic_block bb) if (e->flags & EDGE_ABNORMAL) color = "red"; - fprintf (fp, - "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n " - "[style=%s,color=%s,weight=%d,constraint=%s];\n", - fndecl_uid, e->src->index, - fndecl_uid, e->dest->index, - style, color, weight, - (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true"); + pp_printf (pp, + "\tfn_%d_basic_block_%d:s -> fn_%d_basic_block_%d:n " + "[style=%s,color=%s,weight=%d,constraint=%s];\n", + fndecl_uid, e->src->index, + fndecl_uid, e->dest->index, + style, color, weight, + (e->flags & (EDGE_FAKE | EDGE_DFS_BACK)) ? "false" : "true"); } + pp_flush (pp); } /* Print a graphical representation of the CFG of function FUN. @@ -208,19 +200,19 @@ print_rtl_graph_with_bb (const char *base, tree fndecl) int *rpo = XNEWVEC (int, n_basic_blocks); basic_block bb; int i, n; + pretty_printer *pp = init_graph_slim_pretty_print (fp); - fprintf (fp, - "subgraph \"%s\" {\n" - "\tcolor=\"black\";\n" - "\tlabel=\"%s\";\n", - funcname, funcname); + pp_printf (pp, "subgraph \"%s\" {\n" + "\tcolor=\"black\";\n" + "\tlabel=\"%s\";\n", + funcname, funcname); /* First print all basic blocks. Visit the blocks in reverse post order to get a good ranking of the nodes. */ n = pre_and_rev_post_order_compute (NULL, rpo, true); for (i = 0; i < n; i++) - draw_cfg_node (fp, fndecl_uid, BASIC_BLOCK (rpo[i])); + draw_cfg_node (pp, fndecl_uid, BASIC_BLOCK (rpo[i])); /* Draw all edges at the end to get subgraphs right for GraphViz, which requires nodes to be defined before edges to cluster @@ -232,10 +224,10 @@ print_rtl_graph_with_bb (const char *base, tree fndecl) for ourselves is also not desirable.) */ mark_dfs_back_edges (); FOR_ALL_BB (bb) - draw_cfg_node_succ_edges (fp, fndecl_uid, bb); - - fputs ("\t}\n", fp); + draw_cfg_node_succ_edges (pp, fndecl_uid, bb); + pp_printf (pp, "\t}\n"); + pp_flush (pp); fclose (fp); } |