[PATCH 1/2] JSON Dumping of GENERIC trees

2024-09-21 Thread 4444-thor
From: thor 

This is the second revision of:

  https://gcc.gnu.org/pipermail/gcc-patches/2024-September/662849.html

I've incorporated the feedback given both by Richard and David - I didn't
find any memory leaks when testing in valgrind :)

As before: This patch allows the compiler to dump GENERIC trees as JSON objects.

The dump flag -fdump-tree-original-json dumps each fndecl node in the
C frontend's gimplifier as a JSON object and traverses related nodes
in an analagous manner as to raw-dumping.

Some JSON parsers expect for there to be a single JSON value per file -
the following shell command makes the output conformant:

  tr -d '\n ' < out.json | sed -e 's/\]\[/,/g' | sed -e 's/}{/},{/g'

The information in the dumped JSON is meant to be an amalgation of
tree-pretty-print.cc's dump_generic_node and print-tree.cc's debug_tree.

Bootstrapped and tested on x86_64-pc-linux-gnu without issue (again).

gcc/ChangeLog:
* gcc/Makefile.in: Link tree-emit-json.o to c-gimplify.o
* gcc/dumpfile.h (dump_flag): New dump flag TDF_JSON
* gcc/tree-emit-json.cc: Logic for converting a tree to JSON
and dumping.
* gcc/tree-emit-json.h: For the above
gcc/c-family/ChangeLog
* gcc/c-family/c-gimplify.cc (c_genericize): Hook for
-fdump-tree-original-json

Signed-off-by: Thor C Preimesberger 
---
 gcc/Makefile.in|2 +
 gcc/c-family/c-gimplify.cc |   29 +-
 gcc/dumpfile.cc|1 +
 gcc/dumpfile.h |6 +
 gcc/tree-emit-json.cc  | 3227 
 gcc/tree-emit-json.h   |   73 +
 6 files changed, 3327 insertions(+), 11 deletions(-)
 create mode 100644 gcc/tree-emit-json.cc
 create mode 100644 gcc/tree-emit-json.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 68fda1a7591..b65cc7f0ad5 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1042,6 +1042,7 @@ OPTS_H = $(INPUT_H) $(VEC_H) opts.h $(OBSTACK_H)
 SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h $(OBSTACK_H)
 CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h
 TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) $(DUMPFILE_H)
+TREE_EMIT_JSON_H = tree-emit-json.h $(SPLAY_TREE_H) $(DUMPFILE_H) json.h
 TREE_PASS_H = tree-pass.h $(TIMEVAR_H) $(DUMPFILE_H)
 TREE_SSA_H = tree-ssa.h tree-ssa-operands.h \
