On Sun, Sep 22, 2024 at 5:49 AM 4444-thor <tcpreimesber...@gmail.com> wrote:
>
> From: thor <th...@protonmail.com>
>
> This is the second revision of:
>
>   https://gcc.gnu.org/pipermail/gcc-patches/2024-September/662849.html
>
> I've incorporated the feedback given both by Richard and David - I didn't
> find any memory leaks when testing in valgrind :)
>
> As before: This patch allows the compiler to dump GENERIC trees as JSON 
> objects.
>
> The dump flag -fdump-tree-original-json dumps each fndecl node in the
> C frontend's gimplifier as a JSON object and traverses related nodes
> in an analagous manner as to raw-dumping.
>
> Some JSON parsers expect for there to be a single JSON value per file -
> the following shell command makes the output conformant:
>
>   tr -d '\n ' < out.json | sed -e 's/\]\[/,/g' | sed -e 's/}{/},{/g'
>
> The information in the dumped JSON is meant to be an amalgation of
> tree-pretty-print.cc's dump_generic_node and print-tree.cc's debug_tree.
>
> Bootstrapped and tested on x86_64-pc-linux-gnu without issue (again).

When trying to bootstrap this myself I run into

/home/rguenther/src/gcc/gcc/tree-emit-json.cc: In function
‘std::unique_ptr<json::object> node_emit_json(tree, dump_info_p)’:
/home/rguenther/src/gcc/gcc/tree-emit-json.cc:1711:20: error:
‘it_args’ may be used uninitialized [-Werror=maybe-uninitialized]
 1711 |             delete it_args;
      |                    ^~~~~~~
/home/rguenther/src/gcc/gcc/tree-emit-json.cc:1683:27: note: ‘it_args’
was declared here
 1683 |             json::object* it_args;
      |                           ^~~~~~~
cc1plus: all warnings being treated as errors
make[3]: *** [Makefile:1195: tree-emit-json.o] Error 1

the code looks a bit suspicious and I have no idea how object lifetime
is supposed to be:

            json::object* it_args;
...
            if (arg_node && arg_node != void_list_node && arg_node !=
error_mark_node)
              auto it_args = ::make_unique<json::object> ();
^^^ this it_args shadows it_args above and immediately goes out of scope?

            while (arg_node && arg_node != void_list_node && arg_node
!= error_mark_node)
              {
                it_args = node_to_json_brief(arg_node, di);
^^^ the last it_args - which will still be appended to args_holder
gets deleted below
                args_holder->append(it_args);
                arg_node = TREE_CHAIN (arg_node);
              }
            json_obj->set("type_uid", _id);
            json_obj->set("args", args_holder);
            delete _id;
            delete it_args;

note this is all in code special-casing pointer or reference to
FUNCTION_TYPE while
I would eventually expected that recursion to FUNCTION_TYPE handling which
exists as well would handle it.  This is probably a case where the
emitted JSON is
too close to what a human would expect rather than representing how the raw tree
object looks like?

Indeed when I html-tree a function pointer I get a segfault.  I've
deleted this special
case in my tree and it then works just fine and fixes the bootstrap issue.

Browsing a bit I did notice a lack of dumping of TREE_TYPE of nodes
like VAR_DECLs.
I've added the following to fix that (but didn't look for then
duplicate tree_type emissions
that could be elided).

diff --git a/gcc/tree-emit-json.cc b/gcc/tree-emit-json.cc
index df97069b922..26a47affd22 100644
--- a/gcc/tree-emit-json.cc
+++ b/gcc/tree-emit-json.cc
@@ -1508,7 +1508,11 @@ node_emit_json(tree t, dump_info_p di)
       if (TYPE_LANG_FLAG_7 (t))
        json_obj->set_bool ("type_7", true);
       } //end tcc_type flags
