Hi,
this patch adds a debug function dotfn and a convenience macro DOTFN
similar to dot-fn in gdbhooks.py.
It can be used to have the compiler:
- dump a control flow graph, or
- pop up a control flow graph window
at specific moments in the compilation flow, for debugging purposes.
Bootstrapped and reg-tested on x86_64.
Used for debugging PR81192.
OK for trunk?
Thanks,
- Tom
Add dotfn
2017-06-30 Tom de Vries <t...@codesourcery.com>
* graph.c (get_graph_file_name): New function, factored out of ...
(open_graph_file): ... here.
(dotfn): New function.
* graph.h (dotfn): Declare.
(DOTFN): New macro.
---
gcc/graph.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------
gcc/graph.h | 7 +++++++
2 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/gcc/graph.c b/gcc/graph.c
index 9261732..e6d3f2e 100644
--- a/gcc/graph.c
+++ b/gcc/graph.c
@@ -37,23 +37,45 @@ along with GCC; see the file COPYING3. If not see
ignore that recommendation... */
static const char *const graph_ext = ".dot";
+/* Return filename for dumping our graph to. If NUM, use *NUM in the file name
+ and increase *NUM. */
+
+static char *
+get_graph_file_name (const char *base, unsigned int *num = NULL)
+{
+ size_t namelen = strlen (base);
+ size_t extlen = strlen (graph_ext);
+ size_t numlen = num ? 11 : 0;
+ size_t len = namelen + extlen + numlen + 1;
+ char *buf = XNEWVEC (char, len);
+
+ char *pos = buf;
+ memcpy (pos, base, namelen);
+ pos += namelen;
+ if (num)
+ {
+ pos += snprintf (pos, numlen, ".%u", *num);
+ ++*num;
+ }
+ memcpy (pos, graph_ext, extlen + 1);
+
+ return buf;
+}
+
/* Open a file with MODE for dumping our graph to.
Return the file pointer. */
static FILE *
open_graph_file (const char *base, const char *mode)
{
- size_t namelen = strlen (base);
- size_t extlen = strlen (graph_ext) + 1;
- char *buf = XALLOCAVEC (char, namelen + extlen);
+ char *buf = get_graph_file_name (base);
FILE *fp;
- memcpy (buf, base, namelen);
- memcpy (buf + namelen, graph_ext, extlen);
-
fp = fopen (buf, mode);
if (fp == NULL)
fatal_error (input_location, "can%'t open %s: %m", buf);
+ XDELETEVEC (buf);
+
return fp;
}
@@ -354,3 +376,37 @@ finish_graph_dump_file (const char *base)
end_graph_dump (fp);
fclose (fp);
}
+
+/* Dump graph into file '<base>.dot', or if COUNTER is defined
+ '<base>.<*COUNTER>.dot'. If POPUP, show the graph in a popup window. */
+
+void DEBUG_FUNCTION
+dotfn (const char *base, unsigned int *counter, bool popup)
+{
+ char *name = get_graph_file_name (base, counter);
+
+ FILE *fp = fopen (name, "w");
+ if (fp != NULL)
+ {
+ start_graph_dump (fp, "<debug>");
+ print_graph_cfg (fp, cfun, dump_flags);
+ end_graph_dump (fp);
+ fclose (fp);
+
+ if (popup)
+ {
+ char prog[] = "dot";
+ char arg1[] = "-Tx11";
+ char *const cmd[] = { prog, arg1, name , NULL };
+ struct pex_obj *pex = pex_init (0, prog, NULL);
+ int err;
+ pex_run (pex, PEX_LAST | PEX_SEARCH, prog, cmd, NULL, NULL, &err);
+
+ int status;
+ pex_get_status (pex, 1, &status);
+ pex_free (pex);
+ }
+ }
+
+ XDELETEVEC (name);
+}
diff --git a/gcc/graph.h b/gcc/graph.h
index 4db253f..168b60c 100644
--- a/gcc/graph.h
+++ b/gcc/graph.h
@@ -24,4 +24,11 @@ extern void print_graph_cfg (const char *, struct function *);
extern void clean_graph_dump_file (const char *);
extern void finish_graph_dump_file (const char *);
+extern void dotfn (const char *base, unsigned int *counter, bool popup);
+#define DOTFN(base, popup) \
+ { \
+ static unsigned int counter = 0; \
+ dotfn (base, &counter, popup); \
+ }
+
#endif /* ! GCC_GRAPH_H */