From: Thor C Preimesberger <tcpreimesber...@gmail.com>

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'
 
There is also a debug function that simply prints a node as formatted JSON to
stdout.

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.

ChangeLog:
        * gcc/Makefile.in: Link tree-emit-json.o to c-gimplify.o
        * gcc/c-family/c-gimplify.cc (c_genericize): Hook for
        -fdump-tree-original-json
        * gcc/dumpfile.cc: Include tree-emit-json.h to expose
        node_emit_json and debug_tree_json. Also new headers needed for
        json.h being implicitly exposed
        * 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: Ditto

Signed-off-by: Thor C Preimesberger <tcpreimesber...@gmail.com>

---
 gcc/Makefile.in            |    2 +
 gcc/c-family/c-gimplify.cc |   30 +-
 gcc/cp/dump.cc             |    1 +
 gcc/dumpfile.cc            |    3 +
 gcc/dumpfile.h             |    6 +
 gcc/tree-emit-json.cc      | 3155 ++++++++++++++++++++++++++++++++++++
 gcc/tree-emit-json.h       |   82 +
 7 files changed, 3268 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..8b0c80f4f75 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
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
+#define INCLUDE_MEMORY
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
@@ -43,6 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "context.h"
 #include "tree-pass.h"
 #include "internal-fn.h"
+#include "tree-emit-json.h"
 
 /*  The gimplification pass converts the language-dependent trees
     (ld-trees) emitted by the parser into language-independent trees
@@ -629,20 +631,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/cp/dump.cc b/gcc/cp/dump.cc
index aafb62ffaa0..b1083de5f46 100644
--- a/gcc/cp/dump.cc
+++ b/gcc/cp/dump.cc
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "cp-tree.h"
+#define INCLUDE_MEMORY
 #include "tree-dump.h"
 
 /* Dump a representation of the accessibility information associated
diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
index 074da7df216..44d9451cf7c 100644
--- a/gcc/dumpfile.cc
+++ b/gcc/dumpfile.cc
@@ -43,6 +43,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "spellcheck.h"
 #include "make-unique.h"
 #include "pretty-print-format-impl.h"
+#include "tree-emit-json.h"
+#include "tree-emit-json.h"
 
 /* If non-NULL, return one past-the-end of the matching SUBPART of
    the WHOLE string.  */
@@ -148,6 +150,7 @@ static const kv_pair<dump_flags_t> 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 | TDF_NOUID
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index 877d444ce00..a116df5096f 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -202,6 +202,9 @@ enum dump_flag : uint32_t
 
   /* For error.  */
   TDF_ERROR = ((uint32_t)1 << 30),
+
+  /* Tree JSON dumping */
+  TDF_JSON = ((uint32_t)1 << 31),
 };
 
 /* Dump flags type.  */
@@ -652,6 +655,9 @@ extern bool enable_rtl_dump_file (void);
 /* In tree-dump.cc  */
 extern void dump_node (const_tree, dump_flags_t, FILE *);
 
+/* In tree-emit-json.cc */
+extern void dump_node_json(const_tree, dump_flags_t, FILE *);
+
 /* In cfghooks.cc  */
 extern void dump_bb (FILE *, basic_block, int, dump_flags_t);
 