$(BITMAP_H) sbitmap.h $(BASIC_BLOCK_H) $(GIMPLE_H) \
@@ -1709,6 +1710,7 @@ OBJS = \
tree-diagnostic.o \
tree-diagnostic-client-data-hooks.o \
tree-dump.o \
+   tree-emit-json.o \
tree-eh.o \
tree-emutls.o \
tree-if-conv.o \
diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
index 3e29766e092..e4234071b11 100644
--- a/gcc/c-family/c-gimplify.cc
+++ b/gcc/c-family/c-gimplify.cc
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 #include "config.h"
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
@@ -629,20 +630,26 @@ c_genericize (tree fndecl)
   local_dump_flags = dfi->pflags;
   if (dump_orig)
 {
-  fprintf (dump_orig, "\n;; Function %s",
-  lang_hooks.decl_printable_name (fndecl, 2));
-  fprintf (dump_orig, " (%s)\n",
-  (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
-   : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl;
-  fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name 
(TDI_original));
-  fprintf (dump_orig, "\n");
-
-  if (local_dump_flags & TDF_RAW)
-   dump_node (DECL_SAVED_TREE (fndecl),
+  if (local_dump_flags & TDF_JSON)
+   dump_node_json (DECL_SAVED_TREE (fndecl),
   TDF_SLIM | local_dump_flags, dump_orig);
   else
-   print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
+  {
+   fprintf (dump_orig, "\n;; Function %s",
+lang_hooks.decl_printable_name (fndecl, 2));
+   fprintf (dump_orig, " (%s)\n",
+   (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
+: IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl;
+   fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name 
(TDI_original));
+   fprintf (dump_orig, "\n");
+   if (local_dump_flags & TDF_RAW)
+ dump_node (DECL_SAVED_TREE (fndecl),
+TDF_SLIM | local_dump_flags, dump_orig);
+   else
+ print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
+  
   fprintf (dump_orig, "\n");
+  }
 }
 
   /* Dump all nested functions now.  */
diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
index 074da7df216..0b38f4aa0dd 100644
--- a/gcc/dumpfile.cc
+++ b/gcc/dumpfile.cc
@@ -148,6 +148,7 @@ static const kv_pair dump_options[] =
   {"missed", MSG_MISSED_OPTIMIZATION},
   {"note", MSG_NOTE},
   {"optall", MSG_ALL_KINDS},
+  {"json", TDF_JSON},
   {"all", dump_flags_t (TDF_ALL_VALUES
& ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
| TDF_STMTADDR | TDF_RHS_ONLY | T

[PATCH 2/2] HTML Dumping of trees from gdb

2024-09-21 Thread 4444-thor
From: thor 

This patch allows one to dump a tree as HTML from within gdb by invoking,
i.e,
  htlml-tree tree

gcc/ChangeLog:
* gcc/gdbhooks.py: Rudimentary dumping of GENERIC trees as html through
  one new python function (jsonNodeToHtml) and one new gdb command 
  (html-tree). There is also a parameter to allow html-tree to 
  automatically open a browser to view the HTML, but that needs a fix
  or workaround that I don't understand.

Signed-off-by: Thor C Preimesberger 

---
 gcc/gdbhooks.py | 113 
 1 file changed, 113 insertions(+)

diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py
index 904ee28423a..fff85d738b4 100644
--- a/gcc/gdbhooks.py
+++ b/gcc/gdbhooks.py
@@ -143,6 +143,7 @@ import os.path
 import re
 import sys
 import tempfile
+import json
 
 import gdb
 import gdb.printing
@@ -889,6 +890,118 @@ class DotFn(gdb.Command):
 
 DotFn()
 
+# Quick and dirty way to turn a tree as JSON object into HTML.
+# Used in treeToHtml.
+
+def jsonNodeToHtml(node_list, html_doc):
+for node in node_list:
+id = node["addr"]
+html_doc.write("" % id)
+for key, value in node.items():
+if (key == "addr"):
+html_doc.write("addr:")
+html_doc.write(f"")
+html_doc.write(f"{value}")
+html_doc.write(f"")
+if (type(value) == dict):
+html_doc.write(f"{key}:")
+sub = value
+if "ref_addr" in sub.keys():
+html_doc.write(f"") 
+subAddress = sub["ref_addr"]
+subCode = sub["tree_code"]
+html_doc.write(f"ref_addr: {subAddress}")
+html_doc.write(f"tree_code: {subCode}")
+html_doc.write("")
+# Currently, child tree nodes that are referred to by OMP
+# accsessors are not dumped recursively by
+# dump_generic_node_json, i.e. they have no corresponding
+# entry in node_list. So we just read it out key-value pairs.
+else:
+html_doc.write(f"") 
+for key, value in sub.items():
+html_doc.write(f"{key}: {value}")
+html_doc.write("")
+elif (type(value) == list):
+html_doc.write(f"{key}:")
+html_doc.write(f"") 
+for i in value:
+for key, value in i.items():
+if (key == "ref_addr"):
+html_doc.write("ref_addr:")
+html_doc.write(f"")
+html_doc.write(f"{value}")
+html_doc.write(f"")
+else:
+html_doc.write(f"{key}: {value}")
+html_doc.write("")
+elif (key != "addr"):
+html_doc.write(f"{key}: {value}")
+html_doc.write("")
+
+class GCChtml (gdb.Parameter):
+"""
+This parameter defines what program is used to view HTML files
+by the html-tree command. It will be invoked as gcc-html .
+"""
+def __init__(self):
+super(GCChtml, self).__init__('gcc-html',
+gdb.COMMAND_NONE, gdb.PARAM_STRING)
+self.value = "firefox"
+
+gcc_html_cmd = GCChtml()
+
+class treeToHtml (gdb.Command):
+"""
+A custom command that converts a tree to html after it is
+first parsed to JSON. The html is saved in cwd as  + ".html".
+
+TODO : It'd be nice if we then open the html with the program specified
+by the GCChtml parameter, but there's an error thrown whenever I try
+to do this while attached to cc1/cc1plus.
+
+Examples of use:
+  (gdb) html-tree current_tree
+"""
+
+def __init__(self):
+gdb.Command.__init__(self, 'html-tree', gdb.COMMAND_USER)
+
+def invoke(self, arg, file):
+
+args = gdb.string_to_argv(arg)
+if len(args) >= 2:
+print ("Error: Too many arguments")
+return
+
+if len(args) >= 1:
+treeName = args[0]
+print(treeName)
+
+# We call a function within GCC to dump the JSON
+# and create a tempfile to store the JSON before we pass it into our
+# Python shell.
+f = tempfile.NamedTemporaryFile(delete=False)
+filename = f.name
+gdb.execute('set $%s = fopen (\"%s\", \"w\")' % ("jsonTemp", filename))
+gdb.execute("call debug_dump_node_json (%s, $%s)"
+% (treeName, "jsonTemp"))
+gdb.execute("call fclose($%s)" % "jsonTemp")
+with open(filename, "r") as foobar:
+obj = json.loads(foobar.read())
+
+# Create an html file in cwd, and dump our tree as HTML.
+htmlFile = open(treeName + ".html", "w")
+with open(htmlFile.name, "w") as _:
+jsonNodeToHtml(