-
+
+  // For nodes with a type output a reference to it
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPED) && TREE_TYPE (t))
+    json_obj->set("tree_type", node_to_json_brief(TREE_TYPE(t), di));
+
   // Accessors
   switch (code)
   {

In total I used the attached patch ontop of yours for my testing.

Richard.

> gcc/ChangeLog:
>         * gcc/Makefile.in: Link tree-emit-json.o to c-gimplify.o
>         * gcc/dumpfile.h (dump_flag): New dump flag TDF_JSON
>         * gcc/tree-emit-json.cc: Logic for converting a tree to JSON
>         and dumping.
>         * gcc/tree-emit-json.h: For the above
> gcc/c-family/ChangeLog
>         * gcc/c-family/c-gimplify.cc (c_genericize): Hook for
>         -fdump-tree-original-json
>
> Signed-off-by: Thor C Preimesberger <tcpreimesber...@gmail.com>
> ---
>  gcc/Makefile.in            |    2 +
>  gcc/c-family/c-gimplify.cc |   29 +-
>  gcc/dumpfile.cc            |    1 +
>  gcc/dumpfile.h             |    6 +
>  gcc/tree-emit-json.cc      | 3227 ++++++++++++++++++++++++++++++++++++
>  gcc/tree-emit-json.h       |   73 +
>  6 files changed, 3327 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/tree-emit-json.cc
>  create mode 100644 gcc/tree-emit-json.h
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 68fda1a7591..b65cc7f0ad5 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1042,6 +1042,7 @@ OPTS_H = $(INPUT_H) $(VEC_H) opts.h $(OBSTACK_H)
>  SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h $(OBSTACK_H)
>  CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h
>  TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) $(DUMPFILE_H)
> +TREE_EMIT_JSON_H = tree-emit-json.h $(SPLAY_TREE_H) $(DUMPFILE_H) json.h
>  TREE_PASS_H = tree-pass.h $(TIMEVAR_H) $(DUMPFILE_H)
>  TREE_SSA_H = tree-ssa.h tree-ssa-operands.h \
>                 $(BITMAP_H) sbitmap.h $(BASIC_BLOCK_H) $(GIMPLE_H) \
> @@ -1709,6 +1710,7 @@ OBJS = \
>         tree-diagnostic.o \
>         tree-diagnostic-client-data-hooks.o \
>         tree-dump.o \
> +       tree-emit-json.o \
>         tree-eh.o \
>         tree-emutls.o \
>         tree-if-conv.o \
> diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc
> index 3e29766e092..e4234071b11 100644
> --- a/gcc/c-family/c-gimplify.cc
> +++ b/gcc/c-family/c-gimplify.cc
> @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
>  <http://www.gnu.org/licenses/>.  */
>
>  #include "config.h"
> +#define INCLUDE_MEMORY
>  #include "system.h"
>  #include "coretypes.h"
>  #include "tm.h"
> @@ -629,20 +630,26 @@ c_genericize (tree fndecl)
>    local_dump_flags = dfi->pflags;
>    if (dump_orig)
>      {
> -      fprintf (dump_orig, "\n;; Function %s",
> -              lang_hooks.decl_printable_name (fndecl, 2));
> -      fprintf (dump_orig, " (%s)\n",
> -              (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
> -               : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
> -      fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name 
> (TDI_original));
> -      fprintf (dump_orig, "\n");
> -
> -      if (local_dump_flags & TDF_RAW)
> -       dump_node (DECL_SAVED_TREE (fndecl),
> +      if (local_dump_flags & TDF_JSON)
> +       dump_node_json (DECL_SAVED_TREE (fndecl),
>                    TDF_SLIM | local_dump_flags, dump_orig);
>        else
> -       print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
> +      {
> +       fprintf (dump_orig, "\n;; Function %s",
> +                lang_hooks.decl_printable_name (fndecl, 2));
> +       fprintf (dump_orig, " (%s)\n",
> +               (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
> +                : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
> +       fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name 
> (TDI_original));
> +       fprintf (dump_orig, "\n");
> +       if (local_dump_flags & TDF_RAW)
> +         dump_node (DECL_SAVED_TREE (fndecl),
> +                    TDF_SLIM | local_dump_flags, dump_orig);
> +       else
> +         print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
> +
>        fprintf (dump_orig, "\n");
> +      }
>      }
>
>    /* Dump all nested functions now.  */
> diff --git a/gcc/dumpfile.cc b/gcc/dumpfile.cc
> index 074da7df216..0b38f4aa0dd 100644
> --- a/gcc/dumpfile.cc
> +++ b/gcc/dumpfile.cc
> @@ -148,6 +148,7 @@ static const kv_pair<dump_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..df97069b922
> --- /dev/null
> +++ b/gcc/tree-emit-json.cc
> @@ -0,0 +1,3227 @@
> +/* 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"
> +#include "make-unique.h"
> +
> +static void queue (dump_info_p, const_tree);
> +static void dequeue_and_dump (dump_info_p);
> +static std::unique_ptr<json::array> function_decl_emit_json (tree, 
> dump_info_p );
> +static void identifier_node_add_json (tree, std::unique_ptr<json::object> &);
> +static void decl_node_add_json (tree, std::unique_ptr<json::object> &);
> +static void function_name_add_json (tree t, std::unique_ptr<json::object> & 
> json_obj);
> +static void call_name_add_json (tree t, std::unique_ptr<json::object> & 
> json_obj,
> +                                dump_info_p di);
> +static void omp_iterator_add_json (tree, std::unique_ptr<json::object> &, 
> dump_info_p );
> +static void omp_clause_add_json(tree clause, std::unique_ptr<json::object> & 
> json_obj,
> +                                dump_info_p di);
> +static void omp_atomic_memory_order_add_json (std::unique_ptr<json::object> 
> &,
> +                                              enum omp_memory_order);
> +static std::unique_ptr<json::object> omp_atomic_memory_order_emit_json(
> +                                         omp_memory_order mo);
> +static std::unique_ptr<json::object> omp_clause_emit_json(tree t, 
> dump_info_p di);
> +static std::unique_ptr<json::object> omp_clause_emit_json (tree, dump_info_p 
> );
> +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 void
> +queue (dump_info_p di, const_tree t)
> +{
> +  dump_queue_p dq;
> +  dump_node_info_p dni;
> +
> +  /* 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);
> +  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 args of a function declaration */
> +
> +std::unique_ptr<json::array>
> +function_decl_emit_json (tree t, dump_info_p di)
> +{
> +  bool wrote_arg = false;
> +  tree arg;
> +
> +  auto arg_holder = ::make_unique<json::array> ();
> +
> +  arg = TYPE_ARG_TYPES (t);
> +
> +  while (arg && arg != void_list_node && arg != error_mark_node)
> +    {
> +      wrote_arg = true;
> +      arg_holder->append(node_emit_json(TREE_VALUE (arg), di));
> +      arg = TREE_CHAIN (arg);
> +    }
> +
> +  if (arg == void_list_node && !wrote_arg)
> +    {
> +      auto arg_json = new json::object ();
> +      arg_json->set_bool("void_list_node", true);
> +      arg_holder->append(arg_json);
> +      delete (arg_json);
> +    }
> +  return arg_holder;
> +}
> +
> +/* Adds Identifier information to JSON object */
> +
> +void
> +identifier_node_add_json (tree t, std::unique_ptr<json::object> & json_obj)
> +  {
> +    const char* buff = IDENTIFIER_POINTER (t);
> +    json_obj->set_string("id_to_locale", identifier_to_locale(buff));
> +    buff = IDENTIFIER_POINTER (t);
> +    json_obj->set_string("id_point", buff);
> +  }
> +
> +/* Ditto - adds declaration info to JSON object */
> +
> +void
> +decl_node_add_json (tree t, std::unique_ptr<json::object> & json_obj)
> +{
> +  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), json_obj);
> +        else if (DECL_NAMELESS(t)
> +                 && DECL_IGNORED_P(t))
> +          name = NULL_TREE;
> +        else
> +          identifier_node_add_json(name, json_obj);
> +      }
> +    if (name == NULL_TREE)
> +      {
> +        if (TREE_CODE (t) == LABEL_DECL && LABEL_DECL_UID (t) != -1)
> +          {
> +            json_obj->set_integer("Label_UID", LABEL_DECL_UID(t));
> +          }
> +        else if (TREE_CODE (t) == DEBUG_EXPR_DECL)
> +          {
> +            json_obj->set_integer("Debug_UID", DEBUG_TEMP_UID (t));
> +          }
> +        else
> +          {
> +            const char* c = TREE_CODE (t) == CONST_DECL ? "Const_UID"
> +                                                        : "Decl_UID";
> +            json_obj->set_integer(c, DECL_UID(t));
> +          }
> +      }
> +    if (DECL_PT_UID (t) != DECL_UID (t))
> +      {
> +        json_obj->set_integer("ptDecl", DECL_PT_UID(t));
> +      }
> +}
> +
> +/* Helper for function calls in call_name_add_json. */
> +
> +void
> +function_name_add_json (tree t, std::unique_ptr<json::object> & json_obj)
> +{
> +  if (CONVERT_EXPR_P (t))
> +    t = TREE_OPERAND (t, 0);
> +  if (DECL_NAME (t))
> +    {
> +      json_obj->set_string("decl_name", lang_hooks.decl_printable_name (t, 
> 1));
> +      json_obj->set_integer("uid", DECL_UID(t));
> +    }
> +  else
> +    decl_node_add_json(t, json_obj);
> +}
> +
> +/* Adds the name of a call. Enter iff t is CALL_EXPR_FN */
> +
> +void
> +call_name_add_json (tree t, std::unique_ptr<json::object> & json_obj,
> +                    dump_info_p di)
> +{
> +  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, json_obj);
> +        break;
> +
> +      case ADDR_EXPR:
> +      case INDIRECT_REF:
> +      CASE_CONVERT:
> +        op0 = TREE_OPERAND (op0, 0);
> +        goto again;
> +
> +      case COND_EXPR:
> +        {
> +          auto x = new json::object ();
> +          x->set("if", node_emit_json(TREE_OPERAND(op0, 0), di));
> +          x->set("then", node_emit_json(TREE_OPERAND(op0, 1), di));
> +          x->set("else", node_emit_json(TREE_OPERAND(op0, 2), di));
> +          json_obj->set("call_name", x);
> +        }
> +        break;
> +
> +      case ARRAY_REF:
> +        if (VAR_P (TREE_OPERAND (op0, 0)))
> +       function_name_add_json (TREE_OPERAND (op0, 0), json_obj);
> +        else
> +       json_obj->set("call_name", node_emit_json (op0, di));
> +        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:
> +        json_obj->set("call_name", node_emit_json (op0, di));
> +        break;
> +      default:
> +        break;
> +    }
> +}
> +
> +/* OMP helper. */
> +
> +void
> +omp_iterator_add_json(tree iter, std::unique_ptr<json::object> & json_obj,
> +                      dump_info_p di)
> +{
> +  auto 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), di));
> +        }
> +    }
> +  json_obj->set("omp_iter", iter_holder);
> +  delete iter_holder;
> +}
> +
> +/* OMP helper. */
> +
> +void
> +omp_clause_add_json(tree clause, std::unique_ptr<json::object> & json_obj,
> +                    dump_info_p di)
> +{
> +  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);
> +      json_obj->set (buffer, node_emit_json (OMP_CLAUSE_DECL (clause), di));
> +      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 ();
> +        }
> +      json_obj->set(buffer, node_emit_json (OMP_CLAUSE_IF_EXPR (clause), 
> di));
> +      break;
> +
> +    case OMP_CLAUSE_SELF:
> +      json_obj->set("omp_self", node_emit_json 
> (OMP_CLAUSE_SELF_EXPR(clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_NUM_THREADS:
> +      json_obj->set("omp_num_threads",
> +                 node_emit_json (OMP_CLAUSE_NUM_THREADS_EXPR(clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_NOWAIT:
> +      break;
> +
> +    case OMP_CLAUSE_ORDERED:
> +      json_obj->set("omp_ordered",
> +                 node_emit_json (OMP_CLAUSE_ORDERED_EXPR (clause), di));
> +      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 ();
> +        }
> +      json_obj->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 ();
> +       }
> +      json_obj->set(buffer,
> +                 node_emit_json(OMP_CLAUSE_SCHEDULE_CHUNK_EXPR(clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_UNTIED:
> +      json_obj->set_bool("omp_clause_untied", true);
> +      break;
> +
> +    case OMP_CLAUSE_COLLAPSE:
> +      json_obj->set("omp_collapse_collapse",
> +                 node_emit_json (OMP_CLAUSE_COLLAPSE_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_FINAL:
> +      json_obj->set("omp_final", node_emit_json (OMP_CLAUSE_FINAL_EXPR 
> (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_MERGEABLE:
> +      json_obj->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 ();
> +         }
> +      json_obj->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause), di));
> +      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 ();
> +         }
> +      json_obj->set(buffer, node_emit_json (OMP_CLAUSE_LINEAR_STEP (clause), 
> di));
> +      break;
> +
> +    case OMP_CLAUSE_ALIGNED:
> +      json_obj->set("omp_aligned", node_emit_json (OMP_CLAUSE_DECL(clause), 
> di));
> +      if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
> +       {
> +          json_obj->set("omp_aligned_alignment",
> +                     node_emit_json (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause), 
> di));
> +       }
> +      break;
> +
> +    case OMP_CLAUSE_ALLOCATE:
> +      if (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause))
> +          json_obj->set("omp_allocator",
> +                     node_emit_json (OMP_CLAUSE_ALLOCATE_ALLOCATOR (clause), 
> di));
> +      if (OMP_CLAUSE_ALLOCATE_ALIGN (clause))
> +          json_obj->set("omp_allocate_align",
> +                     node_emit_json (OMP_CLAUSE_ALLOCATE_ALIGN (clause), 
> di));
> +      json_obj->set("omp_allocate",
> +                 node_emit_json (OMP_CLAUSE_DECL (clause), di));
> +      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), json_obj, di);
> +           t = TREE_VALUE (t);
> +         }
> +        json_obj->set("omp_affinity", node_emit_json(t, di));
> +      }
> +      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), json_obj, di);
> +           t = TREE_VALUE (t);
> +         }
> +       if (t == null_pointer_node)
> +         json_obj->set_bool("omp_all_memory", true);
> +       else
> +          json_obj->set(buffer, node_emit_json(t, di));
> +      }
> +      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:");
> +          json_obj->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");
> +              json_obj->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), di));
> +               if (TREE_PURPOSE (t) != integer_zero_node)
> +                 {
> +                    auto x = new json::object ();
> +                   if (OMP_CLAUSE_DOACROSS_SINK_NEGATIVE (t))
> +                      x->set("-", node_emit_json(TREE_PURPOSE (t), di));
> +                   else
> +                      x->set("+", node_emit_json(TREE_PURPOSE (t), di));
> +                    iter_holder->append(x);
> +                 }
> +             }
> +           else
> +             gcc_unreachable ();
> +         delete iter_holder;
> +          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 ();
> +       }
> +      json_obj->set (buffer, node_emit_json (OMP_CLAUSE_DECL (clause), di));
> +     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;
> +           }
> +          json_obj->set (buffer, node_emit_json (OMP_CLAUSE_SIZE (clause), 
> di));
> +       }
> +      if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP
> +         && OMP_CLAUSE_MAP_RUNTIME_IMPLICIT_P (clause))
> +        json_obj->set_bool("implicit", true);
> +      break;
> +
> +    case OMP_CLAUSE_FROM:
> +      strcat (buffer, "omp_from");
> +      if (OMP_CLAUSE_MOTION_PRESENT (clause))
> +       strcat (buffer, "_present");
> +      json_obj->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause), di));
> +      goto print_clause_size;
> +
> +    case OMP_CLAUSE_TO:
> +      strcpy (buffer, "omp_to");
> +      if (OMP_CLAUSE_MOTION_PRESENT (clause))
> +       strcat (buffer, "_present");
> +      json_obj->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause), di));
> +      goto print_clause_size;
> +
> +    case OMP_CLAUSE__CACHE_:
> +      strcat (buffer, "omp__cache__");
> +      if (OMP_CLAUSE__CACHE__READONLY (clause))
> +       strcat (buffer, "_readonly");
> +      json_obj->set(buffer, node_emit_json (OMP_CLAUSE_DECL (clause), di));
> +      goto print_clause_size;
> +
> +    case OMP_CLAUSE_NUM_TEAMS:
> +      strcat (buffer, "omp_num_teams");
> +      if (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (clause))
> +       {
> +          json_obj->set("omp_num_teams_lower",
> +                     node_emit_json (OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR 
> (clause), di));
> +          strcat (buffer, "_upper");
> +       }
> +      else
> +        json_obj->set(buffer,
> +                   node_emit_json (OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (clause), 
> di));
> +      break;
> +
> +    case OMP_CLAUSE_THREAD_LIMIT:
> +      json_obj->set("omp_thread_limit",
> +                 node_emit_json (OMP_CLAUSE_THREAD_LIMIT_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_DEVICE:
> +      strcpy (buffer, "omp_device(");
> +      if (OMP_CLAUSE_DEVICE_ANCESTOR (clause))
> +       strcat (buffer, "_ancestor:");
> +      json_obj->set(buffer,
> +                 node_emit_json (OMP_CLAUSE_DEVICE_ID (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_DIST_SCHEDULE:
> +      strcat (buffer, "omp_dist_schedule(static)");
> +      if (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (clause))
> +       {
> +          json_obj->set(buffer,
> +                     node_emit_json (OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR 
> (clause), di));
> +       }
> +      else
> +        json_obj->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 ();
> +       }
> +      json_obj->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 ();
> +       }
> +      json_obj->set_bool(buffer, true);
> +      break;
> +
> +    case OMP_CLAUSE_SAFELEN:
> +      json_obj->set("omp_safelen",
> +                 node_emit_json (OMP_CLAUSE_SAFELEN_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_SIMDLEN:
> +      json_obj->set("omp_simdlen",
> +                 node_emit_json (OMP_CLAUSE_SIMDLEN_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_PRIORITY:
> +      json_obj->set("omp_priority",
> +                 node_emit_json (OMP_CLAUSE_PRIORITY_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_GRAINSIZE:
> +      strcpy (buffer, "omp_grainsize");
> +      if (OMP_CLAUSE_GRAINSIZE_STRICT (clause))
> +        strcat (buffer, "_strict");
> +      json_obj->set(buffer,
> +                 node_emit_json (OMP_CLAUSE_GRAINSIZE_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_NUM_TASKS:
> +      strcpy (buffer, "omp_num_tasks");
> +      if (OMP_CLAUSE_NUM_TASKS_STRICT (clause))
> +       strcat (buffer, "_strict");
> +      json_obj->set(buffer,
> +                 node_emit_json (OMP_CLAUSE_NUM_TASKS_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_HINT:
> +      json_obj->set("omp_hint",
> +                 node_emit_json (OMP_CLAUSE_HINT_EXPR(clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_FILTER:
> +      json_obj->set("omp_filter",
> +                 node_emit_json (OMP_CLAUSE_FILTER_EXPR(clause), di));
> +      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 ();
> +       }
> +      json_obj->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)");
> +      json_obj->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 ();
> +       }
> +      json_obj->set_bool(buffer, true);
> +      break;
> +
> +    case OMP_CLAUSE__SIMDUID_:
> +      json_obj->set("omp__simduid__",
> +                 node_emit_json(OMP_CLAUSE__SIMDUID__DECL (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE__SIMT_:
> +      json_obj->set_bool("omp__simt__", true);
> +      break;
> +
> +    //In our current implementation, we dump exprs etc even if not NULL.
> +    case OMP_CLAUSE_GANG:
> +      json_obj->set_bool ("omp_gang", true);
> +      if (OMP_CLAUSE_GANG_EXPR (clause) != NULL_TREE)
> +          json_obj->set("num", node_emit_json (OMP_CLAUSE_GANG_EXPR 
> (clause), di));
> +      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, "*");
> +          json_obj->set(buffer,
> +                     node_emit_json (OMP_CLAUSE_GANG_STATIC_EXPR (clause), 
> di));
> +       }
> +      break;
> +
> +    case OMP_CLAUSE_ASYNC:
> +      json_obj->set("omp_async",
> +                 node_emit_json (OMP_CLAUSE_ASYNC_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_AUTO:
> +    case OMP_CLAUSE_SEQ:
> +      strcpy (buffer, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]);
> +      json_obj->set_bool(buffer, true);
> +      break;
> +
> +    case OMP_CLAUSE_WAIT:
> +      json_obj->set("omp_wait",
> +                 node_emit_json (OMP_CLAUSE_WAIT_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_WORKER:
> +      json_obj->set("omp_worker",
> +                 node_emit_json (OMP_CLAUSE_WORKER_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_VECTOR:
> +      json_obj->set("omp_vector",
> +                 node_emit_json (OMP_CLAUSE_VECTOR_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_NUM_GANGS:
> +      json_obj->set("omp_num_gangs",
> +                 node_emit_json (OMP_CLAUSE_NUM_GANGS_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_NUM_WORKERS:
> +      json_obj->set("omp_num_workers",
> +                 node_emit_json (OMP_CLAUSE_NUM_WORKERS_EXPR (clause), di));
> +      break;
> +
> +    case OMP_CLAUSE_VECTOR_LENGTH:
> +      json_obj->set("omp_vector_length",
> +                 node_emit_json (OMP_CLAUSE_VECTOR_LENGTH_EXPR (clause), 
> di));
> +      break;
> +
> +    case OMP_CLAUSE_INBRANCH:
> +      json_obj->set_bool ("inbranch", true);
> +      break;
> +    case OMP_CLAUSE_NOTINBRANCH:
> +      json_obj->set_bool ("notinbranch", true);
> +      break;
> +    case OMP_CLAUSE_FOR:
> +      json_obj->set_bool ("for", true);
> +      break;
> +    case OMP_CLAUSE_PARALLEL:
> +      json_obj->set_bool ("parallel", true);
> +      break;
> +    case OMP_CLAUSE_SECTIONS:
> +      json_obj->set_bool ("sections", true);
> +      break;
> +    case OMP_CLAUSE_TASKGROUP:
> +      json_obj->set_bool ("taskgroup", true);
> +      break;
> +    case OMP_CLAUSE_NOGROUP:
> +      json_obj->set_bool ("nogroup", true);
> +      break;
> +    case OMP_CLAUSE_THREADS:
> +      json_obj->set_bool ("threads", true);
> +      break;
> +    case OMP_CLAUSE_SIMD:
> +      json_obj->set_bool ("simd", true);
> +      break;
> +    case OMP_CLAUSE_INDEPENDENT:
> +      json_obj->set_bool ("independent", true);
> +      break;
> +    case OMP_CLAUSE_TILE:
> +      json_obj->set ("omp_tile", node_emit_json (OMP_CLAUSE_TILE_LIST 
> (clause), di));
> +      break;
> +    case OMP_CLAUSE_PARTIAL:
> +      json_obj->set ("omp_partial",
> +                  node_emit_json (OMP_CLAUSE_PARTIAL_EXPR (clause), di));
> +      break;
> +    case OMP_CLAUSE_FULL:
> +      json_obj->set_bool("full", true);
> +      break;
> +    case OMP_CLAUSE_SIZES:
> +      json_obj->set("omp_sizes", node_emit_json (OMP_CLAUSE_SIZES_LIST 
> (clause), di));
> +      break;
> +    case OMP_CLAUSE_IF_PRESENT:
> +      json_obj->set_bool("if_present", true);
> +      break;
> +    case OMP_CLAUSE_FINALIZE:
> +      json_obj->set_bool("finalize", true);
> +      break;
> +    case OMP_CLAUSE_NOHOST:
> +      json_obj->set_bool("nohost", true);
> +      break;
> +    case OMP_CLAUSE_DETACH:
> +      json_obj->set("omp_detach", node_emit_json (OMP_CLAUSE_DECL (clause), 
> di));
> +      break;
> +    default:
> +      gcc_unreachable();
> +    }
> +}
> +
> +void
> +omp_atomic_memory_order_add_json (std::unique_ptr<json::object> & json_obj, 
> enum omp_memory_order mo)
> +{
> +  switch (mo & OMP_MEMORY_ORDER_MASK)
> +    {
> +    case OMP_MEMORY_ORDER_RELAXED:
> +      json_obj->set_string ("omp_memory_order", "relaxed");
> +      break;
> +    case OMP_MEMORY_ORDER_SEQ_CST:
> +      json_obj->set_string ("omp_memory_order", "seq_cst");
> +      break;
> +    case OMP_MEMORY_ORDER_ACQ_REL:
> +      json_obj->set_string ("omp_memory_order", "acq_rel");
> +      break;
> +    case OMP_MEMORY_ORDER_ACQUIRE:
> +      json_obj->set_string ("omp_memory_order", "acquire");
> +      break;
> +    case OMP_MEMORY_ORDER_RELEASE:
> +      json_obj->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:
> +      json_obj->set_string ("omp_fail_memory_order", "relaxed");
> +      break;
> +    case OMP_FAIL_MEMORY_ORDER_SEQ_CST:
> +      json_obj->set_string ("omp_fail_memory_order", "seq_cst");
> +      break;
> +    case OMP_FAIL_MEMORY_ORDER_ACQUIRE:
> +      json_obj->set_string ("omp_fail_memory_order", "acquire");
> +      break;
> +    case OMP_FAIL_MEMORY_ORDER_UNSPECIFIED:
> +      json_obj->set_string ("omp_fail_memory_order", "unspecified");
> +      break;
> +    default:
> +      gcc_unreachable ();
> +    }
> +}
> +
> +std::unique_ptr<json::object>
> +omp_atomic_memory_order_emit_json(omp_memory_order mo)
> +{
> +  auto x = ::make_unique<json::object> ();
> +  omp_atomic_memory_order_add_json(x, mo);
> +  return x;
> +}
> +
> +std::unique_ptr<json::object>
> +omp_clause_emit_json(tree t, dump_info_p di)
> +{
> +  auto x = ::make_unique<json::object> ();
> +  omp_clause_add_json(t, x, di);
> +  return x;
> +}
> +
> +json::array*
> +loc_emit_json (expanded_location xloc)
> +{
> +  auto loc_holder = new json::array ();
> +  auto 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->append(loc_info);
> +  return loc_holder;
> +  delete loc_holder;
> +  delete loc_info;
> +}
> +
> +/* For some referenced nodes that may be too verbose. This
> + * should only be called by node_to_json and contained in another
> + * json::object, and so we need not worry about memory leaks. */
> +
> +
> +json::object *
> +node_to_json_brief(tree t)
> +{
> +  json::object * json_obj = new json::object ();
> +
> +  char address_buffer [20] = {"\0"};
> +  sprintf(address_buffer, HOST_PTR_PRINTF, (void *)t);
> +
> +  json_obj->set_string("ref_addr", address_buffer);
> +  json_obj->set_string("tree_code", get_tree_code_name(TREE_CODE (t)));
> +  return json_obj;
> +}
> +
> +/* Same as above, but we keep track of di nodes for additional dumping queue
> + * to append them to our dumping queue.*/
> +
> +json::object *
> +node_to_json_brief(tree t, dump_info_p & di)
> +{
> +  queue (di, t);
> +  return node_to_json_brief(t);
> +}
> +
> +/* Here we emit JSON data for a GENERIC node and children.
> + * c.f. dump_generic_node and print-tree's debug_tree().
> + * We need pass di inorder to queue child nodes.*/
> +
> +std::unique_ptr<json::object>
> +node_emit_json(tree t, dump_info_p di)
> +{
> +  tree op0, op1, type;
> +  enum tree_code code;
> +  json::array* holder;
> +
> +
> +  auto json_obj = ::make_unique<json::object> ();
> +
> +  /* Sometimes the operands for some codes are null.
> +  *  Don't dereference them. */
> +  if (!t)
> +    return json_obj;
> +
> +  // For multiple referred nodes
> +  holder = new json::array ();
> +
> +  code = TREE_CODE (t);
> +  const char* code_name = get_tree_code_name(code);
> +
> +  char address_buffer[20] = {"\0"};
> +  sprintf(address_buffer, HOST_PTR_PRINTF, (void *)t);
> +
> +  json_obj->set_string("addr", address_buffer);
> +  json_obj->set_string("tree_code", code_name);
> +
> +  // Flag handling
> +  if (TREE_ADDRESSABLE (t))
> +    json_obj->set_bool ("addressable", true);
> +  if (TREE_THIS_VOLATILE (t))
> +    json_obj->set_bool ("volatile", true);
> +  if (TREE_ASM_WRITTEN (t))
> +    json_obj->set_bool ("asm_written", true);
> +  if (TREE_USED (t))
> +    json_obj->set_bool ("used", true);
> +  if (TREE_NOTHROW (t))
> +    json_obj->set_bool ("nothrow", true);
> +  if (TREE_PUBLIC (t))
> +    json_obj->set_bool ("public", true);
> +  if (TREE_PRIVATE (t))
> +    json_obj->set_bool ("private", true);
> +  if (TREE_PROTECTED (t))
> +    json_obj->set_bool ("protected", true);
> +  if (TREE_STATIC (t))
> +    json_obj->set_bool (code == CALL_EXPR ? " must-tail-call"
> +                                       : " static", true);
> +  if (TREE_DEPRECATED (t))
> +    json_obj->set_bool ("deprecated", true);
> +  if (TREE_VISITED (t))
> +    json_obj->set_bool ("visited", true);
> +
> +  if (code != TREE_VEC && code != SSA_NAME && code != INTEGER_CST)
> +    {
> +      if (TREE_UNAVAILABLE (t))
> +       json_obj->set_bool ("unavailable", true);
> +      if (TREE_LANG_FLAG_0 (t))
> +       json_obj->set_bool ("tree_0", true);
> +      if (TREE_LANG_FLAG_1 (t))
> +        json_obj->set_bool ("tree_1", true);
> +      if (TREE_LANG_FLAG_2 (t))
> +       json_obj->set_bool ("tree_2", true);
> +      if (TREE_LANG_FLAG_3 (t))
> +       json_obj->set_bool ("tree_3", true);
> +      if (TREE_LANG_FLAG_4 (t))
> +       json_obj->set_bool ("tree_4", true);
> +      if (TREE_LANG_FLAG_5 (t))
> +       json_obj->set_bool ("tree_5", true);
> +      if (TREE_LANG_FLAG_6 (t))
> +       json_obj->set_bool ("tree_6", true);
> +    }
> +
> +  if (TREE_CODE_CLASS(code) == tcc_declaration)
> +    {
> +      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> +        {
> +          if (DECL_UNSIGNED (t))
> +           json_obj->set_bool ("unsigned", true);
> +         if (DECL_IGNORED_P (t))
> +           json_obj->set_bool ("ignored", true);
> +         if (DECL_ABSTRACT_P (t))
> +           json_obj->set_bool ("abstract", true);
> +          if (DECL_EXTERNAL (t))
> +            json_obj->set_bool ("external", true);
> +          if (DECL_NONLOCAL (t))
> +            json_obj->set_bool ("nonlocal", true);
> +       }
> +      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
> +        {
> +         if (DECL_WEAK (t))
> +           json_obj->set_bool ("weak", true);
> +         if (DECL_IN_SYSTEM_HEADER (t))
> +           json_obj->set_bool ("in_system_header", true);
> +        }
> +      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL)
> +         && code != LABEL_DECL
> +         && code != FUNCTION_DECL
> +         && DECL_REGISTER (t))
> +       json_obj->set_bool ("regdecl", true);
> +
> +      if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (t))
> +       json_obj->set_bool ("suppress-debug", true);
> +
> +      if (code == FUNCTION_DECL
> +         && DECL_FUNCTION_SPECIFIC_TARGET (t))
> +       json_obj->set_bool ("function-specific-target", true);
> +      if (code == FUNCTION_DECL
> +         && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t))
> +       json_obj->set_bool ("function-specific-opt", true);
> +      if (code == FUNCTION_DECL && DECL_DECLARED_INLINE_P (t))
> +       json_obj->set_bool ("autoinline", true);
> +      if (code == FUNCTION_DECL && DECL_UNINLINABLE (t))
> +       json_obj->set_bool ("uninlinable", true);
> +      if (code == FUNCTION_DECL && fndecl_built_in_p (t))
> +       json_obj->set_bool ("built-in", true);
> +      if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (t))
> +       json_obj->set_bool ("static-chain", true);
> +      if (TREE_CODE (t) == FUNCTION_DECL && decl_is_tm_clone (t))
> +       json_obj->set_bool ("tm-clone", true);
> +
> +      if (code == FIELD_DECL && DECL_PACKED (t))
> +       json_obj->set_bool ("packed", true);
> +      if (code == FIELD_DECL && DECL_BIT_FIELD (t))
> +       json_obj->set_bool ("bit-field", true);
> +      if (code == FIELD_DECL && DECL_NONADDRESSABLE_P (t))
> +       json_obj->set_bool ("nonaddressable", true);
> +
> +      if (code == LABEL_DECL && EH_LANDING_PAD_NR (t))
> +        json_obj->set_integer("landing_pad", EH_LANDING_PAD_NR(t));
> +
> +      if (code == VAR_DECL && DECL_IN_TEXT_SECTION (t))
> +       json_obj->set_bool ("in-text-section", true);
> +      if (code == VAR_DECL && DECL_IN_CONSTANT_POOL (t))
> +       json_obj->set_bool ("in-constant-pool", true);
> +      if (code == VAR_DECL && DECL_COMMON (t))
> +       json_obj->set_bool ("common", true);
> +      if ((code == VAR_DECL || code == PARM_DECL) && DECL_READ_P (t))
> +       json_obj->set_bool ("read", true);
> +      if (code == VAR_DECL && DECL_THREAD_LOCAL_P (t))
> +         json_obj->set_bool (tls_model_names[DECL_TLS_MODEL (t)], true);
> +
> +      if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
> +       {
> +         if (DECL_VIRTUAL_P (t))
> +           json_obj->set_bool ("virtual", true);
> +         if (DECL_PRESERVE_P (t))
> +           json_obj->set_bool ("preserve", true);
> +         if (DECL_LANG_FLAG_0 (t))
> +           json_obj->set_bool ("decl_0", true);
> +         if (DECL_LANG_FLAG_1 (t))
> +           json_obj->set_bool ("decl_1", true);
> +         if (DECL_LANG_FLAG_2 (t))
> +           json_obj->set_bool ("decl_2", true);
> +         if (DECL_LANG_FLAG_3 (t))
> +           json_obj->set_bool ("decl_3", true);
> +         if (DECL_LANG_FLAG_4 (t))
> +           json_obj->set_bool ("decl_4", true);
> +         if (DECL_LANG_FLAG_5 (t))
> +           json_obj->set_bool ("decl_5", true);
> +         if (DECL_LANG_FLAG_6 (t))
> +           json_obj->set_bool ("decl_6", true);
> +         if (DECL_LANG_FLAG_7 (t))
> +           json_obj->set_bool ("decl_7", true);
> +         if (DECL_LANG_FLAG_8 (t))
> +           json_obj->set_bool ("decl_8", true);
> +
> +         json_obj->set_string("mode", GET_MODE_NAME (DECL_MODE (t)));
> +       }
> +
> +
> +      if ((code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
> +         && DECL_BY_REFERENCE (t))
> +       json_obj->set_bool ("passed-by-reference", true);
> +
> +      if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)  && 
> DECL_DEFER_OUTPUT (t))
> +       json_obj->set_bool ("defer-output", true);
> +
> +    } //end tcc_decl flags
> +
> +    if (TREE_CODE_CLASS(code) == tcc_type)
> +      {
> +      if (TYPE_UNSIGNED (t))
> +       json_obj->set_bool ("unsigned", true);
> +
> +      if (TYPE_NO_FORCE_BLK (t))
> +       json_obj->set_bool ("no-force-blk", true);
> +
> +      if (code == ARRAY_TYPE && TYPE_STRING_FLAG (t))
> +       json_obj->set_bool ("string-flag", true);
> +
> +      if (TYPE_NEEDS_CONSTRUCTING (t))
> +       json_obj->set_bool ("needs-constructing", true);
> +
> +      if ((code == RECORD_TYPE
> +          || code == UNION_TYPE
> +          || code == QUAL_UNION_TYPE
> +          || code == ARRAY_TYPE)
> +         && TYPE_REVERSE_STORAGE_ORDER (t))
> +       json_obj->set_bool ("reverse-storage-order", true);
> +
> +      if ((code == RECORD_TYPE
> +          || code == UNION_TYPE)
> +         && TYPE_CXX_ODR_P (t))
> +       json_obj->set_bool ("cxx-odr-p", true);
> +
> +      if ((code == RECORD_TYPE
> +          || code == UNION_TYPE)
> +         && TYPE_CXX_ODR_P (t))
> +       json_obj->set_bool ("cxx-odr-p", true);
> +
> +      if ((code == RECORD_TYPE
> +          || code == UNION_TYPE)
> +         && TYPE_INCLUDES_FLEXARRAY (t))
> +       json_obj->set_bool ("includes-flexarray", true);
> +
> +      if ((code == UNION_TYPE || code == RECORD_TYPE)
> +         && TYPE_TRANSPARENT_AGGR (t))
> +       json_obj->set_bool ("transparent-aggr", true);
> +      else if (code == ARRAY_TYPE
> +              && TYPE_NONALIASED_COMPONENT (t))
> +       json_obj->set_bool ("nonaliased-component", true);
> +
> +      if (TYPE_PACKED (t))
> +       json_obj->set_bool ("packed", true);
> +
> +      if (TYPE_RESTRICT (t))
> +       json_obj->set_bool ("restrict", true);
> +
> +      if (TYPE_LANG_FLAG_0 (t))
> +       json_obj->set_bool ("type_0", true);
> +      if (TYPE_LANG_FLAG_1 (t))
> +       json_obj->set_bool ("type_1", true);
> +      if (TYPE_LANG_FLAG_2 (t))
> +       json_obj->set_bool ("type_2", true);
> +      if (TYPE_LANG_FLAG_3 (t))
> +       json_obj->set_bool ("type_3", true);
> +      if (TYPE_LANG_FLAG_4 (t))
> +       json_obj->set_bool ("type_4", true);
> +      if (TYPE_LANG_FLAG_5 (t))
> +       json_obj->set_bool ("type_5", true);
> +      if (TYPE_LANG_FLAG_6 (t))
> +       json_obj->set_bool ("type_6", true);
> +      if (TYPE_LANG_FLAG_7 (t))
> +       json_obj->set_bool ("type_7", true);
> +      } //end tcc_type flags
> +
> +  // Accessors
> +  switch (code)
> +  {
> +    case IDENTIFIER_NODE:
> +      json_obj->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_to_json_brief(TREE_PURPOSE(t), di));
> +       }
> +       holder->append(node_to_json_brief(TREE_VALUE(t), di));
> +        t = TREE_CHAIN(t);
> +      }
> +      break;
> +    case TREE_BINFO:
> +      holder->append(node_to_json_brief(BINFO_TYPE(t), di));
> +      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_to_json_brief(TREE_VEC_ELT(t, i), di));
> +           }
> +         }
> +      }
> +      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;
> +
> +        auto 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);
> +
> +        json_obj->set("quals", x);
> +
> +       if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (t)))
> +           json_obj->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, json_obj);
> +         else
> +           json_obj->set_string("decl", "<unnamed type decl>");
> +         }
> +       else if (tclass == tcc_type)
> +         {
> +           if (TYPE_NAME (t))
> +           {
> +             if (TREE_CODE(TYPE_NAME (t)) == IDENTIFIER_NODE)
> +                json_obj->set("identifier", node_to_json_brief(TYPE_NAME(t), 
> di));
> +             else if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
> +                      && DECL_NAME (TYPE_NAME (t)))
> +                decl_node_add_json( TYPE_NAME (t), json_obj);
> +             else
> +                json_obj->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 coeffs = new json::object ();
> +                  auto _poly_int = TYPE_VECTOR_SUBPARTS(t);
> +                  coeffs->set_integer("poly_int_coeff", _poly_int.coeffs[i]);
> +                  holder->append(coeffs);
> +                  delete coeffs;
> +                }
> +              json_obj->set("vector_subparts", holder);
> +             }
> +            else if (TREE_CODE (t) == INTEGER_TYPE)
> +             {
> +               if (TYPE_PRECISION (t) == CHAR_TYPE_SIZE)
> +                 json_obj->set_string("type precision", (TYPE_UNSIGNED(t)
> +                                                  ? "unsigned char"
> +                                                  : "signed char"));
> +               else if (TYPE_PRECISION (t) == SHORT_TYPE_SIZE)
> +                 json_obj->set_string("type precision", (TYPE_UNSIGNED(t)
> +                                                  ? "unsigned short"
> +                                                  : "signed short"));
> +               else if (TYPE_PRECISION (t) == INT_TYPE_SIZE)
> +                 json_obj->set_string("type precision", (TYPE_UNSIGNED(t)
> +                                                  ? "unsigned int"
> +                                                  : "signed int"));
> +               else if (TYPE_PRECISION (t) == LONG_TYPE_SIZE)
> +                 json_obj->set_string("type precision", (TYPE_UNSIGNED(t)
> +                                                  ? "unsigned long"
> +                                                  : "signed long"));
> +               else if (TYPE_PRECISION (t) == LONG_LONG_TYPE_SIZE)
> +                 json_obj->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)))
> +                   json_obj->set_integer(TYPE_UNSIGNED(t) ? "uint": "int",
> +                                      TYPE_PRECISION(t));
> +               else
> +                   json_obj->set_integer(TYPE_UNSIGNED(t)
> +                                     ? "unnamed-unsigned"
> +                                     : "unnamed-signed", TYPE_PRECISION(t));
> +             }
> +           else if (TREE_CODE (t) == COMPLEX_TYPE) //make sure this is okay 
> later, need track cmplx here?
> +             {
> +               holder->append(node_to_json_brief(TREE_TYPE(t), di));
> +                json_obj->set("complex", holder);
> +             }
> +           else if (TREE_CODE (t) == REAL_TYPE)
> +             {
> +               json_obj->set_integer("float", TYPE_PRECISION(t));
> +             }
> +           else if (TREE_CODE (t) == FIXED_POINT_TYPE)
> +             {
> +               json_obj->set_integer("fixed point", TYPE_PRECISION(t));
> +             }
> +           else if (TREE_CODE (t) == BOOLEAN_TYPE)
> +             {
> +               json_obj->set_integer(TYPE_UNSIGNED(t)
> +                                  ? "unsigned boolean"
> +                                  : "signed boolean", TYPE_PRECISION(t));
> +             }
> +           else if (TREE_CODE (t) == BITINT_TYPE)
> +             {
> +               json_obj->set_integer(TYPE_UNSIGNED (t)
> +                                  ? "unsigned_BitInt"
> +                                  : "_BitInt", TYPE_PRECISION(t));
> +             }
> +           else if (TREE_CODE (t) == VOID_TYPE)
> +             json_obj->set_bool("float", true);
> +           else
> +             json_obj->set_bool("unnamed type", true);
> +          }
> +      }
> +      break;
> +
> +    case POINTER_TYPE:
> +    case REFERENCE_TYPE:
> +      {
> +        if (TREE_TYPE (t) == NULL)
> +         json_obj->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 ();
> +
> +            json_obj->set("fnode", node_to_json_brief(function_node, di));
> +
> +           if (TYPE_IDENTIFIER (t))
> +             _id->set("type identifier", node_to_json_brief(TYPE_NAME(t), 
> di));
> +            else
> +              {
> +                char buff [20];
> +                print_hex(TYPE_UID(t), buff);
> +               _id->set_string("uid", buff);
> +              }
> +            json_obj->set("function decl", 
> function_decl_emit_json(function_node, di));
> +            if (arg_node && arg_node != void_list_node && arg_node != 
> error_mark_node)
> +             auto it_args = ::make_unique<json::object> ();
> +            while (arg_node && arg_node != void_list_node && arg_node != 
> error_mark_node)
> +             {
> +               it_args = node_to_json_brief(arg_node, di);
> +               args_holder->append(it_args);
> +               arg_node = TREE_CHAIN (arg_node);
> +             }
> +           json_obj->set("type_uid", _id);
> +           json_obj->set("args", args_holder);
> +            delete _id;
> +            delete it_args;
> +            delete args_holder;
> +          }
> +        else
> +          {
> +         unsigned int quals = TYPE_QUALS (t);
> +         json_obj->set("tree_type", node_to_json_brief(TREE_TYPE(t), di));
> +
> +          auto 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);
> +
> +          json_obj->set("quals", x);
> +         if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (t)))
> +           json_obj->set_integer("address space", TYPE_ADDR_SPACE (t));
> +         if (TYPE_REF_CAN_ALIAS_ALL (t))
> +           json_obj->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)
> +              {
> +                json_obj->set("base", node_to_json_brief(TREE_OPERAND (t, 
> 0), di));
> +              }
> +            else
> +              json_obj->set("base", node_to_json_brief(TREE_OPERAND 
> (TREE_OPERAND (t, 0), 0), di));
> +          }
> +        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))
> +            {
> +              json_obj->set("tree_type_size", node_to_json_brief(type, di));
> +            }
> +            json_obj->set("op1_type_size", node_to_json_brief(op1type, di));
> +
> +            if (!integer_zerop (op1))
> +              json_obj->set("offset", node_to_json_brief(op1, di));
> +            if (TREE_CODE(t) == TARGET_MEM_REF)
> +              {
> +                tree temp = TMR_INDEX2 (t);
> +                if (temp)
> +                  json_obj->set("tmr_index2", node_to_json_brief(temp, di));
> +                temp = TMR_INDEX (t);
> +                if (temp)
> +                  {
> +                    json_obj->set("tmr_index", node_to_json_brief(temp, di));
> +                    temp = TMR_STEP(t);
> +                    if (temp)
> +                      json_obj->set("tmr_step", node_to_json_brief(temp, 
> di));
> +                  }
> +              }
> +          }
> +        if (MR_DEPENDENCE_CLIQUE (t) != 0)
> +          {
> +            json_obj->set_integer("clique", MR_DEPENDENCE_CLIQUE(t));
> +            json_obj->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.              */
> +    case ARRAY_TYPE:
> +      {
> +        unsigned int quals = TYPE_QUALS (t);
> +       if (quals & TYPE_QUAL_ATOMIC)
> +         json_obj->set_bool("atomic", true);
> +       if (quals & TYPE_QUAL_CONST)
> +         json_obj->set_bool("const", true);
> +       if (quals & TYPE_QUAL_VOLATILE)
> +         json_obj->set_bool("volatile", true);
> +      }
> +      break;
> +    case RECORD_TYPE:
> +    case UNION_TYPE:
> +    case QUAL_UNION_TYPE:
> +      {
> +        unsigned int quals = TYPE_QUALS (t);
> +
> +        auto 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);
> +
> +        json_obj->set("type_quals", x);
> +
> +        if (TYPE_NAME(t))
> +          json_obj->set("type_name", node_to_json_brief(TYPE_NAME(t), di));
> +      }
> +      break;
> +    case LANG_TYPE:
> +      break;
> +    case INTEGER_CST:
> +      {
> +        json_obj->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_to_json_brief (TREE_TYPE(t), di));
> +            json_obj->set("_Literal", holder);
> +          }
> +        if (TREE_CODE (TREE_TYPE(t)) == POINTER_TYPE)
> +          {
> +            // In bytes
> +            json_obj->set_bool("pointer", true);
> +            json_obj->set_integer("val", TREE_INT_CST_LOW(t));
> +          }
> +        else if (tree_fits_shwi_p(t))
> +          json_obj->set_integer("val", tree_to_shwi (t));
> +        else if (tree_fits_uhwi_p(t))
> +          json_obj->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)));
> +            json_obj->set_string("val", buff);
> +        }
> +      if (TREE_OVERFLOW (t))
> +        json_obj->set_bool("overflow", true);
> +      }
> +      break;
> +
> +    case POLY_INT_CST:
> +      for (unsigned int i = 1; i < NUM_POLY_INT_COEFFS; i++)
> +        holder->append(node_to_json_brief(POLY_INT_CST_COEFF(t, i), di));
> +      json_obj->set("poly_int_cst", holder);
> +      break;
> +
> +    case REAL_CST:
> +      {
> +        REAL_VALUE_TYPE d;
> +
> +        d = TREE_REAL_CST (t);
> +
> +        if (TREE_OVERFLOW (t))
> +          json_obj->set_bool("overflow", true);
> +
> +        if (REAL_VALUE_ISINF (d))
> +          json_obj->set_string("value", REAL_VALUE_NEGATIVE(d) ? "-Inf" : 
> "Inf");
> +        else if (REAL_VALUE_ISNAN(d))
> +          json_obj->set_string("value", "NaN");
> +        else
> +          {
> +            char string[100];
> +            real_to_decimal(string, &d, sizeof (string), 0, 1);
> +            json_obj->set_string("real_value", string);
> +          }
> +      }
> +      break;
> +
> +    case FIXED_CST:
> +      {
> +        char string[100];
> +        fixed_to_decimal(string, TREE_FIXED_CST_PTR(t), sizeof (string));
> +        json_obj->set_string("fixed_cst", string);
> +      }
> +      break;
> +
> +    case STRING_CST:
> +        json_obj->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_to_json_brief(VECTOR_CST_ELT (t, i), di));
> +          }
> +        json_obj->set("vector_cst", holder);
> +      }
> +      break;
> +
> +    case FUNCTION_TYPE:
> +    case METHOD_TYPE:
> +      json_obj->set("type_data", node_to_json_brief(TREE_TYPE (t), di));
> +
> +      if (TREE_CODE (t) == METHOD_TYPE)
> +        {
> +          json_obj->set_bool("method_type", true);
> +          if (TYPE_METHOD_BASETYPE (t))
> +            json_obj->set("basetype", node_to_json_brief (TYPE_NAME 
> (TYPE_METHOD_BASETYPE(t)), di));
> +          else
> +            json_obj->set_string("basetype", "null method basetype");
> +        }
> +      if (TYPE_IDENTIFIER (t))
> +        json_obj->set("type_identifier", node_to_json_brief (TYPE_NAME(t), 
> di));
> +      else if ( TYPE_NAME (t) && DECL_NAME (TYPE_NAME (t)) )
> +        decl_node_add_json( TYPE_NAME(t), json_obj);
> +      else //TDF_NOUID
> +        {
> +          char* buff;
> +          buff = new char ();
> +          print_hex(TYPE_UID(t), buff);
> +         json_obj->set_string("uid", buff);
> +        }
> +      json_obj->set("function_decl", function_decl_emit_json(t, di));
> +      break;
> +
> +
> +    case FUNCTION_DECL:
> +    case CONST_DECL:
> +      decl_node_add_json(t, json_obj);
> +      break;
> +    case LABEL_DECL:
> +      if (DECL_NAME (t))
> +        decl_node_add_json(t, json_obj);
> +      else if (LABEL_DECL_UID (t) != -1)
> +        json_obj->set_integer("LabelDeclUID", LABEL_DECL_UID (t));
> +      else
> +        json_obj->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, json_obj);
> +      else if (TYPE_NAME (TREE_TYPE (t)) != t)
> +        {
> +          json_obj->set(TREE_CODE (TREE_TYPE (t)) == UNION_TYPE ? "union"
> +                                                             : "struct",
> +                     node_to_json_brief( TREE_TYPE (t), di));
> +        }
> +      else
> +        json_obj->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, json_obj);
> +      break;
> +
> +    case RESULT_DECL:
> +      json_obj->set_bool("retval", true);
> +      break;
> +
> +    case COMPONENT_REF:
> +      op0 = TREE_OPERAND (t, 0);
> +      op1 = TREE_OPERAND (t, 1);
> +      //Check if the following is okay later
> +      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);
> +        }
> +      json_obj->set("expr", node_to_json_brief(op0, di));
> +      json_obj->set("field", node_to_json_brief(op1, di));
> +      if (DECL_P (op1))
> +        if (tree off = component_ref_field_offset(t))
> +          if (TREE_CODE (off) != INTEGER_CST)
> +            {
> +              json_obj->set("offset", node_to_json_brief(off, di));
> +            }
> +    break;
> +
> +    case BIT_FIELD_REF:
> +      json_obj->set_string("tree_code", "bit_field_ref");
> +      json_obj->set("expr",
> +                 node_to_json_brief( TREE_OPERAND (t, 0), di));
> +      json_obj->set("bits_ref",
> +                 node_to_json_brief( TREE_OPERAND (t, 1), di));
> +      json_obj->set("bits_first_pos",
> +                 node_to_json_brief( TREE_OPERAND (t, 2), di));
> +      break;
> +
> +    case BIT_INSERT_EXPR:
> +      json_obj->set_string("tree_code", "bit_insert_expr");
> +      json_obj->set("container",
> +                 node_to_json_brief( TREE_OPERAND (t, 0), di));
> +      json_obj->set("replacement",
> +                 node_to_json_brief( TREE_OPERAND (t, 1), di));
> +      json_obj->set("constant_bit_pos",
> +                 node_to_json_brief( TREE_OPERAND (t, 2), di));
> +      break;
> +
> +    case ARRAY_REF:
> +    case ARRAY_RANGE_REF:
> +      op0 = TREE_OPERAND (t, 0);
> +      json_obj->set("array",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("index",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      if (TREE_OPERAND(t, 2))
> +        json_obj->set("type_min_val",
> +                   node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      if (TREE_OPERAND(t, 3))
> +        json_obj->set("element_size",
> +                   node_to_json_brief (TREE_OPERAND (t, 3), di));
> +      break;
> +
> +    case OMP_ARRAY_SECTION:
> +      json_obj->set("op0",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("op1",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      json_obj->set("op2",
> +                 node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      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:
> +              json_obj->set_string("CLOBBER", "storage_begin");
> +              break;
> +            case CLOBBER_STORAGE_END:
> +              json_obj->set_bool("CLOBBER", "storage_end");
> +              break;
> +            case CLOBBER_OBJECT_BEGIN:
> +              json_obj->set_bool("CLOBBER", "object_begin");
> +              break;
> +            case CLOBBER_OBJECT_END:
> +              json_obj->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)
> +          {
> +            auto cst_elt = ::make_unique<json::object> ();
> +            auto _val_json = ::make_unique<json::object> ();
> +            cst_elt->set_integer("cst_elt_index", ix);
> +            if (field)
> +              {
> +                if (is_struct_init)
> +                  cst_elt->set("field", node_to_json_brief(field, di));
> +                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_to_json_brief( 
> TREE_OPERAND( field, 0), di));
> +                        _array_init_json->append( node_to_json_brief( 
> TREE_OPERAND( field, 1), di));
> +                        cst_elt->set("field", _array_init_json);
> +                        delete _array_init_json;
> +                      }
> +                    else
> +                      cst_elt->set ("field", node_to_json_brief (field, di));
> +                  }
> +              }
> +            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)
> +              {
> +                decl_node_add_json (val, _val_json);
> +                cst_elt->set("val", _val_json.get());
> +              }
> +            else
> +              cst_elt->set("val", node_to_json_brief(val, di));
> +
> +            if (TREE_CODE (field) == INTEGER_CST)
> +              curidx = wi::to_widest (field);
> +            holder->append(cst_elt.get());
> +          }
> +        json_obj->set("ctor_elts", holder);
> +      }
> +    break;
> +
> +   case COMPOUND_EXPR:
> +     {
> +        tree *tp;
> +        holder->append( node_to_json_brief( TREE_OPERAND (t, 0), di));
> +
> +        for (tp = &TREE_OPERAND (t, 1);
> +             TREE_CODE (*tp) == COMPOUND_EXPR;
> +             tp = &TREE_OPERAND (*tp, 1))
> +          {
> +          holder->append( node_to_json_brief ( TREE_OPERAND (*tp, 0), di));
> +          }
> +
> +        json_obj->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_to_json_brief (tsi_stmt (si), di));
> +          }
> +        json_obj->set("statement_list", holder);
> +      }
> +      break;
> +
> +    case MODIFY_EXPR:
> +    case INIT_EXPR:
> +      json_obj->set("op0",
> +                 node_to_json_brief( TREE_OPERAND (t, 0), di));
> +      json_obj->set("op1",
> +                 node_to_json_brief( TREE_OPERAND (t, 1), di));
> +      break;
> +
> +    case TARGET_EXPR:
> +      json_obj->set("slot", node_to_json_brief (TARGET_EXPR_SLOT(t), di));
> +      json_obj->set("initial", node_to_json_brief (TARGET_EXPR_INITIAL(t), 
> di));
> +      break;
> +
> +    case DECL_EXPR:
> +      decl_node_add_json(DECL_EXPR_DECL(t), json_obj);
> +      break;
> +
> +    case COND_EXPR:
> +      json_obj->set("if",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      if (COND_EXPR_THEN(t))
> +      {
> +        json_obj->set("then",
> +                   node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      }
> +      if (COND_EXPR_ELSE(t))
> +      {
> +        json_obj->set("else",
> +                 node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      }
> +      break;
> +
> +    case BIND_EXPR:
> +      if (BIND_EXPR_VARS (t))
> +        {
> +          for (op0 = BIND_EXPR_VARS (t); op0; op0 = DECL_CHAIN (op0))
> +            {
> +              holder->append(node_to_json_brief (op0, di));
> +            }
> +          json_obj->set("bind_expr_vars", holder);
> +        }
> +      json_obj->set("bind_expr_body",
> +                 node_to_json_brief(BIND_EXPR_BODY(t), di));
> +      break;
> +
> +    case CALL_EXPR:
> +      {
> +        if (CALL_EXPR_FN (t) != NULL_TREE)
> +          call_name_add_json (CALL_EXPR_FN(t), json_obj, di);
> +        else
> +          json_obj->set_string("internal_fn", internal_fn_name 
> (CALL_EXPR_IFN (t)));
> +        json_obj->set_bool("return_slot_optimization", 
> CALL_EXPR_RETURN_SLOT_OPT(t));
> +        json_obj->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_to_json_brief(arg, di));
> +          }
> +        if (call)
> +          json_obj->set("call_expr_arg", holder);
> +
> +        if (CALL_EXPR_VA_ARG_PACK (t))
> +          json_obj->set_bool("__builtin_va_arg_pack", true);
> +
> +        op1 = CALL_EXPR_STATIC_CHAIN (t);
> +        if (op1)
> +          json_obj->set("static_chain", node_to_json_brief(op1, di));
> +      }
> +      break;
> +    case WITH_CLEANUP_EXPR:
> +      break;
> +    case CLEANUP_POINT_EXPR:
> +      json_obj->set("cleanup_point", node_to_json_brief (TREE_OPERAND(t, 0), 
> di));
> +      break;
> +    case PLACEHOLDER_EXPR:
> +      json_obj->set("placeholder_expr", node_to_json_brief (TREE_OPERAND(t, 
> 0), di));
> +      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);
> +
> +        json_obj->set_string("bin_operator", c);
> +        holder->append(node_to_json_brief(op0, di));
> +        holder->append(node_to_json_brief(op1, di));
> +        json_obj->set("operands", holder);
> +      }
> +      break;
> +
> +    case ADDR_EXPR:
> +      //TDF_GIMPLE_VAL
> +      json_obj->set("_Literal", node_to_json_brief( TREE_TYPE (t), di));
> +      /* 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);
> +        json_obj->set(c, node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      }
> +      break;
> +
> +    case MIN_EXPR:
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,0), di));
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,1), di));
> +      json_obj->set("min_expr", holder);
> +      break;
> +
> +    case MAX_EXPR:
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,0), di));
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,1), di));
> +      json_obj->set("max_expr", holder);
> +      break;
> +
> +    case ABS_EXPR:
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,0), di));
> +      json_obj->set("abs_expr", holder);
> +      break;
> +
> +    case ABSU_EXPR:
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,0), di));
> +      json_obj->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))
> +        {
> +          json_obj->set ("type", node_to_json_brief (type, di));
> +        }
> +      json_obj->set ("operand", node_to_json_brief (op0, di));
> +      break;
> +
> +    case VIEW_CONVERT_EXPR:
> +      holder->append (node_to_json_brief (TREE_TYPE(t), di));
> +      holder->append (node_to_json_brief (TREE_OPERAND(t, 0), di));
> +      json_obj->set("view_convert_expr", holder);
> +      break;
> +
> +    case PAREN_EXPR:
> +      json_obj->set("paren_expr",
> +                 node_to_json_brief (TREE_OPERAND (t,0), di));
> +      break;
> +
> +    case NON_LVALUE_EXPR:
> +      json_obj->set("non_lvalue_expr",
> +                 node_to_json_brief (TREE_OPERAND (t,0), di));
> +      break;
> +
> +    case SAVE_EXPR:
> +      json_obj->set("save_expr",
> +                 node_to_json_brief (TREE_OPERAND (t,0), di));
> +      break;
> +
> +    case COMPLEX_EXPR:
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,0), di));
> +      holder->append (node_to_json_brief (TREE_OPERAND (t,1), di));
> +      json_obj->set("complex_expr", holder);
> +      break;
> +
> +    case CONJ_EXPR:
> +      json_obj->set("conj_expr",
> +                 node_to_json_brief (TREE_OPERAND (t,0), di));
> +      break;
> +
> +    case REALPART_EXPR:
> +      json_obj->set("realpart_expr",
> +                 node_to_json_brief (TREE_OPERAND (t,0), di));
> +      break;
> +
> +    case IMAGPART_EXPR:
> +      json_obj->set("imagpart_expr",
> +                 node_to_json_brief (TREE_OPERAND (t,0), di));
> +      break;
> +
> +    case VA_ARG_EXPR:
> +      json_obj->set("va_arg_expr",
> +                 node_to_json_brief (TREE_OPERAND (t,0), di));
> +      break;
> +
> +    case TRY_FINALLY_EXPR:
> +    case TRY_CATCH_EXPR:
> +      {
> +        tree _t;
> +        json_obj->set("try",
> +                   node_to_json_brief (TREE_OPERAND (t, 0), di));
> +        if (TREE_CODE (t) == TRY_CATCH_EXPR)
> +          {
> +            _t = TREE_OPERAND(t, 1);
> +            json_obj->set("catch",
> +                        node_to_json_brief (_t, di));
> +          }
> +        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);
> +                json_obj->set("finally",
> +                           node_to_json_brief (_t, di));
> +                _t = TREE_OPERAND(_t, 1);
> +                json_obj->set("else",
> +                           node_to_json_brief (_t, di));
> +              }
> +            else
> +              {
> +              json_obj->set("finally",
> +                         node_to_json_brief(_t, di));
> +              }
> +          }
> +      }
> +      break;
> +
> +    case CATCH_EXPR:
> +      json_obj->set("catch_types", node_to_json_brief(CATCH_TYPES(t), di));
> +      json_obj->set("catch_body", node_to_json_brief(CATCH_BODY(t), di));
> +      break;
> +
> +    case EH_FILTER_EXPR:
> +      json_obj->set("eh_filter_types", 
> node_to_json_brief(EH_FILTER_TYPES(t), di));
> +      json_obj->set("eh_filter_failure", 
> node_to_json_brief(EH_FILTER_FAILURE(t), di));
> +      break;
> +
> +    case LABEL_EXPR:
> +      decl_node_add_json (TREE_OPERAND (t, 0), json_obj);
> +      break;
> +
> +    case LOOP_EXPR:
> +      json_obj->set("while (1)", node_to_json_brief (LOOP_EXPR_BODY (t), 
> di));
> +      break;
> +
> +    case PREDICT_EXPR:
> +      if (PREDICT_EXPR_OUTCOME (t))
> +        json_obj->set_string("likely by",
> +                          predictor_name (PREDICT_EXPR_PREDICTOR (t)));
> +      else
> +        json_obj->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)))
> +        {
> +          case annot_expr_ivdep_kind:
> +            json_obj->set("ivdep", node_to_json_brief(TREE_OPERAND (t, 0), 
> di));
> +            break;
> +          case annot_expr_unroll_kind:
> +            json_obj->set("unroll", node_to_json_brief(TREE_OPERAND (t, 0), 
> di));
> +            break;
> +          case annot_expr_no_vector_kind:
> +            json_obj->set("no-vector", node_to_json_brief(TREE_OPERAND (t, 
> 0), di));
> +            break;
> +          case annot_expr_vector_kind:
> +            json_obj->set("vector", node_to_json_brief(TREE_OPERAND (t, 0), 
> di));
> +            break;
> +          case annot_expr_parallel_kind:
> +            json_obj->set("parallel", node_to_json_brief(TREE_OPERAND (t, 
> 0), di));
> +            break;
> +          case annot_expr_maybe_infinite_kind:
> +            json_obj->set("maybe_infinite", node_to_json_brief(TREE_OPERAND 
> (t, 0), di));
> +            break;
> +          default:
> +            gcc_unreachable();
> +        }
> +      }
> +      break;
> +
> +    case RETURN_EXPR:
> +      {
> +        op0 = TREE_OPERAND (t, 0);
> +        if (op0)
> +          {
> +            if (TREE_CODE (op0) == MODIFY_EXPR)
> +              json_obj->set("return_expr", node_to_json_brief (TREE_OPERAND 
> (op0, 1), di));
> +            else
> +              json_obj->set("return_expr", node_to_json_brief (op0, di));
> +          }
> +      }
> +      break;
> +
> +    case EXIT_EXPR:
> +      json_obj->set("exit_if", node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case SWITCH_EXPR:
> +      json_obj->set("switch_cond", node_to_json_brief(SWITCH_COND(t), di));
> +      json_obj->set("switch_body", node_to_json_brief(SWITCH_BODY(t), di));
> +      break;
> +
> +    case GOTO_EXPR:
> +      op0 = GOTO_DESTINATION (t);
> +      json_obj->set("goto", node_to_json_brief(op0, di));
> +      break;
> +
> +    case ASM_EXPR:
> +      json_obj->set("asm_string", node_to_json_brief (ASM_STRING (t), di));
> +      json_obj->set("asm_outputs", node_to_json_brief (ASM_OUTPUTS (t), di));
> +      json_obj->set("asm_inputs", node_to_json_brief (ASM_INPUTS (t), di));
> +      if (ASM_CLOBBERS (t))
> +        json_obj->set("asm_clobbers", node_to_json_brief (ASM_CLOBBERS (t), 
> di));
> +      break;
> +
> +    case CASE_LABEL_EXPR:
> +      if (CASE_LOW(t) && CASE_HIGH(t))
> +        {
> +          json_obj->set ("case_low", node_to_json_brief (CASE_LOW(t), di));
> +          json_obj->set ("case_high", node_to_json_brief (CASE_HIGH(t), di));
> +        }
> +      else if (CASE_LOW(t))
> +        json_obj->set ("case", node_to_json_brief (CASE_LOW(t), di));
> +      else
> +        json_obj->set_string("case", "default");
> +      break;
> +
> +    case OBJ_TYPE_REF:
> +      json_obj->set("obj_type_ref_expr",
> +                 node_to_json_brief(OBJ_TYPE_REF_EXPR(t), di));
> +      json_obj->set("obj_type_ref_object",
> +                 node_to_json_brief(OBJ_TYPE_REF_OBJECT(t), di));
> +      json_obj->set("obj_type_ref_token",
> +                 node_to_json_brief(OBJ_TYPE_REF_TOKEN(t), di));
> +      break;
> +
> +    case SSA_NAME:
> +      {
> +      if (SSA_NAME_IDENTIFIER (t))
> +        json_obj->set("ssa_name_identifier",
> +                   node_to_json_brief (SSA_NAME_IDENTIFIER (t), di));
> +      if (SSA_NAME_IS_DEFAULT_DEF (t))
> +        json_obj->set_bool("ssa_default_def", true);
> +      if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (t))
> +       json_obj->set_bool("abnormal_phi", true);
> +      }
> +      break;
> +
> +    case WITH_SIZE_EXPR:
> +      json_obj->set("expr", node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("size", node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      break;
> +
> +    case SCEV_KNOWN:
> +    case SCEV_NOT_KNOWN:
> +      break;
> +
> +    case POLYNOMIAL_CHREC:
> +      json_obj->set_integer("chrec_var", CHREC_VARIABLE(t));
> +      json_obj->set("chrec_left", node_to_json_brief (CHREC_LEFT(t), di));
> +      json_obj->set("chrec_right", node_to_json_brief (CHREC_RIGHT(t), di));
> +      json_obj->set_bool("chrec_nowrap", CHREC_NOWRAP(t));
> +      break;
> +
> +    case REALIGN_LOAD_EXPR:
> +      json_obj->set("input_0", node_to_json_brief(TREE_OPERAND (t, 0), di));
> +      json_obj->set("input_1", node_to_json_brief(TREE_OPERAND (t, 1), di));
> +      json_obj->set("offset", node_to_json_brief(TREE_OPERAND (t, 2), di));
> +      break;
> +
> +    case VEC_COND_EXPR:
> +      json_obj->set("if",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("then",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      json_obj->set("else",
> +                 node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      break;
> +
> +    case VEC_PERM_EXPR:
> +      json_obj->set("v0",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("v1",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      json_obj->set("mask",
> +                 node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      break;
> +
> +    case DOT_PROD_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("arg2",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      json_obj->set("arg3",
> +                 node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      break;
> +
> +    case WIDEN_MULT_PLUS_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("arg2",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      json_obj->set("arg3",
> +                 node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      break;
> +
> +    case WIDEN_MULT_MINUS_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("arg2",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      json_obj->set("arg3",
> +                 node_to_json_brief (TREE_OPERAND (t, 2), di));
> +      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:
> +      json_obj->set ("arg1",
> +                  node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set ("arg2",
> +                  node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      break;
> +
> +    case VEC_DUPLICATE_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case VEC_UNPACK_HI_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case VEC_UNPACK_LO_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case VEC_UNPACK_FLOAT_HI_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case VEC_UNPACK_FLOAT_LO_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      break;
> +
> +    case VEC_PACK_TRUNC_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("arg2",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      break;
> +
> +    case VEC_PACK_SAT_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("arg2",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      break;
> +
> +    case VEC_PACK_FIX_TRUNC_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("arg2",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      break;
> +
> +    case VEC_PACK_FLOAT_EXPR:
> +      json_obj->set("arg1",
> +                 node_to_json_brief (TREE_OPERAND (t, 0), di));
> +      json_obj->set("arg2",
> +                 node_to_json_brief (TREE_OPERAND (t, 1), di));
> +      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:
> +      json_obj->set("oacc_host_data_clauses",
> +                 omp_clause_emit_json (OACC_HOST_DATA_CLAUSES(t), di));
> +      json_obj->set("oacc_host_data_body",
> +                 omp_clause_emit_json (OACC_HOST_DATA_BODY(t), di));
> +      break;
> +
> +    case OACC_DECLARE:
> +      json_obj->set("oacc_declare_clauses",
> +                 omp_clause_emit_json (OACC_DECLARE_CLAUSES(t), di));
> +      break;
> +
> +    case OACC_UPDATE:
> +      json_obj->set("oacc_update_clauses",
> +                 omp_clause_emit_json (OACC_UPDATE_CLAUSES(t), di));
> +      break;
> +
> +    case OACC_ENTER_DATA:
> +      json_obj->set("oacc_enter_data_clauses",
> +                 omp_clause_emit_json (OACC_ENTER_DATA_CLAUSES(t), di));
> +      break;
> +
> +    case OACC_EXIT_DATA:
> +      json_obj->set("oacc_exit_data_clauses",
> +                 omp_clause_emit_json (OACC_EXIT_DATA_CLAUSES(t), di));
> +      break;
> +
> +    case OACC_CACHE:
> +      json_obj->set("oacc_cache_clauses",
> +                 omp_clause_emit_json (OACC_CACHE_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_PARALLEL:
> +      json_obj->set("omp_parallel_body",
> +                 node_emit_json (OMP_PARALLEL_BODY(t), di));
> +      json_obj->set("omp_parallel_clauses",
> +                 omp_clause_emit_json (OMP_PARALLEL_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_TASK:
> +      {
> +      if (OMP_TASK_BODY (t))
> +        {
> +          json_obj->set_bool("omp_task", true);
> +          json_obj->set("omp_task_body",
> +                     node_emit_json(OMP_TASK_BODY (t), di));
> +          json_obj->set("omp_task_clauses",
> +                     omp_clause_emit_json (OMP_TASK_CLAUSES(t), di));
> +        } else {
> +          json_obj->set_bool("omp_taskwait", true);
> +          json_obj->set("omp_taskwait_clauses",
> +                     omp_clause_emit_json (OMP_TASK_CLAUSES(t), di));
> +        }
> +        break;
> +      }
> +
> +    dump_omp_clauses_body:
> +      json_obj->set("omp_clauses", omp_clause_emit_json (OMP_CLAUSES (t), 
> di));
> +      goto dump_omp_body;
> +
> +    dump_omp_body:
> +      json_obj->set("omp_body", node_emit_json (OMP_BODY(t), di));
> +      json_obj->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:
> +      json_obj->set("omp_for_body",
> +                 node_emit_json(OMP_FOR_BODY (t), di));
> +      json_obj->set("omp_for_clauses",
> +                 omp_clause_emit_json (OMP_FOR_CLAUSES(t), di));
> +      json_obj->set("omp_for_init",
> +                 node_emit_json(OMP_FOR_INIT (t), di));
> +      json_obj->set("omp_for_incr",
> +                 node_emit_json(OMP_FOR_INCR (t), di));
> +      json_obj->set("omp_for_pre_body",
> +                 node_emit_json(OMP_FOR_PRE_BODY (t), di));
> +      json_obj->set("omp_for_orig_decls",
> +                 node_emit_json(OMP_FOR_ORIG_DECLS (t), di));
> +      break;
> +
> +    case OMP_TEAMS:
> +      json_obj->set("omp_teams_body",
> +                 omp_clause_emit_json (OMP_TEAMS_BODY(t), di));
> +      json_obj->set("omp_teams_clauses",
> +                 omp_clause_emit_json (OMP_TEAMS_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_TARGET_DATA:
> +      json_obj->set("omp_target_data_body",
> +                 omp_clause_emit_json (OMP_TARGET_DATA_BODY(t), di));
> +      json_obj->set("omp_target_data_clauses",
> +                 omp_clause_emit_json (OMP_TARGET_DATA_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_TARGET_ENTER_DATA:
> +      json_obj->set("omp_target_enter_data_clauses",
> +                 omp_clause_emit_json (OMP_TARGET_ENTER_DATA_CLAUSES(t), 
> di));
> +      break;
> +
> +    case OMP_TARGET_EXIT_DATA:
> +      json_obj->set("omp_target_exit_data_clauses",
> +                 omp_clause_emit_json (OMP_TARGET_EXIT_DATA_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_TARGET:
> +      json_obj->set("omp_target_body",
> +                 omp_clause_emit_json (OMP_TARGET_BODY(t), di));
> +      json_obj->set("omp_target_clauses",
> +                 omp_clause_emit_json (OMP_TARGET_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_TARGET_UPDATE:
> +      json_obj->set("omp_target_update_clauses",
> +                 omp_clause_emit_json (OMP_TARGET_UPDATE_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_SECTIONS:
> +      json_obj->set("omp_sections_body",
> +                 omp_clause_emit_json (OMP_SECTIONS_BODY(t), di));
> +      json_obj->set("omp_sections_clauses",
> +                 omp_clause_emit_json (OMP_SECTIONS_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_SECTION:
> +      json_obj->set("omp_section_body",
> +                 omp_clause_emit_json (OMP_SECTION_BODY(t), di));
> +      break;
> +
> +    case OMP_STRUCTURED_BLOCK:
> +      json_obj->set("omp_structured_block_body",
> +                 omp_clause_emit_json (OMP_STRUCTURED_BLOCK_BODY(t), di));
> +      break;
> +
> +    case OMP_SCAN:
> +      json_obj->set("omp_scan_body",
> +                 omp_clause_emit_json (OMP_SCAN_BODY(t), di));
> +      json_obj->set("omp_scan_clauses",
> +                 omp_clause_emit_json (OMP_SCAN_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_MASTER:
> +      json_obj->set("omp_master_body",
> +                 omp_clause_emit_json (OMP_MASTER_BODY(t), di));
> +      break;
> +
> +    case OMP_MASKED:
> +      json_obj->set("omp_masked_body",
> +                 omp_clause_emit_json (OMP_MASKED_BODY(t), di));
> +      json_obj->set("omp_masked_clauses",
> +                 omp_clause_emit_json (OMP_MASKED_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_TASKGROUP:
> +      json_obj->set("omp_taskgroup_body",
> +                 omp_clause_emit_json (OMP_TASKGROUP_BODY(t), di));
> +      json_obj->set("omp_taskgroup_clauses",
> +                 omp_clause_emit_json (OMP_TASKGROUP_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_ORDERED:
> +      json_obj->set("omp_ordered_body",
> +                 omp_clause_emit_json (OMP_ORDERED_BODY(t), di));
> +      json_obj->set("omp_ordered_clauses",
> +                 omp_clause_emit_json (OMP_ORDERED_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_CRITICAL:
> +      json_obj->set("omp_masked_body",
> +                 omp_clause_emit_json (OMP_CRITICAL_BODY(t), di));
> +      json_obj->set("omp_masked_clauses",
> +                 omp_clause_emit_json (OMP_CRITICAL_CLAUSES(t), di));
> +      json_obj->set("omp_masked_name",
> +                 node_emit_json (OMP_CRITICAL_NAME(t), di));
> +      break;
> +
> +    case OMP_ATOMIC:
> +      if (OMP_ATOMIC_WEAK (t))
> +        json_obj->set_bool("omp_atomic_weak", true);
> +      else
> +        json_obj->set_bool("omp_atomic_weak", false);
> +      json_obj->set("omp_atomic_memory_order",
> +                 omp_atomic_memory_order_emit_json 
> (OMP_ATOMIC_MEMORY_ORDER(t)));
> +      json_obj->set("op0",
> +                 node_emit_json (TREE_OPERAND(t, 0), di));
> +      json_obj->set("op1",
> +                 node_emit_json (TREE_OPERAND(t, 1), di));
> +      break;
> +
> +    case OMP_ATOMIC_READ:
> +      json_obj->set("omp_atomic_memory_order",
> +                 omp_atomic_memory_order_emit_json 
> (OMP_ATOMIC_MEMORY_ORDER(t)));
> +      json_obj->set("op0",
> +                 node_emit_json (TREE_OPERAND(t, 0), di));
> +      break;
> +
> +    case OMP_ATOMIC_CAPTURE_OLD:
> +    case OMP_ATOMIC_CAPTURE_NEW:
> +      if (OMP_ATOMIC_WEAK (t))
> +        json_obj->set_bool("omp_atomic_capture_weak", true);
> +      else
> +        json_obj->set_bool("omp_atomic_capture", true);
> +      json_obj->set("omp_atomic_memory_order",
> +                 omp_atomic_memory_order_emit_json 
> (OMP_ATOMIC_MEMORY_ORDER(t)));
> +      json_obj->set("op0",
> +                 node_emit_json (TREE_OPERAND(t, 0), di));
> +      json_obj->set("op1",
> +                 node_emit_json (TREE_OPERAND(t, 1), di));
> +      break;
> +
> +    case OMP_SINGLE:
> +      json_obj->set("omp_single_body",
> +                 omp_clause_emit_json (OMP_SINGLE_BODY(t), di));
> +      json_obj->set("omp_single_clauses",
> +                 omp_clause_emit_json (OMP_SINGLE_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_SCOPE:
> +      json_obj->set("omp_scope_body",
> +                 omp_clause_emit_json (OMP_SCOPE_BODY(t), di));
> +      json_obj->set("omp_scope_clauses",
> +                 omp_clause_emit_json (OMP_SCOPE_CLAUSES(t), di));
> +      break;
> +
> +    case OMP_CLAUSE:
> +      json_obj->set("omp_clause",
> +                 omp_clause_emit_json(t, di));
> +      break;
> +
> +    case TRANSACTION_EXPR:
> +      if (TRANSACTION_EXPR_OUTER (t))
> +       json_obj->set_bool ("transaction_expr_outer", true);
> +      if (TRANSACTION_EXPR_RELAXED (t))
> +       json_obj->set_bool ("transaction_expr_relaxed", true);
> +      json_obj->set("omp_transaction_body",
> +                 node_emit_json (TRANSACTION_EXPR_BODY(t), di));
> +      break;
> +
> +    case BLOCK:
> +      {
> +      tree iter;
> +      json::array *subblock, *chain, *vars, *fragment_chain, *nlv_holder;
> +      json_obj->set_integer ("block #", BLOCK_NUMBER (t));
> +      if (BLOCK_SUPERCONTEXT (t))
> +        json_obj->set("block_supercontext",
> +                   node_emit_json(BLOCK_SUPERCONTEXT (t), di));
> +      if (BLOCK_SUBBLOCKS(t))
> +        {
> +          subblock = new json::array ();
> +          for (iter = BLOCK_SUBBLOCKS (t); iter; iter = BLOCK_CHAIN (t))
> +            subblock->append(node_emit_json(iter, di));
> +          json_obj->set("block_subblocks", subblock);
> +          delete 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, di));
> +          json_obj->set("block_chain", chain);
> +          delete 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, di));
> +          json_obj->set("block_vars", vars);
> +          delete 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, di));
> +            }
> +          json_obj->set("block_nonlocalized_vars", nlv_holder);
> +          delete nlv_holder;
> +        }
> +      if (BLOCK_ABSTRACT_ORIGIN (t))
> +        json_obj->set("block_abstract_origin",
> +                   node_emit_json (BLOCK_ABSTRACT_ORIGIN (t), di));
> +      if (BLOCK_FRAGMENT_ORIGIN (t))
> +        json_obj->set("block_fragment_origin",
> +                   node_emit_json (BLOCK_FRAGMENT_ORIGIN (t), di));
> +
> +      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, di));
> +          json_obj->set("block_fragment_chain", fragment_chain);
> +        }
> +      }
> +      break;
> +
> +    case DEBUG_BEGIN_STMT:
> +      json_obj->set_bool("debug_begin", true);
> +      break;
> +    default:
> +      json_obj->set_bool("unsupported code", true);
> +      json_obj->set_string("fallthrough", get_tree_code_name(code));
> +      break;
> +  }
> +  return json_obj;
> +}
> +
> +/* Same as node_emit_json, but we also have the location info at end. */
> +
> +std::unique_ptr<json::object>
> +node_emit_json_loc (tree t, dump_info_p di)
> +{
> +  expanded_location xloc;
> +  enum tree_code code;
> +
> +  code = TREE_CODE(t);
> +  std::unique_ptr<json::object> json_obj = node_emit_json(t, di);
> +
> +  if (TREE_CODE_CLASS (code) == tcc_declaration
> +      && code != TRANSLATION_UNIT_DECL)
> +    {
> +      xloc = expand_location (DECL_SOURCE_LOCATION (t));
> +      json_obj->set("decl_loc", loc_emit_json(xloc));
> +    }
> +  if (EXPR_HAS_LOCATION(t))
> +    {
> +      xloc = expand_location (EXPR_LOCATION (t));
> +      json_obj->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);
> +        json_obj->set("start_loc", loc_emit_json(xloc));
> +      } else {
> +        json_obj->set_string("start_loc", "unknown");
> +      }
> +      if (r.m_finish)
> +      {
> +        xloc = expand_location (r.m_finish);
> +        json_obj->set("finish_loc", loc_emit_json(xloc));
> +      } else {
> +        json_obj->set_string("finish_loc", "unknown");
> +      }
> +    }
> +  return json_obj;
> +}
> +
> +/* Dump the next node in the queue.  */
> +
> +static void
> +dequeue_and_dump (dump_info_p di)
> +{
> +  dump_queue_p dq;
> +  splay_tree_node stn;
> +  tree t;
> +
> +  /* Get the next node from the queue.  */
> +  dq = di->queue;
> +  stn = dq->node;
> +  t = (tree) stn->key;
> +
> +  /* 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;
> +
> +  /* Convert the node to JSON and store it to be dumped later. */
> +
> +  if (di->flags & TDF_LINENO)
> +    {
> +      auto dummy = node_emit_json_loc(t, di).release();
> +      di->json_dump->append(dummy);
> +    } else {
> +      auto dummy = node_emit_json(t, di).release();
> +      di->json_dump->append(dummy);
> +    }
> +}
> +
> +/* Dump T, and all its children, on STREAM as JSON array. */
> +
> +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.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);
> +  delete di.json_dump;
> +}
> +
> +/* c.f. debug_tree(). Logic is same as the above fucntion. */
> +
> +DEBUG_FUNCTION void
> +debug_dump_node_json (tree t, FILE *stream)
> +{
> +  dump_info di;
> +
> +  di.stream = stream;
> +  di.queue = 0;
> +  di.queue_end = 0;
> +  di.free_list = 0;
> +  di.flags = TDF_LINENO;
> +  di.node = t;
> +  di.nodes = splay_tree_new (splay_tree_compare_pointers, 0,
> +                            splay_tree_delete_pointers);
> +  di.json_dump = new json::array ();
> +
> +  queue (&di, t);
> +
> +  while (di.queue)
> +    dequeue_and_dump (&di);
> +
> +  di.json_dump->dump(stream, true);
> +
> +  splay_tree_delete (di.nodes);
> +  delete di.json_dump;
> +}
> diff --git a/gcc/tree-emit-json.h b/gcc/tree-emit-json.h
> new file mode 100644
> index 00000000000..bd86c059936
> --- /dev/null
> +++ b/gcc/tree-emit-json.h
> @@ -0,0 +1,73 @@
> +/* 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
> +{} *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.  */
> +  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 std::unique_ptr<json::object> node_emit_json(tree t, dump_info_p di);
> +extern void dump_node_json (const_tree t, dump_flags_t flags, FILE *stream);
> +#endif /* ! GCC_TREE_JSON_H */
> --
> 2.34.1
>

Attachment: p
Description: Binary data

Reply via email to