diff options
author | CHENG Renquan <rqcheng@smu.edu.sg> | 2010-07-12 16:49:08 +0800 |
---|---|---|
committer | CHENG Renquan <rqcheng@smu.edu.sg> | 2010-07-12 16:49:08 +0800 |
commit | 6e10941cc40ffb9d3835521658e5a95d797ca11e (patch) | |
tree | 7fe1c82678aab965babade0f015137a6ada409d7 | |
parent | fc85c38529fb8c824f616d4ffaf3d1f04badd0a2 (diff) | |
download | gcc-dot-gen-plugin-master.tar.gz gcc-dot-gen-plugin-master.tar.xz gcc-dot-gen-plugin-master.zip |
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | pass-dgen.c | 124 |
2 files changed, 79 insertions, 47 deletions
@@ -7,7 +7,7 @@ PLUGIN_SOURCE_FILES = pass-dgen.c PLUGIN_OBJECT_FILES = $(patsubst %.c,%.o,$(PLUGIN_SOURCE_FILES)) GCCPLUGINS_DIR := $(shell $(GCC) -print-file-name=plugin) -CFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(with_gmp)/include -Wall -O2 +CFLAGS += -I$(GCCPLUGINS_DIR)/include -I$(with_gmp)/include -Wall -fPIC -O2 all: $(PLUGIN_FILE) diff --git a/pass-dgen.c b/pass-dgen.c index 3bf9634..76e36f8 100644 --- a/pass-dgen.c +++ b/pass-dgen.c @@ -30,10 +30,16 @@ along with GCC; see the file COPYING3. If not see #include "tree-flow.h" #include "tree-dump.h" #include "tree-pass.h" +#include "toplev.h" int plugin_is_GPL_compatible; +/* global variables */ static const char *plugin_name; +static int dot_nr; +static FILE *dot_file = NULL; +static bool disabled = false; + static struct plugin_info _version_help_info = { "0.1", /* version */ @@ -42,23 +48,24 @@ static struct plugin_info _version_help_info = }; static void -gimple_cfg2dot (FILE *file) +gimple_cfg2dot (void) { edge e; edge_iterator ei; basic_block bb; + const char *funcname = lang_hooks.decl_printable_name (current_function_decl, 2); /* Write the file header. */ - fprintf (file, "// Function %s\n", funcname); - fprintf (file, "digraph graph_%s {\n\n", funcname); - fprintf (file, " graph [ label=%s, labelloc=top ];\n\n", funcname); + fprintf (dot_file, "// Function %s\n", funcname); + fprintf (dot_file, "digraph graph_%s {\n\n", funcname); + fprintf (dot_file, " graph [ label=%s, labelloc=top ];\n\n", funcname); /* Write blocks and edges. */ FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) { - fprintf (file, " ENTRY -> %d", e->dest->index); + fprintf (dot_file, " ENTRY -> %d", e->dest->index); /* how to represent this in Graphviz dot ??? */ /* if (e->flags & EDGE_FAKE) */ @@ -66,9 +73,9 @@ gimple_cfg2dot (FILE *file) /* else */ /* fprintf (file, " linestyle: solid priority: 100"); */ - fprintf (file, "\n"); + fprintf (dot_file, "\n"); } - fputc ('\n', file); + fputc ('\n', dot_file); FOR_EACH_BB (bb) { @@ -97,65 +104,74 @@ gimple_cfg2dot (FILE *file) else end_name = "no-statement"; - fprintf (file, " %d [ label=\"#%d\\n%s (%d)\\n%s (%d)\" ]\n", + fprintf (dot_file, " %d [ label=\"#%d\\n%s (%d)\\n%s (%d)\" ]\n", bb->index, bb->index, head_name, head_line, end_name, end_line); FOR_EACH_EDGE (e, ei, bb->succs) { if (e->dest == EXIT_BLOCK_PTR) - fprintf (file, " %d -> EXIT\n", bb->index); + fprintf (dot_file, " %d -> EXIT\n", bb->index); else - fprintf (file, " %d -> %d", bb->index, e->dest->index); + { + fprintf (dot_file, " %d -> %d", bb->index, e->dest->index); - /* if (e->flags & EDGE_FAKE) */ - /* fprintf (file, " priority: 10 linestyle: dotted"); */ - /* else */ - /* fprintf (file, " priority: 100 linestyle: solid"); */ + /* if (e->flags & EDGE_FAKE) */ + /* fprintf (file, " priority: 10 linestyle: dotted"); */ + /* else */ + /* fprintf (file, " priority: 100 linestyle: solid"); */ - /* fprintf (file, "\n"); */ + fprintf (dot_file, "\n"); + } } if (bb->next_bb != EXIT_BLOCK_PTR) - fputc ('\n', file); + fputc ('\n', dot_file); } - fprintf (file, "}\n\n"); + fprintf (dot_file, "}\n\n"); } -static unsigned int -execute_pass_cfg2dot () +static void +open_dump_file (void) { - static int dot_nr; - FILE *dot_file = NULL; - - if (!dot_nr) + dot_nr = dump_register (".dot", NULL, NULL, TDF_TREE); + + /* manually set dfi->state to -1 enable it, + because the dump_enable is static, cannot be used + by plugins. + */ + get_dump_file_info (dot_nr)->state = -1; + dot_file = dump_begin (dot_nr, NULL); + if (dot_file) { - dot_nr = dump_register (".dot", NULL, NULL, TDF_TREE); - /* manually set dfi->state to -1 enable it, - because the dump_enable is static, cannot be used - by plugins. - */ - get_dump_file_info (dot_nr)->state = -1; - dot_file = dump_begin (dot_nr, NULL); - if (dot_file) - { - time_t now; - time (&now); - fprintf (dot_file, - "\n// Generated by %s gcc plugin %s at %s\n", - plugin_name, _version_help_info.version, - ctime (&now)); - } + time_t now; + time (&now); + fprintf (dot_file, + "\n// Generated by %s gcc plugin %s at %s\n", + plugin_name, _version_help_info.version, + ctime (&now)); } - - if (!dot_file) - dot_file = dump_begin (dot_nr, NULL); - if (dot_file) + else { - gimple_cfg2dot (dot_file); - dump_end (dot_nr, dot_file); + warning (0, "dot dump file open failed, diable this pass for following functions."); + disabled = true; } +} + +static bool +gate_enabled (void) +{ + return !disabled; +} + +static unsigned int +execute_pass_cfg2dot (void) +{ + if (!dot_file) + open_dump_file (); + + gimple_cfg2dot (); return 0; } @@ -165,7 +181,7 @@ static struct gimple_opt_pass pass_cfg2dot = { GIMPLE_PASS, "*cfg2dot", /* name */ - NULL, /* gate */ + gate_enabled, /* gate */ execute_pass_cfg2dot, /* execute */ NULL, /* sub */ NULL, /* next */ @@ -179,6 +195,18 @@ static struct gimple_opt_pass pass_cfg2dot = } }; +static void +plugin_finish_unit (void *gcc_data, + void *user_data) +{ + if (dot_file) + { + dump_end (dot_nr, dot_file); + dot_file = NULL; + dot_nr = 0; + } +} + int plugin_init (struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) @@ -191,6 +219,10 @@ plugin_init (struct plugin_name_args *plugin_info, PLUGIN_INFO, NULL, &_version_help_info); + register_callback (plugin_name, + PLUGIN_FINISH_UNIT, + plugin_finish_unit, + NULL); regi_info.pass = &pass_cfg2dot.pass; regi_info.reference_pass_name = "cfg"; |