diff --git a/gcc/tree-emit-json.cc b/gcc/tree-emit-json.cc
new file mode 100644
index 00000000000..e6de2029265
--- /dev/null
+++ b/gcc/tree-emit-json.cc
@@ -0,0 +1,3180 @@
+/* Dumping functionality for GENERIC Trees as JSON. Both for
+   the dump -fdump-tree-original-json and a new debug
+   function.
+   Copyright (C) 2024 Thor Preimesberger <tcpreimesber...@gmail.com>
+   Adapted from tree-pretty-print.cc, tree-dump.cc, and
+   print-tree.cc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#define INCLUDE_STRING
+#define INCLUDE_MEMORY
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tree-pretty-print.h"
+#include "tree-emit-json.h"
+#include "langhooks.h"
+#include "tree-iterator.h"
+#include "dumpfile.h"
+#include "json.h"
+#include "tm.h"
+#include "wide-int-print.h"
+#include "real.h" //for real printing
+#include "poly-int.h"
+#include "gomp-constants.h"
+#include "internal-fn.h"
+#include "cgraph.h"
+#include "predict.h"
+#include "fold-const.h"
+#include "vec.h"
+
+static unsigned int queue (dump_info_p, const_tree);
+static void dequeue_and_dump (dump_info_p);
+static json::array* function_decl_emit_json (tree);
+static void identifier_node_add_json (tree, json::object*);
+static void decl_node_add_json (tree, json::object*);
+static void function_name_add_json (tree, json::object*);
+static void omp_iterator_add_json (tree, json::object*);
+static void omp_clause_add_json(tree, json::object*);
+static void omp_atomic_memory_order_add_json (json::object*,
+                                              enum omp_memory_order);
+static json::object* omp_atomic_memory_order_emit_json(omp_memory_order mo);
+static json::object* omp_clause_emit_json (tree);
+static json::array* loc_emit_json(expanded_location);
+
+/* Add T to the end of the queue of nodes to dump.  Returns the index
+   assigned to T.  */
+
+static unsigned int
+queue (dump_info_p di, const_tree t)
+{
+  dump_queue_p dq;
+  dump_node_info_p dni;
+  unsigned int index;
+
+  /* Assign the next available index to T.  */
+  index = ++di->index;
+
+  /* Obtain a new queue node.  */
+  if (di->free_list)
+    {
+      dq = di->free_list;
+      di->free_list = dq->next;
+    }
+  else
+    dq = XNEW (struct dump_queue);
+
+  /* Create a new entry in the splay-tree.  */
+  dni = XNEW (struct dump_node_info);
+  dni->index = index;
+  dq->node = splay_tree_insert (di->nodes, (splay_tree_key) t,
+                               (splay_tree_value) dni);
+
+  /* Add it to the end of the queue.  */
+  dq->next = 0;
+  if (!di->queue_end)
+    di->queue = dq;
+  else
+    di->queue_end->next = dq;
+  di->queue_end = dq;
+
+  /* Return the index.  */
+  return index;
+}
+
+void
+address_add_json (const void* t, json::object* dummy, char* address_buffer)
+{
+  sprintf(address_buffer, HOST_PTR_PRINTF, t);
+  dummy->set_string("addr", address_buffer);
+}
+
+/* Return args of a function declaration */
+
+json::array*
+function_decl_emit_json (tree t)
+{
+  bool wrote_arg = false;
+  tree arg;
+  json::array* arg_holder;
+  json::object* arg_json;
+
+  arg_json = new json::object ();
+  arg_holder = new json::array ();
+
+  arg = TYPE_ARG_TYPES (t);
+
+  while (arg && arg != void_list_node && arg != error_mark_node)
+    {
+      wrote_arg = true;
+      arg_json = node_emit_json(TREE_VALUE (arg));
+      arg_holder->append(arg_json);
+      arg = TREE_CHAIN (arg);
+    }
+
+  if (arg == void_list_node && !wrote_arg)
+{
+      arg_json->set_bool("void_list_node", true);
+      arg_holder->append(arg_json);
+    }
+
+  return arg_holder;
+}
+
+/* Adds Identifier information to JSON object */
+
+void
+identifier_node_add_json (tree t, json::object* dummy)
+  {
+    const char* buff = IDENTIFIER_POINTER (t);
+    dummy->set_string("id_to_locale", identifier_to_locale(buff));
+    buff = IDENTIFIER_POINTER (t);
+    dummy->set_string("id_point", buff);
+  }
+
+void
+decl_node_add_json (tree t, json::object* dummy)
+{
+  tree name = DECL_NAME (t);
+    
+  if (name)
+      {
+        if (HAS_DECL_ASSEMBLER_NAME_P(t)
+            && DECL_ASSEMBLER_NAME_SET_P(t))
+          identifier_node_add_json(DECL_ASSEMBLER_NAME_RAW(t), dummy);
+        else if (DECL_NAMELESS(t)
+                 && DECL_IGNORED_P(t))
+          name = NULL_TREE;
+        else 
+          identifier_node_add_json(name, dummy);
+      }
+    if (name == NULL_TREE)
+      {
+        if (TREE_CODE (t) == LABEL_DECL && LABEL_DECL_UID (t) != -1)
+          {
+            dummy->set_integer("Label_UID", LABEL_DECL_UID(t));
+          }
+        else if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+          {
+            dummy->set_integer("Debug_UID", DEBUG_TEMP_UID (t));
+          }
+        else 
+          {
+            const char* c = TREE_CODE (t) == CONST_DECL ? "Const_UID"
+                                                        : "Decl_UID";
+            dummy->set_integer(c, DECL_UID(t));
+          }
+      }
+    if (DECL_PT_UID (t) != DECL_UID (t))
+      {
+        dummy->set_integer("ptDecl", DECL_PT_UID(t));
+      }
+}
+
+/* Function call */
+
+void
+function_name_add_json (tree t, json::object* dummy)
+{
+  if (CONVERT_EXPR_P (t))
+    t = TREE_OPERAND (t, 0);
+  if (DECL_NAME (t))
+    {
+      dummy->set_string("decl_name", lang_hooks.decl_printable_name (t, 1));
+      dummy->set_integer("uid", DECL_UID(t));
+    }
+  else
+    decl_node_add_json(t, dummy);
+}
+
+/* Adds the name of a call. Enter iff t is CALL_EXPR_FN */
+
+void
+call_name_add_json (tree t, json::object* dummy)
+{
+  tree op0 = t;
+
+  if (TREE_CODE (op0) == NON_LVALUE_EXPR)
+    op0 = TREE_OPERAND (op0, 0);
+  again:
+    switch (TREE_CODE (op0))
+      {
+      case VAR_DECL:
+      case PARM_DECL:
+      case FUNCTION_DECL:
+        function_name_add_json (op0, dummy);
+        break;
+  
+      case ADDR_EXPR:
+      case INDIRECT_REF:
+      CASE_CONVERT:
+        op0 = TREE_OPERAND (op0, 0);
+        goto again;
+  
+      case COND_EXPR:
+        {
+          json::object *_x;
+          _x = new json::object ();
+          _x->set("if", node_emit_json(TREE_OPERAND(op0, 0)));
+          _x->set("then", node_emit_json(TREE_OPERAND(op0, 1)));
+          _x->set("else", node_emit_json(TREE_OPERAND(op0, 2)));
+          dummy->set("call_name", _x);
+        }
+        break;
+  
+      case ARRAY_REF:
+        if (VAR_P (TREE_OPERAND (op0, 0)))
+       function_name_add_json (TREE_OPERAND (op0, 0), dummy);
+        else
+       dummy->set("call_name", node_emit_json (op0));
+        break;
+  
+      case MEM_REF:
+        if (integer_zerop (TREE_OPERAND (op0, 1)))
+       {
+         op0 = TREE_OPERAND (op0, 0);
+         goto again;
+       }
+        /* Fallthrough  */
+      case COMPONENT_REF:
+      case SSA_NAME:
+      case OBJ_TYPE_REF:
+        dummy->set("call_name", node_emit_json (op0));
+        break;
+      default:
+        break;
+    }
+}
+
+/* OMP helper. */
+void
+omp_iterator_add_json(tree iter, json::object* dummy)
+{
+  json::array* iter_holder;
+  iter_holder = new json::array ();
+
+  for (tree it = iter; it; it = TREE_CHAIN (it))
+    {
+      for (int i = 0; i < 4; i++)
+        {
+          if (TREE_VEC_ELT (it, 0) != NULL_TREE)
+            iter_holder->append (node_emit_json (TREE_VEC_ELT (it, 0)));
+        }
+    }
+  dummy->set("omp_iter", iter_holder);
+}
+/* Omp helper. */
+void
+omp_clause_add_json(tree clause, json::object* dummy)
+{
+  char buffer[100] = {'\0'};
+  const char* name;
+  const char* modifier = NULL;
+  switch (OMP_CLAUSE_CODE (clause))
+    {
+    case OMP_CLAUSE_PRIVATE:
+      name = "private";
+      goto print_remap;
+    case OMP_CLAUSE_SHARED:
+      name = "shared";
+      goto print_remap;
+    case OMP_CLAUSE_FIRSTPRIVATE:
+      name = "firstprivate";
+      goto print_remap;
+    case OMP_CLAUSE_LASTPRIVATE:
+      name = "lastprivate";
+      if (OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (clause))
+       modifier = "conditional:";
+      goto print_remap;
+    case OMP_CLAUSE_COPYIN:
+      name = "copyin";
+      goto print_remap;
+    case OMP_CLAUSE_COPYPRIVATE:
+      name = "copyprivate";
+      goto print_remap;
+    case OMP_CLAUSE_UNIFORM:
+      name = "uniform";
+      goto print_remap;
+    case OMP_CLAUSE_USE_DEVICE_PTR:
+      name = "use_device_ptr";
+      if (OMP_CLAUSE_USE_DEVICE_PTR_IF_PRESENT (clause))
+       modifier = "if_present:";
+      goto print_remap;
+    case OMP_CLAUSE_USE_DEVICE_ADDR:
+      name = "use_device_addr";
+      goto print_remap;
+    case OMP_CLAUSE_HAS_DEVICE_ADDR:
+      name = "has_device_addr";
+      goto print_remap;
+    case OMP_CLAUSE_IS_DEVICE_PTR:
+      name = "is_device_ptr";
+      goto print_remap;
+    case OMP_CLAUSE_INCLUSIVE:
+      name = "inclusive";
+      goto print_remap;
+    case OMP_CLAUSE_EXCLUSIVE:
+      name = "exclusive";
+      goto print_remap;
+    case OMP_CLAUSE__LOOPTEMP_:
+      name = "_looptemp_";
+      goto print_remap;
+    case OMP_CLAUSE__REDUCTEMP_:
+      name = "_reductemp_";
+      goto print_remap;
+    case OMP_CLAUSE__CONDTEMP_:
+      name = "_condtemp_";
+      goto print_remap;
+    case OMP_CLAUSE__SCANTEMP_:
+      name = "_scantemp_";
+      goto print_remap;
+    case OMP_CLAUSE_ENTER:
+      if (OMP_CLAUSE_ENTER_TO (clause))
+       name = "to";
+      else
+       name = "enter";
+      goto print_remap;
+    case OMP_CLAUSE_LINK:
+      name = "link";
+      goto print_remap;
+    case OMP_CLAUSE_NONTEMPORAL:
+      name = "nontemporal";
+      goto print_remap;
+  print_remap: //FIX LATER
+      strcpy(buffer, name);
+      if (modifier)
+        strcat(buffer, modifier);
+      dummy->set (buffer, node_emit_json (OMP_CLAUSE_DECL (clause)));
+      break;
+
+    case OMP_CLAUSE_TASK_REDUCTION:
+    case OMP_CLAUSE_IN_REDUCTION:
+    case OMP_CLAUSE_REDUCTION:
+      break;
+
+    case OMP_CLAUSE_IF:
+      strcpy(buffer, "omp_clause_if");
+      switch (OMP_CLAUSE_IF_MODIFIER (clause))
+        {
+        case ERROR_MARK: break;
+        case VOID_CST: strcat(buffer, "_cancel"); break;
+        case OMP_PARALLEL: strcat(buffer, "_parallel"); break;
+        case OMP_SIMD: strcat(buffer, "_simd"); break; 
+        case OMP_TASK: strcat(buffer, "_task"); break;
+        case OMP_TASKLOOP: strcat(buffer, "_taskloop"); break;
+        case OMP_TARGET_DATA: strcat(buffer, "_target_data"); break;
+        case OMP_TARGET: strcat(buffer, "_target"); break;
+        case OMP_TARGET_UPDATE: strcat(buffer, "_target_update"); break;
+        case OMP_TARGET_ENTER_DATA: strcat(buffer, "_target_enter_data");
+          break;
+        case OMP_TARGET_EXIT_DATA: strcat(buffer, "_target_exit_data"); break;
+        default: gcc_unreachable ();
+        }
+      dummy->set(buffer, node_emit_json (OMP_CLAUSE_IF_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_SELF:
+      dummy->set("omp_self", node_emit_json (OMP_CLAUSE_SELF_EXPR(clause)));
+      break;
+
+    case OMP_CLAUSE_NUM_THREADS:
+      dummy->set("omp_num_threads",
+                 node_emit_json (OMP_CLAUSE_NUM_THREADS_EXPR(clause)));
+      break;
+
+    case OMP_CLAUSE_NOWAIT:
+      break;
+
+    case OMP_CLAUSE_ORDERED:
+      dummy->set("omp_ordered",
+                 node_emit_json (OMP_CLAUSE_ORDERED_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_DEFAULT:
+      strcpy(buffer, "omp_default");
+      switch (OMP_CLAUSE_DEFAULT_KIND (clause))
+        {
+       case OMP_CLAUSE_DEFAULT_UNSPECIFIED:
+         break;
+       case OMP_CLAUSE_DEFAULT_SHARED:
+         strcat (buffer, "_shared");
+         break;
+       case OMP_CLAUSE_DEFAULT_NONE:
+         strcat (buffer, "_none");
+         break;
+       case OMP_CLAUSE_DEFAULT_PRIVATE:
+         strcat (buffer, "_private");
+         break;
+       case OMP_CLAUSE_DEFAULT_FIRSTPRIVATE:
+         strcat (buffer, "_firstprivate");
+         break;
+       case OMP_CLAUSE_DEFAULT_PRESENT:
+         strcat (buffer, "_present");
+         break;
+       default:
+         gcc_unreachable ();
+        }
+      dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE_SCHEDULE:
+      strcpy (buffer, "schedule");
+      if (OMP_CLAUSE_SCHEDULE_KIND (clause)
+         & (OMP_CLAUSE_SCHEDULE_MONOTONIC
+            | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
+       {
+         if (OMP_CLAUSE_SCHEDULE_KIND (clause)
+             & OMP_CLAUSE_SCHEDULE_MONOTONIC)
+           strcat (buffer, "_monotonic");
+         else
+           strcat (buffer, "_nonmonotonic");
+       }
+      if (OMP_CLAUSE_SCHEDULE_SIMD (clause))
+       strcat (buffer, "_simd");
+
+      switch (OMP_CLAUSE_SCHEDULE_KIND (clause) & OMP_CLAUSE_SCHEDULE_MASK)
+       {
+       case OMP_CLAUSE_SCHEDULE_STATIC:
+         strcat (buffer, "_static");
+         break;
+       case OMP_CLAUSE_SCHEDULE_DYNAMIC:
+         strcat (buffer, "_dynamic");
+         break;
+       case OMP_CLAUSE_SCHEDULE_GUIDED:
+         strcat (buffer, "_guided");
+         break;
+       case OMP_CLAUSE_SCHEDULE_RUNTIME:
+         strcat (buffer, "_runtime");
+         break;
+       case OMP_CLAUSE_SCHEDULE_AUTO:
+         strcat (buffer, "_auto");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      dummy->set(buffer,
+                 node_emit_json(OMP_CLAUSE_SCHEDULE_CHUNK_EXPR(clause)));
+      break;
+
+    case OMP_CLAUSE_UNTIED:
+      dummy->set_bool("omp_clause_untied", true);
+      break;
+
+    case OMP_CLAUSE_COLLAPSE:
+      dummy->set("omp_collapse_collapse",
+                 node_emit_json (OMP_CLAUSE_COLLAPSE_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_FINAL:
+      dummy->set("omp_final", 
+                 node_emit_json (OMP_CLAUSE_FINAL_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_MERGEABLE:
+      dummy->set_bool("omp_clause_mergeable", true);
+      break;
+
+    case OMP_CLAUSE_LINEAR:
+      strcpy (buffer, "omp_linear");
+      if (OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (clause))
+       switch (OMP_CLAUSE_LINEAR_KIND (clause))
+         {
+         case OMP_CLAUSE_LINEAR_DEFAULT:
+           break;
+         case OMP_CLAUSE_LINEAR_REF:
+           strcat (buffer, "_ref");
+           break;
+         case OMP_CLAUSE_LINEAR_VAL:
+           strcat (buffer, "_val");
+           break;
+         case OMP_CLAUSE_LINEAR_UVAL:
+           strcat (buffer, "_uval");
+           break;
+         default:
+           gcc_unreachable ();
+         }
+      dummy->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause)));
+      if (!OMP_CLAUSE_LINEAR_OLD_LINEAR_MODIFIER (clause)
+         && OMP_CLAUSE_LINEAR_KIND (clause) != OMP_CLAUSE_LINEAR_DEFAULT)
+       switch (OMP_CLAUSE_LINEAR_KIND (clause))
+         {
+           case OMP_CLAUSE_LINEAR_REF:
+             strcpy (buffer, "_ref,step");
+             break;
+           case OMP_CLAUSE_LINEAR_VAL:
+             strcpy (buffer, "_val,step");
+             break;
+           case OMP_CLAUSE_LINEAR_UVAL:
+             strcpy (buffer, "_uval,step");
+             break;
+           default:
+             gcc_unreachable ();
+         }
+      dummy->set(buffer, node_emit_json (OMP_CLAUSE_LINEAR_STEP (clause)));
+      break;
+
+    case OMP_CLAUSE_ALIGNED:
+      dummy->set("omp_aligned", node_emit_json (OMP_CLAUSE_DECL(clause)));
+      if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
+       {
+          dummy->set("omp_aligned_alignment",
+                     node_emit_json (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause)));
+       }
+      break;
+
+    case OMP_CLAUSE_ALLOCATE:
+      if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
+          dummy->set("omp_allocator",
+                     node_emit_json (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause)));
+      if (OMP_CLAUSE_ALLOCATE_ALIGN (clause))
+          dummy->set("omp_allocate_align",
+                     node_emit_json (OMP_CLAUSE_ALLOCATE_ALIGN (clause)));
+      dummy->set("omp_allocate",
+                 node_emit_json (OMP_CLAUSE_DECL (clause)));
+      break;
+
+    case OMP_CLAUSE_AFFINITY:
+      {
+       tree t = OMP_CLAUSE_DECL (clause);
+       if (TREE_CODE (t) == TREE_LIST
+           && TREE_PURPOSE (t)
+           && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+         {
+            omp_iterator_add_json(TREE_PURPOSE (t), dummy);
+           t = TREE_VALUE (t);
+         }
+        dummy->set("omp_affinity", node_emit_json(t));
+      }
+      break;
+
+    case OMP_CLAUSE_DEPEND:
+      strcpy (buffer, "omp_depend");
+      switch (OMP_CLAUSE_DEPEND_KIND (clause))
+       {
+       case OMP_CLAUSE_DEPEND_DEPOBJ:
+         strcat (buffer, "_depobj");
+         break;
+       case OMP_CLAUSE_DEPEND_IN:
+         strcat (buffer, "_in");
+         break;
+       case OMP_CLAUSE_DEPEND_OUT:
+         strcat (buffer, "_out");
+         break;
+       case OMP_CLAUSE_DEPEND_INOUT:
+         strcat (buffer, "_inout");
+         break;
+       case OMP_CLAUSE_DEPEND_MUTEXINOUTSET:
+         strcat (buffer, "_mutexinoutset");
+         break;
+       case OMP_CLAUSE_DEPEND_INOUTSET:
+         strcat (buffer, "_inoutset");
+         break;
+       case OMP_CLAUSE_DEPEND_LAST:
+         strcat (buffer, "__internal__");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      {
+       tree t = OMP_CLAUSE_DECL (clause);
+       if (TREE_CODE (t) == TREE_LIST
+           && TREE_PURPOSE (t)
+           && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC)
+         {
+           omp_iterator_add_json(TREE_PURPOSE (t), dummy);
+           t = TREE_VALUE (t);
+         }
+       if (t == null_pointer_node)
+         dummy->set_bool("omp_all_memory", true);
+       else
+          dummy->set(buffer, node_emit_json(t));
+      }
+      break;
+
+    case OMP_CLAUSE_DOACROSS:
+      strcpy (buffer, OMP_CLAUSE_DOACROSS_DEPEND (clause)
+                    ? "omp_depend" : "omp_doacross");
+      switch (OMP_CLAUSE_DOACROSS_KIND (clause))
+       {
+       case OMP_CLAUSE_DOACROSS_SOURCE:
+         if (OMP_CLAUSE_DOACROSS_DEPEND (clause))
+           strcat (buffer, "_source");
+         else
+           strcat (buffer, "_source:");
+          dummy->set_bool(buffer, true);
+         break;
+        
+       case OMP_CLAUSE_DOACROSS_SINK:
+          json::array* iter_holder;
+          iter_holder = new json::array ();
+         strcat (buffer, "_sink:");
+         if (OMP_CLAUSE_DECL (clause) == NULL_TREE)
+           {
+             strcat (buffer, "_omp_cur_iteration-1");
+              dummy->set_bool(buffer, true);
+             break;
+           }
+         for (tree t = OMP_CLAUSE_DECL (clause); t; t = TREE_CHAIN (t))
+           if (TREE_CODE (t) == TREE_LIST)
+             {
+               iter_holder->append(node_emit_json(TREE_VALUE (t)));
+               if (TREE_PURPOSE (t) != integer_zero_node)
+                 {
+                    json::object *_x;
+                    _x = new json::object ();
+                   if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (t))
+                      _x->set("-", node_emit_json(TREE_PURPOSE (t)));
+                   else
+                      _x->set("+", node_emit_json(TREE_PURPOSE (t)));
+                    iter_holder->append(_x);
+                 }
+             }
+           else
+             gcc_unreachable ();
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      break;
+    case OMP_CLAUSE_MAP:
+      strcat (buffer, "omp_map");
+      if (OMP_CLAUSE_MAP_READONLY (clause))
+       strcat (buffer, "_readonly,");
+      switch (OMP_CLAUSE_MAP_KIND (clause))
+       {
+       case GOMP_MAP_ALLOC:
+       case GOMP_MAP_POINTER:
+       case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
+         strcat (buffer, "_alloc");
+         break;
+       case GOMP_MAP_IF_PRESENT:
+         strcat (buffer, "_no_alloc");
+         break;
+       case GOMP_MAP_TO:
+       case GOMP_MAP_TO_PSET:
+         strcat (buffer, "_to");
+         break;
+       case GOMP_MAP_FROM:
+         strcat (buffer, "_from");
+         break;
+       case GOMP_MAP_TOFROM:
+         strcat (buffer, "_tofrom");
+         break;
+       case GOMP_MAP_FORCE_ALLOC:
+         strcat (buffer, "_force_alloc");
+         break;
+       case GOMP_MAP_FORCE_TO:
+         strcat (buffer, "_force_to");
+         break;
+       case GOMP_MAP_FORCE_FROM:
+         strcat (buffer, "_force_from");
+         break;
+       case GOMP_MAP_FORCE_TOFROM:
+         strcat (buffer, "_force_tofrom");
+         break;
+       case GOMP_MAP_FORCE_PRESENT:
+         strcat (buffer, "_force_present");
+         break;
+       case GOMP_MAP_DELETE:
+         strcat (buffer, "_delete");
+         break;
+       case GOMP_MAP_FORCE_DEVICEPTR:
+         strcat (buffer, "_force_deviceptr");
+         break;
+       case GOMP_MAP_ALWAYS_TO:
+         strcat (buffer, "_always,to");
+         break;
+       case GOMP_MAP_ALWAYS_FROM:
+         strcat (buffer, "_always,from");
+         break;
+       case GOMP_MAP_ALWAYS_TOFROM:
+         strcat (buffer, "_always,tofrom");
+         break;
+       case GOMP_MAP_RELEASE:
+         strcat (buffer, "_release");
+         break;
+       case GOMP_MAP_FIRSTPRIVATE_POINTER:
+         strcat (buffer, "_firstprivate");
+         break;
+       case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
+         strcat (buffer, "_firstprivate ref");
+         break;
+       case GOMP_MAP_STRUCT:
+         strcat (buffer, "_struct");
+         break;
+       case GOMP_MAP_STRUCT_UNORD:
+         strcat (buffer, "_struct_unord");
+         break;
+       case GOMP_MAP_ALWAYS_POINTER:
+         strcat (buffer, "_always_pointer");
+         break;
+       case GOMP_MAP_DEVICE_RESIDENT:
+         strcat (buffer, "_device_resident");
+         break;
+       case GOMP_MAP_LINK:
+         strcat (buffer, "_link");
+         break;
+       case GOMP_MAP_ATTACH:
+         strcat (buffer, "_attach");
+         break;
+       case GOMP_MAP_DETACH:
+         strcat (buffer, "_detach");
+         break;
+       case GOMP_MAP_FORCE_DETACH:
+         strcat (buffer, "_force_detach");
+         break;
+       case GOMP_MAP_ATTACH_DETACH:
+         strcat (buffer, "_attach_detach");
+         break;
+       case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
+         strcat (buffer, "_attach_zero_length_array_section");
+         break;
+       case GOMP_MAP_PRESENT_ALLOC:
+         strcat (buffer, "_present,alloc");
+         break;
+       case GOMP_MAP_PRESENT_TO:
+         strcat (buffer, "_present,to");
+         break;
+       case GOMP_MAP_PRESENT_FROM:
+         strcat (buffer, "_present,from");
+         break;
+       case GOMP_MAP_PRESENT_TOFROM:
+         strcat (buffer, "_present,tofrom");
+         break;
+       case GOMP_MAP_ALWAYS_PRESENT_TO:
+         strcat (buffer, "_always,present,to");
+         break;
+       case GOMP_MAP_ALWAYS_PRESENT_FROM:
+         strcat (buffer, "_always,present,from");
+         break;
+       case GOMP_MAP_ALWAYS_PRESENT_TOFROM:
+         strcat (buffer, "_always,present,tofrom");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      dummy->set (buffer, node_emit_json (OMP_CLAUSE_DECL (clause)));
+     print_clause_size:
+      if (OMP_CLAUSE_SIZE (clause))
+       {
+         switch (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
+                 ? OMP_CLAUSE_MAP_KIND (clause) : GOMP_MAP_TO)
+           {
+           case GOMP_MAP_POINTER:
+           case GOMP_MAP_FIRSTPRIVATE_POINTER:
+           case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
+           case GOMP_MAP_ALWAYS_POINTER:
+             strcpy (buffer, "pointer assign, bias");
+             break;
+           case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION:
+             strcpy (buffer,
+                     "pointer assign, zero-length array section, bias");
+             break;
+           case GOMP_MAP_TO_PSET:
+             strcpy (buffer, "pointer set, len");
+             break;
+           case GOMP_MAP_ATTACH:
+           case GOMP_MAP_DETACH:
+           case GOMP_MAP_FORCE_DETACH:
+           case GOMP_MAP_ATTACH_DETACH:
+           case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION:
+             strcpy (buffer, "bias");
+             break;
+           case GOMP_MAP_RELEASE:
+           case GOMP_MAP_DELETE:
+             if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
+                 && OMP_CLAUSE_RELEASE_DESCRIPTOR (clause))
+               {
+                 strcpy (buffer, "pointer set, len");
+                 break;
+               }
+             /* Fallthrough.  */
+           default:
+             strcpy (buffer, "len");
+             break;
+           }
+          dummy->set (buffer, node_emit_json (OMP_CLAUSE_SIZE (clause)));
+       }
+      if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
+         && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause))
+        dummy->set_bool("implicit", true);
+      break;
+
+    case OMP_CLAUSE_FROM:
+      strcat (buffer, "omp_from");
+      if (OMP_CLAUSE_MOTION_PRESENT (clause))
+       strcat (buffer, "_present");
+      dummy->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause)));
+      goto print_clause_size;
+
+    case OMP_CLAUSE_TO:
+      strcpy (buffer, "omp_to");
+      if (OMP_CLAUSE_MOTION_PRESENT (clause))
+       strcat (buffer, "_present");
+      dummy->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause)));
+      goto print_clause_size;
+
+    case OMP_CLAUSE__CACHE_:
+      strcat (buffer, "omp__cache__");
+      if (OMP_CLAUSE__CACHE__READONLY (clause))
+       strcat (buffer, "_readonly");
+      dummy->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause)));
+      goto print_clause_size;
+
+    case OMP_CLAUSE_NUM_TEAMS:
+      strcat (buffer, "omp_num_teams");
+      if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (clause))
+       {
+          dummy->set("omp_num_teams_lower",
+                     node_emit_json (
+                         OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (clause)));
+          strcat (buffer, "_upper");
+       }
+      else
+        dummy->set(buffer,
+                   node_emit_json (OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_THREAD_LIMIT:
+      dummy->set("omp_thread_limit",
+                 node_emit_json (OMP_CLAUSE_THREAD_LIMIT_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_DEVICE:
+      strcpy (buffer, "omp_device(");
+      if (OMP_CLAUSE_DEVICE_ANCESTOR (clause))
+       strcat (buffer, "_ancestor:");
+      dummy->set(buffer,
+                 node_emit_json (OMP_CLAUSE_DEVICE_ID (clause)));
+      break;
+
+    case OMP_CLAUSE_DIST_SCHEDULE:
+      strcat (buffer, "omp_dist_schedule(static)");
+      if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause))
+       {
+         dummy->set(buffer,
+                    node_emit_json (
+                        OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause)));
+       }
+      else
+        dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE_PROC_BIND:
+      strcpy (buffer, "omp_proc_bind(");
+      switch (OMP_CLAUSE_PROC_BIND_KIND (clause))
+       {
+       case OMP_CLAUSE_PROC_BIND_MASTER:
+         strcat (buffer, "_master");
+         break;
+       case OMP_CLAUSE_PROC_BIND_CLOSE:
+         strcat (buffer, "_close");
+         break;
+       case OMP_CLAUSE_PROC_BIND_SPREAD:
+         strcat (buffer, "_spread");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE_DEVICE_TYPE:
+    strcpy (buffer, "omp_device_type");
+      switch (OMP_CLAUSE_DEVICE_TYPE_KIND (clause))
+       {
+       case OMP_CLAUSE_DEVICE_TYPE_HOST:
+         strcat (buffer, "_host");
+         break;
+       case OMP_CLAUSE_DEVICE_TYPE_NOHOST:
+         strcat (buffer, "_nohost");
+         break;
+       case OMP_CLAUSE_DEVICE_TYPE_ANY:
+         strcat (buffer, "_any");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE_SAFELEN:
+      dummy->set("omp_safelen",
+                 node_emit_json (OMP_CLAUSE_SAFELEN_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_SIMDLEN:
+      dummy->set("omp_simdlen",
+                 node_emit_json (OMP_CLAUSE_SIMDLEN_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_PRIORITY:
+      dummy->set("omp_priority",
+                 node_emit_json (OMP_CLAUSE_PRIORITY_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_GRAINSIZE:
+      strcpy (buffer, "omp_grainsize");
+      if (OMP_CLAUSE_GRAINSIZE_STRICT (clause))
+        strcat (buffer, "_strict");
+      dummy->set(buffer,
+                 node_emit_json (OMP_CLAUSE_GRAINSIZE_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_NUM_TASKS:
+      strcpy (buffer, "omp_num_tasks");
+      if (OMP_CLAUSE_NUM_TASKS_STRICT (clause))
+       strcat (buffer, "_strict");
+      dummy->set(buffer,
+                 node_emit_json (OMP_CLAUSE_NUM_TASKS_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_HINT:
+      dummy->set("omp_hint",
+                 node_emit_json (OMP_CLAUSE_HINT_EXPR(clause)));
+      break;
+
+    case OMP_CLAUSE_FILTER:
+      dummy->set("omp_filter",
+                 node_emit_json (OMP_CLAUSE_FILTER_EXPR(clause)));
+      break;
+
+    case OMP_CLAUSE_DEFAULTMAP:
+      strcat (buffer, "omp_defaultmap");
+      switch (OMP_CLAUSE_DEFAULTMAP_BEHAVIOR (clause))
+       {
+       case OMP_CLAUSE_DEFAULTMAP_ALLOC:
+         strcat (buffer, "_alloc");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_TO:
+         strcat (buffer, "_to");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_FROM:
+         strcat (buffer, "_from");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_TOFROM:
+         strcat (buffer, "_tofrom");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE:
+         strcat (buffer, "_firstprivate");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_NONE:
+         strcat (buffer, "_none");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_PRESENT:
+         strcat (buffer, "_present");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_DEFAULT:
+         strcat (buffer, "_default");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      //Check later if we're happy with this
+      switch (OMP_CLAUSE_DEFAULTMAP_CATEGORY (clause))
+       {
+       case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALL:
+         strcat (buffer, ":all");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
+         strcat (buffer, ":scalar");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
+         strcat (buffer, ":aggregate");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_CATEGORY_ALLOCATABLE:
+         strcat (buffer, ":allocatable");
+         break;
+       case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
+         strcat (buffer, ":pointer");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE_ORDER:
+      strcpy (buffer, "omp_order_");
+      if (OMP_CLAUSE_ORDER_UNCONSTRAINED (clause))
+       strcat (buffer, "unconstrained:");
+      else if (OMP_CLAUSE_ORDER_REPRODUCIBLE (clause))
+       strcat (buffer, "reproducible:");
+      strcat (buffer, "concurrent)");
+      dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE_BIND:
+      strcpy (buffer, "omp_bind");
+      switch (OMP_CLAUSE_BIND_KIND (clause))
+       {
+       case OMP_CLAUSE_BIND_TEAMS:
+         strcat (buffer, "_teams");
+         break;
+       case OMP_CLAUSE_BIND_PARALLEL:
+         strcat (buffer, "_parallel");
+         break;
+       case OMP_CLAUSE_BIND_THREAD:
+         strcat (buffer, "_thread");
+         break;
+       default:
+         gcc_unreachable ();
+       }
+      dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE__SIMDUID_:
+      dummy->set("omp__simduid__", 
+                 node_emit_json(OMP_CLAUSE__SIMDUID__DECL (clause)));
+      break;
+
+    case OMP_CLAUSE__SIMT_:
+      dummy->set_bool("omp__simt__", true);
+      break;
+
+    //In our current implementation, we dump exprs etc even if not NULL.
+    case OMP_CLAUSE_GANG: 
+      dummy->set_bool ("omp_gang", true);
+      if (OMP_CLAUSE_GANG_EXPR (clause) != NULL_TREE)
+          dummy->set("num", node_emit_json (OMP_CLAUSE_GANG_EXPR (clause)));
+      if (OMP_CLAUSE_GANG_STATIC_EXPR (clause) != NULL_TREE)
+       {
+         strcpy (buffer, "static");
+         if (OMP_CLAUSE_GANG_STATIC_EXPR (clause)
+             == integer_minus_one_node)
+           strcat (buffer, "*"); 
+          dummy->set(buffer,
+                     node_emit_json (OMP_CLAUSE_GANG_STATIC_EXPR (clause)));
+       }
+      break;
+
+    case OMP_CLAUSE_ASYNC:
+      dummy->set("omp_async", 
+                 node_emit_json (OMP_CLAUSE_ASYNC_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_AUTO:
+    case OMP_CLAUSE_SEQ:
+      strcpy (buffer, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
+      dummy->set_bool(buffer, true);
+      break;
+
+    case OMP_CLAUSE_WAIT:
+      dummy->set("omp_wait",
+                 node_emit_json (OMP_CLAUSE_WAIT_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_WORKER:
+      dummy->set("omp_worker",
+                 node_emit_json (OMP_CLAUSE_WORKER_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_VECTOR:
+      dummy->set("omp_vector",
+                 node_emit_json (OMP_CLAUSE_VECTOR_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_NUM_GANGS:
+      dummy->set("omp_num_gangs",
+                 node_emit_json (OMP_CLAUSE_NUM_GANGS_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_NUM_WORKERS:
+      dummy->set("omp_num_workers",
+                 node_emit_json (OMP_CLAUSE_NUM_WORKERS_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_VECTOR_LENGTH:
+      dummy->set("omp_vector_length",
+                 node_emit_json (OMP_CLAUSE_VECTOR_LENGTH_EXPR (clause)));
+      break;
+
+    case OMP_CLAUSE_INBRANCH:
+      dummy->set_bool ("inbranch", true);
+      break;
+    case OMP_CLAUSE_NOTINBRANCH:
+      dummy->set_bool ("notinbranch", true);
+      break;
+    case OMP_CLAUSE_FOR:
+      dummy->set_bool ("for", true);
+      break;
+    case OMP_CLAUSE_PARALLEL:
+      dummy->set_bool ("parallel", true);
+      break;
+    case OMP_CLAUSE_SECTIONS:
+      dummy->set_bool ("sections", true);
+      break;
+    case OMP_CLAUSE_TASKGROUP:
+      dummy->set_bool ("taskgroup", true);
+      break;
+    case OMP_CLAUSE_NOGROUP:
+      dummy->set_bool ("nogroup", true);
+      break;
+    case OMP_CLAUSE_THREADS:
+      dummy->set_bool ("threads", true);
+      break;
+    case OMP_CLAUSE_SIMD:
+      dummy->set_bool ("simd", true);
+      break;
+    case OMP_CLAUSE_INDEPENDENT:
+      dummy->set_bool ("independent", true);
+      break;
+    case OMP_CLAUSE_TILE:
+      dummy->set ("omp_tile", node_emit_json (OMP_CLAUSE_TILE_LIST (clause)));
+      break;
+    case OMP_CLAUSE_PARTIAL:
+      dummy->set ("omp_partial",
+                  node_emit_json (OMP_CLAUSE_PARTIAL_EXPR (clause)));
+      break;
+    case OMP_CLAUSE_FULL:
+      dummy->set_bool("full", true);
+      break;
+    case OMP_CLAUSE_SIZES:
+      dummy->set("omp_sizes", node_emit_json (
+                 OMP_CLAUSE_SIZES_LIST (clause)));
+      break;
+    case OMP_CLAUSE_IF_PRESENT:
+      dummy->set_bool("if_present", true);
+      break;
+    case OMP_CLAUSE_FINALIZE:
+      dummy->set_bool("finalize", true);
+      break;
+    case OMP_CLAUSE_NOHOST:
+      dummy->set_bool("nohost", true);
+      break;
+    case OMP_CLAUSE_DETACH:
+      dummy->set("omp_detach", node_emit_json (OMP_CLAUSE_DECL (clause)));
+      break;
+    default:
+      gcc_unreachable();
+    }
+}
+
+void
+omp_atomic_memory_order_add_json (json::object* dummy, 
+                                  enum omp_memory_order mo)
+{
+  switch (mo & OMP_MEMORY_ORDER_MASK)
+    {
+    case OMP_MEMORY_ORDER_RELAXED:
+      dummy->set_string ("omp_memory_order", "relaxed");
+      break;
+    case OMP_MEMORY_ORDER_SEQ_CST:
+      dummy->set_string ("omp_memory_order", "seq_cst");
+      break;
+    case OMP_MEMORY_ORDER_ACQ_REL:
+      dummy->set_string ("omp_memory_order", "acq_rel");
+      break;
+    case OMP_MEMORY_ORDER_ACQUIRE:
+      dummy->set_string ("omp_memory_order", "acquire");
+      break;
+    case OMP_MEMORY_ORDER_RELEASE:
+      dummy->set_string ("omp_memory_order", "release");
+      break;
+    case OMP_MEMORY_ORDER_UNSPECIFIED:
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  switch (mo & OMP_FAIL_MEMORY_ORDER_MASK)
+    {
+    case OMP_FAIL_MEMORY_ORDER_RELAXED:
+      dummy->set_string ("omp_memory_order", "fail(relaxed)");
+      break;
+    case OMP_FAIL_MEMORY_ORDER_SEQ_CST:
+      dummy->set_string ("omp_memory_order", "fail(seq_cst)");
+      break;
+    case OMP_FAIL_MEMORY_ORDER_ACQUIRE:
+      dummy->set_string ("omp_memory_order", "fail(acquire)");
+      break;
+    case OMP_FAIL_MEMORY_ORDER_UNSPECIFIED:
+      dummy->set_string ("omp_memory_order", "fail(unspecified)");
+      break;
+    default:
+      gcc_unreachable ();
+    }
+}
+
+json::object*
+omp_atomic_memory_order_emit_json(omp_memory_order mo)
+{
+  json::object* _x;
+  _x = new json::object ();
+  omp_atomic_memory_order_add_json(_x, mo);
+  return _x;
+}
+
+json::object*
+omp_clause_emit_json(tree t)
+{
+  json::object* _x;
+  _x = new json::object ();
+  omp_clause_add_json(t, _x);
+  return _x;
+}
+
+json::array*
+loc_emit_json (expanded_location xloc)
+{
+  json::array *loc_holder;
+  json::object *loc_info;
+  loc_info = new json::object ();
+  loc_info->set_string("file", xloc.file);
+  loc_info->set_integer("line", xloc.line);
+  loc_info->set_integer("column", xloc.column);
+  loc_holder = new json::array ();
+  loc_holder->append(loc_info);
+  return loc_holder;
+}
+
+/* Here we emit JSON data for a GENERIC node and children. 
+ * c.f. dump_generic_node and print-tree's debug_tree().   */
+
+json::object* 
+node_emit_json(tree t)
+{
+  tree op0, op1, type;
+  enum tree_code code;
+  expanded_location xloc;
+  json::object *dummy;
+  json::array* holder;
+  char address_buffer[sizeof(&t)] = {"\0"};
+
+  dummy = new json::object ();
+  holder = new json::array ();
+
+  code = TREE_CODE (t);
+
+  address_add_json(t, dummy, address_buffer);
+
+  if (TREE_CODE_CLASS (code) == tcc_declaration
+      && code != TRANSLATION_UNIT_DECL)
+    {
+    xloc = expand_location (DECL_SOURCE_LOCATION (t));
+    dummy->set("decl_loc", loc_emit_json(xloc));
+    }
+  if (EXPR_HAS_LOCATION(t))
+    {
+      xloc = expand_location (EXPR_LOCATION (t));
+      dummy->set("expr_loc", loc_emit_json(xloc));
+    }
+  if (EXPR_HAS_RANGE (t))
+    {
+      source_range r = EXPR_LOCATION_RANGE (t);
+      if (r.m_start)
+      {
+        xloc = expand_location (r.m_start);
+        dummy->set("start_loc", loc_emit_json(xloc));
+      } else {
+        dummy->set_string("start_loc", "unknown");
+      }
+      if (r.m_finish)
+      {
+        xloc = expand_location (r.m_finish);
+        dummy->set("finish_loc", loc_emit_json(xloc));
+      } else {
+        dummy->set_string("finish_loc", "unknown");
+      }
+    }
+  dummy->set_string("tree code", get_tree_code_name(TREE_CODE (t)));
+  //Flag handling
+  if (TREE_ADDRESSABLE (t))
+    dummy->set_bool ("addressable", true);
+  if (TREE_THIS_VOLATILE (t))
+    dummy->set_bool ("volatile", true);
+  if (TREE_ASM_WRITTEN (t))
+    dummy->set_bool ("asm_written", true);
+  if (TREE_USED (t))
+    dummy->set_bool ("used", true);
+  if (TREE_NOTHROW (t))
+    dummy->set_bool ("nothrow", true);
+  if (TREE_PUBLIC (t))
+    dummy->set_bool ("public", true);
+  if (TREE_PRIVATE (t))
+    dummy->set_bool ("private", true);
+  if (TREE_PROTECTED (t))
+    dummy->set_bool ("protected", true);
+  if (TREE_STATIC (t))
+    dummy->set_bool (code == CALL_EXPR ? " must-tail-call"
+                                       : " static", true);
+  if (TREE_DEPRECATED (t))
+    dummy->set_bool ("deprecated", true);
+  if (TREE_VISITED (t))
+    dummy->set_bool ("visited", true);
+
+  if (code != TREE_VEC && code != SSA_NAME && code != INTEGER_CST)
+    {
+      if (TREE_UNAVAILABLE (t))
+       dummy->set_bool ("unavailable", true);
+      if (TREE_LANG_FLAG_0 (t))
+       dummy->set_bool ("tree_0", true);
+      if (TREE_LANG_FLAG_1 (t))
+        dummy->set_bool ("tree_1", true);
+      if (TREE_LANG_FLAG_2 (t))
+       dummy->set_bool ("tree_2", true);
+      if (TREE_LANG_FLAG_3 (t))
+       dummy->set_bool ("tree_3", true);
+      if (TREE_LANG_FLAG_4 (t))
+       dummy->set_bool ("tree_4", true);
+      if (TREE_LANG_FLAG_5 (t))
+       dummy->set_bool ("tree_5", true);
+      if (TREE_LANG_FLAG_6 (t))
+       dummy->set_bool ("tree_6", true);
+    }
+
+  if (TREE_CODE_CLASS(code) == tcc_declaration)
+    {
+      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+        {
+          if (DECL_UNSIGNED (t))
+            dummy->set_bool ("unsigned", true);
+          if (DECL_IGNORED_P (t))
+            dummy->set_bool ("ignored", true);
+          if (DECL_ABSTRACT_P (t))
+            dummy->set_bool ("abstract", true);
+          if (DECL_EXTERNAL (t))
+            dummy->set_bool ("external", true);
+         if (DECL_NONLOCAL (t))
+           dummy->set_bool ("nonlocal", true);
+       }
+      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
+        {
+         if (DECL_WEAK (t))
+           dummy->set_bool ("weak", true);
+         if (DECL_IN_SYSTEM_HEADER (t))
+           dummy->set_bool ("in_system_header", true);
+        }
+      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL)
+         && code != LABEL_DECL
+         && code != FUNCTION_DECL
+         && DECL_REGISTER (t))
+       dummy->set_bool ("regdecl", true);
+
+      if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (t))
+       dummy->set_bool ("suppress-debug", true);
+
+      if (code == FUNCTION_DECL
+         && DECL_FUNCTION_SPECIFIC_TARGET (t))
+       dummy->set_bool ("function-specific-target", true);
+      if (code == FUNCTION_DECL
+         && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t))
+       dummy->set_bool ("function-specific-opt", true);
+      if (code == FUNCTION_DECL && DECL_DECLARED_INLINE_P (t))
+       dummy->set_bool ("autoinline", true);
+      if (code == FUNCTION_DECL && DECL_UNINLINABLE (t))
+       dummy->set_bool ("uninlinable", true);
+      if (code == FUNCTION_DECL && fndecl_built_in_p (t))
+       dummy->set_bool ("built-in", true);
+      if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (t))
+       dummy->set_bool ("static-chain", true);
+      if (TREE_CODE (t) == FUNCTION_DECL && decl_is_tm_clone (t))
+       dummy->set_bool ("tm-clone", true);
+
+      if (code == FIELD_DECL && DECL_PACKED (t))
+       dummy->set_bool ("packed", true);
+      if (code == FIELD_DECL && DECL_BIT_FIELD (t))
+       dummy->set_bool ("bit-field", true);
+      if (code == FIELD_DECL && DECL_NONADDRESSABLE_P (t))
+       dummy->set_bool ("nonaddressable", true);
+
+      if (code == LABEL_DECL && EH_LANDING_PAD_NR (t))
+        dummy->set_integer("landing_pad", EH_LANDING_PAD_NR(t));
+
+      if (code == VAR_DECL && DECL_IN_TEXT_SECTION (t))
+       dummy->set_bool ("in-text-section", true);
+      if (code == VAR_DECL && DECL_IN_CONSTANT_POOL (t))
+       dummy->set_bool ("in-constant-pool", true);
+      if (code == VAR_DECL && DECL_COMMON (t))
+       dummy->set_bool ("common", true);
+      if ((code == VAR_DECL || code == PARM_DECL) && DECL_READ_P (t))
+       dummy->set_bool ("read", true);
+      if (code == VAR_DECL && DECL_THREAD_LOCAL_P (t))
+         dummy->set_bool (tls_model_names[DECL_TLS_MODEL (t)], true);
+
+      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
+       {
+         if (DECL_VIRTUAL_P (t))
+           dummy->set_bool ("virtual", true);
+         if (DECL_PRESERVE_P (t))
+           dummy->set_bool ("preserve", true);
+         if (DECL_LANG_FLAG_0 (t))
+           dummy->set_bool ("decl_0", true);
+         if (DECL_LANG_FLAG_1 (t))
+           dummy->set_bool ("decl_1", true);
+         if (DECL_LANG_FLAG_2 (t))
+           dummy->set_bool ("decl_2", true);
+         if (DECL_LANG_FLAG_3 (t))
+           dummy->set_bool ("decl_3", true);
+         if (DECL_LANG_FLAG_4 (t))
+           dummy->set_bool ("decl_4", true);
+         if (DECL_LANG_FLAG_5 (t))
+           dummy->set_bool ("decl_5", true);
+         if (DECL_LANG_FLAG_6 (t))
+           dummy->set_bool ("decl_6", true);
+         if (DECL_LANG_FLAG_7 (t))
+           dummy->set_bool ("decl_7", true);
+         if (DECL_LANG_FLAG_8 (t))
+           dummy->set_bool ("decl_8", true);
+
+         dummy->set_string("mode", GET_MODE_NAME (DECL_MODE (t)));
+       }
+
+
+      if ((code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
+         && DECL_BY_REFERENCE (t))
+       dummy->set_bool ("passed-by-reference", true);
+
+      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)
+                                && DECL_DEFER_OUTPUT (t))
+       dummy->set_bool ("defer-output", true);
+
+    } //end tcc_decl flags
+
+    if (TREE_CODE_CLASS(code) == tcc_type)
+      {
+      if (TYPE_UNSIGNED (t))
+       dummy->set_bool ("unsigned", true);
+
+      if (TYPE_NO_FORCE_BLK (t))
+       dummy->set_bool ("no-force-blk", true);
+
+      if (code == ARRAY_TYPE && TYPE_STRING_FLAG (t))
+       dummy->set_bool ("string-flag", true);
+
+      if (TYPE_NEEDS_CONSTRUCTING (t))
+       dummy->set_bool ("needs-constructing", true);
+
+      if ((code == RECORD_TYPE
+          || code == UNION_TYPE
+          || code == QUAL_UNION_TYPE
+          || code == ARRAY_TYPE)
+         && TYPE_REVERSE_STORAGE_ORDER (t))
+       dummy->set_bool ("reverse-storage-order", true);
+
+      if ((code == RECORD_TYPE
+          || code == UNION_TYPE)
+         && TYPE_CXX_ODR_P (t))
+       dummy->set_bool ("cxx-odr-p", true);
+
+      if ((code == RECORD_TYPE
+          || code == UNION_TYPE)
+         && TYPE_CXX_ODR_P (t))
+       dummy->set_bool ("cxx-odr-p", true);
+
+      if ((code == RECORD_TYPE
+          || code == UNION_TYPE)
+         && TYPE_INCLUDES_FLEXARRAY (t))
+       dummy->set_bool ("includes-flexarray", true);
+
+      if ((code == UNION_TYPE || code == RECORD_TYPE)
+         && TYPE_TRANSPARENT_AGGR (t))
+       dummy->set_bool ("transparent-aggr", true);
+      else if (code == ARRAY_TYPE
+              && TYPE_NONALIASED_COMPONENT (t))
+       dummy->set_bool ("nonaliased-component", true);
+
+      if (TYPE_PACKED (t))
+       dummy->set_bool ("packed", true);
+
+      if (TYPE_RESTRICT (t))
+       dummy->set_bool ("restrict", true);
+
+      if (TYPE_LANG_FLAG_0 (t))
+       dummy->set_bool ("type_0", true);
+      if (TYPE_LANG_FLAG_1 (t))
+       dummy->set_bool ("type_1", true);
+      if (TYPE_LANG_FLAG_2 (t))
+       dummy->set_bool ("type_2", true);
+      if (TYPE_LANG_FLAG_3 (t))
+       dummy->set_bool ("type_3", true);
+      if (TYPE_LANG_FLAG_4 (t))
+       dummy->set_bool ("type_4", true);
+      if (TYPE_LANG_FLAG_5 (t))
+       dummy->set_bool ("type_5", true);
+      if (TYPE_LANG_FLAG_6 (t))
+       dummy->set_bool ("type_6", true);
+      if (TYPE_LANG_FLAG_7 (t))
+       dummy->set_bool ("type_7", true);
+      } //end tcc_type flags
+
+  // Accessors
+  switch (code)
+  {
+    case IDENTIFIER_NODE:
+      dummy->set_string("identifier", 
+                        identifier_to_locale ((IDENTIFIER_POINTER(t))));
+      break;
+    case TREE_LIST:
+      while (t && t != error_mark_node)
+      {
+        if (TREE_PURPOSE (t))
+       {
+          holder->append(node_emit_json(TREE_PURPOSE(t)));
+       }
+       holder->append(node_emit_json(TREE_VALUE(t)));
+        t = TREE_CHAIN(t);
+      }
+      break;
+    case TREE_BINFO:
+      holder->append(node_emit_json(BINFO_TYPE(t)));
+      break;
+    case TREE_VEC:
+      {
+        size_t i;
+        if (TREE_VEC_LENGTH(t) > 0)
+         {
+            size_t len = TREE_VEC_LENGTH (t);
+           for (i = 0; i < len ; i++)
+           {
+             holder->append(node_emit_json(TREE_VEC_ELT(t, i)));
+           }
+         }
+      }
+      break;
+
+    case VOID_TYPE:
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+    case FIXED_POINT_TYPE:
+    case COMPLEX_TYPE:
+    case VECTOR_TYPE:
+    case ENUMERAL_TYPE:
+    case BOOLEAN_TYPE:
+    case BITINT_TYPE:
+    case OPAQUE_TYPE:
+      {
+       unsigned int quals = TYPE_QUALS (t);
+       enum tree_code_class tclass;
+        json::object* _x;
+
+        _x = new json::object ();
+
+       if (quals & TYPE_QUAL_ATOMIC)
+         _x->set_bool("atomic", true);
+       if (quals & TYPE_QUAL_CONST)
+         _x->set_bool("const", true);
+       if (quals & TYPE_QUAL_VOLATILE)
+         _x->set_bool("volatile", true);
+       if (quals & TYPE_QUAL_RESTRICT)
+         _x->set_bool("restrict", true);
+
+        dummy->set("quals", _x);
+
+       if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (t)))
+           dummy->set_integer("address space", TYPE_ADDR_SPACE(t));
+       
+       tclass = TREE_CODE_CLASS (TREE_CODE(t));
+
+       if (tclass == tcc_declaration)
+         {
+         if (DECL_NAME (t))
+            decl_node_add_json(t, dummy);
+         else
+           dummy->set_string("decl", "<unnamed type decl>");
+         }
+       else if (tclass == tcc_type)
+         {
+           if (TYPE_NAME (t))
+           {  
+             if (TREE_CODE(TYPE_NAME (t)) == IDENTIFIER_NODE)
+                dummy->set("identifier", node_emit_json(TYPE_NAME(t)));
+             else if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
+                      && DECL_NAME (TYPE_NAME (t)))
+                decl_node_add_json( TYPE_NAME (t), dummy);
+             else 
+                dummy->set_string("type_name", "unnamed");
+           }
+            else if (TREE_CODE (t) == VECTOR_TYPE)
+             {
+              for (long unsigned int i = 0; i < NUM_POLY_INT_COEFFS; i++)
+                {
+                  auto _poly_int = TYPE_VECTOR_SUBPARTS(t);
+                  dummy->set_integer("foo", _poly_int.coeffs[i]);
+                }
+              dummy->set("vector_subparts", holder);
+             }
+            else if (TREE_CODE (t) == INTEGER_TYPE)
+             {
+               if (TYPE_PRECISION (t) == CHAR_TYPE_SIZE)
+                 dummy->set_string("type precision", (TYPE_UNSIGNED(t)
+                                                  ? "unsigned char"
+                                                  : "signed char"));
+               else if (TYPE_PRECISION (t) == SHORT_TYPE_SIZE)
+                 dummy->set_string("type precision", (TYPE_UNSIGNED(t)
+                                                  ? "unsigned short"
+                                                  : "signed short"));
+               else if (TYPE_PRECISION (t) == INT_TYPE_SIZE)
+                 dummy->set_string("type precision", (TYPE_UNSIGNED(t)
+                                                  ? "unsigned int"
+                                                  : "signed int"));
+               else if (TYPE_PRECISION (t) == LONG_TYPE_SIZE)
+                 dummy->set_string("type precision", (TYPE_UNSIGNED(t)
+                                                  ? "unsigned long"
+                                                  : "signed long"));
+               else if (TYPE_PRECISION (t) == LONG_LONG_TYPE_SIZE)
+                 dummy->set_string("type precision", (TYPE_UNSIGNED(t)
+                                                  ? "unsigned long long"
+                                                  : "signed long long"));
+               else if (TYPE_PRECISION (t) == CHAR_TYPE_SIZE
+ && pow2p_hwi (TYPE_PRECISION (t)))
+                   dummy->set_integer(TYPE_UNSIGNED(t) ? "uint": "int",
+                                      TYPE_PRECISION(t));
+               else
+                   dummy->set_integer(TYPE_UNSIGNED(t)
+                                     ? "unnamed-unsigned"
+                                     : "unnamed-signed", TYPE_PRECISION(t));
+             }
+           else if (TREE_CODE (t) == COMPLEX_TYPE)
+             {
+               holder->append(node_emit_json(TREE_TYPE(t)));
+                dummy->set("complex", holder);
+             }
+           else if (TREE_CODE (t) == REAL_TYPE)
+             {
+               dummy->set_integer("float", TYPE_PRECISION(t));
+             }
+           else if (TREE_CODE (t) == FIXED_POINT_TYPE)
+             {
+               dummy->set_integer("fixed point", TYPE_PRECISION(t));
+             }
+           else if (TREE_CODE (t) == BOOLEAN_TYPE)
+             {
+               dummy->set_integer(TYPE_UNSIGNED(t) 
+                                  ? "unsigned boolean"
+                                  : "signed boolean", TYPE_PRECISION(t));
+             }
+           else if (TREE_CODE (t) == BITINT_TYPE)
+             {
+               dummy->set_integer(TYPE_UNSIGNED (t)
+                                  ? "unsigned_BitInt"
+                                  : "_BitInt", TYPE_PRECISION(t));
+             }
+           else if (TREE_CODE (t) == VOID_TYPE)
+             dummy->set_bool("float", true);
+           else
+             dummy->set_bool("unnamed type", true);
+          }
+      }
+      break;
+
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+      {
+        if (TREE_TYPE (t) == NULL)
+         dummy->set_bool("null type", true);
+        else if (TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
+          {
+            tree function_node = TREE_TYPE(t);
+           tree arg_node = TYPE_ARG_TYPES(function_node);
+           json::array* args_holder;
+           json::object* it_args;
+           json::object* _id;
+
+           args_holder = new json::array ();
+           _id = new json::object ();
+           
+            dummy->set("fnode", node_emit_json(function_node));
+   
+           if (TYPE_IDENTIFIER (t))
+             _id->set("type identifier", node_emit_json(TYPE_NAME(t)));
+            else 
+              {
+                char* buff;
+                buff = new char ();
+                print_hex(TYPE_UID(t), buff);
+               _id->set_string("uid", buff);
+              }
+            dummy->set("function decl",
+                       function_decl_emit_json(function_node));
+            if (arg_node && arg_node != void_list_node
+                && arg_node != error_mark_node)
+             it_args = new json::object();
+            while (arg_node && arg_node != void_list_node
+                   && arg_node != error_mark_node)
+             {
+               it_args = node_emit_json(arg_node);
+               args_holder->append(it_args);
+               arg_node = TREE_CHAIN (arg_node);
+             }
+           dummy->set("type_uid", _id);
+           dummy->set("args", args_holder);
+          }
+        else
+          {
+         unsigned int quals = TYPE_QUALS (t);
+         dummy->set("tree_type", node_emit_json(TREE_TYPE(t)));
+         json::object *_x; 
+
+          _x = new json::object ();
+  
+         if (quals & TYPE_QUAL_ATOMIC)
+           _x->set_bool("atomic", true);
+         if (quals & TYPE_QUAL_CONST)
+           _x->set_bool("const", true);
+         if (quals & TYPE_QUAL_VOLATILE)
+           _x->set_bool("volatile", true);
+         if (quals & TYPE_QUAL_RESTRICT)
+           _x->set_bool("restrict", true);
+        
+          dummy->set("quals", _x);
+         if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (t)))
+           dummy->set_integer("address space", TYPE_ADDR_SPACE (t));
+         if (TYPE_REF_CAN_ALIAS_ALL (t))
+           dummy->set_bool("ref can alias all", true);
+          }
+      }
+      break;
+
+    case OFFSET_TYPE:
+      break;
+
+    case MEM_REF:
+    case TARGET_MEM_REF:
+      {
+        if (TREE_CODE (t) == MEM_REF
+            && integer_zerop (TREE_OPERAND (t, 1))
+            && TREE_CODE (TREE_OPERAND (t, 0)) != INTEGER_CST
+            && TREE_TYPE (TREE_OPERAND (t, 0)) != NULL_TREE
+            && (TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 0)))
+                == TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 1))))
+            && (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 0)))
+                == TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 1))))
+            && (TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (t, 0)))
+                == TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (t, 1))))
+            && (TYPE_MAIN_VARIANT (TREE_TYPE (t))
+                == TYPE_MAIN_VARIANT (
+                       TREE_TYPE (TREE_TYPE (TREE_OPERAND (t, 1))))))
+          {
+            if (TREE_CODE (TREE_OPERAND (t, 0)) != ADDR_EXPR)
+              {
+                dummy->set("base", node_emit_json(TREE_OPERAND (t, 0)));
+              }
+            else
+              dummy->set("base", node_emit_json(
+                                     TREE_OPERAND (TREE_OPERAND (t, 0), 0)));
+          }
+        else
+          { //Check later
+            tree type = TREE_TYPE(t);
+            tree op1 = TREE_OPERAND(t, 1);
+            tree op1type = TYPE_MAIN_VARIANT (TREE_TYPE (op1));
+
+            tree op0size = TYPE_SIZE(type);
+            tree op1size = TYPE_SIZE (TREE_TYPE(op1type));
+
+            if (!op0size || !op1size 
+                || ! operand_equal_p(op0size, op1size, 0))
+            {
+              dummy->set("tree_type_size", node_emit_json(type));
+            }
+            dummy->set("op1_type_size", node_emit_json(op1type));
+
+            if (!integer_zerop (op1))
+              dummy->set("offset", node_emit_json(op1));
+            if (TREE_CODE(t) == TARGET_MEM_REF)
+              {
+                tree temp = TMR_INDEX2 (t);
+                if (temp)
+                  dummy->set("tmr_index2", node_emit_json(temp));
+                temp = TMR_INDEX (t);
+                if (temp)
+                  {
+                    dummy->set("tmr_index", node_emit_json(temp));
+                    temp = TMR_STEP(t);
+                    if (temp)
+                      dummy->set("tmr_step", node_emit_json(temp));
+                  }
+              }
+          }
+        if (MR_DEPENDENCE_CLIQUE (t) != 0)
+          {
+            dummy->set_integer("clique", MR_DEPENDENCE_CLIQUE(t));
+            dummy->set_integer("base", MR_DEPENDENCE_BASE(t));
+          }
+      }
+    break;
+
+    /* FIXME : As in tree-pretty-print.cc, the following four codes are
+     *         incomplete. See print_struct_decl therein the above. */
+    case ARRAY_TYPE:
+      {
+        unsigned int quals = TYPE_QUALS (t);
+       if (quals & TYPE_QUAL_ATOMIC)
+         dummy->set_bool("atomic", true);
+       if (quals & TYPE_QUAL_CONST)
+         dummy->set_bool("const", true);
+       if (quals & TYPE_QUAL_VOLATILE)
+         dummy->set_bool("volatile", true);
+      }
+      break;
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      {
+        unsigned int quals = TYPE_QUALS (t);
+        json::object *_x;
+
+        _x = new json::object ();
+
+        if (quals & TYPE_QUAL_ATOMIC)
+          _x->set_bool("atomic", true);
+        if (quals & TYPE_QUAL_CONST)
+          _x->set_bool("const", true);
+        if (quals & TYPE_QUAL_VOLATILE)
+          _x->set_bool("volatile", true);
+        
+        dummy->set("type_quals", _x);
+
+        if (TYPE_NAME(t))
+          dummy->set("type_name", node_emit_json(TYPE_NAME(t)));
+      }
+      break;
+    case LANG_TYPE:
+      break;
+    case INTEGER_CST:
+      {
+        dummy->set_bool("integer_cst", true);
+
+        if ((POINTER_TYPE_P (TREE_TYPE (t))) 
+            || (TYPE_PRECISION (TREE_TYPE (t))
+                < TYPE_PRECISION (integer_type_node))
+            || exact_log2 (TYPE_PRECISION (TREE_TYPE (t))) == -1
+            || tree_int_cst_sgn (t) < 0)
+          {
+            holder->append( node_emit_json (TREE_TYPE(t)));
+            dummy->set("_Literal", holder);
+          }
+        if (TREE_CODE (TREE_TYPE(t)) == POINTER_TYPE) 
+          {
+            // In bytes
+            dummy->set_bool("pointer", true);
+            dummy->set_integer("val", TREE_INT_CST_LOW(t));
+          }
+        else if (tree_fits_shwi_p(t))
+          dummy->set_integer("val", tree_to_shwi (t));
+        else if (tree_fits_uhwi_p(t))
+          dummy->set_integer("val", tree_to_uhwi (t));
+        else
+          {
+            wide_int val = wi::to_wide (t);
+            char buff[WIDE_INT_PRINT_BUFFER_SIZE];
+        
+            print_dec(wi::to_wide (t), buff, TYPE_SIGN (TREE_TYPE (t)));
+            dummy->set_string("val", buff);
+        }
+      if (TREE_OVERFLOW (t))
+        dummy->set_bool("overflow", true);
+      }
+      break;
+
+    case POLY_INT_CST:
+      for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; i++)
+        holder->append(node_emit_json(POLY_INT_CST_COEFF(t, i)));
+      dummy->set("poly_int_cst", holder);
+      break;
+
+    case REAL_CST:
+      {
+        REAL_VALUE_TYPE d;
+
+        d = TREE_REAL_CST (t);
+
+        if (TREE_OVERFLOW (t))
+          dummy->set_bool("overflow", true);
+
+        if (REAL_VALUE_ISINF (d))
+          dummy->set_string("value", REAL_VALUE_NEGATIVE(d) ? "-Inf" : "Inf");
+        else if (REAL_VALUE_ISNAN(d))
+          dummy->set_string("value", "NaN");
+        else
+          {
+            char string[100];
+            real_to_decimal(string, &d, sizeof (string), 0, 1);
+            dummy->set_string("real_value", string);
+          }
+      }
+      break;
+
+    case FIXED_CST:
+      {
+        char string[100];
+        fixed_to_decimal(string, TREE_FIXED_CST_PTR(t), sizeof (string));
+        dummy->set_string("fixed_cst", string);
+      }
+      break;
+
+    case STRING_CST:
+        dummy->set_string("string_cst", TREE_STRING_POINTER(t));
+        break;
+
+    case VECTOR_CST:
+      {
+        unsigned int i;
+        unsigned HOST_WIDE_INT nunits;
+
+        if (!VECTOR_CST_NELTS (t).is_constant (&nunits))
+          nunits = vector_cst_encoded_nelts (t);
+        for (i = 0; i < nunits; i++)
+          {
+            holder->append(node_emit_json(VECTOR_CST_ELT (t, i)));
+          }
+        dummy->set("vector_cst", holder);
+      }
+      break;
+
+    case FUNCTION_TYPE:
+    case METHOD_TYPE:
+      dummy->set("type_data", node_emit_json(TREE_TYPE (t)));
+
+      if (TREE_CODE (t) == METHOD_TYPE)
+        {
+          dummy->set_bool("method_type", true);
+          if (TYPE_METHOD_BASETYPE (t))
+            dummy->set("basetype", node_emit_json (
+                                       TYPE_NAME (TYPE_METHOD_BASETYPE(t))));
+          else 
+            dummy->set_string("basetype", "null method basetype");
+        }
+      if (TYPE_IDENTIFIER (t))
+        dummy->set("type_identifier", node_emit_json (TYPE_NAME(t)));
+      else if ( TYPE_NAME (t) && DECL_NAME (TYPE_NAME (t)) )
+        decl_node_add_json( TYPE_NAME(t), dummy);
+      else //TDF_NOUID
+        {
+          char* buff;
+          buff = new char ();
+          print_hex(TYPE_UID(t), buff);
+         dummy->set_string("uid", buff);
+        }
+      dummy->set("function_decl", function_decl_emit_json(t));
+      break;
+
+
+    case FUNCTION_DECL:
+    case CONST_DECL:
+      decl_node_add_json(t, dummy);
+      break;
+    case LABEL_DECL:
+      if (DECL_NAME (t))
+        decl_node_add_json(t, dummy);
+      else if (LABEL_DECL_UID (t) != -1)
+        dummy->set_integer("LabelDeclUID", LABEL_DECL_UID (t));
+      else 
+        dummy->set_integer("DeclUID", DECL_UID(t));
+      break;
+
+    case TYPE_DECL:
+      if (DECL_IS_UNDECLARED_BUILTIN (t)) //parity w/ dump_generic_node
+        break;
+      if (DECL_NAME (t))
+        decl_node_add_json(t, dummy);
+      else if (TYPE_NAME (TREE_TYPE (t)) != t)
+        {
+          dummy->set(TREE_CODE (TREE_TYPE (t)) == UNION_TYPE ? "union"
+                                                             : "struct",
+                     node_emit_json( TREE_TYPE (t)));
+        }
+      else
+        dummy->set_bool("anon_type_decl", true);
+      break;
+
+    case VAR_DECL:
+    case PARM_DECL:
+    case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
+    case NAMESPACE_DECL:
+    case NAMELIST_DECL:
+      decl_node_add_json(t, dummy);
+      break;
+      
+    case RESULT_DECL:
+      dummy->set_bool("retval", true);
+      break;
+
+    case COMPONENT_REF:
+      op0 = TREE_OPERAND (t, 0);
+      op1 = TREE_OPERAND (t, 1);
+      if (op0
+          && (TREE_CODE (op0) == INDIRECT_REF
+              || (TREE_CODE (op0) == MEM_REF
+                  && TREE_CODE (TREE_OPERAND (op0, 0)) != ADDR_EXPR
+                  && integer_zerop (TREE_OPERAND (op0, 1))
+                  //We want to be explicit about Integer_CSTs
+                  && TREE_CODE (TREE_OPERAND (op0, 0)) != INTEGER_CST
+                  // To play nice with SSA
+                  && TREE_TYPE (TREE_OPERAND (op0, 0)) != NULL_TREE
+                  // I don't understand what the qualm is here
+                  && (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0)))
+                      == (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 1)))))
+                  && (TYPE_MODE (TREE_TYPE (TREE_OPERAND (op0, 0)))
+                      == (TYPE_MODE (TREE_TYPE (TREE_OPERAND (op0, 1)))))
+                  && (TYPE_REF_CAN_ALIAS_ALL (
+                          TREE_TYPE (TREE_OPERAND (op0, 0)))
+                      == (TYPE_REF_CAN_ALIAS_ALL (
+                              TREE_TYPE (TREE_OPERAND (op0, 1)))))
+                  // Understand this later too
+                  && (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
+                      == TYPE_MAIN_VARIANT (
+                             TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 1)))))
+                  && MR_DEPENDENCE_CLIQUE (op0) == 0)))
+        {
+          //
+          op0 = TREE_OPERAND (op0, 0);
+        }
+      dummy->set("expr", node_emit_json(op0));
+      dummy->set("field", node_emit_json(op1));
+      if (DECL_P (op1))
+        if (tree off = component_ref_field_offset(t))
+          if (TREE_CODE (off) != INTEGER_CST)
+            {
+              dummy->set("offset", node_emit_json(off));
+            }
+    break;
+
+    case BIT_FIELD_REF:
+      dummy->set_string("tree_code", "bit_field_ref");
+      dummy->set("expr",
+                 node_emit_json( TREE_OPERAND (t, 0)));
+      dummy->set("bits_ref",
+                 node_emit_json( TREE_OPERAND (t, 1)));
+      dummy->set("bits_first_pos",
+                 node_emit_json( TREE_OPERAND (t, 2)));
+      break;
+
+    case BIT_INSERT_EXPR:
+      dummy->set_string("tree_code", "bit_insert_expr");
+      dummy->set("container",
+                 node_emit_json( TREE_OPERAND (t, 0)));
+      dummy->set("replacement",
+                 node_emit_json( TREE_OPERAND (t, 1)));
+      dummy->set("constant_bit_pos",
+                 node_emit_json( TREE_OPERAND (t, 2)));
+      break;
+
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+      op0 = TREE_OPERAND (t, 0);
+      dummy->set("array",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("index",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      if (TREE_OPERAND(t, 2))
+        dummy->set("type_min_val", 
+                   node_emit_json (TREE_OPERAND (t, 2)));
+      if (TREE_OPERAND(t, 3))
+        dummy->set("element_size", 
+                   node_emit_json (TREE_OPERAND (t, 3)));
+      break;
+  
+    case OMP_ARRAY_SECTION:
+      dummy->set("op0",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("op1",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      dummy->set("op2",
+                 node_emit_json (TREE_OPERAND (t, 2)));
+      break;
+
+    case CONSTRUCTOR:
+      {
+        unsigned HOST_WIDE_INT ix;
+        tree field, val;
+        bool is_struct_init = false;
+        bool is_array_init = false;
+        widest_int curidx;
+
+        if (TREE_CLOBBER_P (t))
+          switch (CLOBBER_KIND(t))
+            {
+          case CLOBBER_STORAGE_BEGIN:
+              dummy->set_string("CLOBBER", "storage_begin");
+              break;
+            case CLOBBER_STORAGE_END:
+              dummy->set_bool("CLOBBER", "storage_end");
+              break;
+            case CLOBBER_OBJECT_BEGIN:
+              dummy->set_bool("CLOBBER", "object_begin");
+              break;
+            case CLOBBER_OBJECT_END:
+              dummy->set_bool("CLOBBER", "object_end");
+              break;
+            default:
+              break;
+          }
+        else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
+                 || TREE_CODE (TREE_TYPE (t)) == UNION_TYPE)
+          is_struct_init = true;
+        else if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
+                 && TYPE_DOMAIN (TREE_TYPE (t))
+                 && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (t))))
+                    == INTEGER_CST)
+          {
+            tree minv = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (t)));
+            is_array_init = true;
+            curidx = wi::to_widest (minv);
+          }
+        FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), ix, field, val)
+          {
+            json::object* cst_elt;
+            json::object* _val_json;
+            cst_elt = new json::object ();
+            cst_elt->set_integer("", ix); //fix
+            if (field)
+              {
+                if (is_struct_init)
+                  cst_elt->set("field", node_emit_json(field));
+                else if (is_array_init 
+                         && (TREE_CODE (field) != INTEGER_CST
+                             || curidx != wi::to_widest (field)))
+                  {
+                    json::array* _array_init_json;
+                    if (TREE_CODE (field) == RANGE_EXPR)
+                      {
+                        _array_init_json = new json::array ();
+                        _array_init_json->append(node_emit_json(
+                                                     TREE_OPERAND(field, 0)));
+                        _array_init_json->append(node_emit_json(
+                                                     TREE_OPERAND(field, 1)));
+                        cst_elt->set("field", _array_init_json);
+                      }
+                    else 
+                      cst_elt->set ("field", node_emit_json (field));
+                  }
+              }
+            if (is_array_init)
+              curidx += 1;
+            if (val && TREE_CODE (val) == ADDR_EXPR)
+              if (TREE_CODE (TREE_OPERAND (val, 0)) == FUNCTION_DECL)
+                val = TREE_OPERAND (val, 0);
+            if (val && TREE_CODE (val) == FUNCTION_DECL)
+              {
+                _val_json = new json::object ();
+                decl_node_add_json (val, _val_json);
+                cst_elt->set("val", _val_json);
+              }
+            else
+              cst_elt->set("val", node_emit_json(val));
+
+            if (TREE_CODE (field) == INTEGER_CST)
+              curidx = wi::to_widest (field);
+            holder->append(cst_elt);
+          }
+        dummy->set("ctor_elts", holder);
+      }
+    break;
+
+   case COMPOUND_EXPR:
+     {
+        tree *tp;
+        holder->append( node_emit_json( TREE_OPERAND (t, 0)));
+
+        for (tp = &TREE_OPERAND (t, 1);
+             TREE_CODE (*tp) == COMPOUND_EXPR;
+             tp = &TREE_OPERAND (*tp, 1))
+          {
+          holder->append( node_emit_json ( TREE_OPERAND (*tp, 0)));
+          }
+
+        dummy->set("compound_expr", holder);
+      }
+      break;
+
+    case STATEMENT_LIST:
+      {
+        tree_stmt_iterator si;
+
+        for (si =  tsi_start (t); !tsi_end_p (si); tsi_next (&si))
+          {
+            holder->append( node_emit_json (tsi_stmt (si)));
+          }
+        dummy->set("statement_list", holder);
+      }
+      break;
+
+    case MODIFY_EXPR:
+    case INIT_EXPR:
+      dummy->set("op0",
+                 node_emit_json( TREE_OPERAND (t, 0)));
+      dummy->set("op1",
+                 node_emit_json( TREE_OPERAND (t, 1)));
+      break;
+
+    case TARGET_EXPR:
+      dummy->set("slot", node_emit_json (TARGET_EXPR_SLOT(t)));
+      dummy->set("initial", node_emit_json (TARGET_EXPR_INITIAL(t)));
+      break;
+
+    case DECL_EXPR:
+      decl_node_add_json(DECL_EXPR_DECL(t), dummy);
+      break;
+
+    case COND_EXPR:
+      dummy->set("if",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      if (COND_EXPR_THEN(t))
+      {
+        dummy->set("then",
+                   node_emit_json (TREE_OPERAND (t, 1)));
+      }
+      if (COND_EXPR_ELSE(t))
+      {
+        dummy->set("else",
+                 node_emit_json (TREE_OPERAND (t, 2)));
+      }
+      break;
+
+    case BIND_EXPR:
+      if (BIND_EXPR_VARS (t))
+        {
+          for (op0 = BIND_EXPR_VARS (t); op0; op0 = DECL_CHAIN (op0))
+            {
+              holder->append(node_emit_json (op0));
+            }
+          dummy->set("bind_expr_vars", holder);
+        }
+      dummy->set("bind_expr_body", 
+                 node_emit_json(BIND_EXPR_BODY(t)));
+      break;
+
+    case CALL_EXPR:
+      {
+        if (CALL_EXPR_FN (t) != NULL_TREE)
+          call_name_add_json (CALL_EXPR_FN(t), dummy);
+        else
+          dummy->set_string("internal_fn",
+                            internal_fn_name (CALL_EXPR_IFN (t)));
+        dummy->set_bool("return_slot_optimization",
+                        CALL_EXPR_RETURN_SLOT_OPT(t));
+        dummy->set_bool("tail_call", CALL_EXPR_TAILCALL(t));
+
+        tree arg;
+        call_expr_arg_iterator iter;
+        bool call;
+        FOR_EACH_CALL_EXPR_ARG(arg, iter, t)
+          {
+            call = true;
+            holder->append(node_emit_json(arg));
+          }
+        if (call)
+          dummy->set("call_expr_arg", holder);
+
+        if (CALL_EXPR_VA_ARG_PACK (t))
+          dummy->set_bool("__builtin_va_arg_pack", true);
+        
+        op1 = CALL_EXPR_STATIC_CHAIN (t);
+        if (op1)
+          dummy->set("static_chain", node_emit_json(op1));
+      }
+      break;
+    case WITH_CLEANUP_EXPR:
+      break;
+    case CLEANUP_POINT_EXPR:
+      dummy->set("cleanup_point", node_emit_json (TREE_OPERAND(t, 0)));
+      break;
+    case PLACEHOLDER_EXPR:
+      dummy->set("placeholder_expr", node_emit_json (TREE_OPERAND(t, 0)));
+      break;
+
+    /* Binary operations */
+    case WIDEN_SUM_EXPR:
+    case WIDEN_MULT_EXPR:
+    case MULT_EXPR:
+    case MULT_HIGHPART_EXPR:
+    case PLUS_EXPR:
+    case POINTER_PLUS_EXPR:
+    case POINTER_DIFF_EXPR:
+    case MINUS_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case TRUNC_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case FLOOR_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+    case RDIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+    case LROTATE_EXPR:
+    case RROTATE_EXPR:
+    case WIDEN_LSHIFT_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case BIT_AND_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+    case EQ_EXPR:
+    case NE_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
+    case ORDERED_EXPR:
+    case UNORDERED_EXPR:
+      {
+        const char* c = op_symbol_code(TREE_CODE(t), TDF_NONE);
+        op0 = TREE_OPERAND(t, 0);
+        op1 = TREE_OPERAND(t, 1);
+        
+        dummy->set_string("bin_operator", c);
+        holder->append(node_emit_json(op0));
+        holder->append(node_emit_json(op1));
+        dummy->set("operands", holder);
+      }
+      break;
+
+    case ADDR_EXPR:
+      //TDF_GIMPLE_VAL
+      dummy->set("_Literal", node_emit_json( TREE_TYPE (t)));
+      /* FALLTHROUGH */
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case INDIRECT_REF:
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+      {
+        const char * c = op_symbol_code(code, TDF_NONE);
+        dummy->set(c, node_emit_json (TREE_OPERAND (t, 0)));
+      }
+      break;
+
+    case MIN_EXPR:
+      holder->append (node_emit_json (TREE_OPERAND (t,0)));
+      holder->append (node_emit_json (TREE_OPERAND (t,1)));
+      dummy->set("min_expr", holder);
+      break;
+
+    case MAX_EXPR:
+      holder->append (node_emit_json (TREE_OPERAND (t,0)));
+      holder->append (node_emit_json (TREE_OPERAND (t,1)));
+      dummy->set("max_expr", holder);
+      break;
+
+    case ABS_EXPR:
+      holder->append (node_emit_json (TREE_OPERAND (t,0)));
+      dummy->set("abs_expr", holder);
+      break;
+
+    case ABSU_EXPR:
+      holder->append (node_emit_json (TREE_OPERAND (t,0)));
+      dummy->set("absu_expr", holder);
+      break;
+
+    case RANGE_EXPR:
+      break;
+
+    case ADDR_SPACE_CONVERT_EXPR:
+    case FIXED_CONVERT_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FLOAT_EXPR:
+    CASE_CONVERT: 
+      type = TREE_TYPE (t);
+      op0 = TREE_OPERAND (t, 0);
+      if (type != TREE_TYPE(op0))
+        {
+          dummy->set ("type", node_emit_json (type));
+        }
+      dummy->set ("operand", node_emit_json (op0));
+      break;
+
+    case VIEW_CONVERT_EXPR:
+      holder->append (node_emit_json (TREE_TYPE(t)));
+      holder->append (node_emit_json (TREE_OPERAND(t, 0)));
+      dummy->set("view_convert_expr", holder);
+      break;
+
+    case PAREN_EXPR:
+      dummy->set("paren_expr",
+                 node_emit_json (TREE_OPERAND (t,0)));
+      break;
+
+    case NON_LVALUE_EXPR:
+      dummy->set("non_lvalue_expr",
+                 node_emit_json (TREE_OPERAND (t,0)));
+      break;
+
+    case SAVE_EXPR:
+      dummy->set("save_expr",
+                 node_emit_json (TREE_OPERAND (t,0)));
+      break;
+
+    case COMPLEX_EXPR:
+      holder->append (node_emit_json (TREE_OPERAND (t,0)));
+      holder->append (node_emit_json (TREE_OPERAND (t,1)));
+      dummy->set("complex_expr", holder);
+      break;
+
+    case CONJ_EXPR:
+      dummy->set("conj_expr",
+                 node_emit_json (TREE_OPERAND (t,0)));
+      break;
+
+    case REALPART_EXPR:
+      dummy->set("realpart_expr",
+                 node_emit_json (TREE_OPERAND (t,0)));
+      break;
+
+    case IMAGPART_EXPR:
+      dummy->set("imagpart_expr",
+                 node_emit_json (TREE_OPERAND (t,0)));
+      break;
+
+    case VA_ARG_EXPR:
+      dummy->set("va_arg_expr",
+                 node_emit_json (TREE_OPERAND (t,0)));
+      break;
+
+    case TRY_FINALLY_EXPR:
+    case TRY_CATCH_EXPR:
+      {
+        tree _t;
+        dummy->set("try",
+                   node_emit_json (TREE_OPERAND (t, 0)));
+        if (TREE_CODE (t) == TRY_CATCH_EXPR)
+          {
+            _t = TREE_OPERAND(t, 1);
+            dummy->set("catch",
+                        node_emit_json (_t));
+          }
+        else
+          {
+            gcc_assert(TREE_CODE (t) == TRY_FINALLY_EXPR);
+            _t = TREE_OPERAND(t, 1);
+            if (TREE_CODE (t) == EH_ELSE_EXPR)
+              {
+                _t = TREE_OPERAND (_t, 0);
+                dummy->set("finally",
+                           node_emit_json (_t));
+                _t = TREE_OPERAND(_t, 1);
+                dummy->set("else",
+                           node_emit_json (_t));
+              }
+            else
+              {
+              dummy->set("finally",
+                         node_emit_json(_t));
+              }
+          }
+      }
+      break;
+
+    case CATCH_EXPR:
+      dummy->set("catch_types", node_emit_json(CATCH_TYPES(t)));
+      dummy->set("catch_body", node_emit_json(CATCH_BODY(t)));
+      break;
+
+    case EH_FILTER_EXPR:
+      dummy->set("eh_filter_types", node_emit_json(EH_FILTER_TYPES(t)));
+      dummy->set("eh_filter_failure", node_emit_json(EH_FILTER_FAILURE(t)));
+      break;
+
+    case LABEL_EXPR:
+      decl_node_add_json (TREE_OPERAND (t, 0), dummy);
+      break;
+
+    case LOOP_EXPR:
+      dummy->set("while (1)", node_emit_json (LOOP_EXPR_BODY (t)));
+      break;
+
+    case PREDICT_EXPR:
+      if (PREDICT_EXPR_OUTCOME (t))
+        dummy->set_string("likely by",
+                          predictor_name (PREDICT_EXPR_PREDICTOR (t)));
+      else
+        dummy->set_string("unlikely by",
+                          predictor_name (PREDICT_EXPR_PREDICTOR (t)));
+      break;
+    case ANNOTATE_EXPR:
+      {
+      switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND(t,1)))
+        { //Is this expensive? ask later
+          case annot_expr_ivdep_kind:
+            dummy->set("ivdep", node_emit_json (TREE_OPERAND (t, 0)));
+            break;
+          case annot_expr_unroll_kind:
+            dummy->set("unroll", node_emit_json (TREE_OPERAND (t, 0)));
+            break;
+          case annot_expr_no_vector_kind:
+            dummy->set("no-vector", node_emit_json (TREE_OPERAND (t, 0)));
+            break;
+          case annot_expr_vector_kind:
+            dummy->set("vector", node_emit_json (TREE_OPERAND (t, 0)));
+            break;
+          case annot_expr_parallel_kind:
+            dummy->set("parallel", node_emit_json (TREE_OPERAND (t, 0)));
+            break;
+          case annot_expr_maybe_infinite_kind:
+            dummy->set("maybe_infinite",
+                       node_emit_json (TREE_OPERAND (t, 0)));
+            break;
+          default:
+            gcc_unreachable();
+        }
+      }
+      break;
+
+    case RETURN_EXPR:
+      {
+        op0 = TREE_OPERAND(t, 0);
+        if (op0)
+          {
+            if (TREE_CODE(op0) == MODIFY_EXPR)
+              dummy->set("return_expr", node_emit_json(TREE_OPERAND(op0, 1)));
+            else
+              dummy->set("return_expr", node_emit_json(op0));
+          }
+      }
+      break;
+
+    case EXIT_EXPR:
+      dummy->set("exit_if", node_emit_json(TREE_OPERAND (t, 0)));
+      break;
+
+    case SWITCH_EXPR:
+      dummy->set("switch_cond", node_emit_json(SWITCH_COND(t)));
+      dummy->set("switch_body", node_emit_json(SWITCH_BODY(t)));
+      break;
+
+    case GOTO_EXPR:
+      op0 = GOTO_DESTINATION(t);
+      dummy->set("goto", node_emit_json(op0));
+      break;
+
+    case ASM_EXPR:
+      dummy->set("asm_string", node_emit_json (ASM_STRING (t)));
+      dummy->set("asm_outputs", node_emit_json (ASM_OUTPUTS (t)));
+      dummy->set("asm_inputs", node_emit_json (ASM_INPUTS (t)));
+      if (ASM_CLOBBERS (t))
+        dummy->set("asm_clobbers", node_emit_json (ASM_CLOBBERS (t)));
+      break;
+
+    case CASE_LABEL_EXPR:
+      if (CASE_LOW(t) && CASE_HIGH(t))
+        {
+          dummy->set ("case_low", node_emit_json (CASE_LOW(t)));
+          dummy->set ("case_high", node_emit_json (CASE_HIGH(t)));
+        }
+      else if (CASE_LOW(t))
+        dummy->set ("case", node_emit_json (CASE_LOW(t)));
+      else
+        dummy->set_string("case", "default");
+      break;
+
+    // check later - okay?
+    case OBJ_TYPE_REF:
+      dummy->set("obj_type_ref_expr",
+                 node_emit_json(OBJ_TYPE_REF_EXPR(t)));
+      dummy->set("obj_type_ref_object",
+                 node_emit_json(OBJ_TYPE_REF_OBJECT(t)));
+      dummy->set("obj_type_ref_token",
+                 node_emit_json(OBJ_TYPE_REF_TOKEN(t)));
+      break;
+
+    case SSA_NAME:
+      {
+      if (SSA_NAME_IDENTIFIER (t))
+        dummy->set("ssa_name_identifier",
+                   node_emit_json (SSA_NAME_IDENTIFIER (t)));
+      if (SSA_NAME_IS_DEFAULT_DEF (t))
+        dummy->set_bool("ssa_default_def", true);
+      if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (t))
+       dummy->set_bool("abnormal_phi", true);
+      }
+      break;
+
+    case WITH_SIZE_EXPR:
+      dummy->set("expr", node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("size", node_emit_json (TREE_OPERAND (t, 1)));
+      break;
+
+    case SCEV_KNOWN:
+    case SCEV_NOT_KNOWN:
+      break;
+
+    case POLYNOMIAL_CHREC:
+      dummy->set_integer("chrec_var", CHREC_VARIABLE(t));
+      dummy->set("chrec_left", node_emit_json (CHREC_LEFT(t)));
+      dummy->set("chrec_right", node_emit_json (CHREC_RIGHT(t)));
+      dummy->set_bool("chrec_nowrap", CHREC_NOWRAP(t));
+      break;
+
+    case REALIGN_LOAD_EXPR:
+      dummy->set("input_0", node_emit_json(TREE_OPERAND (t, 0)));
+      dummy->set("input_1", node_emit_json(TREE_OPERAND (t, 1)));
+      dummy->set("offset", node_emit_json(TREE_OPERAND (t, 2)));
+      break;
+
+    case VEC_COND_EXPR:
+      dummy->set("if",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("then",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      dummy->set("else",
+                 node_emit_json (TREE_OPERAND (t, 2)));
+      break;
+
+    case VEC_PERM_EXPR:
+      dummy->set("v0",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("v1",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      dummy->set("mask",
+                 node_emit_json (TREE_OPERAND (t, 2)));
+      break;
+
+    case DOT_PROD_EXPR: //check later
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      dummy->set("arg3",
+                 node_emit_json (TREE_OPERAND (t, 2)));
+      break;
+
+    case WIDEN_MULT_PLUS_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      dummy->set("arg3",
+                 node_emit_json (TREE_OPERAND (t, 2)));
+      break;
+
+    case WIDEN_MULT_MINUS_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      dummy->set("arg3",
+                 node_emit_json (TREE_OPERAND (t, 2)));
+      break;
+
+    case VEC_SERIES_EXPR:
+    case VEC_WIDEN_MULT_HI_EXPR:
+    case VEC_WIDEN_MULT_LO_EXPR:
+    case VEC_WIDEN_MULT_ODD_EXPR:
+    case VEC_WIDEN_LSHIFT_HI_EXPR:
+    case VEC_WIDEN_LSHIFT_LO_EXPR:
+      dummy->set("arg1", 
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      break;
+
+    case VEC_DUPLICATE_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      break;
+
+    case VEC_UNPACK_HI_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      break;
+
+    case VEC_UNPACK_LO_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      break;
+
+    case VEC_UNPACK_FLOAT_HI_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      break;
+
+    case VEC_UNPACK_FLOAT_LO_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      break;
+
+    case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      break;
+
+    case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      break;
+
+    case VEC_PACK_TRUNC_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      break;
+
+    case VEC_PACK_SAT_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      break;
+
+    case VEC_PACK_FIX_TRUNC_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      break;
+
+    case VEC_PACK_FLOAT_EXPR:
+      dummy->set("arg1",
+                 node_emit_json (TREE_OPERAND (t, 0)));
+      dummy->set("arg2",
+                 node_emit_json (TREE_OPERAND (t, 1)));
+      break;
+    /*OACC and OMP */
+    case OACC_PARALLEL:
+      goto dump_omp_clauses_body;
+
+    case OACC_KERNELS:
+      goto dump_omp_clauses_body;
+
+    case OACC_SERIAL:
+      goto dump_omp_clauses_body;
+
+    case OACC_DATA:
+      goto dump_omp_clauses_body;
+
+    case OACC_HOST_DATA:
+      dummy->set("oacc_host_data_clauses", 
+                 omp_clause_emit_json (OACC_HOST_DATA_CLAUSES(t)));
+      dummy->set("oacc_host_data_body", 
+                 omp_clause_emit_json (OACC_HOST_DATA_BODY(t)));
+      break;
+
+    case OACC_DECLARE:
+      dummy->set("oacc_declare_clauses", 
+                 omp_clause_emit_json (OACC_DECLARE_CLAUSES(t)));
+      break;
+
+    case OACC_UPDATE:
+      dummy->set("oacc_update_clauses",
+                 omp_clause_emit_json (OACC_UPDATE_CLAUSES(t)));
+      break;
+
+    case OACC_ENTER_DATA:
+      dummy->set("oacc_enter_data_clauses",
+                 omp_clause_emit_json (OACC_ENTER_DATA_CLAUSES(t)));
+      break;
+      
+    case OACC_EXIT_DATA:
+      dummy->set("oacc_exit_data_clauses",
+                 omp_clause_emit_json (OACC_EXIT_DATA_CLAUSES(t)));
+      break;
+
+    case OACC_CACHE:
+      dummy->set("oacc_cache_clauses",
+                 omp_clause_emit_json (OACC_CACHE_CLAUSES(t)));
+      break;
+
+    case OMP_PARALLEL:
+      dummy->set("omp_parallel_body",
+                 node_emit_json (OMP_PARALLEL_BODY(t)));
+      dummy->set("omp_parallel_clauses",
+                 omp_clause_emit_json (OMP_PARALLEL_CLAUSES(t)));
+      break;
+
+    case OMP_TASK:
+      {
+      if (OMP_TASK_BODY (t))
+        {
+          dummy->set_bool("omp_task", true);
+          dummy->set("omp_task_body",
+                     node_emit_json(OMP_TASK_BODY (t)));
+          dummy->set("omp_task_clauses",
+                     omp_clause_emit_json (OMP_TASK_CLAUSES(t)));
+        } else {
+          dummy->set_bool("omp_taskwait", true);
+          dummy->set("omp_taskwait_clauses",
+                     omp_clause_emit_json (OMP_TASK_CLAUSES(t)));
+        }
+        break;
+      }
+
+    dump_omp_clauses_body:
+      dummy->set("omp_clauses", omp_clause_emit_json (OMP_CLAUSES (t)));
+      goto dump_omp_body;
+
+    dump_omp_body:
+      dummy->set("omp_body", node_emit_json (OMP_BODY(t)));
+      dummy->set_bool("is_expr", false);
+      break;
+
+    case OMP_FOR:
+      goto dump_omp_loop;
+      
+    case OMP_SIMD:
+      goto dump_omp_loop;
+
+    case OMP_DISTRIBUTE:
+      goto dump_omp_loop;
+
+    case OMP_TASKLOOP:
+      goto dump_omp_loop;
+
+    case OMP_LOOP:
+      goto dump_omp_loop;
+
+    case OMP_TILE:
+      goto dump_omp_loop;
+
+    case OMP_UNROLL:
+      goto dump_omp_loop;
+
+    case OACC_LOOP:
+      goto dump_omp_loop;
+      
+    dump_omp_loop:
+      dummy->set("omp_for_body",
+                 node_emit_json(OMP_FOR_BODY (t)));
+      dummy->set("omp_for_clauses",
+                 omp_clause_emit_json (OMP_FOR_CLAUSES(t)));
+      dummy->set("omp_for_init",
+                 node_emit_json(OMP_FOR_INIT (t)));
+      dummy->set("omp_for_incr",
+                 node_emit_json(OMP_FOR_INCR (t)));
+      dummy->set("omp_for_pre_body",
+                 node_emit_json(OMP_FOR_PRE_BODY (t)));
+      dummy->set("omp_for_orig_decls",
+                 node_emit_json(OMP_FOR_ORIG_DECLS (t)));
+      break;
+
+    case OMP_TEAMS:
+      dummy->set("omp_teams_body",
+                 omp_clause_emit_json (OMP_TEAMS_BODY(t)));
+      dummy->set("omp_teams_clauses",
+                 omp_clause_emit_json (OMP_TEAMS_CLAUSES(t)));
+      break;
+
+    case OMP_TARGET_DATA:
+      dummy->set("omp_target_data_body",
+                 omp_clause_emit_json (OMP_TARGET_DATA_BODY(t)));
+      dummy->set("omp_target_data_clauses",
+                 omp_clause_emit_json (OMP_TARGET_DATA_CLAUSES(t)));
+      break;
+
+    case OMP_TARGET_ENTER_DATA:
+      dummy->set("omp_target_enter_data_clauses",
+                 omp_clause_emit_json (OMP_TARGET_ENTER_DATA_CLAUSES(t)));
+      break;
+
+    case OMP_TARGET_EXIT_DATA:
+      dummy->set("omp_target_exit_data_clauses",
+                 omp_clause_emit_json (OMP_TARGET_EXIT_DATA_CLAUSES(t)));
+      break;
+
+    case OMP_TARGET:
+      dummy->set("omp_target_body",
+                 omp_clause_emit_json (OMP_TARGET_BODY(t)));
+      dummy->set("omp_target_clauses",
+                 omp_clause_emit_json (OMP_TARGET_CLAUSES(t)));
+      break;
+
+    case OMP_TARGET_UPDATE:
+      dummy->set("omp_target_update_clauses",
+                 omp_clause_emit_json (OMP_TARGET_UPDATE_CLAUSES(t)));
+      break;
+
+    case OMP_SECTIONS:
+      dummy->set("omp_sections_body",
+                 omp_clause_emit_json (OMP_SECTIONS_BODY(t)));
+      dummy->set("omp_sections_clauses",
+                 omp_clause_emit_json (OMP_SECTIONS_CLAUSES(t)));
+      break;
+
+    case OMP_SECTION:
+      dummy->set("omp_section_body",
+                 omp_clause_emit_json (OMP_SECTION_BODY(t)));
+      break;
+
+    case OMP_STRUCTURED_BLOCK:
+      dummy->set("omp_structured_block_body",
+                 omp_clause_emit_json (OMP_STRUCTURED_BLOCK_BODY(t)));
+      break;
+
+    case OMP_SCAN:
+      dummy->set("omp_scan_body",
+                 omp_clause_emit_json (OMP_SCAN_BODY(t)));
+      dummy->set("omp_scan_clauses",
+                 omp_clause_emit_json (OMP_SCAN_CLAUSES(t)));
+      break;
+
+    case OMP_MASTER:
+      dummy->set("omp_master_body",
+                 omp_clause_emit_json (OMP_MASTER_BODY(t)));
+      break;
+
+    case OMP_MASKED:
+      dummy->set("omp_masked_body",
+                 omp_clause_emit_json (OMP_MASKED_BODY(t)));
+      dummy->set("omp_masked_clauses",
+                 omp_clause_emit_json (OMP_MASKED_CLAUSES(t)));
+      break;
+
+    case OMP_TASKGROUP:
+      dummy->set("omp_taskgroup_body",
+                 omp_clause_emit_json (OMP_TASKGROUP_BODY(t)));
+      dummy->set("omp_taskgroup_clauses",
+                 omp_clause_emit_json (OMP_TASKGROUP_CLAUSES(t)));
+      break;
+
+    case OMP_ORDERED:
+      dummy->set("omp_ordered_body",
+                 omp_clause_emit_json (OMP_ORDERED_BODY(t)));
+      dummy->set("omp_ordered_clauses",
+                 omp_clause_emit_json (OMP_ORDERED_CLAUSES(t)));
+      break;
+
+    case OMP_CRITICAL:
+      dummy->set("omp_masked_body",
+                 omp_clause_emit_json (OMP_CRITICAL_BODY(t)));
+      dummy->set("omp_masked_clauses",
+                 omp_clause_emit_json (OMP_CRITICAL_CLAUSES(t)));
+      dummy->set("omp_masked_name",
+                 node_emit_json (OMP_CRITICAL_NAME(t)));
+      break;
+
+    case OMP_ATOMIC:
+      if (OMP_ATOMIC_WEAK (t))
+        dummy->set_bool("omp_atomic_weak", true);
+      else
+        dummy->set_bool("omp_atomic_weak", false);
+      dummy->set("omp_atomic_memory_order",
+                 omp_atomic_memory_order_emit_json(
+                     OMP_ATOMIC_MEMORY_ORDER(t)));
+      dummy->set("op0",
+                 node_emit_json (TREE_OPERAND(t, 0)));
+      dummy->set("op1",
+                 node_emit_json (TREE_OPERAND(t, 1)));
+      break;
+
+    case OMP_ATOMIC_READ:
+      dummy->set("omp_atomic_memory_order",
+                 omp_atomic_memory_order_emit_json(
+                     OMP_ATOMIC_MEMORY_ORDER(t)));
+      dummy->set("op0",
+                 node_emit_json(TREE_OPERAND(t, 0)));
+      break;
+
+    case OMP_ATOMIC_CAPTURE_OLD:
+    case OMP_ATOMIC_CAPTURE_NEW:
+      if (OMP_ATOMIC_WEAK (t))
+        dummy->set_bool("omp_atomic_capture_weak", true);
+      else
+        dummy->set_bool("omp_atomic_capture", true);
+      dummy->set("omp_atomic_memory_order",
+                 omp_atomic_memory_order_emit_json 
(OMP_ATOMIC_MEMORY_ORDER(t)));
+      dummy->set("op0",
+                 node_emit_json(TREE_OPERAND(t, 0)));
+      dummy->set("op1",
+                 node_emit_json(TREE_OPERAND(t, 1)));
+      break;
+
+    case OMP_SINGLE:
+      dummy->set("omp_single_body",
+                 omp_clause_emit_json (OMP_SINGLE_BODY(t)));
+      dummy->set("omp_single_clauses",
+                 omp_clause_emit_json (OMP_SINGLE_CLAUSES(t)));
+      break;
+
+    case OMP_SCOPE:
+      dummy->set("omp_scope_body",
+                 omp_clause_emit_json (OMP_SCOPE_BODY(t)));
+      dummy->set("omp_scope_clauses",
+                 omp_clause_emit_json (OMP_SCOPE_CLAUSES(t)));
+      break;
+
+    case OMP_CLAUSE:
+      dummy->set("omp_clause",
+                 omp_clause_emit_json(t));
+      break;
+
+    case TRANSACTION_EXPR:
+      if (TRANSACTION_EXPR_OUTER (t))
+       dummy->set_bool ("transaction_expr_outer", true);
+      if (TRANSACTION_EXPR_RELAXED (t))
+       dummy->set_bool ("transaction_expr_relaxed", true);
+      dummy->set("omp_transaction_body", 
+                 node_emit_json (TRANSACTION_EXPR_BODY(t)));
+      break;
+
+    case BLOCK:
+      {
+      tree iter;
+      json::array *subblock, *chain, *vars, *fragment_chain, *nlv_holder;
+      dummy->set_integer ("block #", BLOCK_NUMBER (t));
+      if (BLOCK_SUPERCONTEXT (t))
+        dummy->set("block_supercontext",
+                   node_emit_json(BLOCK_SUPERCONTEXT (t)));
+      if (BLOCK_SUBBLOCKS(t))
+        {
+          subblock = new json::array ();
+          for (iter = BLOCK_SUBBLOCKS (t); iter; iter = BLOCK_CHAIN (t))
+            subblock->append(node_emit_json(iter));
+          dummy->set("block_subblocks", subblock);
+        }
+      if (BLOCK_CHAIN (t))
+        {
+          chain = new json::array ();
+          for (iter = BLOCK_SUBBLOCKS (t); iter; iter = BLOCK_CHAIN (t))
+              chain->append(node_emit_json(iter));
+          dummy->set("block_chain", chain);
+        
+        }
+      if (BLOCK_VARS (t))
+        {
+          vars = new json::array ();
+          for (iter = BLOCK_VARS (t); iter; iter = TREE_CHAIN (t))
+              vars->append(node_emit_json(iter));
+          dummy->set("block_vars", vars);
+        }
+      if (vec_safe_length (BLOCK_NONLOCALIZED_VARS (t)) > 0)
+        {
+          unsigned i;
+          vec<tree, va_gc> *nlv = BLOCK_NONLOCALIZED_VARS (t);
+
+          nlv_holder = new json::array ();
+
+          FOR_EACH_VEC_ELT (*nlv, i, t)
+            {
+              nlv_holder->append(node_emit_json(t));
+            }
+          dummy->set("block_nonlocalized_vars", nlv_holder);
+        }
+      if (BLOCK_ABSTRACT_ORIGIN (t))
+        dummy->set("block_abstract_origin",
+                   node_emit_json (BLOCK_ABSTRACT_ORIGIN (t)));
+      if (BLOCK_FRAGMENT_ORIGIN (t))
+        dummy->set("block_fragment_origin",
+                   node_emit_json (BLOCK_FRAGMENT_ORIGIN (t)));
+
+      if (BLOCK_FRAGMENT_CHAIN (t))
+        {
+          fragment_chain = new json::array ();
+          for( iter=BLOCK_FRAGMENT_CHAIN (t);
+               iter;
+               iter=BLOCK_FRAGMENT_CHAIN (t) )
+              fragment_chain->append(node_emit_json(iter));
+          dummy->set("block_fragment_chain", fragment_chain);
+        }
+      }
+      break;
+
+    case DEBUG_BEGIN_STMT:
+      dummy->set_bool("debug_begin", true);
+      break;
+    default:
+      dummy->set_bool("unsupported code", true);
+      dummy->set_string("fallthrough", get_tree_code_name(code));
+      break;
+  }
+  return dummy;
+}
+
+/* Dump the next node in the queue.  */
+
+static void
+dequeue_and_dump (dump_info_p di)
+{
+  dump_queue_p dq;
+  splay_tree_node stn;
+//  dump_node_info_p dni;
+  tree t;
+  json::object* dummy;
+
+  dummy = new json::object ();
+
+  /* Get the next node from the queue.  */
+  dq = di->queue;
+  stn = dq->node;
+  t = (tree) stn->key;
+//  dni = (dump_node_info_p) stn->value;
+
+  /* Remove the node from the queue, and put it on the free list.  */
+  di->queue = dq->next;
+  if (!di->queue)
+    di->queue_end = 0;
+  dq->next = di->free_list;
+  di->free_list = dq;
+
+  dummy = node_emit_json(t);
+  di->json_dump->append(dummy);
+}
+
+/* Dump T, and all its children, on STREAM.  */
+
+void
+dump_node_json (const_tree t, dump_flags_t flags, FILE *stream)
+{
+  struct dump_info di;
+  dump_queue_p dq;
+  dump_queue_p next_dq;
+  pretty_printer pp;
+  /* Initialize the dump-information structure.  */
+  di.stream = stream;
+  di.index = 0;
+  di.column = 0;
+  di.queue = 0;
+  di.queue_end = 0;
+  di.free_list = 0;
+  di.flags = flags;
+  di.node = t;
+  di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
+                            splay_tree_delete_pointers);
+  di.json_dump = new json::array ();
+  /* Queue up the first node.  */
+  queue (&di, t);
+
+  /* Until the queue is empty, keep dumping nodes.  */
+  while (di.queue)
+    dequeue_and_dump (&di);
+
+  di.json_dump->dump(stream, true);
+  fputs("\n", stream);
+  /* Now, clean up.  */
+  for (dq = di.free_list; dq; dq = next_dq)
+    {
+      next_dq = dq->next;
+      free (dq);
+    }
+  splay_tree_delete (di.nodes);
+}
+
+DEBUG_FUNCTION void
+debug_tree_json (tree t)
+{
+  json::object* _x = node_emit_json(t);
+  _x->dump(stderr, true);
+  fprintf(stderr, "\n");
+}
diff --git a/gcc/tree-emit-json.h b/gcc/tree-emit-json.h
new file mode 100644
index 00000000000..ea81466a940
--- /dev/null
+++ b/gcc/tree-emit-json.h
@@ -0,0 +1,82 @@
+/* Tree-dumping functionality for intermediate representation.
+   Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   Written by Mark Mitchell <m...@codesourcery.com>
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_TREE_JSON_H
+#define GCC_TREE_JSON_H
+
+#include "splay-tree.h"
+#include "dumpfile.h"
+#define INCLUDE_MEMORY
+#include "json.h"
+
+typedef struct dump_info *dump_info_p;
+
+/* Information about a node to be dumped.  */
+
+typedef struct dump_node_info
+{
+  /* The index for the node.  */
+  unsigned int index;
+  /* Nonzero if the node is a binfo.  */
+  unsigned int binfo_p : 1;
+} *dump_node_info_p;
+
+/* A dump_queue is a link in the queue of things to be dumped.  */
+
+typedef struct dump_queue
+{
+  /* The queued tree node.  */
+  splay_tree_node node;
+  /* The next node in the queue.  */
+  struct dump_queue *next;
+} *dump_queue_p;
+
+/* A dump_info gives information about how we should perform the dump
+   and about the current state of the dump.  */
+
+struct dump_info
+{
+  /* The stream on which to dump the information.  */
+  FILE *stream;
+  /* The original node.  */
+  const_tree node;
+  /* User flags.  */
+  dump_flags_t flags;
+  /* The next unused node index.  */
+  unsigned int index;
+  /* The next column.  */
+  unsigned int column;
+  /* The first node in the queue of nodes to be written out.  */
+  dump_queue_p queue;
+  /* The last node in the queue.  */
+  dump_queue_p queue_end;
+  /* Free queue nodes.  */
+  dump_queue_p free_list;
+  /* The tree nodes which we have already written out.  The
+     keys are the addresses of the nodes; the values are the integer
+     indices we assigned them.  */
+  splay_tree nodes;
+  /* JSON tree holder. Carries everything, each node is a sub-array */
+  json::array* json_dump;
+};
+
+extern json::object* node_emit_json(tree t);
+extern void dump_node_json (const_tree t, dump_flags_t flags, FILE *stream);
+#endif /* ! GCC_TREE_JSON_H */
-- 
2.34.1

Reply via email to