public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH,RFC,V3 4/5] CTF generation for a single compilation unit
  2019-06-27  6:37 [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 3/5] Setup for CTF generation and emission Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 5/5] Update CTF testsuite Indu Bhagat
@ 2019-06-27  6:37 ` Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 1/5] Add new function lang_GNU_GIMPLE Indu Bhagat
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-06-27  6:37 UTC (permalink / raw)
  To: gcc-patches, richard.guenther

For each translation unit, a CTF container (ctf_container_t) is used to
keep the CTF debug info.

- ctfout.c hosts the compiler facing routines for CTF generation and emission.
- ctfcreate.c contains the CTF format specific CTF creation routines.
- ctfutils.c contains helper routines for CTF creation.

gcc/ChangeLog :
 
	* Makefile.in: Add new object files.
	* ctfcreate.c: New file.
	* ctfout.c (ctf_dtu_d_union_selector): New helper function for garbage
	collection of dtd_u union in ctf_dtdef_t.
	(ctf_dtdef_hash::hash): New function to generate hashkey for a CTF Type
	record.
	(hash_dtd_tree_decl): New function.
	(ctf_dtdef_hash::equal): Likewise.
	(is_ctf_base_type): Likewise.
	(get_cvr_quals_for_type): Likewise.
	(get_type_name_string): Likewise.
	(get_decl_name_string): Likewise.
	(ctf_type_exists): Likewise.
	(init_ctf_string_table): Likewise.
	(new_ctf_container): Allocate contents of CTF container.
	(delete_ctf_container): Cleanup contents of CTF container.
	(init_ctf_sections): Prepare for LTO.
	(gen_ctf_base_type): New function.
	(gen_ctf_pointer_type): Likewise.
	(gen_ctf_array_type): Likewise.
	(gen_ctf_forward_type): Likewise.
	(gen_ctf_enum_const_list): Likewise.
	(gen_ctf_enum_type): Likewise.
	(gen_ctf_function_type): Likewise.
	(gen_ctf_cvrquals): Likewise.
	(gen_ctf_sou_type): Likewise.
	(gen_ctf_typedef): Likewise.
	(gen_ctf_variable): Likewise.
	(gen_ctf_function): Likewise.
	(gen_ctf_type): Likewise.
	(gen_ctf_bitfield_type_for_decl): Likewise.
	(gen_ctf_type_for_decl): Likewise.
	(ctf_preprocess_var): Likewise.
	(ctf_dvd_preprocess_cb): Likewise.
	(ctf_dtd_preprocess_cb): Likewise.
	(ctf_preprocess): Likewise.
	(ctf_asm_stype): Likewise.
	(ctf_asm_type): Likewise.
	(ctf_asm_slice): Likewise.
	(ctf_asm_array): Likewise.
	(ctf_asm_varent): Likewise.
	(ctf_asm_sou_lmember): Likewise.
	(ctf_asm_sou_member): Likewise.
	(ctf_asm_enum_const): Likewise.
	(output_ctf_header): Output the CTF section if the CTF container is not
	empty.
	(output_ctf_func_info): New function.
	(output_ctf_vars): Likewise.
	(output_ctf_strs): Likewise.
	(output_asm_ctf_sou_fields): Likewise.
	(output_asm_ctf_enum_list): Likewise.
	(output_asm_ctf_vlen_bytes): Likewise.
	(output_asm_ctf_type): Likewise.
	(output_ctf_types): Likewise.
	(ctf_decl): Likewise.
	(ctf_early_finish): Trigger CTF emission.
	(ctf_early_global_decl): Invoke CTF generation function.
	(ctfout_c_finalize): Add cleanup of CTF container.
	* ctfout.h (typedef struct GTY): New Data Structures.
	(struct ctf_dtdef_hash): CTF Type structure hasher.
	* ctfutils.c: New file.

include/ChangeLog :
 
	* ctf.h: Sync with binutils.  Keep ctf_slice_t aligned.

---
 gcc/ChangeLog     |   64 +++
 gcc/Makefile.in   |    2 +
 gcc/ctfcreate.c   |  526 ++++++++++++++++++
 gcc/ctfout.c      | 1582 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gcc/ctfout.h      |  312 ++++++++++-
 gcc/ctfutils.c    |  198 +++++++
 include/ChangeLog |    4 +
 include/ctf.h     |   10 +-
 8 files changed, 2683 insertions(+), 15 deletions(-)
 create mode 100644 gcc/ctfcreate.c
 create mode 100644 gcc/ctfutils.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 8ce2405..1851403 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1255,6 +1255,8 @@ OBJS = \
 	cfgloopmanip.o \
 	cfgrtl.o \
 	ctfout.o \
+	ctfutils.o \
+	ctfcreate.o \
 	symtab.o \
 	cgraph.o \
 	cgraphbuild.o \
diff --git a/gcc/ctfcreate.c b/gcc/ctfcreate.c
new file mode 100644
index 0000000..0ee700f
--- /dev/null
+++ b/gcc/ctfcreate.c
@@ -0,0 +1,526 @@
+/* Functions to create and update CTF from GCC.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+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/>.  */
+
+/* Create CTF types.  The code is mostly adapted from libctf.
+
+   These functions perform the task of adding CTF types to the CTF container.
+   No de-duplication is done by them; the onus is on the calling function to do
+   so.  The caller must first do a lookup via ctf_dtd_lookup or
+   ctf_dvd_lookup, as applicable, to ascertain that the CTF type or the CTF
+   variable respectively does not already exist, and then add it.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "ctfout.h"
+
+void
+ctf_dtd_insert (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
+{
+  ctf_dtdef_ref entry = dtd;
+  bool existed = ctfc->ctfc_types->put (entry, dtd);
+  /* Duplicate CTF type records not expected to be inserted.  And dtd_decl
+     cannot be NULL.  */
+  gcc_assert (dtd->dtd_decl != NULL && !existed);
+}
+
+/* Lookup CTF type given a tree type or decl node.  dtd_key_flags are not
+   necessary for lookup in most cases, because they are needed only for CTF
+   types with no corresponding tree type or decl to begin with.  */
+
+ctf_dtdef_ref
+ctf_dtd_lookup (const ctf_container_ref ctfc, const tree type)
+{
+  return ctf_dtd_lookup_with_flags (ctfc, type, 0);
+}
+
+/* Lookup CTF type given a tree type or decl node and key_flags.  */
+
+ctf_dtdef_ref
+ctf_dtd_lookup_with_flags (const ctf_container_ref ctfc, const tree type,
+			   const unsigned int key_flags)
+{
+  ctf_dtdef_ref * slot;
+
+  ctf_dtdef_t entry;
+  entry.dtd_key.dtdk_key_decl = type;
+  entry.dtd_key.dtdk_key_flags = key_flags;
+
+  slot = ctfc->ctfc_types->get (&entry);
+
+  if (slot)
+    return (ctf_dtdef_ref) (*slot);
+
+  return NULL;
+}
+
+void
+ctf_dvd_insert (ctf_container_ref ctfc, ctf_dvdef_ref dvd)
+{
+  bool existed = ctfc->ctfc_vars->put (dvd->dvd_decl, dvd);
+  /* Duplicate variable records not expected to be inserted.  And dvd_decl
+     cannot be NULL.  */
+  gcc_assert (dvd->dvd_decl != NULL && !existed);
+}
+
+/* Lookup CTF variable given a decl node.  */
+
+ctf_dvdef_ref
+ctf_dvd_lookup (const ctf_container_ref ctfc, const tree decl)
+{
+  ctf_dvdef_ref * slot;
+
+  slot = ctfc->ctfc_vars->get (decl);
+
+  if (slot)
+    return (ctf_dvdef_ref) (*slot);
+
+  return NULL;
+}
+
+static ctf_id_t
+ctf_add_generic (ctf_container_ref ctfc, uint32_t flag, const char * name,
+		 ctf_dtdef_ref * rp, tree treetype, uint32_t key_flags)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  gcc_assert (flag == CTF_ADD_NONROOT || flag == CTF_ADD_ROOT);
+
+  dtd = ggc_cleared_alloc<ctf_dtdef_t> ();
+
+  type = ctfc->ctfc_nextid++;
+  gcc_assert (type < CTF_MAX_TYPE); /* CTF type ID overflow.  */
+
+  /* Buffer the strings in the CTF string table.  */
+  dtd->dtd_name = ctf_add_string (ctfc, name, &(dtd->dtd_data.ctti_name));
+  dtd->dtd_type = type;
+  dtd->dtd_key.dtdk_key_decl = treetype;
+  dtd->dtd_key.dtdk_key_flags = key_flags;
+
+  if ((name != NULL) && strcmp (name, ""))
+    ctfc->ctfc_strlen += strlen (name) + 1;
+
+  ctf_dtd_insert (ctfc, dtd);
+
+  *rp = dtd;
+  return type;
+}
+
+static ctf_id_t
+ctf_add_encoded (ctf_container_ref ctfc, uint32_t flag, const char * name,
+		 const ctf_encoding_t * ep, uint32_t kind, tree treetype)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, 0);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0);
+
+  uint32_t roundup_nbytes = (ROUND_UP (ep->cte_bits, BITS_PER_UNIT)
+				    / BITS_PER_UNIT);
+
+  /* A void type has a size of zero.  A power of 2 is expected otherwise.  */
+  gcc_assert (!roundup_nbytes
+	      || (exact_log2 (roundup_nbytes) != -1));
+  dtd->dtd_data.ctti_size = roundup_nbytes ? (1 << ceil_log2 (roundup_nbytes))
+			   : roundup_nbytes;
+  dtd->dtd_u.dtu_enc = *ep;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+static ctf_id_t
+ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+		 uint32_t kind, tree treetype, uint32_t cvrint)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+  uint32_t key_flags = 0;
+
+  /* dtd_key_flags are set only for const, volatile and restrict.  */
+  if (cvrint && (kind == CTF_K_VOLATILE || kind == CTF_K_CONST
+		  || kind == CTF_K_RESTRICT))
+    key_flags = kind;
+
+  gcc_assert (ref > 0 && ref <= CTF_MAX_TYPE);
+
+  type = ctf_add_generic (ctfc, flag, NULL, &dtd, treetype, key_flags);
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0);
+  /* Caller of this API must guarantee that a CTF type with id = ref already
+     exists.  This will also be validated for us at link-time.  */
+  dtd->dtd_data.ctti_type = (uint32_t) ref;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_forward (ctf_container_ref ctfc, uint32_t flag, const char * name,
+		 uint32_t kind, tree treetype)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type = 0;
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, 0);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_FORWARD, flag, 0);
+  dtd->dtd_data.ctti_type = kind;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_typedef (ctf_container_ref ctfc, uint32_t flag, const char * name,
+		 ctf_id_t ref, tree treetype)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  gcc_assert (ref > 0 && ref <= CTF_MAX_TYPE);
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, 0);
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_TYPEDEF, flag, 0);
+  /* Caller of this API must guarantee that a CTF type with id = ref already
+     exists.  This will also be validated for us at link-time.  */
+  dtd->dtd_data.ctti_type = (uint32_t) ref;
+
+  gcc_assert (dtd->dtd_type != dtd->dtd_data.ctti_type);
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_slice (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+	       const ctf_encoding_t * ep, tree treetype)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+  uint32_t roundup_nbytes;
+
+  gcc_assert ((ep->cte_bits <= 255) && (ep->cte_offset <= 255));
+
+  gcc_assert (ref > 0 && ref <= CTF_MAX_TYPE);
+
+  type = ctf_add_generic (ctfc, flag, NULL, &dtd, treetype, 0);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
+
+  roundup_nbytes = (ROUND_UP (ep->cte_bits, BITS_PER_UNIT) / BITS_PER_UNIT);
+  gcc_assert (roundup_nbytes);
+  /* FIXME, stay close to what libctf does.  But by getting next power of two,
+     aren't we conveying less precise information, especially for bitfields.
+     For example, cte_bits = 33, roundup_nbytes = 5, ctti_size = 8 in the
+     implementation below.  */
+  dtd->dtd_data.ctti_size = (1 << ceil_log2 (roundup_nbytes));
+
+  /* Caller of this API must guarantee that a CTF type with id = ref already
+     exists.  This will also be validated for us at link-time.  */
+  dtd->dtd_u.dtu_slice.cts_type = (uint32_t) ref;
+  dtd->dtd_u.dtu_slice.cts_bits = ep->cte_bits;
+  dtd->dtd_u.dtu_slice.cts_offset = ep->cte_offset;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_volatile (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+		  tree type, uint32_t cvrint)
+{
+  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_VOLATILE, type, cvrint));
+}
+
+ctf_id_t
+ctf_add_const (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+	       tree type, uint32_t cvrint)
+{
+  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_CONST, type, cvrint));
+}
+
+ctf_id_t
+ctf_add_restrict (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+		  tree type, uint32_t cvrint)
+{
+  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_RESTRICT, type, cvrint));
+}
+
+ctf_id_t
+ctf_add_float (ctf_container_ref ctfc, uint32_t flag,
+	       const char * name, const ctf_encoding_t * ep, tree type)
+{
+  return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_FLOAT, type));
+}
+
+ctf_id_t
+ctf_add_integer (ctf_container_ref ctfc, uint32_t flag,
+		 const char * name, const ctf_encoding_t * ep, tree type)
+{
+  return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_INTEGER, type));
+}
+
+ctf_id_t
+ctf_add_pointer (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+		 tree type)
+{
+  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_POINTER, type, 0));
+}
+
+ctf_id_t
+ctf_add_array (ctf_container_ref ctfc, uint32_t flag, const ctf_arinfo_t * arp,
+	       tree treetype)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  gcc_assert (arp);
+
+  /* Caller of this API must make sure CTF type for arp->ctr_contents and
+     arp->ctr_index are already added.  This will also be validated for us at
+     link-time.  */
+
+  type = ctf_add_generic (ctfc, flag, NULL, &dtd, treetype, 0);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_ARRAY, flag, 0);
+  dtd->dtd_data.ctti_size = 0;
+  dtd->dtd_u.dtu_arr = *arp;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_enum (ctf_container_ref ctfc, uint32_t flag, const char * name,
+	     HOST_WIDE_INT size, tree enum_type)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  /* In the compiler, no need to handle the case of promoting forwards to
+     enums.  This comment is simply to note a divergence from libctf.  */
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, enum_type, 0);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_ENUM, flag, 0);
+
+  /* Size in bytes should always fit, of course.
+     TBD WARN - warn instead?  */
+  gcc_assert (size <= CTF_MAX_SIZE);
+
+  dtd->dtd_data.ctti_size = size;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+int
+ctf_add_enumerator (ctf_container_ref ctfc, ctf_id_t enid, const char * name,
+		    HOST_WIDE_INT value, tree enum_type)
+{
+  /* Callers of this API must make sure that CTF_K_ENUM with enid has been
+     addded.  This will also be validated for us at link-time.  */
+  ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, enum_type);
+  gcc_assert (dtd);
+  gcc_assert (dtd->dtd_type == enid);
+
+  ctf_dmdef_t * dmd;
+
+  uint32_t kind, vlen, root;
+
+  gcc_assert (name);
+
+  kind = CTF_V2_INFO_KIND (dtd->dtd_data.ctti_info);
+  root = CTF_V2_INFO_ISROOT (dtd->dtd_data.ctti_info);
+  vlen = CTF_V2_INFO_VLEN (dtd->dtd_data.ctti_info);
+
+  gcc_assert (kind == CTF_K_ENUM && vlen < CTF_MAX_VLEN);
+
+  dmd = ggc_cleared_alloc<ctf_dmdef_t> ();
+
+  /* Buffer the strings in the CTF string table.  */
+  dmd->dmd_name = ctf_add_string (ctfc, name, &(dmd->dmd_name_offset));
+  dmd->dmd_type = CTF_NULL_TYPEID;
+  dmd->dmd_offset = 0;
+  /* Variable value is of type HOST_WIDE_INT, dmd_value is int32_t on the other
+     hand.  Check bounds.  TBD WARN - warn instead or skip type ?  */
+  gcc_assert ((value <= INT_MAX) && (value >= INT_MIN));
+  dmd->dmd_value = value;
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, root, vlen + 1);
+  ctf_dmd_list_append (&dtd->dtd_u.dtu_members, dmd);
+
+  if ((name != NULL) && strcmp (name, ""))
+    ctfc->ctfc_strlen += strlen (name) + 1;
+
+  return (0);
+}
+
+int
+ctf_add_member_offset (ctf_container_ref ctfc, tree sou, const char * name,
+		       ctf_id_t type, unsigned long bit_offset)
+{
+  ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, sou);
+  ctf_dmdef_t * dmd;
+
+  uint32_t kind, vlen, root;
+
+  /* The type of the member being added must already exist.  */
+  gcc_assert (dtd);
+
+  kind = CTF_V2_INFO_KIND (dtd->dtd_data.ctti_info);
+  root = CTF_V2_INFO_ISROOT (dtd->dtd_data.ctti_info);
+  vlen = CTF_V2_INFO_VLEN (dtd->dtd_data.ctti_info);
+
+  gcc_assert (kind == CTF_K_STRUCT || kind == CTF_K_UNION);
+  gcc_assert (vlen < CTF_MAX_VLEN);
+
+#if 0
+  /* Check duplicate members with the same name.  May be a useful check if
+     members of anonymous truct or union are folded into the parent struct (if
+     exists); See a pending TBD in gen_ctf_sou_type for more info.  */
+  if (name != NULL)
+    {
+      for (dmd = dtd->dtd_u.dtu_members;
+	   dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+	{
+	  if (dmd->dmd_name != NULL)
+	    gcc_assert (strcmp (dmd->dmd_name, name) != 0);
+	}
+    }
+#endif
+
+  dmd = ggc_cleared_alloc<ctf_dmdef_t> ();
+
+  /* Buffer the strings in the CTF string table.  */
+  dmd->dmd_name = ctf_add_string (ctfc, name, &(dmd->dmd_name_offset));
+  dmd->dmd_type = type;
+  dmd->dmd_value = -1;
+
+  if (kind == CTF_K_STRUCT && vlen != 0)
+    dmd->dmd_offset = bit_offset;
+  else
+    dmd->dmd_offset = 0;
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, root, vlen + 1);
+  ctf_dmd_list_append (&dtd->dtd_u.dtu_members, dmd);
+
+  if ((name != NULL) && strcmp (name, ""))
+    ctfc->ctfc_strlen += strlen (name) + 1;
+
+  return 0;
+}
+
+int
+ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_id_t ref,
+		  tree decl)
+{
+  ctf_dvdef_ref dvd;
+
+  gcc_assert (name);
+
+  if (name != NULL)
+    {
+      dvd = ggc_cleared_alloc<ctf_dvdef_t> ();
+      /* Buffer the strings in the CTF string table.  */
+      dvd->dvd_name = ctf_add_string (ctfc, name, &(dvd->dvd_name_offset));
+      dvd->dvd_type = ref;
+      dvd->dvd_decl = decl;
+      ctf_dvd_insert (ctfc, dvd);
+
+      if (strcmp (name, ""))
+	ctfc->ctfc_strlen += strlen (name) + 1;
+    }
+
+  return 0;
+}
+
+ctf_id_t
+ctf_add_function (ctf_container_ref ctfc, uint32_t flag, const char * name,
+		  const ctf_funcinfo_t * ctc, ctf_func_arg_t * argv,
+		  tree func_decl_or_type)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+  uint32_t vlen;
+
+  gcc_assert (ctc);
+  if (ctc->ctc_argc)
+    gcc_assert (argv);
+
+  vlen = ctc->ctc_argc;
+
+  /* Caller must make sure CTF types for ctc->ctc_return and function
+     arguements are already added.  */
+
+  gcc_assert (vlen <= CTF_MAX_VLEN);
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, func_decl_or_type, 0);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
+  dtd->dtd_data.ctti_type = (uint32_t) ctc->ctc_return;
+
+  dtd->dtd_u.dtu_argv = argv;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_sou (ctf_container_ref ctfc, uint32_t flag, const char * name,
+	     uint32_t kind, size_t size, tree treetype)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type = 0;
+
+  gcc_assert ((kind == CTF_K_STRUCT) || (kind == CTF_K_UNION));
+
+  /* In the compiler, no need to handle the case of promoting forwards to
+     structs.  This comment is simply to note a divergence from libctf.  */
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, 0);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0);
+
+  if (size > CTF_MAX_SIZE)
+    {
+      dtd->dtd_data.ctti_size = CTF_LSIZE_SENT;
+      dtd->dtd_data.ctti_lsizehi = CTF_SIZE_TO_LSIZE_HI (size);
+      dtd->dtd_data.ctti_lsizelo = CTF_SIZE_TO_LSIZE_LO (size);
+      ctfc->ctfc_num_types++;
+    }
+  else
+    {
+      dtd->dtd_data.ctti_size = (uint32_t) size;
+      ctfc->ctfc_num_stypes++;
+    }
+
+  return type;
+}
diff --git a/gcc/ctfout.c b/gcc/ctfout.c
index 1ce9829..e7e1980 100644
--- a/gcc/ctfout.c
+++ b/gcc/ctfout.c
@@ -46,12 +46,16 @@ static GTY (()) section * ctf_info_section;
 #ifndef CTF_INFO_SECTION_NAME
 #define CTF_INFO_SECTION_NAME  ".ctf"
 #endif
+#ifndef CTF_LTO_INFO_SECTION_NAME
+#define CTF_LTO_INFO_SECTION_NAME  ".gnu.debuglto_.ctf"
+#endif
 
 /* Section flags for .ctf section.  */
 
 /* CTF debug info section.  */
 
 #define CTF_INFO_SECTION_FLAGS (SECTION_DEBUG)
+#define CTF_LTO_INFO_SECTION_FLAGS (SECTION_DEBUG | SECTION_EXCLUDE)
 
 /* Maximum size (in bytes) of an artificially generated CTF label.  */
 
@@ -63,8 +67,297 @@ static char ctf_info_section_label[MAX_CTF_LABEL_BYTES];
 #define CTF_INFO_SECTION_LABEL			"Lctf"
 #endif
 
+/* Forward declarations for some routines defined in this file.  */
+
+/* Generate CTF type for the given type.  Types already added are skipped.  */
+
+static ctf_id_t gen_ctf_type (ctf_container_ref, tree);
+
+/* Generate CTF type for the given decl.  Types already added are skipped.  */
+
+static ctf_id_t gen_ctf_type_for_decl (ctf_container_ref, tree);
+
+/* CTF preprocess callback arguments.  */
+
+typedef struct ctf_dtd_preprocess_arg
+{
+  unsigned long dtd_global_func_idx;
+  ctf_container_ref dtd_arg_ctfc;
+} ctf_dtd_preprocess_arg_t;
+
+typedef struct ctf_dvd_preprocess_arg
+{
+  ctf_container_ref dvd_arg_ctfc;
+} ctf_dvd_preprocess_arg_t;
+
+/* CTF cvr qualifier mask.  */
+
+const int ctf_cvr_qual_mask = (TYPE_QUAL_CONST
+			      | TYPE_QUAL_VOLATILE
+			      | TYPE_QUAL_RESTRICT);
+
+/* Return which member of the union is used in CTFTYPE.  Used for garbage
+   collection.  */
+
+enum ctf_dtu_d_union_enum
+ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype)
+{
+  unsigned int kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+  switch (kind)
+    {
+    case CTF_K_INTEGER:
+    case CTF_K_FLOAT:
+      return CTF_DTU_D_ENCODING;
+    case CTF_K_STRUCT:
+    case CTF_K_UNION:
+    case CTF_K_ENUM:
+      return CTF_DTU_D_MEMBERS;
+    case CTF_K_ARRAY:
+      return CTF_DTU_D_ARRAY;
+    case CTF_K_FUNCTION:
+      return CTF_DTU_D_ARGUMENTS;
+    case CTF_K_SLICE:
+      return CTF_DTU_D_SLICE;
+    default:
+      /* The largest member as default.  */
+      return CTF_DTU_D_ARRAY;
+    }
+}
+
+/* Returns a hash code for CTF type records.  */
+
+hashval_t
+ctf_dtdef_hash::hash (ctf_dtdef_ref e1)
+{
+  ctf_dtdef_ref e = e1;
+  tree e_decl = e->dtd_decl;
+  uint32_t key_flags = e->dtd_key_flags;
+
+  hashval_t key = hash_dtd_tree_decl (e_decl, key_flags);
+
+  return key;
+}
+
+hashval_t
+hash_dtd_tree_decl (tree e_decl, uint32_t key_flags)
+{
+  hashval_t key;
+  tree type = NULL;
+
+  if ((TREE_CODE (e_decl) == FIELD_DECL)
+      || (TREE_CODE (e_decl) == TYPE_DECL))
+    type = TREE_TYPE (e_decl);
+  else
+    type = e_decl; /* TREE_TYPE was used as dtd_key otherwise.  */
+
+  if (TREE_CODE (e_decl) == TYPE_DECL
+      || TREE_CODE (e_decl) == FUNCTION_DECL
+      /* No CTF type de-duplication for slices.  See note in
+	 gen_ctf_bitfield_type_for_decl.  */
+      || ((TREE_CODE (e_decl) == FIELD_DECL) && DECL_BIT_FIELD_TYPE (e_decl)))
+    {
+      key = (hashval_t) htab_hash_pointer (e_decl);
+    }
+  else
+    {
+      gcc_assert (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type);
+      key = (hashval_t) TYPE_UID (type);
+    }
+
+  if (key_flags)
+    key = iterative_hash (&key_flags, sizeof (key_flags), key);
+
+  return key;
+}
+
+/* Returns nonzero if entry1 and entry2 are the same CTF types.  */
+
+bool
+ctf_dtdef_hash::equal (ctf_dtdef_ref entry1, ctf_dtdef_ref entry2)
+{
+  bool eq = 0;
+  tree e1_type, e2_type;
+  int e1_cvr_quals = 0, e2_cvr_quals = 0;
+
+  ctf_dtdef_ref e1 = entry1;
+  ctf_dtdef_ref e2 = entry2;
+
+  tree e1_decl = e1->dtd_decl;
+  tree e2_decl = e2->dtd_decl;
+
+  gcc_assert (e1_decl);
+  gcc_assert (e2_decl);
+  /* This pre-check is useful because dtd_decl can be either type or decl tree
+     references.  */
+  eq = (TREE_CODE (e1_decl) == TREE_CODE (e2_decl));
+  if (eq)
+    {
+      if ((TREE_CODE (e1_decl) == FIELD_DECL)
+	  || (TREE_CODE (e1_decl) == TYPE_DECL))
+	{
+	  e1_type = TREE_TYPE (e1_decl);
+	  e2_type = TREE_TYPE (e2_decl);
+	}
+      else
+	{
+	  /* TREE_TYPE was used as dtd_key otherwise.  */
+	  e1_type = e1_decl;
+	  e2_type = e2_decl;
+	}
+
+      if (TREE_CODE (e1_decl) == TYPE_DECL
+	  || TREE_CODE (e1_decl) == FUNCTION_DECL
+	  /* No CTF type de-duplication for slices.  See note in
+	     gen_ctf_bitfield_type_for_decl.  */
+	  || ((TREE_CODE (e1_decl) == FIELD_DECL)
+	      && DECL_BIT_FIELD_TYPE (e1_decl)))
+
+	{
+	  eq = (htab_hash_pointer (e1_decl) ==  htab_hash_pointer (e2_decl));
+	}
+      else
+	{
+	  gcc_assert (TREE_CODE_CLASS (TREE_CODE (e1_type)) == tcc_type);
+	  gcc_assert (TREE_CODE_CLASS (TREE_CODE (e2_type)) == tcc_type);
+
+	  eq = (TYPE_UID (e1_type) == TYPE_UID (e2_type));
+
+	  /* Always compare cvr_quals when available.  */
+	  e1_cvr_quals = (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (e1_type)
+			  & ctf_cvr_qual_mask);
+	  e2_cvr_quals = (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (e2_type)
+			  & ctf_cvr_qual_mask);
+
+	  if (eq && e1_cvr_quals)
+	    {
+	      e2_cvr_quals = (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (e2_type)
+			      & ctf_cvr_qual_mask);
+	      eq = (e1_cvr_quals == e2_cvr_quals);
+	    }
+	}
+
+      if (eq)
+	{
+	  /* dtd_key_flags are set only for CTF type records which have no
+	     direct corresponding tree type or decl.  They will be 0
+	     otherwise.  */
+	  eq = (e1->dtd_key_flags == e2->dtd_key_flags);
+	}
+    }
+
+  return eq;
+}
+
+static inline int
+is_ctf_base_type (tree type)
+{
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE:
+    case REAL_TYPE:
+    case FIXED_POINT_TYPE:
+    case COMPLEX_TYPE:
+    case BOOLEAN_TYPE:
+    case VOID_TYPE:
+      return 1;
+
+    case ARRAY_TYPE:
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+    case ENUMERAL_TYPE:
+    case FUNCTION_TYPE:
+    case METHOD_TYPE:
+    case POINTER_TYPE:
+    case REFERENCE_TYPE:
+    case NULLPTR_TYPE:
+    case OFFSET_TYPE:
+    case LANG_TYPE:
+    case VECTOR_TYPE:
+      return 0;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return 0;
+}
+
+static inline int
+get_cvr_quals_for_type (tree type)
+{
+  int cvr_quals = 0;
+
+  if (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type)
+    cvr_quals = TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (type);
+
+  return cvr_quals;
+}
+
+static const char *
+get_type_name_string (tree type)
+{
+  gcc_assert (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type);
+
+  tree type_name = TYPE_IDENTIFIER (type);
+  const char * name_string = type_name ? IDENTIFIER_POINTER (type_name) : NULL;
+
+  return name_string;
+}
+
+static const char *
+get_decl_name_string (tree decl)
+{
+  gcc_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == tcc_declaration);
+
+  tree decl_name = DECL_NAME (decl);
+  const char * name_string = decl_name ? IDENTIFIER_POINTER (decl_name) : NULL;
+
+  return name_string;
+}
+
+/* Check if CTF for TYPE has already been generated.  Mainstay for
+   de-duplication.  If CTF type already exists, returns TRUE and updates
+   the TYPE_ID for the caller.  */
+
+static bool
+ctf_type_exists (ctf_container_ref ctfc, tree type,
+		 ctf_id_t * type_id)
+{
+  bool exists = false;
+
+  ctf_dtdef_ref ctf_type_seen = ctf_dtd_lookup (ctfc, type);
+  if (ctf_type_seen)
+    {
+      exists = true;
+      /* CTF type for this type exists.  */
+      *type_id = ctf_type_seen->dtd_type;
+    }
+
+  return exists;
+}
+
 /* CTF container setup and teardown routines.  */
 
+/* Initialize the CTF string table.
+   The first entry in the CTF string table (empty string) is added.  */
+
+static void
+init_ctf_string_table (ctf_container_ref ctfc)
+{
+  ctfc->ctfc_strtable.ctstab_head = NULL;
+  ctfc->ctfc_strtable.ctstab_tail = NULL;
+  ctfc->ctfc_strtable.ctstab_num = 0;
+  ctfc->ctfc_strtable.ctstab_len = 0;
+
+  /* The first entry in the CTF string table is an empty string.  E.g., CTF
+     type records with no name (like CTF_K_CONST, CTF_K_VOLATILE etc) point to
+     this string.  */
+  uint32_t estr_offset = 0;
+  ctfc->ctfc_strtable.ctstab_estr = ctf_add_string (ctfc, "", &estr_offset);
+  ctfc->ctfc_strlen++;
+}
+
 /* Allocate a new CTF container with the desired flags.  */
 
 static inline ctf_container_ref
@@ -75,6 +368,15 @@ new_ctf_container (unsigned char ctp_flags)
   tu_ctfc->ctfc_magic = CTF_MAGIC;
   tu_ctfc->ctfc_version = CTF_VERSION;
   tu_ctfc->ctfc_flags = ctp_flags;
+  tu_ctfc->ctfc_nextid = CTF_INIT_TYPEID;
+
+  tu_ctfc->ctfc_types
+    = hash_map<ctf_dtdef_hash, ctf_dtdef_ref>::create_ggc (100);
+
+  tu_ctfc->ctfc_vars
+    = hash_map<tree_decl_hash, ctf_dvdef_ref>::create_ggc (100);
+
+  init_ctf_string_table (tu_ctfc);
 
   return tu_ctfc;
 }
@@ -97,22 +399,920 @@ delete_ctf_container (ctf_container_ref ctfc)
      including the hash_map members etc. ?  */
   if (ctfc)
     {
-      ctfc = NULL;
+      if (ctfc->ctfc_vars_list)
+	{
+	  ggc_free (ctfc->ctfc_vars_list);
+	  ctfc->ctfc_vars_list = NULL;
+	}
+      if (ctfc->ctfc_types_list)
+	{
+	  ggc_free (ctfc->ctfc_types_list);
+	  ctfc->ctfc_types_list = NULL;
+	}
+      if (ctfc->ctfc_gfuncs_list)
+	{
+	  ggc_free (ctfc->ctfc_gfuncs_list);
+	  ctfc->ctfc_gfuncs_list = NULL;
+	}
+
+      ctfc= NULL;
     }
 }
 
 /* Initialize the various sections and labels for CTF output.  */
 
 void
-init_ctf_sections (void)
+init_ctf_sections (bool early_lto_debug)
 {
-  ctf_info_section = get_section (CTF_INFO_SECTION_NAME,
-				  CTF_INFO_SECTION_FLAGS,
-				  NULL);
+  // TBD - If the producer is LTO, there can be multiple translation units
+
+  if (early_lto_debug)
+    {
+      ctf_info_section = get_section (CTF_LTO_INFO_SECTION_NAME,
+				      CTF_LTO_INFO_SECTION_FLAGS,
+				      NULL);
+    }
+  else
+    {
+      ctf_info_section = get_section (CTF_INFO_SECTION_NAME,
+				      CTF_INFO_SECTION_FLAGS,
+				      NULL);
+    }
+
   ASM_GENERATE_INTERNAL_LABEL (ctf_info_section_label,
 			       CTF_INFO_SECTION_LABEL, ctf_label_num++);
 }
 
+/* Leaf routines for CTF type generation.
+   Called via the gen_ctf_type (), these APIs update the CTF container with new
+   CTF records.  CTF type de-duplication must be done by the caller API
+   (See "Parent routines for CTF generation below).  */
+
+/* Generate CTF for base type (integer, boolean, real, fixed point and complex).
+   Important: the caller of this API must make sure that duplicate types are
+   not added.  */
+
+static ctf_id_t
+gen_ctf_base_type (ctf_container_ref ctfc, tree type)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+
+  ctf_encoding_t ctf_encoding = {0, 0, 0};
+  HOST_WIDE_INT size = int_size_in_bytes (type);
+
+  uint32_t encoding = 0;
+
+  const char * name_string = get_type_name_string (type);
+  /* Base TYPE node must have had a TYPE_IDENTIFIER node, else retrieval of
+     name string of the base type will need to be adjusted.  */
+  gcc_assert (name_string);
+
+  /* Add the type of variable.  */
+  switch (TREE_CODE (type))
+    {
+    case INTEGER_TYPE:
+      {
+	/* Note - CTF_INT_VARARGS is unused in CTF.  */
+
+	/* Update size and encoding.  */
+	if (TYPE_STRING_FLAG (type))
+	  {
+	    if (TYPE_UNSIGNED (type))
+	      encoding = CTF_INT_CHAR;
+	    else
+	      encoding = CTF_INT_CHAR | CTF_INT_SIGNED;
+	  }
+	else if (!TYPE_UNSIGNED (type))
+	  encoding = CTF_INT_SIGNED;
+
+	ctf_encoding.cte_format = encoding;
+	ctf_encoding.cte_bits = size * 8;
+
+	type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
+				   &ctf_encoding, type);
+
+	break;
+      }
+
+  case BOOLEAN_TYPE:
+    encoding = CTF_INT_BOOL;
+
+    ctf_encoding.cte_format = encoding;
+    ctf_encoding.cte_bits = size * 8;
+
+    type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
+			       &ctf_encoding, type);
+    break;
+
+  case REAL_TYPE:
+    if (size == sizeof (float))
+      encoding = CTF_FP_SINGLE;
+    else if (size == sizeof (double))
+      encoding = CTF_FP_DOUBLE;
+    else if (size == sizeof (long double))
+      encoding = CTF_FP_LDOUBLE;
+    /* Encoding must be appropriately initialized by now.  */
+    gcc_assert (encoding && encoding <= CTF_FP_MAX);
+
+    ctf_encoding.cte_format = encoding;
+    ctf_encoding.cte_bits = size * 8;
+
+    type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
+			     &ctf_encoding, type);
+    break;
+
+  /* FIXME - We do not have a fixed point type in CTF yet.  */
+  case FIXED_POINT_TYPE:
+    /* TBD WARN - warn instead or skip type ?  */
+    gcc_assert (false);
+    break;
+
+  case COMPLEX_TYPE:
+    encoding = 0;
+
+    if (size == sizeof (float))
+      encoding = CTF_FP_CPLX;
+    else if (size == sizeof (double))
+      encoding = CTF_FP_DCPLX;
+    else if (size == sizeof (long double))
+      encoding = CTF_FP_LDCPLX;
+    /* Encoding must be appropriately initialized by now.  */
+    gcc_assert (encoding && encoding != CTF_FP_MAX);
+
+    ctf_encoding.cte_format = encoding;
+    ctf_encoding.cte_bits = size * 8;
+
+    type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
+			     &ctf_encoding, type);
+    break;
+
+  case VOID_TYPE:
+    encoding = CTF_INT_SIGNED;
+    ctf_encoding.cte_format = encoding;
+    ctf_encoding.cte_bits = 0;
+
+    type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
+			       &ctf_encoding, type);
+
+    break;
+
+  default:
+    /* No other TREE_CODEs are expected as CTF base types.  */
+    gcc_unreachable () ;
+  }
+
+  return type_id;
+}
+
+static ctf_id_t
+gen_ctf_pointer_type (ctf_container_ref ctfc, tree ptr_type)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+  ctf_id_t pointer_to_type_id = CTF_NULL_TYPEID;
+
+  tree pointertotype = TREE_TYPE (ptr_type);
+
+  type_id = gen_ctf_type (ctfc, pointertotype);
+
+  /* Type de-duplication.
+     Consult the ctfc_types hash again before adding the CTF pointer type
+     because there can be cases where a pointer type may have been added by
+     the gen_ctf_type call above.  For example, a struct have a member of type
+     pointer to the struct, e.g.,
+     struct link { struct link * next; } * slink;  */
+  if (ctf_type_exists (ctfc, ptr_type, &pointer_to_type_id))
+    return pointer_to_type_id;
+
+  pointer_to_type_id = ctf_add_pointer (ctfc, CTF_ADD_ROOT, type_id,
+					  ptr_type);
+
+  return pointer_to_type_id;
+}
+
+static ctf_id_t
+gen_ctf_array_type (ctf_container_ref ctfc, tree array_type)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+  tree lower, upper;
+  ctf_arinfo_t arinfo;
+  HOST_WIDE_INT min_index = 0, max_index = 0;
+  uint32_t num_elements = 0;
+  ctf_id_t ctf_contents_type_id = CTF_NULL_TYPEID;
+  ctf_id_t ctf_index_type_id = CTF_NULL_TYPEID;
+
+  tree type_of_array_element = TREE_TYPE (array_type);
+  tree type_of_index = TYPE_DOMAIN (array_type);
+
+  /* type_of_index may be NULL in some cases, e.g., when we parse
+     extern const char _var_example[];
+     In this case of unsized uninitialized array declaration, CTF encodes an
+     explicit zero for the number of elements.  This is quite distinct from
+     DWARF which encodes no bound information in such a case.
+     TBD - confirm this behaviour.  */
+  if (type_of_index)
+    {
+      lower = TYPE_MIN_VALUE (type_of_index);
+      upper = TYPE_MAX_VALUE (type_of_index);
+      min_index = tree_to_shwi (lower);
+      /* TYPE_MAX_VALUE of index may be null for variable-length arrays.  */
+      max_index = upper ? tree_to_shwi (upper) : 0;
+      gcc_assert (max_index >= min_index);
+      /* If max_index == min_index, both the values must be zero; num_elements
+	 set to zero in that case.  */
+      num_elements = (max_index != min_index) ? max_index - min_index + 1 : 0;
+      gcc_assert (num_elements <= CTF_MAX_SIZE);
+    }
+
+  arinfo.ctr_nelems = num_elements;
+
+  /* Overwrite the type_of_index with integer_type_node.
+     TYPE_DOMAIN of ARRAY_TYPE have code INTEGER_TYPE, but have no
+     IDENTIFIER_NODES.  This causes issues in retrieving the name string of
+     the index type (See gen_ctf_base_type) becuase the TYPE_IDENTIFIER is NULL
+     in those cases.
+     Use integer_type_node instead.  This also helps gen_ctf_base_type to not
+     generate crooked (and duplicate) int records with wierd "integer" size for
+     arrays.  */
+  type_of_index = integer_type_node;
+
+  ctf_index_type_id = gen_ctf_type (ctfc, type_of_index);
+  arinfo.ctr_index = ctf_index_type_id;
+
+  ctf_contents_type_id = gen_ctf_type (ctfc, type_of_array_element);
+  arinfo.ctr_contents = ctf_contents_type_id;
+
+  type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, array_type);
+
+  return type_id;
+}
+
+static ctf_id_t
+gen_ctf_forward_type (ctf_container_ref ctfc, tree fwd_type, uint32_t kind)
+{
+  ctf_id_t fwd_type_id = 0;
+
+  const char * fwd_name = get_type_name_string (fwd_type);
+  /* Type de-duplication is already done by now.  See gen_ctf_type ().
+     Simple add the forward type.  */
+  fwd_type_id = ctf_add_forward (ctfc, CTF_ADD_ROOT, fwd_name, kind, fwd_type);
+
+  return fwd_type_id;
+}
+
+static void
+gen_ctf_enum_const_list (ctf_container_ref ctfc, const tree enum_type,
+			 const ctf_id_t enum_type_id)
+{
+  tree link;
+  tree enum_value;
+  HOST_WIDE_INT value;
+  /* Append the enum values to the CTF_K_ENUM record.  */
+  for (link = TYPE_VALUES (enum_type); link != NULL; link = TREE_CHAIN (link))
+    {
+      enum_value = TREE_VALUE (link);
+      /* For now, handle enumeration constants not wider than
+	 HOST_WIDE_INT.  TBD handle this.  */
+      gcc_assert (int_size_in_bytes (TREE_TYPE (enum_value))*HOST_BITS_PER_CHAR
+		  <= HOST_BITS_PER_WIDE_INT || tree_fits_shwi_p (enum_value));
+
+      value = TREE_INT_CST_LOW (enum_value);
+      const char * enum_valname = IDENTIFIER_POINTER (TREE_PURPOSE (link));
+      gcc_assert (enum_valname);
+
+      ctf_add_enumerator (ctfc, enum_type_id, enum_valname, value, enum_type);
+    }
+}
+
+static ctf_id_t
+gen_ctf_enum_type (ctf_container_ref ctfc, tree enum_type)
+{
+  ctf_id_t enum_type_id = CTF_NULL_TYPEID;
+  HOST_WIDE_INT size;
+
+  gcc_assert (TREE_CODE (enum_type) == ENUMERAL_TYPE);
+
+  if (!TYPE_SIZE (enum_type))
+    {
+      /* Add CTF forward type of enum kind.  */
+      uint32_t kind = CTF_K_ENUM;
+      enum_type_id = gen_ctf_forward_type (ctfc, enum_type, kind);
+      return enum_type_id;
+    }
+
+  const char * enum_name = get_type_name_string (enum_type);
+  size = int_size_in_bytes (enum_type);
+
+  /* Add CTF enum type.  */
+  enum_type_id = ctf_add_enum (ctfc, CTF_ADD_ROOT, enum_name, size, enum_type);
+  /* Add CTF records for enum const values.  */
+  gen_ctf_enum_const_list (ctfc, enum_type, enum_type_id);
+
+  return enum_type_id;
+}
+
+static ctf_id_t
+gen_ctf_function_type (ctf_container_ref ctfc, tree func_decl_or_type,
+		       const char * func_name)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID, return_type_id = CTF_NULL_TYPEID;
+  tree func_type;
+  tree link;
+  tree first_param_type;
+  tree formal_type = NULL;
+  tree return_type = NULL;
+  tree param_type;
+  uint32_t num_args = 0;
+  ctf_func_arg_t * argv_ids;
+  ctf_funcinfo_t func_info;
+
+  if (TREE_CODE (func_decl_or_type) == FUNCTION_TYPE)
+    func_type = func_decl_or_type;
+  else
+    func_type = TREE_TYPE (func_decl_or_type);
+
+  return_type = TREE_TYPE (func_type);
+  first_param_type = TYPE_ARG_TYPES (func_type);
+
+  /* Add CTF record for function return type.  */
+  return_type_id = gen_ctf_type (ctfc, return_type);
+  func_info.ctc_return = return_type_id;
+
+  /* Make our first pass over the list of formal parameter types and count
+     them.  */
+  for (link = first_param_type; link;)
+    {
+      formal_type = TREE_VALUE (link);
+      if (formal_type == void_type_node)
+	break;
+
+      num_args++;
+
+      link = TREE_CHAIN (link);
+    }
+
+  /* Check if this function type has an ellipsis.  */
+  if (formal_type != void_type_node)
+    {
+      func_info.ctc_flags |= CTF_FUNC_VARARG;
+      /* Increment the number of args.  This is the number of args we write
+	 after the CTF_K_FUNCTION CTF record.  */
+      num_args++;
+    }
+
+  /* The number of typed arguments should include the ellipsis.  */
+  func_info.ctc_argc = num_args;
+
+  /* Create an array of ctf_id_t to hold CTF types for args (including the
+     ellipsis).  */
+  argv_ids = ggc_vec_alloc<ctf_func_arg_t>(num_args);
+
+  /* Make a pass over the list of formal parameter types and generate CTF for
+     each.  */
+  unsigned int i = 0;
+  for (link = TYPE_ARG_TYPES (func_type);
+       link && TREE_VALUE (link);
+       link = TREE_CHAIN (link))
+    {
+      param_type = TREE_VALUE (link);
+
+      if (param_type == void_type_node)
+	break;
+
+      argv_ids[i++].farg_type = gen_ctf_type (ctfc, param_type);
+    }
+
+  if (formal_type != void_type_node)
+    {
+      /* Add trailing zero to indicate varargs.  */
+      argv_ids[i].farg_type = 0;
+      gcc_assert (i == num_args - 1);
+    }
+
+  type_id = ctf_add_function (ctfc, CTF_ADD_ROOT, func_name,
+			      (const ctf_funcinfo_t *)&func_info, argv_ids,
+			      func_decl_or_type);
+
+  return type_id;
+}
+
+/* Add CTF qualifier record.
+
+   If there are multiple qualifiers, the recommended ordering for CTF qualifier
+   records is const, volatile, restrict (from top-most to bottom-most).  */
+
+static ctf_id_t
+gen_ctf_cvrquals (ctf_container_ref ctfc, tree type, ctf_id_t type_id)
+{
+  tree qualified_type;
+  int flags;
+  uint32_t cvrint = 0;
+  int quals_index = 0;
+
+  ctf_id_t qual_type_id = type_id;
+  int cvr_quals = get_cvr_quals_for_type (type);
+
+  int quals_order[3] = { TYPE_QUAL_RESTRICT,
+			 TYPE_QUAL_VOLATILE,
+			 TYPE_QUAL_CONST };
+  ctf_id_t (*func_ptrs[3]) (ctf_container_ref, uint32_t, ctf_id_t, tree,
+			    uint32_t) = { ctf_add_restrict,
+					  ctf_add_volatile,
+					  ctf_add_const };
+  unsigned int key_flags[3] = { CTF_K_RESTRICT, CTF_K_VOLATILE, CTF_K_CONST };
+  ctf_id_t (*ctf_add_qual_func) (ctf_container_ref, uint32_t, ctf_id_t, tree,
+				 uint32_t);
+
+  qualified_type = get_qualified_type (type, cvr_quals);
+
+  /* Type de-duplication for cvr records.
+     Do not add CTF types for the same type with the matching cvr qual
+     if already present.  */
+  if (qualified_type)
+    {
+      if (ctf_type_exists (ctfc, qualified_type, &qual_type_id))
+	return qual_type_id;
+    }
+  else
+    /* If the qualified_type is NULL, use TREE_TYPE of the decl to add
+       the CTF record.  CTF for unqualified type must have been added by
+       now.  */
+    gcc_assert (ctf_type_exists (ctfc, type, &qual_type_id));
+
+  /* CTF represents distinct type records for each qualifier (CTF_K_RESTRICT,
+     CTF_K_VOLATILE, CTF_K_CONST). The records can be shared between types.
+     Here we try to de-duplicate these records as well.  */
+  while (cvr_quals)
+    {
+      flags = cvr_quals & quals_order[quals_index];
+      ctf_add_qual_func = func_ptrs[quals_index];
+      if (flags)
+	{
+	  /* Reset the corresponding cvr_qual flag so that it is not processed
+	     again.  */
+	  cvr_quals &= ~quals_order[quals_index];
+	  cvrint = (cvr_quals != 0);
+
+	 /* The dtd_decl of the all CTF type records should be non-null for
+	    de-duplication to work.  CTF records for CVR quals of a type will
+	    have the same dtd_decl in this case.  So, to prevent collisions, we
+	    use dtd_decl and dtd_key_flags for creating the hashkey.  */
+	  ctf_dtdef_ref qual_type_exists
+	    = ctf_dtd_lookup_with_flags (ctfc, type, key_flags[quals_index]);
+	  if (qual_type_exists)
+	    qual_type_id = qual_type_exists->dtd_type;
+	  else
+	    qual_type_id = ctf_add_qual_func (ctfc, CTF_ADD_ROOT, qual_type_id,
+					      type, cvrint);
+	}
+      quals_index++;
+    }
+
+  /* At least one CTF record must have been added or found to be duplicate
+     by now.  */
+  gcc_assert (qual_type_id != type_id);
+
+  return qual_type_id;
+}
+
+static ctf_id_t
+gen_ctf_sou_type (ctf_container_ref ctfc, tree sou_type)
+{
+  HOST_WIDE_INT sou_size;
+
+  ctf_id_t sou_type_id = CTF_NULL_TYPEID;
+  ctf_id_t field_type_id = CTF_NULL_TYPEID;
+
+  tree field;
+  HOST_WIDE_INT bit_offset = 0;
+
+  gcc_assert (RECORD_OR_UNION_TYPE_P (sou_type));
+
+  /* Handle anonymous record or union.  */
+#if 0
+  if (TYPE_NAME (sou_type) == NULL)
+    {
+      /* TBD - confirm this behaviour.
+	 The compiler will not flatten an anonymous struct or union into its
+	 parent if one exists.  Members of anonymous struct or union continue
+	 to be wrappped by the respective anonymous record.  */
+    }
+#endif
+  uint32_t kind = (TREE_CODE (sou_type) == RECORD_TYPE)
+		  ? CTF_K_STRUCT : CTF_K_UNION;
+
+  if (!TYPE_SIZE (sou_type))
+    {
+      /* Add CTF forward type of struct or union kind.  */
+      sou_type_id = gen_ctf_forward_type (ctfc, sou_type, kind);
+      return sou_type_id;
+    }
+
+    const char * sou_name = get_type_name_string (sou_type);
+    sou_size = int_size_in_bytes (sou_type);
+
+    /* Add CTF struct/union type.  */
+    if ((TREE_CODE (sou_type) == RECORD_TYPE)
+	|| (TREE_CODE (sou_type) == UNION_TYPE))
+      sou_type_id = ctf_add_sou (ctfc, CTF_ADD_ROOT, sou_name, kind, sou_size,
+				 sou_type);
+    /* QUAL_UNION_TYPE not expected in C.  */
+    else
+      gcc_unreachable ();
+
+    /* Add members of the struct.  */
+    for (field = TYPE_FIELDS (sou_type); field != NULL_TREE;
+	 field = TREE_CHAIN (field))
+      {
+	/* Enum members have DECL_NAME (field) as NULL.  */
+	const char * field_name = get_decl_name_string (field);
+
+	/* variable bit offsets are not handled at the moment.  */
+	gcc_assert (TREE_CODE (DECL_FIELD_BIT_OFFSET (field)) == INTEGER_CST);
+
+	bit_offset = int_bit_position (field);
+	/* Add the CTF type record for the field, followed by the field
+	   itself.  */
+	field_type_id = gen_ctf_type_for_decl (ctfc, field);
+	ctf_add_member_offset (ctfc, sou_type, field_name, field_type_id,
+			       bit_offset);
+      }
+
+  return sou_type_id;
+}
+
+/* Parent routines for CTF generation.
+   These routines are entry points for CTF generation.  Given a type or decl,
+   these routines perform de-duplication before invoking the Leaf CTF
+   generation routines for adding types.  */
+
+/* Generate CTF typedef records for a given declaration.  Performs
+   de-duplication before adding typedef.  */
+
+static ctf_id_t
+gen_ctf_typedef (ctf_container_ref ctfc, tree decl)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID, typedef_type_id = CTF_NULL_TYPEID;
+
+  tree type = TREE_TYPE (decl);
+  const char * decl_name_string = get_type_name_string (type);
+
+  /* CTF type de-duplication in the compiler.
+     Do not add duplicate typedef.  */
+  if (ctf_type_exists (ctfc, decl, &type_id))
+    return type_id;
+
+  /* Generate the type if not already done.  */
+  type_id = gen_ctf_type_for_decl (ctfc, decl);
+
+  /* Add typedef.  dtd_decl points to the typedef tree node.  */
+  typedef_type_id = ctf_add_typedef (ctfc, CTF_ADD_ROOT, decl_name_string,
+				     type_id, decl);
+  type_id = typedef_type_id;
+
+  return type_id;
+}
+
+/* Generate CTF variable records for a given declaration.  Performs
+   de-duplication before adding variable.  */
+
+static ctf_id_t
+gen_ctf_variable (ctf_container_ref ctfc, tree decl)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID, var_type_id = CTF_NULL_TYPEID;
+
+  const char* name = get_decl_name_string (decl);
+
+  ctf_dvdef_ref var_type_seen = ctf_dvd_lookup (tu_ctfc, decl);
+  /* Avoid duplicates.  A VAR_DECL is duplicate if it is the same decl node.
+     See hash_dvd_tree_decl.  */
+  if (!var_type_seen)
+    {
+      type_id = gen_ctf_type_for_decl (ctfc, decl);
+      /* Now add the variable.  */
+      var_type_id = ctf_add_variable (tu_ctfc, name, type_id, decl);
+    }
+  else
+    var_type_id = var_type_seen->dvd_type;
+
+  return var_type_id;
+}
+
+/* Generate CTF function records for a given declaration.  */
+
+static ctf_id_t
+gen_ctf_function (ctf_container_ref ctfc, tree func_decl)
+{
+  gcc_assert (TREE_CODE (func_decl) == FUNCTION_DECL);
+
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+
+  const char * func_name = get_decl_name_string (func_decl);
+
+  /* Duplicate function types are expected to be seen as functions with same
+     signature will show the same function type.  For each distinct function
+     declaration, however, CTF function type records must be added anew.
+     Duplicate function *declarations* must, however be avoided.  This is
+     expected to happen if the gen_ctf_function API is called multiple times
+     for the same func_decl.  */
+
+  bool exists = ctf_type_exists (ctfc, func_decl, &type_id);
+  gcc_assert (!exists);
+
+  /* Add CTF Function type.  */
+  type_id = gen_ctf_function_type (ctfc, func_decl, func_name);
+
+  /* Update global functions count.  */
+  if (TREE_PUBLIC (func_decl))
+    ctfc->ctfc_num_global_funcs++;
+
+  return type_id;
+}
+
+/* Add CTF type record(s) for the given input type.  */
+static ctf_id_t
+gen_ctf_type (ctf_container_ref ctfc, tree type)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+
+  /* This API expects to handle tcc_type nodes only.
+     ctf_add_int/float etc  == type ==  INTEGER_TYPE, REAL_TYPE etc
+     ctf_add_pointer	    == type ==  POINTER_TYPE
+     ctf_add_array	    == type ==  ARRAY_TYPE
+     ctf_add_sou	    == type ==  RECORD_TYPE, UNION_TYPE.  */
+  gcc_assert (TREE_CODE_CLASS (TREE_CODE (type)) == tcc_type);
+
+  int cvr_quals = get_cvr_quals_for_type (type);
+
+  /* For a type of ARRAY_TYPE, type qualifiers (if any) are with
+     TREE_TYPE (type).  TYPE_MAIN_VARIANT (type) however will not contain
+     these quals.  Need to pass the former to gen_ctf_array_type.  */
+  tree gen_type = (TREE_CODE (type) == ARRAY_TYPE)
+		  ? type : TYPE_MAIN_VARIANT (type);
+
+  /* CTF type de-duplication in the compiler.  */
+  if (!ctf_type_exists (ctfc, gen_type, &type_id))
+    {
+      /* Encountering a CTF type for the first time.  Add the CTF type.  */
+
+      if (is_ctf_base_type (gen_type))
+	type_id = gen_ctf_base_type (ctfc, gen_type);
+
+      else if (RECORD_OR_UNION_TYPE_P (gen_type))
+	type_id = gen_ctf_sou_type (ctfc, gen_type);
+
+      else if (TREE_CODE (gen_type) == ARRAY_TYPE)
+	type_id = gen_ctf_array_type (tu_ctfc, gen_type);
+
+      else if (TREE_CODE (gen_type) == ENUMERAL_TYPE)
+	type_id = gen_ctf_enum_type (tu_ctfc, gen_type);
+
+      else if (POINTER_TYPE_P (gen_type))
+	type_id = gen_ctf_pointer_type (tu_ctfc, gen_type);
+
+      else if (TREE_CODE (gen_type) == FUNCTION_TYPE)
+	/* Function pointers.  */
+	type_id = gen_ctf_function_type (tu_ctfc, gen_type, NULL);
+
+      else
+	/* No other type is expected for C frontend.  */
+	gcc_unreachable ();
+    }
+
+  /* Add qualifiers if any.  */
+  if (cvr_quals & ctf_cvr_qual_mask)
+    type_id = gen_ctf_cvrquals (ctfc, type, type_id);
+
+  return type_id;
+}
+
+/* Generate CTF records for bitfield declarations.  */
+
+static ctf_id_t
+gen_ctf_bitfield_type_for_decl (ctf_container_ref ctfc, const tree field,
+				const ctf_id_t type_id)
+{
+  ctf_id_t bitfield_type_id = CTF_NULL_TYPEID;
+
+  gcc_assert (TREE_CODE (field) == FIELD_DECL);
+
+  gcc_assert (ctfc);
+  HOST_WIDE_INT size_in_bits = tree_to_shwi (DECL_SIZE (field));
+
+  ctf_encoding_t ep = {0,0,0};
+  /* Assume default encoding as unsigned.  */
+  uint32_t encoding = 0;
+  tree type = TREE_TYPE (field);
+
+  /* The type of a bit field can only be integral.  */
+  if (TREE_CODE (type) != INTEGER_TYPE)
+    gcc_unreachable ();
+
+  /* Handle both enum bitfields and integer bitfields.  */
+  if (TYPE_STRING_FLAG (type))
+    {
+      if (TYPE_UNSIGNED (type))
+	encoding = CTF_INT_CHAR;
+      else
+	encoding = CTF_INT_CHAR | CTF_INT_SIGNED;
+    }
+  else if (!TYPE_UNSIGNED (type))
+    encoding = CTF_INT_SIGNED;
+
+  ep.cte_format = encoding;
+  /* The offset of the slice is the offset into a machine word.
+     TBD Handle big-endian - should the offset be byte-order dependent ?  */
+  ep.cte_offset = int_bit_position (field) % BITS_PER_WORD;
+  ep.cte_bits = size_in_bits;
+
+  /* No type de-duplication for slices.
+     (Probe the CTF container with field_decl)
+     There is no way to de-duplicate two bitfields using just type or decl
+     references as dtd_key_decl.  Two field declarations may share the
+     same TREE_TYPE and DECL_BIT_FIELD_TYPE references, but may have different
+     offset and num bits.  */
+
+  bitfield_type_id = ctf_add_slice (ctfc, CTF_ADD_NONROOT, type_id, &ep,
+				    field);
+
+  return bitfield_type_id;
+}
+
+static ctf_id_t
+gen_ctf_type_for_decl (ctf_container_ref ctfc, tree decl)
+{
+  gcc_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == tcc_declaration);
+
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+  tree type;
+  tree bitfield_type = NULL;
+
+  type = TREE_TYPE (decl);
+
+  /* In a FIELD_DECL, this indicates whether the field was a bitfield.  */
+  if (TREE_CODE (decl) == FIELD_DECL)
+    bitfield_type = DECL_BIT_FIELD_TYPE (decl);
+
+  /* Create CTF for the unqualified type, if it not done already.  If it's a
+     bitfield type, use that to generate the CTF type record.  */
+  if (bitfield_type)
+    type = bitfield_type;
+
+  /* CTF type de-duplication in the compiler.
+     Lookup if CTF for unqualified type has already been added.  CTF slices are
+     not shared across declarations.  */
+  if (ctf_type_exists (ctfc, type, &type_id))
+    {
+      if (!bitfield_type)
+	return type_id;
+    }
+  else
+    type_id = gen_ctf_type (ctfc, type);
+
+  /* Now, create CTF slice if it is a bitfield.  */
+  if (bitfield_type)
+    type_id = gen_ctf_bitfield_type_for_decl (ctfc, decl, type_id);
+
+  return type_id;
+}
+
+/* Routines for CTF pre-processing.  */
+
+static void
+ctf_preprocess_var (ctf_container_ref ctfc, ctf_dvdef_ref var)
+{
+  /* Add it to the list of types.  This array of types will be sorted before
+     assembling into output.  */
+  list_add_ctf_vars (ctfc, var);
+}
+
+/* CTF preprocess callback routine for CTF variables.  */
+
+bool
+ctf_dvd_preprocess_cb (tree const & ARG_UNUSED (key), ctf_dvdef_ref * slot,
+		       void * arg)
+{
+  ctf_dvd_preprocess_arg_t * dvd_arg =  (ctf_dvd_preprocess_arg_t *)arg;
+
+  ctf_container_ref arg_ctfc = dvd_arg->dvd_arg_ctfc;
+  ctf_dvdef_ref var = (ctf_dvdef_ref) *slot;
+
+  ctf_preprocess_var (arg_ctfc, var);
+
+  return 1;
+}
+
+/* CTF preprocess callback routine for CTF types.  */
+
+bool
+ctf_dtd_preprocess_cb (ctf_dtdef_ref const & ARG_UNUSED (key),
+		       ctf_dtdef_ref * slot, void * arg)
+{
+  uint32_t kind, vlen;
+  tree func_decl;
+
+  ctf_dtdef_ref ctftype = (ctf_dtdef_ref) *slot;
+  ctf_dtd_preprocess_arg_t * dtd_arg = (ctf_dtd_preprocess_arg_t *)arg;
+
+  ctf_container_ref arg_ctfc = dtd_arg->dtd_arg_ctfc;
+
+  size_t index = ctftype->dtd_type;
+  gcc_assert (index <= arg_ctfc->ctfc_types->elements ());
+
+  /* CTF types need to be output in the order of their type IDs.  In other
+     words, if type A is used to define type B, type ID of type A must
+     appear before type ID of type B.  */
+  arg_ctfc->ctfc_types_list[index] = ctftype;
+
+  /* Keep track of the CTF type if it's a function type.  */
+  kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+  if (kind == CTF_K_FUNCTION)
+    {
+      func_decl = ctftype->dtd_decl;
+      if ((TREE_CODE_CLASS (TREE_CODE (func_decl)) == tcc_declaration)
+	  && TREE_PUBLIC (func_decl))
+	{
+	  arg_ctfc->ctfc_gfuncs_list[dtd_arg->dtd_global_func_idx] = ctftype;
+	  dtd_arg->dtd_global_func_idx++;
+	  vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info);
+	  /* Update the function info section size in bytes.  Avoid using
+	     ctf_calc_num_vbytes API, the latter is only meant to convey
+	     the vlen bytes after CTF types in the CTF data types section.  */
+	  arg_ctfc->ctfc_num_funcinfo_bytes += (vlen + 2) * sizeof (uint32_t);
+	}
+    }
+
+  /* Calculate the vlen bytes.  */
+  arg_ctfc->ctfc_num_vlen_bytes += ctf_calc_num_vbytes (ctftype);
+
+  return 1;
+}
+
+/* CTF preprocessing.
+   After the CTF types for the compilation unit have been generated fully, the
+   compiler writes out the asm for the CTF types.
+
+   CTF writeout in the compiler requires two passes over the CTF types.  In the
+   first pass, the CTF preprocess pass:
+     1.  CTF types are sorted in the order of their type IDs.
+     2.  The variable number of bytes after each CTF type record are calculated.
+	 This is used to calculate the offsets in the ctf_header_t.
+     3.  If the CTF type is of CTF_K_FUNCTION, the number of bytes in the
+	 funcinfo sub-section are calculated.  This is used to calculate the
+	 offsets in the ctf_header_t.
+     4.  Keep the list of CTF variables in ASCIIbetical order of their names.
+
+   In the second pass, the CTF writeout pass, asm tags are written out using
+   the compiler's afore-generated internal pre-processed CTF types.  */
+
+static void
+ctf_preprocess (ctf_container_ref ctfc)
+{
+  size_t num_ctf_vars = ctfc->ctfc_vars->elements ();
+  if (num_ctf_vars)
+    {
+      ctf_dvd_preprocess_arg_t dvd_arg;
+      dvd_arg.dvd_arg_ctfc = ctfc;
+
+      /* Allocate CTF var list.  */
+      ctfc->ctfc_vars_list = ggc_vec_alloc<ctf_dvdef_ref>(num_ctf_vars);
+      /* Variables appear in the sort ASCIIbetical order of their names.  This
+	 permits binary searching in the CTF reader.  Add the variables to a
+	 list for sorting.  */
+      ctfc->ctfc_vars->traverse<void *, ctf_dvd_preprocess_cb> (&dvd_arg);
+      /* Sort the list.  */
+      qsort (ctfc->ctfc_vars_list, num_ctf_vars, sizeof (ctf_dvdef_ref),
+	     ctf_varent_compare);
+    }
+
+  size_t num_ctf_types = ctfc->ctfc_types->elements ();
+
+  /* Initialize an array to keep track of the CTF functions types for global
+     functions in the in the CTF data section.  */
+  size_t num_global_funcs = ctfc->ctfc_num_global_funcs;
+  if (num_global_funcs)
+    {
+      ctfc->ctfc_gfuncs_list = ggc_vec_alloc<ctf_dtdef_t*>(num_global_funcs);
+      gcc_assert (num_ctf_types);
+    }
+
+  if (num_ctf_types)
+    {
+      ctf_dtd_preprocess_arg_t dtd_arg;
+      dtd_arg.dtd_global_func_idx = 0;
+      dtd_arg.dtd_arg_ctfc = tu_ctfc;
+      /* Allocate the CTF types list.  Add 1 because type ID 0 is never a valid
+	 CTF type ID.  No CTF type record should appear at that offset, this
+	 eases debugging and readability.  */
+      ctfc->ctfc_types_list = ggc_vec_alloc<ctf_dtdef_ref>(num_ctf_types + 1);
+      /* Pre-process CTF types.  */
+      ctfc->ctfc_types->traverse<void *, ctf_dtd_preprocess_cb> (&dtd_arg);
+
+      gcc_assert (dtd_arg.dtd_global_func_idx == num_global_funcs);
+    }
+}
+
+/* CTF asm helper routines.  */
+
 /* Asm'out the CTF preamble.  */
 
 static void
@@ -124,7 +1324,78 @@ ctf_asm_preamble (ctf_container_ref ctfc)
   dw2_asm_output_data (1, ctfc->ctfc_flags, "CTF preamble flags");
 }
 
-/* Output the CTF header.  */
+static void
+ctf_asm_stype (ctf_dtdef_ref type)
+{
+  dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name");
+  dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info");
+  /* union.  */
+  dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size or ctt_type");
+}
+
+static void
+ctf_asm_type (ctf_dtdef_ref type)
+{
+  dw2_asm_output_data (4, type->dtd_data.ctti_name, "ctt_name");
+  dw2_asm_output_data (4, type->dtd_data.ctti_info, "ctt_info");
+  /* union.  */
+  dw2_asm_output_data (4, type->dtd_data.ctti_size, "ctt_size");
+  dw2_asm_output_data (4, type->dtd_data.ctti_lsizehi, "ctt_lsizehi");
+  dw2_asm_output_data (4, type->dtd_data.ctti_lsizelo, "ctt_lsizelo");
+}
+
+static void
+ctf_asm_slice (ctf_dtdef_ref type)
+{
+  dw2_asm_output_data (4, type->dtd_u.dtu_slice.cts_type, "cts_type");
+  dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_offset, "cts_offset");
+  dw2_asm_output_data (2, type->dtd_u.dtu_slice.cts_bits, "cts_bits");
+}
+
+static void
+ctf_asm_array (ctf_dtdef_ref dtd)
+{
+  dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_contents, "cta_contents");
+  dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_index, "cta_index");
+  dw2_asm_output_data (4, dtd->dtd_u.dtu_arr.ctr_nelems, "cta_nelems");
+}
+
+static void
+ctf_asm_varent (ctf_dvdef_ref var)
+{
+  /* Output the reference to the name in the string table.  */
+  dw2_asm_output_data (4, var->dvd_name_offset, "ctv_name");
+  /* Output the type index.  */
+  dw2_asm_output_data (4, var->dvd_type, "ctv_typeidx");
+}
+
+static void
+ctf_asm_sou_lmember (ctf_dmdef_t * dmd)
+{
+  dw2_asm_output_data (4, dmd->dmd_name_offset, "ctlm_name");
+  dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMHI (dmd->dmd_offset),
+		       "ctlm_offsethi");
+  dw2_asm_output_data (4, dmd->dmd_type, "ctlm_type");
+  dw2_asm_output_data (4, CTF_OFFSET_TO_LMEMLO (dmd->dmd_offset),
+		       "ctlm_offsetlo");
+}
+
+static void
+ctf_asm_sou_member (ctf_dmdef_t * dmd)
+{
+  dw2_asm_output_data (4, dmd->dmd_name_offset, "ctm_name");
+  dw2_asm_output_data (4, dmd->dmd_offset, "ctm_offset");
+  dw2_asm_output_data (4, dmd->dmd_type, "ctm_type");
+}
+
+static void
+ctf_asm_enum_const (ctf_dmdef_t * dmd)
+{
+  dw2_asm_output_data (4, dmd->dmd_name_offset, "cte_name");
+  dw2_asm_output_data (4, dmd->dmd_value, "cte_value");
+}
+
+/* CTF writeout to asm file.  */
 
 static void
 output_ctf_header (ctf_container_ref ctfc)
@@ -133,6 +1404,282 @@ output_ctf_header (ctf_container_ref ctfc)
   ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label);
 
   ctf_asm_preamble (ctfc);
+
+  /* For a single compilation unit, the parent container's name and label are
+     NULL.  */
+  dw2_asm_output_data (4, 0, "cth_parlabel");
+  dw2_asm_output_data (4, 0, "cth_parname");
+
+  int typeslen = 0;
+  /* Initialize the offsets.  The offsets are from after the CTF header.  */
+  uint32_t lbloff = 0;
+  uint32_t objtoff = 0;
+  uint32_t funcoff = 0;
+  uint32_t varoff = 0;
+  uint32_t typeoff = 0;
+  uint32_t stroff = 0;
+
+  if (! is_empty_container (ctfc))
+    {
+      gcc_assert (get_num_ctf_types (ctfc)
+		  == (ctfc->ctfc_num_types + ctfc->ctfc_num_stypes));
+
+      /* Vars appear after function info.  */
+      varoff = funcoff + get_ctfc_num_funcinfo_bytes (ctfc);
+      /* CTF types appear after vars.  */
+      typeoff = varoff + get_num_ctf_vars (ctfc) * sizeof (ctf_varent_t);
+      /* The total number of bytes for CTF types is the sum of the number of
+	 times struct ctf_type_t, struct ctf_stype_t are written, plus the
+	 amount of variable length data after each one of these.  */
+      typeslen = ctfc->ctfc_num_types * sizeof (ctf_type_t)
+		+ ctfc->ctfc_num_stypes * (sizeof (ctf_stype_t))
+		+ get_ctfc_num_vlen_bytes (ctfc);
+
+      /* Strings appear after types.  */
+      stroff = typeoff + typeslen;
+    }
+
+    /* Offset of label section.  */
+    dw2_asm_output_data (4, lbloff, "cth_lbloff");
+    /* Offset of object section.  */
+    dw2_asm_output_data (4, objtoff, "cth_objtoff");
+    /* Offset of function section.  */
+    dw2_asm_output_data (4, funcoff, "cth_funcoff");
+    /* Offset of variable section.  */
+    dw2_asm_output_data (4, varoff, "cth_varoff");
+    /* Offset of type section.  */
+    dw2_asm_output_data (4, typeoff, "cth_typeoff");
+    /* Offset of string section.  */
+    dw2_asm_output_data (4, stroff, "cth_stroff");
+    /* Length of string section in bytes.  */
+    dw2_asm_output_data (4, ctfc->ctfc_strlen, "cth_strlen");
+}
+
+static void
+output_ctf_func_info (ctf_container_ref ctfc)
+{
+  unsigned long i, j;
+  ctf_dtdef_ref ctftype;
+  uint32_t vlen;
+
+  /* Compiler spits out the function type, return type, and args of each global
+     function in the CTF funcinfo section.  In no specific order.
+     TBD - An index needs to be added to associate these with the names.  */
+  for (i = 0; i < ctfc->ctfc_num_global_funcs; i++)
+    {
+      ctftype = ctfc->ctfc_gfuncs_list[i];
+      vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info);
+
+      /* function type.  */
+      dw2_asm_output_data (4, ctftype->dtd_type, "funcinfo_func_type");
+
+      /* return type.  */
+      dw2_asm_output_data (4, ctftype->dtd_data.ctti_type,
+			   "funcinfo_func_return_type");
+
+      /* function args types.  */
+      for (j = 0; j < vlen; j++)
+	dw2_asm_output_data (4, ctftype->dtd_u.dtu_argv[j].farg_type,
+			     "funcinfo_func_args");
+    }
+}
+
+/* Output the CTF variables.  Variables appear in the sort ASCIIbetical order
+   of their names.  This permits binary searching in the CTF reader.  */
+
+static void
+output_ctf_vars (ctf_container_ref ctfc)
+{
+  size_t i;
+  size_t num_ctf_vars = ctfc->ctfc_vars->elements ();
+  if (num_ctf_vars)
+    {
+      /* Iterate over the list of sorted vars and output the asm.  */
+      for (i = 0; i < num_ctf_vars; i++)
+	ctf_asm_varent (ctfc->ctfc_vars_list[i]);
+    }
+}
+
+/* Output the CTF string records.  */
+
+static void
+output_ctf_strs (ctf_container_ref ctfc)
+{
+  ctf_string_t * ctf_string = ctfc->ctfc_strtable.ctstab_head;
+
+  while (ctf_string)
+    {
+      dw2_asm_output_nstring (ctf_string->cts_str, -1, "ctf_string");
+      ctf_string = ctf_string->cts_next;
+    }
+}
+
+static void
+output_asm_ctf_sou_fields (ctf_container_ref ARG_UNUSED (ctfc),
+			   ctf_dtdef_ref dtd)
+{
+  ctf_dmdef_t * dmd;
+
+  /* Function pointer to dump struct/union members.  */
+  void (*ctf_asm_sou_field_func) (ctf_dmdef_t *);
+
+  uint32_t size = dtd->dtd_data.ctti_size;
+
+  /* The variable length data struct/union CTF types is an array of
+     ctf_member or ctf_lmember, depending on size of the member.  */
+  if (size >= CTF_LSTRUCT_THRESH)
+    ctf_asm_sou_field_func = ctf_asm_sou_lmember;
+  else
+    ctf_asm_sou_field_func = ctf_asm_sou_member;
+
+  for (dmd = dtd->dtd_u.dtu_members;
+       dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+    ctf_asm_sou_field_func (dmd);
+}
+
+static void
+output_asm_ctf_enum_list (ctf_container_ref ARG_UNUSED (ctfc),
+			  ctf_dtdef_ref dtd)
+{
+  ctf_dmdef_t * dmd;
+
+  for (dmd = dtd->dtd_u.dtu_members;
+       dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+    ctf_asm_enum_const (dmd);
+}
+
+static void
+output_asm_ctf_vlen_bytes (ctf_container_ref ctfc, ctf_dtdef_ref ctftype)
+{
+  uint32_t encoding;
+  uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+  uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info);
+  uint32_t i;
+
+  switch (kind)
+    {
+      case CTF_K_INTEGER:
+      case CTF_K_FLOAT:
+	if (kind == CTF_K_INTEGER)
+	  {
+	    encoding = CTF_INT_DATA (ctftype->dtd_u.dtu_enc.cte_format,
+				     ctftype->dtd_u.dtu_enc.cte_offset,
+				     ctftype->dtd_u.dtu_enc.cte_bits);
+	  }
+	else
+	  {
+	    encoding = CTF_FP_DATA (ctftype->dtd_u.dtu_enc.cte_format,
+				    ctftype->dtd_u.dtu_enc.cte_offset,
+				    ctftype->dtd_u.dtu_enc.cte_bits);
+	  }
+	dw2_asm_output_data (4, encoding, "ctf_encoding_data");
+	break;
+      case CTF_K_FUNCTION:
+	  {
+	    for (i = 0; i < vlen; i++)
+	      dw2_asm_output_data (4, ctftype->dtd_u.dtu_argv[i].farg_type,
+				   "dtu_argv");
+	    /* FIXME - CTF_PADDING_FOR_ALIGNMENT.
+	       libctf expects this padding for alignment reasons.  Expected to
+	       be redundant in CTF_VERSION_4.  */
+	    if (vlen & 1)
+	      dw2_asm_output_data (4, 0, "dtu_argv_padding");
+
+	    break;
+	  }
+      case CTF_K_ARRAY:
+	ctf_asm_array (ctftype);
+	break;
+      case CTF_K_SLICE:
+	ctf_asm_slice (ctftype);
+	break;
+
+      case CTF_K_STRUCT:
+      case CTF_K_UNION:
+	output_asm_ctf_sou_fields (ctfc, ctftype);
+	break;
+      case CTF_K_ENUM:
+	output_asm_ctf_enum_list (ctfc, ctftype);
+	break;
+
+      default:
+	/* CTF types of kind CTF_K_VOLATILE, CTF_K_CONST, CTF_K_RESTRICT,
+	   etc have no vlen data to write.  */
+	break;
+    }
+}
+
+static void
+output_asm_ctf_type (ctf_container_ref ctfc, ctf_dtdef_ref type)
+{
+  if (type->dtd_data.ctti_size <= CTF_MAX_SIZE)
+    ctf_asm_stype (type);
+  else
+    ctf_asm_type (type);
+  /* Now comes the variable-length portion for defining types completely.
+     E.g., encoding follows CTF_INT_DATA, CTF_FP_DATA types,
+     struct ctf_array_t follows CTF_K_ARRAY types, or a bunch of
+     struct ctf_member / ctf_lmember ctf_enum sit in there for CTF_K_STRUCT or
+     CTF_K_UNION.  */
+  output_asm_ctf_vlen_bytes (ctfc, type);
+}
+
+/* Output the CTF type records.  */
+
+static void
+output_ctf_types (ctf_container_ref ctfc)
+{
+  size_t i;
+  size_t num_ctf_types = ctfc->ctfc_types->elements ();
+  if (num_ctf_types)
+    {
+      /* Type ID = 0 is used as sentinel value; not a valid type.  */
+      for (i = 1; i <= num_ctf_types; i++)
+	output_asm_ctf_type (ctfc, ctfc->ctfc_types_list[i]);
+    }
+}
+
+static void
+ctf_decl (tree decl)
+{
+  switch (TREE_CODE (decl))
+    {
+    case ERROR_MARK:
+      return;
+
+    case FUNCTION_DECL:
+      gen_ctf_function (tu_ctfc, decl);
+      break;
+
+    case VAR_DECL:
+      gen_ctf_variable (tu_ctfc, decl);
+      break;
+
+    case TYPE_DECL:
+      /* Stay aligned to what DWARF does.
+	 DWARF has this check so as to not emit stubs for types unless they are
+	 needed by other DIEs.  */
+      if (TYPE_DECL_SUPPRESS_DEBUG (decl))
+	return;
+
+      if (DECL_IS_BUILTIN (decl))
+	return;
+
+      /* If we are in terse mode, don't generate any CTF for types.  */
+      if (ctf_debug_info_level <= CTFINFO_LEVEL_TERSE)
+	return;
+      /* If function-scope tag, do not generate CTF type info for it.  */
+      if (decl_function_context (decl))
+	return;
+
+      gen_ctf_typedef (tu_ctfc, decl);
+
+      break;
+
+    default:
+      /* No other TREE_CODE is expected at this time.  */
+      gcc_unreachable ();
+    }
 }
 
 /* CTF routines interfacing to the compiler.  */
@@ -149,16 +1696,32 @@ ctf_early_finish (const char * ARG_UNUSED (filename))
   if (ctf_debug_info_level == CTFINFO_LEVEL_NONE)
     return;
 
-  init_ctf_sections ();
+  init_ctf_sections (false);
+
+  /* Pre-process CTF before generating assembly.  */
+  ctf_preprocess (tu_ctfc);
 
   output_ctf_header (tu_ctfc);
+  output_ctf_func_info (tu_ctfc);
+  output_ctf_vars (tu_ctfc);
+  output_ctf_types (tu_ctfc);
+  output_ctf_strs (tu_ctfc);
+
+  /* The total number of string bytes must be equal to those processed out to
+     the str subsection.  */
+  gcc_assert (tu_ctfc->ctfc_strlen == get_cur_ctf_str_len (tu_ctfc));
+
+  delete_ctf_container (tu_ctfc);
 }
 
 void
-ctf_early_global_decl (tree ARG_UNUSED (decl))
+ctf_early_global_decl (tree decl)
 {
   /* Generate CTF type information if appropriate debug level is set
-     (ctf_debug_info_level == CTFINFO_LEVEL_NORMAL).  */
+     to CTFINFO_LEVEL_NORMAL.  */
+
+  if (ctf_debug_info_level == CTFINFO_LEVEL_NORMAL)
+    ctf_decl (decl);
 }
 
 /* Reset all state within ctfout.c so that we can rerun the compiler
@@ -170,6 +1733,7 @@ ctfout_c_finalize (void)
   ctf_info_section = NULL;
 
   delete_ctf_container (tu_ctfc);
+  tu_ctfc = NULL;
 }
 
 #include "gt-ctfout.h"
diff --git a/gcc/ctfout.h b/gcc/ctfout.h
index f281aaf..1ad360d 100644
--- a/gcc/ctfout.h
+++ b/gcc/ctfout.h
@@ -24,10 +24,189 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_CTFOUT_H
 #define GCC_CTFOUT_H 1
 
+#include "config.h"
+#include "system.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "tree-hash-traits.h"
 #include "ctf.h"
 
+/* Invalid CTF type ID definition.  */
+
+#define CTF_NULL_TYPEID 0
+
+/* Value to start generating the CTF type ID from.  */
+
+#define CTF_INIT_TYPEID 1
+
+/* CTF type ID.  */
+
+typedef unsigned long ctf_id_t;
+
+/* CTF string table element (list node).  */
+
+typedef struct GTY ((chain_next ("%h.cts_next"))) ctf_string
+{
+  const char * cts_str;		  /* CTF string.  */
+  struct ctf_string * cts_next;   /* A list node.  */
+} ctf_string_t;
+
+/* Internal representation of CTF string table.  */
+
+typedef struct GTY (()) ctf_strtable
+{
+  ctf_string_t * ctstab_head;	    /* Head str ptr.  */
+  ctf_string_t * ctstab_tail;	    /* Tail.  new str appended to tail.  */
+  int ctstab_num;		    /* Number of strings in the table.  */
+  size_t ctstab_len;		    /* Size of string table in bytes.  */
+  const char * ctstab_estr;	    /* Empty string "".  */
+} ctf_strtable_t;
+
+/* Encoding information for integers, floating-point values etc.  The flags
+   field will contain values appropriate for the type defined in <ctf.h>.  */
+
+typedef struct GTY (()) ctf_encoding
+{
+  unsigned int cte_format;  /* Data format (CTF_INT_* or CTF_FP_* flags).  */
+  unsigned int cte_offset;  /* Offset of value in bits.  */
+  unsigned int cte_bits;    /* Size of storage in bits.  */
+} ctf_encoding_t;
+
+/* Array information for CTF generation.  */
+
+typedef struct GTY (()) ctf_arinfo
+{
+  ctf_id_t ctr_contents;	/* Type of array contents.  */
+  ctf_id_t ctr_index;		/* Type of array index.  */
+  unsigned int ctr_nelems;	/* Number of elements.  */
+} ctf_arinfo_t;
+
+/* Function information for CTF generation.  */
+
+typedef struct GTY (()) ctf_funcinfo
+{
+  ctf_id_t ctc_return;		/* Function return type.  */
+  unsigned int ctc_argc;	/* Number of typed arguments to function.  */
+  unsigned int ctc_flags;	/* Function attributes (see below).  */
+} ctf_funcinfo_t;
+
+typedef struct GTY (()) ctf_sliceinfo
+{
+  unsigned int cts_type;	/* Reference CTF type.  */
+  unsigned short cts_offset;	/* Offset in bits of the first bit.  */
+  unsigned short cts_bits;	/* Size in bits.  */
+} ctf_sliceinfo_t;
+
+/* CTF type representation internal to the compiler.  It closely reflects the
+   ctf_type_t type node in <ctf.h> except the GTY (()) tags.  */
+
+typedef struct GTY (()) ctf_itype
+{
+  unsigned int ctti_name;	/* Reference to name in string table.  */
+  unsigned int ctti_info;	/* Encoded kind, variant length (see below).  */
+  union GTY ((desc ("0")))
+  {
+    unsigned int GTY ((tag ("0"))) _size;/* Size of entire type in bytes.  */
+    unsigned int GTY ((tag ("1"))) _type;/* Reference to another type.  */
+  } _u;
+  unsigned int ctti_lsizehi;	/* High 32 bits of type size in bytes.  */
+  unsigned int ctti_lsizelo;	/* Low 32 bits of type size in bytes.  */
+} ctf_itype_t;
+
+#define ctti_size _u._size
+#define ctti_type _u._type
+
+/* Function arguments end with varargs.  */
+
+#define CTF_FUNC_VARARG 0x1
+
+/* Struct/union/enum member definition for CTF generation.  */
+
+typedef struct GTY ((chain_next ("%h.dmd_next"))) ctf_dmdef
+{
+  const char * dmd_name;	/* Name of this member.  */
+  ctf_id_t dmd_type;		/* Type of this member (for sou).  */
+  unsigned int dmd_name_offset;	/* Offset of the name in str table.  */
+  unsigned long dmd_offset;	/* Offset of this member in bits (for sou).  */
+  int dmd_value;		/* Value of this member (for enum).  */
+  struct ctf_dmdef * dmd_next;	/* A list node.  */
+} ctf_dmdef_t;
+
+/* Function Argument.  (Encapsulated because GTY machinery does not like
+   non struct/union members.  See usage in ctf_dtdef_t.)  */
+
+typedef struct GTY (()) ctf_func_arg
+{
+  ctf_id_t farg_type;		/* Type identifier of the argument.  */
+} ctf_func_arg_t;
+
+typedef struct GTY (()) ctf_dtdef_key
+{
+  tree dtdk_key_decl;		/* Tree decl corresponding to the type.  */
+  unsigned int dtdk_key_flags;  /* Extra flags for hashing the type.  */
+} ctf_dtdef_key_t;
+
+/* Type definition for CTF generation.  */
+
+typedef struct GTY (()) ctf_dtdef
+{
+  ctf_dtdef_key_t dtd_key;    /* Type key for hashing.  */
+  const char * dtd_name;      /* Name associated with definition (if any).  */
+  ctf_id_t dtd_type;	      /* Type identifier for this definition.  */
+  ctf_itype_t dtd_data;	      /* Type node.  */
+  union GTY ((desc ("ctf_dtu_d_union_selector (&%1)")))
+  {
+    /* struct, union, or enum.  */
+    ctf_dmdef_t * GTY ((tag ("CTF_DTU_D_MEMBERS"))) dtu_members;
+    /* array.  */
+    ctf_arinfo_t GTY ((tag ("CTF_DTU_D_ARRAY"))) dtu_arr;
+    /* integer or float.  */
+    ctf_encoding_t GTY ((tag ("CTF_DTU_D_ENCODING"))) dtu_enc;
+    /* function.  */
+    ctf_func_arg_t * GTY ((tag ("CTF_DTU_D_ARGUMENTS"))) dtu_argv;
+    /* slice.  */
+    ctf_sliceinfo_t GTY ((tag ("CTF_DTU_D_SLICE"))) dtu_slice;
+  } dtd_u;
+} ctf_dtdef_t;
+
+#define dtd_decl dtd_key.dtdk_key_decl
+#define dtd_key_flags dtd_key.dtdk_key_flags
+
+/* Variable definition for CTF generation.  */
+
+typedef struct GTY (()) ctf_dvdef
+{
+  tree dvd_decl;		/* Tree decl corresponding to the variable.  */
+  const char * dvd_name;	/* Name associated with variable.  */
+  unsigned int dvd_name_offset;	/* Offset of the name in str table.  */
+  ctf_id_t dvd_type;		/* Type of variable.  */
+} ctf_dvdef_t;
+
+typedef ctf_dvdef_t * ctf_dvdef_ref;
+typedef ctf_dtdef_t * ctf_dtdef_ref;
+
+/* Helper enum and api for the GTY machinery to work on union dtu_d.  */
+
+enum ctf_dtu_d_union_enum {
+  CTF_DTU_D_MEMBERS,
+  CTF_DTU_D_ARRAY,
+  CTF_DTU_D_ENCODING,
+  CTF_DTU_D_ARGUMENTS,
+  CTF_DTU_D_SLICE
+};
+
+enum ctf_dtu_d_union_enum
+ctf_dtu_d_union_selector (ctf_dtdef_ref);
+
+struct ctf_dtdef_hash : ggc_ptr_hash<ctf_dtdef_t>
+{
+  typedef ctf_dtdef_ref compare_type;
+  static hashval_t hash (ctf_dtdef_ref);
+  static bool equal (ctf_dtdef_ref, ctf_dtdef_ref);
+};
+
 /* CTF container structure.
-   It is the context passed around when generating CTF debug info.  There is
+   It is the context passed around when generating ctf debug info.  There is
    one container per translation unit.  */
 
 typedef struct GTY (()) ctf_container
@@ -36,12 +215,63 @@ typedef struct GTY (()) ctf_container
   unsigned short ctfc_magic;
   unsigned char ctfc_version;
   unsigned char ctfc_flags;
-  /* CTF Types.  */
-  // hash_map <ctf_dtdef_hash, ctf_dtdefp_t> * GTY (()) ctfc_types;
+
+  /* CTF types.  */
+  hash_map <ctf_dtdef_hash, ctf_dtdef_ref> * GTY (()) ctfc_types;
+  /* CTF variables.  */
+  hash_map <tree_decl_hash, ctf_dvdef_ref> * GTY (()) ctfc_vars;
+  /* CTF string table.  */
+  ctf_strtable_t ctfc_strtable;
+
+  unsigned long ctfc_num_types;
+  unsigned long ctfc_num_stypes;
+  unsigned long ctfc_num_global_funcs;
+
+  unsigned long ctfc_num_funcinfo_bytes;
+  /* Number of vlen bytes - the variable length portion after ctf_type_t and
+     ctf_stype_t in the CTF section.  This is used to calculate the offsets in
+     the CTF header.  */
+  unsigned long ctfc_num_vlen_bytes;
+
+  /* Next CTF type id to assign.  */
+  ctf_id_t ctfc_nextid;
+  /* List of pre-processed CTF Variables.  CTF requires that the variables
+     appear in the sorted order of their names.  */
+  ctf_dvdef_t ** GTY ((length ("%h.ctfc_vars ? %h.ctfc_vars->elements () : 0"))) ctfc_vars_list;
+  /* List of pre-processed CTF types.  CTF requires that a shared type must
+     appear before the type that uses it.  For the compiler, this means types
+     are emitted in sorted order of their type IDs.  */
+  ctf_dtdef_t ** GTY ((length ("%h.ctfc_types ? %h.ctfc_types->elements () : 0"))) ctfc_types_list;
+  /* List of CTF function types for global functions.  The order of global
+     function entries in the CTF funcinfo section is undefined by the
+     compiler.  */
+  ctf_dtdef_t ** GTY ((length ("%h.ctfc_num_global_funcs"))) ctfc_gfuncs_list;
+
+  /* Following members are for debugging only.  They do not add functional
+     value to the task of CTF creation.  These can be cleaned up once CTF
+     generation stabilizes.  */
+
+  /* Keep a count of the number of bytes dumped in asm for debugging
+     purposes.  */
+  unsigned long ctfc_numbytes_asm;
+   /* Total length of all strings in CTF.  */
+  size_t ctfc_strlen;
+
 } ctf_container_t;
 
 typedef ctf_container_t * ctf_container_ref;
 
+/* If the next ctf type id is still set to the init value, no ctf records to
+   report.  */
+#define is_empty_container(ctfc) (((ctfc)->ctfc_nextid == CTF_INIT_TYPEID))
+#define get_num_ctf_vars(ctfc)   (ctfc->ctfc_vars->elements ())
+#define get_num_ctf_types(ctfc)  (ctfc->ctfc_types->elements ())
+
+#define get_cur_ctf_str_len(ctfc)      ((ctfc)->ctfc_strtable.ctstab_len)
+
+#define get_ctfc_num_vlen_bytes(ctfc)	((ctfc)->ctfc_num_vlen_bytes)
+#define get_ctfc_num_funcinfo_bytes(ctfc) ((ctfc)->ctfc_num_funcinfo_bytes)
+
 void ctf_debug_init (void);
 
 void ctf_early_global_decl (tree decl);
@@ -50,4 +280,80 @@ void ctf_early_finish (const char * filename);
 
 void ctfout_c_finalize (void);
 
+/* The compiler demarcates whether types are visible at top-level scope or not.
+   The only example so far of a type not visible at top-level scope is slices.
+   CTF_ADD_NONROOT is used to indicate the latter.  */
+#define	CTF_ADD_NONROOT	0	/* CTF type only visible in nested scope.  */
+#define	CTF_ADD_ROOT	1	/* CTF type visible at top-level scope.  */
+
+/* Interface from ctfcreate.c to ctfout.c.
+   These APIs create CTF types and add them to the CTF container associated
+   with the translation unit.  The return value is the typeID of the CTF type
+   added to the container.  */
+extern ctf_id_t ctf_add_volatile (ctf_container_ref, uint32_t, ctf_id_t, tree,
+				  uint32_t);
+extern ctf_id_t ctf_add_const (ctf_container_ref, uint32_t, ctf_id_t, tree,
+			       uint32_t);
+extern ctf_id_t ctf_add_restrict (ctf_container_ref, uint32_t, ctf_id_t, tree,
+				  uint32_t);
+extern ctf_id_t ctf_add_enum (ctf_container_ref, uint32_t, const char *,
+			      HOST_WIDE_INT, tree);
+extern ctf_id_t ctf_add_slice (ctf_container_ref, uint32_t, ctf_id_t,
+			       const ctf_encoding_t *, tree);
+extern ctf_id_t ctf_add_float (ctf_container_ref, uint32_t, const char *,
+			       const ctf_encoding_t *, tree);
+extern ctf_id_t ctf_add_integer (ctf_container_ref, uint32_t, const char *,
+				 const ctf_encoding_t *, tree);
+extern ctf_id_t ctf_add_pointer (ctf_container_ref, uint32_t flag, ctf_id_t,
+				 tree);
+extern ctf_id_t ctf_add_array (ctf_container_ref, uint32_t,
+			       const ctf_arinfo_t *, tree);
+extern ctf_id_t ctf_add_forward (ctf_container_ref, uint32_t, const char *,
+				 uint32_t, tree);
+extern ctf_id_t ctf_add_typedef (ctf_container_ref, uint32_t, const char *,
+				 ctf_id_t, tree);
+extern ctf_id_t ctf_add_function (ctf_container_ref, uint32_t, const char *,
+				  const ctf_funcinfo_t *, ctf_func_arg_t *,
+				  tree);
+extern ctf_id_t ctf_add_sou (ctf_container_ref, uint32_t, const char *,
+			     uint32_t, size_t, tree);
+
+extern int ctf_add_enumerator (ctf_container_ref, ctf_id_t, const char *,
+			       HOST_WIDE_INT, tree);
+extern int ctf_add_member_offset (ctf_container_ref, tree, const char *,
+				  ctf_id_t, unsigned long);
+extern int ctf_add_variable (ctf_container_ref, const char *, ctf_id_t, tree);
+
+/* Interface from ctfutils.c.
+   Utility functions for CTF generation.  */
+
+#define ctf_dmd_list_next(elem)		((ctf_dmdef_t *)((elem)->dmd_next))
+
+extern void ctf_dmd_list_append (ctf_dmdef_t **, ctf_dmdef_t *);
+
+extern void ctf_dtd_insert (ctf_container_ref, ctf_dtdef_ref);
+extern void ctf_dtd_delete (ctf_container_ref, ctf_dtdef_ref);
+extern ctf_dtdef_ref ctf_dtd_lookup (const ctf_container_ref, const tree);
+extern ctf_dtdef_ref ctf_dtd_lookup_with_flags (const ctf_container_ref,
+						const tree,
+						const unsigned int);
+
+extern void ctf_dvd_insert (ctf_container_ref, ctf_dvdef_ref);
+extern void ctf_dvd_delete (ctf_container_ref, ctf_dvdef_ref);
+extern ctf_dvdef_ref ctf_dvd_lookup (const ctf_container_ref, const tree);
+
+extern int ctf_varent_compare (const void *, const void *);
+extern unsigned long ctf_calc_num_vbytes (ctf_dtdef_ref);
+
+/* Add a str to the CTF string table.  */
+extern const char * ctf_add_string (ctf_container_ref, const char *,
+				    uint32_t *);
+
+extern void list_add_ctf_vars (ctf_container_ref, ctf_dvdef_ref);
+
+/* Interface from ctfout.c to ctfutils.c.  */
+
+extern hashval_t hash_dtd_tree_decl (tree, uint32_t);
+extern hashval_t hash_dvd_tree_decl (tree);
+
 #endif /* GCC_CTFOUT_H */
diff --git a/gcc/ctfutils.c b/gcc/ctfutils.c
new file mode 100644
index 0000000..805c91f
--- /dev/null
+++ b/gcc/ctfutils.c
@@ -0,0 +1,198 @@
+/* Functions to create and update CTF from GCC.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+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/>.  */
+
+/* This file contains implementation of various utility functions to collect
+   and keep CTF information.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "ctfout.h"
+
+/* Append member definition to the list.  Member list is a singly-linked list
+   with list start pointing to the head.  */
+
+void
+ctf_dmd_list_append (ctf_dmdef_t ** dmd, ctf_dmdef_t * elem)
+{
+  ctf_dmdef_t * tail = (dmd && *dmd) ? *dmd : NULL;
+  if (tail)
+    {
+      while (tail->dmd_next)
+	tail = tail->dmd_next;
+
+      tail->dmd_next = elem;
+    }
+  else
+    *dmd = elem;
+
+  elem->dmd_next = NULL;
+}
+
+/* Compare two CTF variable definition entries.  Currently used for sorting
+   by name.  */
+
+int
+ctf_varent_compare (const void * entry1, const void * entry2)
+{
+  int result;
+  const ctf_dvdef_t * e1 = *(const ctf_dvdef_t * const*) entry1;
+  const ctf_dvdef_t * e2 = *(const ctf_dvdef_t * const*) entry2;
+
+  result = strcmp (e1->dvd_name, e2->dvd_name);
+
+  return result;
+}
+
+/* Add str to CTF string table.  No de-duplication of CTF strings is done by
+   the compiler.  */
+
+static void
+ctfc_strtable_add_str (ctf_strtable_t * str_table, const char * str)
+{
+  ctf_string_t * ctf_string = ggc_cleared_alloc<ctf_string_t> ();
+  /* Keep a reference to the input STR.  */
+  ctf_string->cts_str = str;
+  ctf_string->cts_next = NULL;
+
+  if (!str_table->ctstab_head)
+    str_table->ctstab_head = ctf_string;
+
+  /* Append to the end of the list.  */
+  if (str_table->ctstab_tail)
+    str_table->ctstab_tail->cts_next = ctf_string;
+
+  str_table->ctstab_tail = ctf_string;
+}
+
+const char *
+ctf_add_string (ctf_container_ref ctfc, const char * name,
+		uint32_t * name_offset)
+{
+  size_t len;
+  char * ctf_string;
+  /* Return value is the offset to the string in the string table.  */
+  uint32_t str_offset = get_cur_ctf_str_len (ctfc);
+
+  /* Add empty string only once at the beginning of the string table.  Also, do
+     not add null strings, return the offset to the empty string for them.  */
+  if ((!name || (name != NULL && !strcmp (name, ""))) && str_offset)
+    {
+      ctf_string = CONST_CAST (char *, ctfc->ctfc_strtable.ctstab_estr);
+      str_offset = 0;
+    }
+  else
+    {
+      gcc_assert (name);
+      /* Add null-terminated strings to the string table.  */
+      len = strlen (name) + 1;
+      ctf_string = CONST_CAST (char *, ggc_strdup (name));
+
+      ctfc_strtable_add_str (&(ctfc->ctfc_strtable), ctf_string);
+      /* Add string to the string table.  Keep number of strings updated.  */
+      ctfc->ctfc_strtable.ctstab_num++;
+      /* Keep the number of bytes contained in the CTF string table updated.  */
+      (ctfc)->ctfc_strtable.ctstab_len += len;
+    }
+
+  *name_offset = str_offset;
+
+  return (const char *) ctf_string;
+}
+
+/* A CTF type record may be followed by variable-length of bytes to encode the
+   CTF type completely.  This routine calculates the number of bytes, in the
+   final binary CTF format, which are used to encode information about the type
+   completely.
+
+   This function must always be in sync with the CTF header.  */
+
+unsigned long
+ctf_calc_num_vbytes (ctf_dtdef_ref ctftype)
+{
+  uint32_t size;
+  unsigned long vlen_bytes = 0;
+
+  uint32_t kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+  uint32_t vlen = CTF_V2_INFO_VLEN (ctftype->dtd_data.ctti_info);
+
+  ctf_dmdef_t * dmd;
+  uint32_t size_per_member = 0;
+  unsigned int num_members = 0;
+
+  switch (kind)
+    {
+      case CTF_K_FORWARD:
+      case CTF_K_UNKNOWN:
+      case CTF_K_POINTER:
+      case CTF_K_TYPEDEF:
+      case CTF_K_VOLATILE:
+      case CTF_K_CONST:
+      case CTF_K_RESTRICT:
+	/* These types have no vlen data.  */
+	break;
+
+      case CTF_K_INTEGER:
+      case CTF_K_FLOAT:
+	/* 4 bytes to represent encoding CTF_INT_DATA, CTF_FP_DATA.  */
+	vlen_bytes += sizeof (uint32_t);
+	break;
+      case CTF_K_FUNCTION:
+	/* FIXME - CTF_PADDING_FOR_ALIGNMENT.  */
+	vlen_bytes += (vlen + (vlen & 1)) * sizeof (uint32_t);
+	break;
+      case CTF_K_ARRAY:
+	/* This has a single ctf_array_t.  */
+	vlen_bytes += sizeof (ctf_array_t);
+	break;
+      case CTF_K_SLICE:
+	vlen_bytes += sizeof (ctf_slice_t);
+	break;
+      case CTF_K_STRUCT:
+      case CTF_K_UNION:
+	/* Count the number and type of members.  */
+	size = ctftype->dtd_data.ctti_size;
+	size_per_member = size >= CTF_LSTRUCT_THRESH
+			  ? sizeof (ctf_lmember_t) : sizeof (ctf_member_t);
+
+	/* Sanity check - number of members of struct must be the same as
+	   vlen.  */
+	for (dmd = ctftype->dtd_u.dtu_members;
+	     dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
+	  num_members++;
+	gcc_assert (vlen == num_members);
+
+	vlen_bytes += (num_members * size_per_member);
+	break;
+      case CTF_K_ENUM:
+	vlen_bytes += vlen * sizeof (ctf_enum_t);
+	break;
+      default :
+	break;
+    }
+  return vlen_bytes;
+}
+
+void
+list_add_ctf_vars (ctf_container_ref ctfc, ctf_dvdef_ref var)
+{
+  /* FIXME - static may not fly with multiple CUs.  */
+  static int num_vars_added = 0;
+  ctfc->ctfc_vars_list[num_vars_added++] = var;
+}
diff --git a/include/ctf.h b/include/ctf.h
index 3a6f266..5289846 100644
--- a/include/ctf.h
+++ b/include/ctf.h
@@ -378,13 +378,17 @@ union
    ctt_type, which must be a type which has an encoding (fp, int, or enum).  We
    also store the referenced type in here, because it is easier to keep the
    ctt_size correct for the slice than to shuffle the size into here and keep
-   the ctt_type where it is for other types.  */
+   the ctt_type where it is for other types.
+
+   In a future version, where we loosen requirements on alignment in the CTF
+   file, the cts_offset and cts_bits will be chars: but for now they must be
+   shorts or everything after a slice will become unaligned.  */
 
 typedef struct ctf_slice
 {
   uint32_t cts_type;
-  unsigned char cts_offset;
-  unsigned char cts_bits;
+  unsigned short cts_offset;
+  unsigned short cts_bits;
 } ctf_slice_t;
 
 typedef struct ctf_array
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH,RFC,V3 1/5] Add new function lang_GNU_GIMPLE
  2019-06-27  6:37 [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
                   ` (2 preceding siblings ...)
  2019-06-27  6:37 ` [PATCH,RFC,V3 4/5] CTF generation for a single compilation unit Indu Bhagat
@ 2019-06-27  6:37 ` Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 2/5] Add CTF command line options : -gtLEVEL Indu Bhagat
  2019-07-02 17:43 ` [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
  5 siblings, 0 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-06-27  6:37 UTC (permalink / raw)
  To: gcc-patches, richard.guenther

gcc/ChangeLog:

	* langhooks.c (lang_GNU_GIMPLE): New Function.
	* langhooks.h: New Prototype.
 
---
 gcc/ChangeLog   | 5 +++++
 gcc/langhooks.c | 9 +++++++++
 gcc/langhooks.h | 1 +
 3 files changed, 15 insertions(+)

diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 2df97f2..f3a64c1 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -825,3 +825,12 @@ lang_GNU_OBJC (void)
 {
   return strncmp (lang_hooks.name, "GNU Objective-C", 15) == 0;
 }
+
+/* Returns true if the current lang_hooks represents the GNU GIMPLE
+   frontend.  */
+
+bool
+lang_GNU_GIMPLE (void)
+{
+  return strncmp (lang_hooks.name, "GNU GIMPLE", 10) == 0;
+}
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index a45579b..0ac794e 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -570,5 +570,6 @@ extern bool lang_GNU_C (void);
 extern bool lang_GNU_CXX (void);
 extern bool lang_GNU_Fortran (void);
 extern bool lang_GNU_OBJC (void);
+extern bool lang_GNU_GIMPLE (void);
 
 #endif /* GCC_LANG_HOOKS_H */
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH,RFC,V3 5/5] Update CTF testsuite
  2019-06-27  6:37 [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 3/5] Setup for CTF generation and emission Indu Bhagat
@ 2019-06-27  6:37 ` Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 4/5] CTF generation for a single compilation unit Indu Bhagat
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-06-27  6:37 UTC (permalink / raw)
  To: gcc-patches, richard.guenther

gcc/testsuite/ChangeLog : 
 
	* gcc.dg/debug/ctf/ctf-2.c: New test.
	* gcc.dg/debug/ctf/ctf-anonymous-struct-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-anonymous-union-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-array-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-bitfields-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-bitfields-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-cvr-quals-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-cvr-quals-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-cvr-quals-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-enum-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-forward-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-forward-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-function-pointers-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-functions-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-pointers-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-str-table-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-array-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-struct-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-union-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-variables-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-float-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-int-1.c: Likewise.

---
 gcc/testsuite/ChangeLog                            | 28 ++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c             | 10 +++++
 .../gcc.dg/debug/ctf/ctf-anonymous-struct-1.c      | 23 +++++++++++
 .../gcc.dg/debug/ctf/ctf-anonymous-union-1.c       | 26 +++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c       | 31 +++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c   | 30 +++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c   | 39 +++++++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c   | 44 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c   | 30 +++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c   | 41 ++++++++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c        | 21 +++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c       | 16 ++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c     | 36 ++++++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c     | 16 ++++++++
 .../gcc.dg/debug/ctf/ctf-function-pointers-1.c     | 24 ++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c   | 34 +++++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c         | 17 +++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c    | 26 +++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c   | 26 +++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c      | 25 ++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c      | 30 +++++++++++++++
 .../gcc.dg/debug/ctf/ctf-struct-array-1.c          | 36 ++++++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c     | 23 +++++++++++
 .../gcc.dg/debug/ctf/ctf-typedef-struct-1.c        | 12 ++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c       | 14 +++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c   | 25 ++++++++++++
 26 files changed, 683 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c

diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c
new file mode 100644
index 0000000..891f20e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c
@@ -0,0 +1,10 @@
+/* A LEVEL of 0 with -gt turns off CTF debug info generation.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt0 -dA" } */
+
+/* { dg-final { scan-assembler-times "0xdff2.*CTF preamble magic number" 0} } */
+/* { dg-final { scan-assembler-times "0x4.*CTF preamble version" 0 } } */
+/* { dg-final { scan-assembler-times "0.*CTF preamble flags" 0 } } */
+
+const char * _CONTEXT_NAME = "foobar";
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c
new file mode 100644
index 0000000..0973b2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c
@@ -0,0 +1,23 @@
+/* Test compilation and CTF generation of anonymous structs.  An anonymous
+   struct type is encoded as no-name CTF struct type.
+
+   For this testcase, a single CTF anonymous struct is expected.
+   struct {} : ctt_name = 0 (point to offset 0 in the CTF string table to
+			    denote empty string)
+   
+   Two CTF struct records should be generated in total.
+   struct a : ctt_info = 0x1a000002 (2 fields)
+   struct {} : ctt_info = 0x1a000001 (1 field)  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 1 } } */
+/* { dg-final { scan-assembler-times "0x1a000002\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "0x1a000001\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+struct a
+{
+  struct { int b1; } a1;
+  int a2;
+} my_a;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c
new file mode 100644
index 0000000..71b491a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c
@@ -0,0 +1,26 @@
+/* Test compilation and CTF generation of anonymous union.  An anonymous union
+   is encoded as no-name CTF union type.
+
+   For this testcase, a single CTF anonymous union is expected.
+   struct {} : ctt_name = 0 (point to offset 0 in the CTF string table to
+			    denote empty string)
+   
+   Two CTF struct records should be generated in total.
+   struct anon_union : ctt_info = 0x1a000001 (1 field)
+   union {} : ctt_info = 0x1e000002 (2 fields)  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 1 } } */
+/* { dg-final { scan-assembler-times "0x1a000001\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "0x1e000002\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+struct anon_union
+{
+  union
+    {
+      char name;
+      int value;
+    };
+} my_anon_u;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c
new file mode 100644
index 0000000..cca8c42
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c
@@ -0,0 +1,31 @@
+/* CTF generation for array type.
+
+   Unsized arrays are encoded with a 0 for the number of elements.
+
+   In this testcase, 5 distinct CTF records for arrays are expected
+   b1 : cta_nelems = 2
+   c1 : cta_nelems = 3
+   a1 : cta_nelems = 2, 5
+   buf1 : cta_nelems = 0.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "0x12000000\[\t \]+\[^\n\]*ctt_info" 5 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cta_nelems" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t \]+\[^\n\]*cta_nelems" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x5\[\t \]+\[^\n\]*cta_nelems" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*cta_nelems" 1 } } */
+
+int b1[2] = {0,1};
+int c1[5] = {0,1,2,3,4};
+int a1[2][3] = { {3,4,5}, {2,3,4} };
+
+/* Variable length struct using arrays.  */
+struct my_array
+{
+  int flags;
+  int length;
+  int buf[];
+} my_array_obj;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c
new file mode 100644
index 0000000..5f26629
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c
@@ -0,0 +1,30 @@
+/* CTF generation for bitfields.
+   
+   In this testcase, two slices are expected - one for enum and the other for
+   int.  CTF slices are unnamed records.  */
+   
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_bits" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t \]+\[^\n\]*cts_bits" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 2 } } */
+
+enum color
+{
+  RED,
+  GREEN,
+  BLUE,
+  YELLOW,
+  ORANGE,
+  BLACK
+};
+
+struct quickcolor
+{
+  enum color col:3;
+  int brushid:2;
+  int strokes;
+};
+
+struct quickcolor qc;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c
new file mode 100644
index 0000000..ed85cf3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c
@@ -0,0 +1,39 @@
+/* The bitfield type (int) may be shared, but slices are not de-duplicated.
+
+   In this testcase, it is expected to see a total of 6 CTF slices and 2 CTF
+   integer types for the bitfields - unsigned long long and signed long long.
+   
+   cts_offset is the offset of the bitfield into a machine word.
+   TBD - hardcoding cts_offset checks into the testcase will cause it to break
+   across targets with different BIT_PER_WORD.  Is there a way to add
+   cts_offset related checks in the testcase?  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x6\[\t \]+\[^\n\]*cts_type" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_type" 3 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0xf\[\t \]+\[^\n\]*cts_bits" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x21\[\t \]+\[^\n\]*cts_bits" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x10\[\t \]+\[^\n\]*cts_bits" 2 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"long long unsigned int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"long long int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+struct fields
+{
+  unsigned long long u1 : 15;
+  unsigned long long u2 : 33;
+  unsigned long long u3 : 16;
+  signed long long   s1 : 15;
+  signed long long   s2 : 33;
+  signed long long   s3 : 16;
+} flags;
+
+int i = 33;
+
+int main ()
+{
+    return flags.u1 + i;
+}
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c
new file mode 100644
index 0000000..318a171
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c
@@ -0,0 +1,44 @@
+/* Test compilation of stubs with various qualifiers - const, restrict and
+   volatile.
+
+   Testcase includes a std header to allow testing of shared types across
+   files.  Only one CTF record for int is expected.
+   
+   CTF records for CVR qualifiers are no-name records.  In this testcase, there
+   are 7 qualifiers across constructs.  2 more no-name CTF records correspond to
+   CTF pointer records.
+
+    TYPEID: name string (size) -> ref TYPEID : ref name string (size) -> ...
+
+    b: volatile int (size 4) -> 5: int (size 4)
+    c: const volatile int (size 4) -> b: volatile int (size 4) -> 5: int (size 4)
+    e: int *restrict (size 8) -> d: int * (size 8) -> 5: int (size 4)
+    f: const int (size 4) -> 5: int (size 4)
+    10: const int * (size 8) -> f: const int (size 4) -> 5: int (size 4)
+    12: int *const (size 8) -> d: int * (size 8) -> 5: int (size 4)
+    14: const int *restrict (size 8) -> 10: const int * (size 8) -> f: const int (size 4) -> 5: int (size 4)
+    */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 9 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+#include "stddef.h"
+
+const volatile int a = 5;
+int *restrict b;
+
+const int * i;
+int const * j;
+
+typedef int * INTP;
+const INTP int_p;
+
+void foo (size_t n, int *restrict p, const int *restrict q)
+{
+  while (n-- > 0)
+    *p++ = *q++;
+}
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c
new file mode 100644
index 0000000..8ce6676
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c
@@ -0,0 +1,30 @@
+/* Test compilation of stubs with various expressions involving const
+   qualifier.
+   
+   In this testcase, a single CTF record for const int is expected. A total of
+   two const qualifier CTF records are expected (const int and const struct
+   s1).  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+struct mystruct
+{
+  struct
+    {
+      int a; 
+      const int b;
+    } s1;
+  char * name;
+} my_a;
+
+struct s1
+{
+  int i;
+  const int ci;
+} s;
+
+const struct s1 cs;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c
new file mode 100644
index 0000000..6ec17a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c
@@ -0,0 +1,41 @@
+/* Test compilation of stubs with various expressions involving const and
+   volatile qualifiers.
+   
+   In this testcase, it is expected to have const and volatile CTF records,
+   some of which are shared or referenced (shown by '->' below) :
+
+   Types:
+    1: unsigned char (size 1)
+    2: volatile unsigned char (size 1) -> 1: unsigned char (size 1)
+    3: const volatile unsigned char (size 1) -> 2: volatile unsigned char (size 1) -> 1: unsigned char (size 1)
+    4: const volatile unsigned char * (size 8) -> 3: const volatile unsigned char (size 1) -> 2: volatile unsigned char (size 1) -> 1: unsigned char (size 1) [POINTER_TYPE]
+    5: int (size 4)
+    6: float (size 4)
+    7: volatile float (size 4) -> 6: float (size 4)
+    8: volatile float [2] (size 8) [ARRAY_TYPE]
+    9: char (size 1)
+    a: volatile char (size 1) -> 9: char (size 1)
+    b: const volatile char (size 1) -> a: volatile char (size 1) -> 9: char (size 1)
+    c: const volatile char [2] (size 2) [ARRAY_TYPE]
+
+    Types 2, 3, 7, a, and b are CTF types of kind CTF_K_CONST or CTF_K_VOLATILE.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2e000000\[\t \]+\[^\n\]*ctt_info" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+/* Two arrays.  */
+/* { dg-final { scan-assembler-times "\[\t \]0x12000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+
+const volatile unsigned char  vicar = 11;
+
+const volatile unsigned char * vicarage = &vicar;
+
+volatile float vilify[2];
+
+const volatile char victor = 'Y';
+
+const volatile char vindictive[2];
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c
new file mode 100644
index 0000000..d91a419
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c
@@ -0,0 +1,21 @@
+/* CTF generation for enums.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"RED.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"GREEN.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"BLUE.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"YELLOW.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "cte_value" 4} } */
+
+
+enum foo_color
+{
+  RED,
+  GREEN,
+  BLUE,
+  YELLOW
+};
+
+enum foo_color my_color;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c
new file mode 100644
index 0000000..ae2dfc2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c
@@ -0,0 +1,16 @@
+/* Tests for CTF float base types.
+   - Verify that there is a single record for the base types.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler-times "ascii \"float.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"long double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+float a;
+float b = 33;
+
+double c = 44;
+double d = 45;
+
+long double e;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
new file mode 100644
index 0000000..8254d3e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
@@ -0,0 +1,36 @@
+/* CTF forward type is generated for forward declarations of types in C.
+   
+   Check that the ctf-kind of CTF_K_FOWARD type is CTF_K_STRUCT or CTF_K_UNION.
+   For forward types, the compiler encodes the CTF kind in the ctt_type field.
+   CTF_K_FORWARD is used as the CTF type as usual in the ctt_info.  */
+
+/* Note - A value of 6 in "ctt_size or ctt_type" appears twice in this
+   testcase. This might be misconstrued as  2 CTK_K_FORWARD records of struct
+   type.  The second assembler tag is due to a ref type in a CVR CTF record.
+   TBD - perhaps a more robust string pattern is needed.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x26000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x6\[\t \]+\[^\n\]*ctt_size or ctt_type" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x7\[\t \]+\[^\n\]*ctt_size or ctt_type" 1 } } */
+
+typedef struct __locale_struct
+{
+  struct __locale_data *__locales[13]; /* forward struct type.  */
+
+  const int *__ctype_toupper;
+  const char *__names[13];
+} *__locale_t;
+
+typedef __locale_t locale_t;
+
+typedef struct __inter_struct
+{
+  union __inter_data * __inters[13]; /* forward union type.  */
+
+  const int * __ctype_kind;
+} * __inter_t;
+
+typedef __inter_t inter_t;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c
new file mode 100644
index 0000000..33080f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c
@@ -0,0 +1,16 @@
+/* CTF forward type is generated for forward declarations of enum types in C.
+   
+   Check that the ctf-kind of CTF_K_FOWARD type is CTF_K_ENUM.
+   For forward types, the compiler encodes the CTF kind in the ctt_type field.
+   CTF_K_FORWARD is used as the CTF type as usual in the ctt_info.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x26000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x8\[\t \]+\[^\n\]*ctt_size or ctt_type" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"vibgyor.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+enum vibgyor;
+
+char * (*get_color_name) (enum vibgyor);
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c
new file mode 100644
index 0000000..e324445
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c
@@ -0,0 +1,24 @@
+/* CTF generation of function pointers.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler-times "\[\t \]0x16000001\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x16000002\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x16000003\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"__foo_fn.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"destroy.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"func.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+int (*func) (int *, char);
+
+typedef int __foo_fn (void *__cookie, char *__buf, int __nbytes);
+
+typedef struct object
+{
+   int myint;
+   char mychar;
+   void (*destroy)(struct object *);
+} object_t;
+
+object_t myobj;
+__foo_fn fooit;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c
new file mode 100644
index 0000000..20bade1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c
@@ -0,0 +1,34 @@
+/* CTF generation for functions with varargs or otherwise.
+
+   In this testcase, it is expected to see one CTF_K_FUNCTION record with two
+   function arguments.  The second function argument with a value of 0
+   corresponds to the ellipsis.
+
+   Example CTF section excerpt on x86_64 :
+
+    .long   0x5     # ctt_name		    (name = format)
+    .long   0x16000002      # ctt_info	    (CTF_K_FUNCTION with 2 arguments)
+    .long   0x2     # ctt_size or ctt_type  (return typeID)
+    .long   0x2     # dtu_argv		    (TypeID of the First argument)
+    .long   0       # dtu_argv		    (TypeID of the second argument)
+    .ascii "\0"     # ctf_string
+    .ascii "int\0"  # ctf_string
+    .ascii "format\0"       # ctf_string
+
+    */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x16000002\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "dtu_argv" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*dtu_argv" 1 } } */
+
+int foo (void);
+
+int bar (int);
+
+int * format (int * fmt, ...)
+{
+  return fmt;
+}
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c
new file mode 100644
index 0000000..88f2a3a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c
@@ -0,0 +1,17 @@
+/* Tests for CTF integer base types.
+   - Verify that there is a single record for the base types.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"short int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"long int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+int a;
+int b = 33;
+
+short int c = 44;
+short int d = 45;
+
+long int e = 90;
+long int f;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c
new file mode 100644
index 0000000..32da7bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c
@@ -0,0 +1,26 @@
+/* CTF generation for pointer types.
+
+   In this testcase, two CTF pointer type records are expected
+     - int *
+     - struct foo_struct *
+  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"foo_struct.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+int b = 44;
+int * a = &b;
+
+struct foo_struct
+{
+  int bar_mem_1;
+  int bar_mem_2;
+  float d;
+  struct foo_struct *next;
+};
+
+struct foo_struct * node;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c
new file mode 100644
index 0000000..2c5e352
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c
@@ -0,0 +1,26 @@
+/* CTF String Table as generated by the compiler is expected to have only a
+   single empty string.  Just an optimization by the compiler, it is not
+   mandated by the CTF format.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler-times "ascii \".0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+union wait
+{
+  int w_status;
+  struct
+    {
+      int __w_termsig;
+      int __w_coredump;
+    } __wait_terminated;
+   struct
+    {
+      int __w_stopval;
+      int __w_stopsig;
+    } __wait_stopped;
+};
+
+typedef union { union wait * __uptr; int * iptr; } __WAIT_STATUS;
+
+__WAIT_STATUS waitstatus;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c
new file mode 100644
index 0000000..5d496d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c
@@ -0,0 +1,25 @@
+/* Test compilation of struct type.
+
+   In this testcase, two CTF_K_STRUCT records are expected
+   struct a : ctt_info = 0x1a000004 (4 field members)
+   struct b : ctt_into = 0x1a000002 (2 field members)
+*/
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1a000004\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1a000002\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "ctm_name" 6 } } */
+
+struct a
+{
+  int d1;
+  int d2;
+  float c;
+  struct b
+    {
+      int time;
+      int wall;
+    } b1;
+} my_a;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c
new file mode 100644
index 0000000..5b9c9c1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c
@@ -0,0 +1,30 @@
+/* Test for compilation of self-referntial structs.
+
+   Further, the compiler is expected to generate a single CTF struct type for
+   struct dmx_dtdef (due to Type de-duplication at CTF generation).  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler-times "ascii \"dmx_dtdef.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"dtd_name.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"dtd_type.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"dmx_dtdef_t.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+struct link
+{
+  struct link * next;
+} * s_link;
+
+typedef long dmx_id_t;
+
+typedef struct dmx_dtdef
+{
+  char * dtd_name;
+  dmx_id_t dtd_type;
+} dmx_dtdef_t;
+
+typedef struct dmx_bundle
+{
+  dmx_id_t dmb_type;
+  dmx_dtdef_t * dmb_dtd;
+} dmx_bundle_t;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c
new file mode 100644
index 0000000..552be47
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c
@@ -0,0 +1,36 @@
+/* Test Compilation of mixed constructs containing structs and arrays.
+
+   Further, the compiler is expected to generate a single CTF struct type for
+   struct cmodel (due to Type de-duplication at CTF generation).
+   
+   const qualifiers in fields of structs should be processed.  It appears as a
+   no-name CTF record with appropriate ctt_info.  In this testcase, 2 const
+   qualifier records are expected - const char and const struct cmodel.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler-times "ascii \"cmodel.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"cname.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"cpointer.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"cmodel_t.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+struct a
+{
+  int a1[2];
+  struct { int b[3]; } a2;
+};
+
+typedef struct cmodel
+{
+  const char *cname;
+  int ccode;
+  int cpointer;
+} cmodel_t;
+
+static const cmodel_t _models[] = {
+  {"ILP32", 0, 4},
+  {"LP64", 0, 8},
+  {"", 0, 0}
+};
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c
new file mode 100644
index 0000000..227d7db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c
@@ -0,0 +1,23 @@
+/* CTF_K_TYPEDEF record generation.
+
+   In this testcase, 7 typedef records are expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "0x2a000000\[\t \]+\[^\n\]*ctt_info" 7 } } */
+
+typedef int my_int;
+typedef int bar_int;
+typedef int foo_int;
+
+typedef struct { int a[2]; } my_array;
+
+typedef const int CINT;
+typedef const int * CINTP;
+
+typedef struct my_node
+{
+  int flags;
+  char value;
+} my_node_t;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c
new file mode 100644
index 0000000..a7e5249
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+typedef struct my_int
+{
+  int upper;
+  int lower;
+  struct bitmask
+    {
+      int flags;
+    } my_mask;
+} my_int_t;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c
new file mode 100644
index 0000000..59b4cb7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c
@@ -0,0 +1,14 @@
+/* CTF generation for union type.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1e000004\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "ctm_name" 4 } } */
+
+union c
+{
+  int c1;
+  int c2;
+  int c3;
+  int c4;
+} my_u_c;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c
new file mode 100644
index 0000000..a2e2557
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c
@@ -0,0 +1,25 @@
+/* CTF generation for global variables.
+
+   In this testcase, 7 records in the variable info section are expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ctv_name" 7 } } */
+
+float var1;
+double var2;
+long double var3;
+
+char ascii = 'a';
+
+int a = 33;
+int a1[2] = {22, 33};
+
+struct d
+{
+  int d1;
+  int d2;
+};
+
+struct d d_instance;
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH,RFC,V3 0/5] Support for CTF in GCC
@ 2019-06-27  6:37 Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 3/5] Setup for CTF generation and emission Indu Bhagat
                   ` (5 more replies)
  0 siblings, 6 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-06-27  6:37 UTC (permalink / raw)
  To: gcc-patches, richard.guenther

Hello,

This patch series adds support for CTF generation in GCC.

[Changes from V2]
 - Patch 1, 2, and 3 have minor edits if any.
 - Patch 4 is a new addition.
 - Patch 5 is a new addition.

Summary of the GCC RFC V3 patch set :
Patch 1, 2, and 3 do the preparatory work of adding the CTF command line options
and setting up the framework for CTF generation and emission.  More details on
these patches can be seen in the previous posting
https://gcc.gnu.org/ml/gcc-patches/2019-06/msg00718.html

With Patch 4 in the current set, the compiler can generate a .ctf section for a
single compilation unit if -gt (when unspecified, LEVEL defaults to 2) or -gt2
is specified.  Recall that -gt2 produces type information for entities
(functions, variables etc.) at file-scope or global-scope.

For each translation unit, a CTF container (ctf_container_t) is used to
keep the generated CTF.  Two hash_map structures are kept to hold the generated
CTF for type and variables.  CTF does need pre-processing before emission into
a section; there are code comments in ctfout.c to help understand this.

There are a couple of TBDs and FIXMEs in Patch 4 which will be resolved as I
progress further; Inputs on some of which will be very helpful :

- ctf_dtdef_hash : The compiler uses a hashing scheme to keep track of whether
  CTF has been generated for a type of decl.  For a type, the hashing scheme
  uses TYPE_UID, but for a decl it uses htab_hash_pointer (decl).  Is there a
  better way to do this ? (See hash_dtd_tree_decl in ctfout.c)

- delete_ctf_container routine in ctfout.c : I have used the GTY (()) tags in
  the CTF container structs.  Does this ensure that if I set the CTF container
  global variable (ctfc) to NULL, the garbage collection machinery will take
  care of cleaning up the the internals of the container (including hash_map).
  Haven't been able to get a definitive answer looking at the code in
  hash-map.h and the generated code in gtype-desc.c.

Testing :
- Bootstrapped and regression tested on x86_64/linux and aarch64/linux.
  Also bootstrapped on SPARC64/linux with some testing.
- Parsed .ctf sections of libdtrace-ctf files via a CTF dumping utility on
  x86_64/linux.  This simply ensures that the CTF sections are well-formed.
- Interaction with an internally available GDB looks promising.  Basic whatis
  and ptype tests work.  GDB patches to uptake CTF debug info are in the works
  and will be upstreamed soon.

In the subsequent patches, I intend to close some open ends in the current
patch and add LTO support.

Thanks,

Indu Bhagat (5):
  Add new function lang_GNU_GIMPLE
  Add CTF command line options : -gtLEVEL
  Setup for CTF generation and emission
  CTF generation for a single compilation unit
  Update CTF testsuite

 gcc/ChangeLog                                      |   91 +
 gcc/Makefile.in                                    |    5 +
 gcc/cgraphunit.c                                   |   12 +-
 gcc/common.opt                                     |    9 +
 gcc/ctfcreate.c                                    |  526 ++++++
 gcc/ctfout.c                                       | 1739 ++++++++++++++++++++
 gcc/ctfout.h                                       |  359 ++++
 gcc/ctfutils.c                                     |  198 +++
 gcc/doc/invoke.texi                                |   16 +
 gcc/flag-types.h                                   |   13 +
 gcc/gengtype.c                                     |    4 +-
 gcc/langhooks.c                                    |    9 +
 gcc/langhooks.h                                    |    1 +
 gcc/opts.c                                         |   26 +
 gcc/passes.c                                       |    7 +-
 gcc/testsuite/ChangeLog                            |   35 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c             |    6 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c             |   10 +
 .../gcc.dg/debug/ctf/ctf-anonymous-struct-1.c      |   23 +
 .../gcc.dg/debug/ctf/ctf-anonymous-union-1.c       |   26 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c       |   31 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c   |   30 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c   |   39 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c   |   44 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c   |   30 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c   |   41 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c        |   21 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c       |   16 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c     |   36 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c     |   16 +
 .../gcc.dg/debug/ctf/ctf-function-pointers-1.c     |   24 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c   |   34 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c         |   17 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c    |   26 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c    |   11 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c   |   26 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c      |   25 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c      |   30 +
 .../gcc.dg/debug/ctf/ctf-struct-array-1.c          |   36 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c     |   23 +
 .../gcc.dg/debug/ctf/ctf-typedef-struct-1.c        |   12 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c       |   14 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c   |   25 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp             |   41 +
 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c          |    7 +
 gcc/toplev.c                                       |   18 +
 include/ChangeLog                                  |    8 +
 include/ctf.h                                      |  487 ++++++
 48 files changed, 4277 insertions(+), 6 deletions(-)
 create mode 100644 gcc/ctfcreate.c
 create mode 100644 gcc/ctfout.c
 create mode 100644 gcc/ctfout.h
 create mode 100644 gcc/ctfutils.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c
 create mode 100644 include/ctf.h

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH,RFC,V3 3/5] Setup for CTF generation and emission
  2019-06-27  6:37 [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
@ 2019-06-27  6:37 ` Indu Bhagat
  2019-06-27  6:37 ` [PATCH,RFC,V3 5/5] Update CTF testsuite Indu Bhagat
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-06-27  6:37 UTC (permalink / raw)
  To: gcc-patches, richard.guenther

Initialize CTF container when -gtLEVEL is specified.  Generate CTF debug info
for global decls.  Import the CTF header from binutils.

gcc/ChangeLog :
 
	* Makefile.in: Add ctfout.* files to GTFILES.
	* cgraphunit.c (symbol_table::finalize_compilation_unit): Generate CTF
	debug info for decl. Invoke CTF debug info emission.
	* ctfout.c: New file.
	* ctfout.h: Likewise.
	* gengtype.c (open_base_files): Add ctfout.h to ifiles.
	* passes.c (rest_of_decl_compilation): Generate CTF debug info for
	decl.
	* toplev.c (process_options): Warn and ignore -gtLEVEL if frontend is
	not C.
	(toplev::finalize): Finalize CTF containers.

gcc/testsuite/ChangeLog :

	* gcc.dg/debug/ctf/ctf-1.c: New test.
	* gcc.dg/debug/ctf/ctf-preamble-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf.exp: Add CTF testsuite.
	* gcc.dg/debug/dwarf2-ctf-1.c: New test.

include/ChangeLog :

	* ctf.h: Import from binutils.

---
 gcc/ChangeLog                                   |  14 +
 gcc/Makefile.in                                 |   3 +
 gcc/cgraphunit.c                                |  12 +-
 gcc/ctfout.c                                    | 175 +++++++++
 gcc/ctfout.h                                    |  53 +++
 gcc/gengtype.c                                  |   4 +-
 gcc/passes.c                                    |   7 +-
 gcc/testsuite/ChangeLog                         |   7 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c          |   6 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c |  11 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp          |  41 ++
 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c       |   7 +
 gcc/toplev.c                                    |  18 +
 include/ChangeLog                               |   4 +
 include/ctf.h                                   | 483 ++++++++++++++++++++++++
 15 files changed, 839 insertions(+), 6 deletions(-)
 create mode 100644 gcc/ctfout.c
 create mode 100644 gcc/ctfout.h
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c
 create mode 100644 include/ctf.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d9e0885..8ce2405 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1254,6 +1254,7 @@ OBJS = \
 	cfgloopanal.o \
 	cfgloopmanip.o \
 	cfgrtl.o \
+	ctfout.o \
 	symtab.o \
 	cgraph.o \
 	cgraphbuild.o \
@@ -2532,6 +2533,8 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/dwarf2asm.c \
   $(srcdir)/dwarf2cfi.c \
   $(srcdir)/dwarf2out.c \
+  $(srcdir)/ctfout.h \
+  $(srcdir)/ctfout.c \
   $(srcdir)/tree-vect-generic.c \
   $(srcdir)/dojump.c $(srcdir)/emit-rtl.h \
   $(srcdir)/emit-rtl.c $(srcdir)/except.h $(srcdir)/explow.c $(srcdir)/expr.c \
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index f4d6688..9cf6252 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -205,6 +205,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "lto-section-names.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "ctfout.h"
 
 /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
    secondary queue used during optimization to accommodate passes that
@@ -2844,17 +2845,22 @@ symbol_table::finalize_compilation_unit (void)
 
   if (!seen_error ())
     {
-      /* Emit early debug for reachable functions, and by consequence,
-	 locally scoped symbols.  */
+      /* Emit early debug and CTF debug info for reachable functions, and by
+	 consequence, locally scoped symbols.  */
       struct cgraph_node *cnode;
       FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cnode)
-	(*debug_hooks->early_global_decl) (cnode->decl);
+	{
+	  (*debug_hooks->early_global_decl) (cnode->decl);
+	  ctf_early_global_decl (cnode->decl);
+	}
 
       /* Clean up anything that needs cleaning up after initial debug
 	 generation.  */
       debuginfo_early_start ();
       (*debug_hooks->early_finish) (main_input_filename);
+      ctf_early_finish (main_input_filename);
       debuginfo_early_stop ();
+
     }
 
   /* Finally drive the pass manager.  */
diff --git a/gcc/ctfout.c b/gcc/ctfout.c
new file mode 100644
index 0000000..1ce9829
--- /dev/null
+++ b/gcc/ctfout.c
@@ -0,0 +1,175 @@
+/* Output CTF format from GCC.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+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/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "target.h"
+#include "rtl.h"
+#include "tree.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "varasm.h"
+#include "output.h"
+#include "dwarf2asm.h"
+#include "debug.h"
+#include "ctfout.h"
+
+/* A CTF container object - one per translation unit.  */
+
+static GTY (()) ctf_container_ref tu_ctfc;
+
+static int ctf_label_num;
+
+/* Pointers to various CTF sections.  */
+
+static GTY (()) section * ctf_info_section;
+
+/* Section names used to hold CTF debugging information.  */
+
+#ifndef CTF_INFO_SECTION_NAME
+#define CTF_INFO_SECTION_NAME  ".ctf"
+#endif
+
+/* Section flags for .ctf section.  */
+
+/* CTF debug info section.  */
+
+#define CTF_INFO_SECTION_FLAGS (SECTION_DEBUG)
+
+/* Maximum size (in bytes) of an artificially generated CTF label.  */
+
+#define MAX_CTF_LABEL_BYTES 40
+
+static char ctf_info_section_label[MAX_CTF_LABEL_BYTES];
+
+#ifndef CTF_INFO_SECTION_LABEL
+#define CTF_INFO_SECTION_LABEL			"Lctf"
+#endif
+
+/* CTF container setup and teardown routines.  */
+
+/* Allocate a new CTF container with the desired flags.  */
+
+static inline ctf_container_ref
+new_ctf_container (unsigned char ctp_flags)
+{
+  tu_ctfc = ggc_cleared_alloc<ctf_container_t> ();
+
+  tu_ctfc->ctfc_magic = CTF_MAGIC;
+  tu_ctfc->ctfc_version = CTF_VERSION;
+  tu_ctfc->ctfc_flags = ctp_flags;
+
+  return tu_ctfc;
+}
+
+/* Initialize a CTF container per translation unit.  */
+
+static void
+init_ctf_containers (void)
+{
+  tu_ctfc = new_ctf_container (0);
+}
+
+/* Delete the CTF container's resources.  */
+
+static void
+delete_ctf_container (ctf_container_ref ctfc)
+{
+  /* FIXME - CTF container can be cleaned up now.
+     Will the ggc machinery take care of cleaning up the container structure
+     including the hash_map members etc. ?  */
+  if (ctfc)
+    {
+      ctfc = NULL;
+    }
+}
+
+/* Initialize the various sections and labels for CTF output.  */
+
+void
+init_ctf_sections (void)
+{
+  ctf_info_section = get_section (CTF_INFO_SECTION_NAME,
+				  CTF_INFO_SECTION_FLAGS,
+				  NULL);
+  ASM_GENERATE_INTERNAL_LABEL (ctf_info_section_label,
+			       CTF_INFO_SECTION_LABEL, ctf_label_num++);
+}
+
+/* Asm'out the CTF preamble.  */
+
+static void
+ctf_asm_preamble (ctf_container_ref ctfc)
+{
+  dw2_asm_output_data (2, ctfc->ctfc_magic,
+		       "CTF preamble magic number");
+  dw2_asm_output_data (1, ctfc->ctfc_version, "CTF preamble version");
+  dw2_asm_output_data (1, ctfc->ctfc_flags, "CTF preamble flags");
+}
+
+/* Output the CTF header.  */
+
+static void
+output_ctf_header (ctf_container_ref ctfc)
+{
+  switch_to_section (ctf_info_section);
+  ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label);
+
+  ctf_asm_preamble (ctfc);
+}
+
+/* CTF routines interfacing to the compiler.  */
+
+void
+ctf_debug_init (void)
+{
+  init_ctf_containers ();
+}
+
+void
+ctf_early_finish (const char * ARG_UNUSED (filename))
+{
+  if (ctf_debug_info_level == CTFINFO_LEVEL_NONE)
+    return;
+
+  init_ctf_sections ();
+
+  output_ctf_header (tu_ctfc);
+}
+
+void
+ctf_early_global_decl (tree ARG_UNUSED (decl))
+{
+  /* Generate CTF type information if appropriate debug level is set
+     (ctf_debug_info_level == CTFINFO_LEVEL_NORMAL).  */
+}
+
+/* Reset all state within ctfout.c so that we can rerun the compiler
+   within the same process.  For use by toplev::finalize.  */
+
+void
+ctfout_c_finalize (void)
+{
+  ctf_info_section = NULL;
+
+  delete_ctf_container (tu_ctfc);
+}
+
+#include "gt-ctfout.h"
diff --git a/gcc/ctfout.h b/gcc/ctfout.h
new file mode 100644
index 0000000..f281aaf
--- /dev/null
+++ b/gcc/ctfout.h
@@ -0,0 +1,53 @@
+/* ctfout.h - Various declarations for functions found in ctfout.c
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+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/>.  */
+
+/* This file defines all data structures used by the compiler to generate
+   CTF types.  These are compiler internal representations and closely
+   reflect the CTF format requirements in <ctf.h>.  */
+
+#ifndef GCC_CTFOUT_H
+#define GCC_CTFOUT_H 1
+
+#include "ctf.h"
+
+/* CTF container structure.
+   It is the context passed around when generating CTF debug info.  There is
+   one container per translation unit.  */
+
+typedef struct GTY (()) ctf_container
+{
+  /* CTF Preamble.  */
+  unsigned short ctfc_magic;
+  unsigned char ctfc_version;
+  unsigned char ctfc_flags;
+  /* CTF Types.  */
+  // hash_map <ctf_dtdef_hash, ctf_dtdefp_t> * GTY (()) ctfc_types;
+} ctf_container_t;
+
+typedef ctf_container_t * ctf_container_ref;
+
+void ctf_debug_init (void);
+
+void ctf_early_global_decl (tree decl);
+
+void ctf_early_finish (const char * filename);
+
+void ctfout_c_finalize (void);
+
+#endif /* GCC_CTFOUT_H */
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 5331733..39de737 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1724,8 +1724,8 @@ open_base_files (void)
       "tree-dfa.h", "tree-ssa.h", "reload.h", "cpplib.h", "tree-chrec.h",
       "except.h", "output.h",  "cfgloop.h", "target.h", "lto-streamer.h",
       "target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
-      "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
-      "omp-offload.h", NULL
+      "ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "ctfout.h",
+      "omp-general.h", "omp-offload.h", NULL
     };
     const char *const *ifp;
     outf_p gtype_desc_c;
diff --git a/gcc/passes.c b/gcc/passes.c
index c6331cb..c0f1e57 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-core.h" /* for fnotice */
 #include "stringpool.h"
 #include "attribs.h"
+#include "ctfout.h"
 
 using namespace gcc;
 
@@ -322,7 +323,11 @@ rest_of_decl_compilation (tree decl,
       /* Avoid confusing the debug information machinery when there are
 	 errors.  */
       && !seen_error ())
-    (*debug_hooks->early_global_decl) (decl);
+	{
+	  (*debug_hooks->early_global_decl) (decl);
+	  /* Generate CTF debug info.  */
+	  ctf_early_global_decl (decl);
+	}
 }
 
 /* Called after finishing a record, union or enumeral type.  */
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c
new file mode 100644
index 0000000..1be0dfb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+
+void func(void)
+{
+}
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c
new file mode 100644
index 0000000..476ca80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c
@@ -0,0 +1,11 @@
+/* Verify the CTF preamble in the CTF section.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+/* { dg-final { scan-assembler "0xdff2.*CTF preamble magic number" } } */
+/* { dg-final { scan-assembler "0x4.*CTF preamble version" } } */
+/* { dg-final { scan-assembler "0.*CTF preamble flags" } } */
+
+void func (void)
+{
+}
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp
new file mode 100644
index 0000000..46055f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf.exp
@@ -0,0 +1,41 @@
+#   Copyright (C) 2002-2019 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+# 
+# This program 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/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# Disable on ptx (in sync with DWARF testsuite)
+if { [istarget nvptx-*-*] } {
+    return
+}
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+    set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\] ]] \
+	"" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c b/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c
new file mode 100644
index 0000000..4ffa8ee
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c
@@ -0,0 +1,7 @@
+/* Verify that CTF debug info can co-exist with other debug formats.  */
+/* { dg-do compile } */
+/* { dg-options "-gt -dA" } */
+/* { dg-final { scan-assembler "0xdff2.*CTF preamble magic number" } } */
+
+void func (void)
+{ }
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 116be7b..d150dfc 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -72,6 +72,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "pass_manager.h"
 #include "auto-profile.h"
 #include "dwarf2out.h"
+#include "ctfout.h"
 #include "ipa-reference.h"
 #include "symbol-summary.h"
 #include "tree-vrp.h"
@@ -1312,6 +1313,8 @@ parse_alignment_opts (void)
 static void
 process_options (void)
 {
+  const char *language_string = lang_hooks.name;
+
   /* Just in case lang_hooks.post_options ends up calling a debug_hook.
      This can happen with incorrect pre-processed input. */
   debug_hooks = &do_nothing_debug_hooks;
@@ -1484,6 +1487,17 @@ process_options (void)
 	debug_info_level = DINFO_LEVEL_NONE;
     }
 
+  /* CTF is supported for only C at this time.
+     Compiling with -flto results in frontend language of GNU GIMPLE.  */
+  if (!lang_GNU_C () && !lang_GNU_GIMPLE ()
+      && ctf_debug_info_level > CTFINFO_LEVEL_NONE)
+    {
+      warning_at (UNKNOWN_LOCATION, 0,
+		  "CTF debug info requested, but not supported for %s frontend",
+		  language_string);
+      ctf_debug_info_level = CTFINFO_LEVEL_NONE;
+    }
+
   if (flag_dump_final_insns && !flag_syntax_only && !no_backend)
     {
       FILE *final_output = fopen (flag_dump_final_insns, "w");
@@ -1556,6 +1570,9 @@ process_options (void)
       flag_var_tracking_uninit = 0;
     }
 
+  if (ctf_debug_info_level > CTFINFO_LEVEL_NONE)
+    ctf_debug_init ();
+
   /* The debug hooks are used to implement -fdump-go-spec because it
      gives a simple and stable API for all the information we need to
      dump.  */
@@ -2391,6 +2408,7 @@ toplev::finalize (void)
   cgraph_c_finalize ();
   cgraphunit_c_finalize ();
   dwarf2out_c_finalize ();
+  ctfout_c_finalize ();
   gcse_c_finalize ();
   ipa_cp_c_finalize ();
   ira_costs_c_finalize ();
diff --git a/include/ctf.h b/include/ctf.h
new file mode 100644
index 0000000..3a6f266
--- /dev/null
+++ b/include/ctf.h
@@ -0,0 +1,483 @@
+/* CTF format description.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+
+   This file is part of libctf.
+
+   libctf 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.
+
+   This program 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 this program; see the file COPYING.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef	_CTF_H
+#define	_CTF_H
+
+#include <sys/types.h>
+#include <limits.h>
+#include <stdint.h>
+
+
+#ifdef	__cplusplus
+extern "C"
+{
+#endif
+
+/* CTF - Compact ANSI-C Type Format
+
+   This file format can be used to compactly represent the information needed
+   by a debugger to interpret the ANSI-C types used by a given program.
+   Traditionally, this kind of information is generated by the compiler when
+   invoked with the -g flag and is stored in "stabs" strings or in the more
+   modern DWARF format.  CTF provides a representation of only the information
+   that is relevant to debugging a complex, optimized C program such as the
+   operating system kernel in a form that is significantly more compact than
+   the equivalent stabs or DWARF representation.  The format is data-model
+   independent, so consumers do not need different code depending on whether
+   they are 32-bit or 64-bit programs; libctf automatically compensates for
+   endianness variations.  CTF assumes that a standard ELF symbol table is
+   available for use in the debugger, and uses the structure and data of the
+   symbol table to avoid storing redundant information.  The CTF data may be
+   compressed on disk or in memory, indicated by a bit in the header.  CTF may
+   be interpreted in a raw disk file, or it may be stored in an ELF section,
+   typically named .ctf.  Data structures are aligned so that a raw CTF file or
+   CTF ELF section may be manipulated using mmap(2).
+
+   The CTF file or section itself has the following structure:
+
+   +--------+--------+---------+----------+----------+-------+--------+
+   |  file  |  type  |  data   | function | variable | data  | string |
+   | header | labels | objects |   info   |   info   | types | table  |
+   +--------+--------+---------+----------+----------+-------+--------+
+
+   The file header stores a magic number and version information, encoding
+   flags, and the byte offset of each of the sections relative to the end of the
+   header itself.  If the CTF data has been uniquified against another set of
+   CTF data, a reference to that data also appears in the the header.  This
+   reference is the name of the label corresponding to the types uniquified
+   against.
+
+   Following the header is a list of labels, used to group the types included in
+   the data types section.  Each label is accompanied by a type ID i.  A given
+   label refers to the group of types whose IDs are in the range [0, i].
+
+   Data object and function records are stored in the same order as they appear
+   in the corresponding symbol table, except that symbols marked SHN_UNDEF are
+   not stored and symbols that have no type data are padded out with zeroes.
+   For each data object, the type ID (a small integer) is recorded.  For each
+   function, the type ID of the return type and argument types is recorded.
+
+   Variable records (as distinct from data objects) provide a modicum of support
+   for non-ELF systems, mapping a variable name to a CTF type ID.  The variable
+   names are sorted into ASCIIbetical order, permitting binary searching.
+
+   The data types section is a list of variable size records that represent each
+   type, in order by their ID.  The types themselves form a directed graph,
+   where each node may contain one or more outgoing edges to other type nodes,
+   denoted by their ID.
+
+   Strings are recorded as a string table ID (0 or 1) and a byte offset into the
+   string table.  String table 0 is the internal CTF string table.  String table
+   1 is the external string table, which is the string table associated with the
+   ELF symbol table for this object.  CTF does not record any strings that are
+   already in the symbol table, and the CTF string table does not contain any
+   duplicated strings.
+
+   If the CTF data has been merged with another parent CTF object, some outgoing
+   edges may refer to type nodes that exist in another CTF object.  The debugger
+   and libctf library are responsible for connecting the appropriate objects
+   together so that the full set of types can be explored and manipulated.
+
+   This connection is done purely using the ctf_import() function.  There is no
+   notation anywhere in the child CTF file indicating which parent it is
+   connected to: it is the debugger's responsibility to track this.  */
+
+#define CTF_MAX_TYPE	0xfffffffe	/* Max type identifier value.  */
+#define CTF_MAX_PTYPE	0x7fffffff	/* Max parent type identifier value.  */
+#define CTF_MAX_NAME 0x7fffffff		/* Max offset into a string table.  */
+#define CTF_MAX_VLEN	0xffffff /* Max struct, union, enum members or args.  */
+
+/* See ctf_type_t */
+#define CTF_MAX_SIZE	0xfffffffe	/* Max size of a v2 type in bytes. */
+#define CTF_LSIZE_SENT	0xffffffff	/* Sentinel for v2 ctt_size.  */
+
+  /* Start of actual data structure definitions.
+
+     Every field in these structures must have corresponding code in the
+     endianness-swapping machinery in libctf/ctf-open.c.  */
+
+typedef struct ctf_preamble
+{
+  unsigned short ctp_magic;	/* Magic number (CTF_MAGIC).  */
+  unsigned char ctp_version;	/* Data format version number (CTF_VERSION).  */
+  unsigned char ctp_flags;	/* Flags (see below).  */
+} ctf_preamble_t;
+
+typedef struct ctf_header
+{
+  ctf_preamble_t cth_preamble;
+  uint32_t cth_parlabel;	/* Ref to name of parent lbl uniq'd against.  */
+  uint32_t cth_parname;		/* Ref to basename of parent.  */
+  uint32_t cth_lbloff;		/* Offset of label section.  */
+  uint32_t cth_objtoff;		/* Offset of object section.  */
+  uint32_t cth_funcoff;		/* Offset of function section.  */
+  uint32_t cth_varoff;		/* Offset of variable section.  */
+  uint32_t cth_typeoff;		/* Offset of type section.  */
+  uint32_t cth_stroff;		/* Offset of string section.  */
+  uint32_t cth_strlen;		/* Length of string section in bytes.  */
+} ctf_header_t;
+
+#define cth_magic   cth_preamble.ctp_magic
+#define cth_version cth_preamble.ctp_version
+#define cth_flags   cth_preamble.ctp_flags
+
+#define CTF_MAGIC	0xdff2	/* Magic number identifying header.  */
+
+/* Data format version number.  */
+
+/* v1 upgraded to v2 is not quite the same as native v2 (the boundary between
+   parent and child types is different), and you can write it out again via
+   ctf_compress_write(), so we must track whether the thing was originally v1 or
+   not.  If we were writing the header from scratch, we would add a *pair* of
+   version number fields to allow for this, but this will do for now.  (A flag
+   will not do, because we need to encode both the version we came from and the
+   version we went to, not just "we were upgraded".) */
+
+# define CTF_VERSION_1 1
+# define CTF_VERSION_1_UPGRADED_3 2
+# define CTF_VERSION_2 3
+
+#define CTF_VERSION_3 4
+#define CTF_VERSION CTF_VERSION_3 /* Current version.  */
+
+#define CTF_F_COMPRESS	0x1	/* Data buffer is compressed by libctf.  */
+
+typedef struct ctf_lblent
+{
+  uint32_t ctl_label;		/* Ref to name of label.  */
+  uint32_t ctl_type;		/* Last type associated with this label.  */
+} ctf_lblent_t;
+
+typedef struct ctf_varent
+{
+  uint32_t ctv_name;		/* Reference to name in string table.  */
+  uint32_t ctv_type;		/* Index of type of this variable.  */
+} ctf_varent_t;
+
+/* In format v2, type sizes, measured in bytes, come in two flavours.  Nearly
+   all of them fit into a (UINT_MAX - 1), and thus can be stored in the ctt_size
+   member of a ctf_stype_t.  The maximum value for these sizes is CTF_MAX_SIZE.
+   Types larger than this must be stored in the ctf_lsize member of a
+   ctf_type_t.  Use of this member is indicated by the presence of
+   CTF_LSIZE_SENT in ctt_size.  */
+
+typedef struct ctf_stype
+{
+  uint32_t ctt_name;		/* Reference to name in string table.  */
+  uint32_t ctt_info;		/* Encoded kind, variant length (see below).  */
+#ifndef __GNUC__
+  union
+  {
+    uint32_t _size;		/* Size of entire type in bytes.  */
+    uint32_t _type;		/* Reference to another type.  */
+  } _u;
+#else
+  __extension__
+  union
+  {
+    uint32_t ctt_size;		/* Size of entire type in bytes.  */
+    uint32_t ctt_type;		/* Reference to another type.  */
+  };
+#endif
+} ctf_stype_t;
+
+typedef struct ctf_type
+{
+  uint32_t ctt_name;		/* Reference to name in string table.  */
+  uint32_t ctt_info;		/* Encoded kind, variant length (see below).  */
+#ifndef __GNUC__
+union
+  {
+    uint32_t _size;		/* Always CTF_LSIZE_SENT.  */
+    uint32_t _type;		/* Do not use.  */
+  } _u;
+#else
+  __extension__
+  union
+  {
+    uint32_t ctt_size;		/* Always CTF_LSIZE_SENT.  */
+    uint32_t ctt_type;		/* Do not use.  */
+  };
+#endif
+  uint32_t ctt_lsizehi;		/* High 32 bits of type size in bytes.  */
+  uint32_t ctt_lsizelo;		/* Low 32 bits of type size in bytes.  */
+} ctf_type_t;
+
+#ifndef __GNUC__
+#define ctt_size _u._size	/* For fundamental types that have a size.  */
+#define ctt_type _u._type	/* For types that reference another type.  */
+#endif
+
+/* The following macros and inline functions compose and decompose values for
+   ctt_info and ctt_name, as well as other structures that contain name
+   references.  Use outside libdtrace-ctf itself is explicitly for access to CTF
+   files directly: types returned from the library will always appear to be
+   CTF_V2.
+
+   v1: (transparently upgraded to v2 at open time: may be compiled out of the
+   library)
+               ------------------------
+   ctt_info:   | kind | isroot | vlen |
+               ------------------------
+               15   11    10    9     0
+
+   v2:
+               ------------------------
+   ctt_info:   | kind | isroot | vlen |
+               ------------------------
+               31    26    25  24     0
+
+   CTF_V1 and V2 _INFO_VLEN have the same interface:
+
+   kind = CTF_*_INFO_KIND(c.ctt_info);     <-- CTF_K_* value (see below)
+   vlen = CTF_*_INFO_VLEN(fp, c.ctt_info); <-- length of variable data list
+
+   stid = CTF_NAME_STID(c.ctt_name);     <-- string table id number (0 or 1)
+   offset = CTF_NAME_OFFSET(c.ctt_name); <-- string table byte offset
+
+   c.ctt_info = CTF_TYPE_INFO(kind, vlen);
+   c.ctt_name = CTF_TYPE_NAME(stid, offset);  */
+
+# define CTF_V1_INFO_KIND(info)		(((info) & 0xf800) >> 11)
+# define CTF_V1_INFO_ISROOT(info)	(((info) & 0x0400) >> 10)
+# define CTF_V1_INFO_VLEN(info)		(((info) & CTF_MAX_VLEN_V1))
+
+#define CTF_V2_INFO_KIND(info)		(((info) & 0xfc000000) >> 26)
+#define CTF_V2_INFO_ISROOT(info)	(((info) & 0x2000000) >> 25)
+#define CTF_V2_INFO_VLEN(info)		(((info) & CTF_MAX_VLEN))
+
+#define CTF_NAME_STID(name)		((name) >> 31)
+#define CTF_NAME_OFFSET(name)		((name) & CTF_MAX_NAME)
+
+/* V2 only. */
+#define CTF_TYPE_INFO(kind, isroot, vlen) \
+	(((kind) << 26) | (((isroot) ? 1 : 0) << 25) | ((vlen) & CTF_MAX_VLEN))
+
+#define CTF_TYPE_NAME(stid, offset) \
+	(((stid) << 31) | ((offset) & CTF_MAX_NAME))
+
+/* The next set of macros are for public consumption only.  Not used internally,
+   since the relevant type boundary is dependent upon the version of the file at
+   *opening* time, not the version after transparent upgrade.  Use
+   ctf_type_isparent() / ctf_type_ischild() for that.  */
+
+#define CTF_V2_TYPE_ISPARENT(fp, id)	((id) <= CTF_MAX_PTYPE)
+#define CTF_V2_TYPE_ISCHILD(fp, id)	((id) > CTF_MAX_PTYPE)
+#define CTF_V2_TYPE_TO_INDEX(id)	((id) & CTF_MAX_PTYPE)
+#define CTF_V2_INDEX_TO_TYPE(id, child) ((child) ? ((id) | (CTF_MAX_PTYPE+1)) : (id))
+
+# define CTF_V1_TYPE_ISPARENT(fp, id)	((id) <= CTF_MAX_PTYPE_V1)
+# define CTF_V1_TYPE_ISCHILD(fp, id)	((id) > CTF_MAX_PTYPE_V1)
+# define CTF_V1_TYPE_TO_INDEX(id)	((id) & CTF_MAX_PTYPE_V1)
+# define CTF_V1_INDEX_TO_TYPE(id, child) ((child) ? ((id) | (CTF_MAX_PTYPE_V1+1)) : (id))
+
+/* Valid for both V1 and V2. */
+#define CTF_TYPE_LSIZE(cttp) \
+	(((uint64_t)(cttp)->ctt_lsizehi) << 32 | (cttp)->ctt_lsizelo)
+#define CTF_SIZE_TO_LSIZE_HI(size)	((uint32_t)((uint64_t)(size) >> 32))
+#define CTF_SIZE_TO_LSIZE_LO(size)	((uint32_t)(size))
+
+#define CTF_STRTAB_0	0	/* String table id 0 (in-CTF).  */
+#define CTF_STRTAB_1	1	/* String table id 1 (ELF strtab).  */
+
+/* Values for CTF_TYPE_KIND().  If the kind has an associated data list,
+   CTF_INFO_VLEN() will extract the number of elements in the list, and
+   the type of each element is shown in the comments below. */
+
+#define CTF_K_UNKNOWN	0	/* Unknown type (used for padding).  */
+#define CTF_K_INTEGER	1	/* Variant data is CTF_INT_DATA (see below).  */
+#define CTF_K_FLOAT	2	/* Variant data is CTF_FP_DATA (see below).  */
+#define CTF_K_POINTER	3	/* ctt_type is referenced type.  */
+#define CTF_K_ARRAY	4	/* Variant data is single ctf_array_t.  */
+#define CTF_K_FUNCTION	5	/* ctt_type is return type, variant data is
+				   list of argument types (unsigned short's for v1,
+				   uint32_t's for v2).  */
+#define CTF_K_STRUCT	6	/* Variant data is list of ctf_member_t's.  */
+#define CTF_K_UNION	7	/* Variant data is list of ctf_member_t's.  */
+#define CTF_K_ENUM	8	/* Variant data is list of ctf_enum_t's.  */
+#define CTF_K_FORWARD	9	/* No additional data; ctt_name is tag.  */
+#define CTF_K_TYPEDEF	10	/* ctt_type is referenced type.  */
+#define CTF_K_VOLATILE	11	/* ctt_type is base type.  */
+#define CTF_K_CONST	12	/* ctt_type is base type.  */
+#define CTF_K_RESTRICT	13	/* ctt_type is base type.  */
+#define CTF_K_SLICE	14	/* Variant data is a ctf_slice_t.  */
+
+#define CTF_K_MAX	63	/* Maximum possible (V2) CTF_K_* value.  */
+
+/* Values for ctt_type when kind is CTF_K_INTEGER.  The flags, offset in bits,
+   and size in bits are encoded as a single word using the following macros.
+   (However, you can also encode the offset and bitness in a slice.)  */
+
+#define CTF_INT_ENCODING(data) (((data) & 0xff000000) >> 24)
+#define CTF_INT_OFFSET(data)   (((data) & 0x00ff0000) >> 16)
+#define CTF_INT_BITS(data)     (((data) & 0x0000ffff))
+
+#define CTF_INT_DATA(encoding, offset, bits) \
+       (((encoding) << 24) | ((offset) << 16) | (bits))
+
+#define CTF_INT_SIGNED	0x01	/* Integer is signed (otherwise unsigned).  */
+#define CTF_INT_CHAR	0x02	/* Character display format.  */
+#define CTF_INT_BOOL	0x04	/* Boolean display format.  */
+#define CTF_INT_VARARGS	0x08	/* Varargs display format.  */
+
+/* Use CTF_CHAR to produce a char that agrees with the system's native
+   char signedness.  */
+#if CHAR_MIN == 0
+# define CTF_CHAR (CTF_INT_CHAR)
+#else
+# define CTF_CHAR (CTF_INT_CHAR | CTF_INT_SIGNED)
+#endif
+
+/* Values for ctt_type when kind is CTF_K_FLOAT.  The encoding, offset in bits,
+   and size in bits are encoded as a single word using the following macros.
+   (However, you can also encode the offset and bitness in a slice.)  */
+
+#define CTF_FP_ENCODING(data)  (((data) & 0xff000000) >> 24)
+#define CTF_FP_OFFSET(data)    (((data) & 0x00ff0000) >> 16)
+#define CTF_FP_BITS(data)      (((data) & 0x0000ffff))
+
+#define CTF_FP_DATA(encoding, offset, bits) \
+       (((encoding) << 24) | ((offset) << 16) | (bits))
+
+/* Variant data when kind is CTF_K_FLOAT is an encoding in the top eight bits.  */
+#define CTF_FP_ENCODING(data)	(((data) & 0xff000000) >> 24)
+
+#define CTF_FP_SINGLE	1	/* IEEE 32-bit float encoding.  */
+#define CTF_FP_DOUBLE	2	/* IEEE 64-bit float encoding.  */
+#define CTF_FP_CPLX	3	/* Complex encoding.  */
+#define CTF_FP_DCPLX	4	/* Double complex encoding.  */
+#define CTF_FP_LDCPLX	5	/* Long double complex encoding.  */
+#define CTF_FP_LDOUBLE	6	/* Long double encoding.  */
+#define CTF_FP_INTRVL	7	/* Interval (2x32-bit) encoding.  */
+#define CTF_FP_DINTRVL	8	/* Double interval (2x64-bit) encoding.  */
+#define CTF_FP_LDINTRVL	9	/* Long double interval (2x128-bit) encoding.  */
+#define CTF_FP_IMAGRY	10	/* Imaginary (32-bit) encoding.  */
+#define CTF_FP_DIMAGRY	11	/* Long imaginary (64-bit) encoding.  */
+#define CTF_FP_LDIMAGRY	12	/* Long double imaginary (128-bit) encoding.  */
+
+#define CTF_FP_MAX	12	/* Maximum possible CTF_FP_* value */
+
+/* A slice increases the offset and reduces the bitness of the referenced
+   ctt_type, which must be a type which has an encoding (fp, int, or enum).  We
+   also store the referenced type in here, because it is easier to keep the
+   ctt_size correct for the slice than to shuffle the size into here and keep
+   the ctt_type where it is for other types.  */
+
+typedef struct ctf_slice
+{
+  uint32_t cts_type;
+  unsigned char cts_offset;
+  unsigned char cts_bits;
+} ctf_slice_t;
+
+typedef struct ctf_array
+{
+  uint32_t cta_contents;	/* Reference to type of array contents.  */
+  uint32_t cta_index;		/* Reference to type of array index.  */
+  uint32_t cta_nelems;		/* Number of elements.  */
+} ctf_array_t;
+
+/* Most structure members have bit offsets that can be expressed using a short.
+   Some don't.  ctf_member_t is used for structs which cannot contain any of
+   these large offsets, whereas ctf_lmember_t is used in the latter case.  If
+   any member of a given struct has an offset that cannot be expressed using a
+   uint32_t, all members will be stored as type ctf_lmember_t.  This is expected
+   to be very rare (but nonetheless possible).  */
+
+#define CTF_LSTRUCT_THRESH	536870912
+
+typedef struct ctf_member_v2
+{
+  uint32_t ctm_name;		/* Reference to name in string table.  */
+  uint32_t ctm_offset;		/* Offset of this member in bits.  */
+  uint32_t ctm_type;		/* Reference to type of member.  */
+} ctf_member_t;
+
+typedef struct ctf_lmember_v2
+{
+  uint32_t ctlm_name;		/* Reference to name in string table.  */
+  uint32_t ctlm_offsethi;	/* High 32 bits of member offset in bits.  */
+  uint32_t ctlm_type;		/* Reference to type of member.  */
+  uint32_t ctlm_offsetlo;	/* Low 32 bits of member offset in bits.  */
+} ctf_lmember_t;
+
+#define	CTF_LMEM_OFFSET(ctlmp) \
+	(((uint64_t)(ctlmp)->ctlm_offsethi) << 32 | (ctlmp)->ctlm_offsetlo)
+#define	CTF_OFFSET_TO_LMEMHI(offset)	((uint32_t)((uint64_t)(offset) >> 32))
+#define	CTF_OFFSET_TO_LMEMLO(offset)	((uint32_t)(offset))
+
+typedef struct ctf_enum
+{
+  uint32_t cte_name;		/* Reference to name in string table.  */
+  int32_t cte_value;		/* Value associated with this name.  */
+} ctf_enum_t;
+
+/* The ctf_archive is a collection of ctf_file_t's stored together. The format
+   is suitable for mmap()ing: this control structure merely describes the
+   mmap()ed archive (and overlaps the first few bytes of it), hence the
+   greater care taken with integral types.  All CTF files in an archive
+   must have the same data model.  (This is not validated.)
+
+   All integers in this structure are stored in little-endian byte order.
+
+   The code relies on the fact that everything in this header is a uint64_t
+   and thus the header needs no padding (in particular, that no padding is
+   needed between ctfa_ctfs and the unnamed ctfa_archive_modent array
+   that follows it).
+
+   This is *not* the same as the data structure returned by the ctf_arc_*()
+   functions:  this is the low-level on-disk representation.  */
+
+#define CTFA_MAGIC 0x8b47f2a4d7623eeb	/* Random.  */
+struct ctf_archive
+{
+  /* Magic number.  (In loaded files, overwritten with the file size
+     so ctf_arc_close() knows how much to munmap()).  */
+  uint64_t ctfa_magic;
+
+  /* CTF data model.  */
+  uint64_t ctfa_model;
+
+  /* Number of CTF files in the archive.  */
+  uint64_t ctfa_nfiles;
+
+  /* Offset of the name table.  */
+  uint64_t ctfa_names;
+
+  /* Offset of the CTF table.  Each element starts with a size (a uint64_t
+     in network byte order) then a ctf_file_t of that size.  */
+  uint64_t ctfa_ctfs;
+};
+
+/* An array of ctfa_nnamed of this structure lies at
+   ctf_archive[ctf_archive->ctfa_modents] and gives the ctfa_ctfs or
+   ctfa_names-relative offsets of each name or ctf_file_t.  */
+
+typedef struct ctf_archive_modent
+{
+  uint64_t name_offset;
+  uint64_t ctf_offset;
+} ctf_archive_modent_t;
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif				/* _CTF_H */
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH,RFC,V3 2/5] Add CTF command line options : -gtLEVEL
  2019-06-27  6:37 [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
                   ` (3 preceding siblings ...)
  2019-06-27  6:37 ` [PATCH,RFC,V3 1/5] Add new function lang_GNU_GIMPLE Indu Bhagat
@ 2019-06-27  6:37 ` Indu Bhagat
  2019-07-02 17:43 ` [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
  5 siblings, 0 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-06-27  6:37 UTC (permalink / raw)
  To: gcc-patches, richard.guenther

-gtLEVEL is used to request CTF debug information and also to specify how much
CTF debug information.

gcc/ChangeLog :
 
	* common.opt: Add CTF debug info options.
	* doc/invoke.texi: Document the CTF debug info options.
	* flag-types.h (enum ctf_debug_info_levels): New enum.
	* opts.c (common_handle_option): New Function.
	(set_ctf_debug_level): Handle the new CTF debug info options.

---
 gcc/ChangeLog       |  8 ++++++++
 gcc/common.opt      |  9 +++++++++
 gcc/doc/invoke.texi | 16 ++++++++++++++++
 gcc/flag-types.h    | 13 +++++++++++++
 gcc/opts.c          | 26 ++++++++++++++++++++++++++
 5 files changed, 72 insertions(+)

diff --git a/gcc/common.opt b/gcc/common.opt
index a1544d0..52cd7b2 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -125,6 +125,11 @@ enum debug_info_levels debug_info_level = DINFO_LEVEL_NONE
 Variable
 bool use_gnu_debug_info_extensions
 
+; Level of CTF debugging information we are producing.  See flag-types.h
+; for the definitions of the different possible levels.
+Variable
+enum ctf_debug_info_levels ctf_debug_info_level = CTFINFO_LEVEL_NONE
+
 ; Original value of maximum field alignment in bytes, specified via
 ; -fpack-struct=<value>.
 Variable
@@ -2999,6 +3004,10 @@ gcolumn-info
 Common Driver Var(debug_column_info,1) Init(1)
 Record DW_AT_decl_column and DW_AT_call_column in DWARF.
 
+gt
+Common Driver RejectNegative JoinedOrMissing
+Generate CTF debug information at default level.
+
 gdwarf
 Common Driver JoinedOrMissing Negative(gdwarf-)
 Generate debug information in default version of DWARF format.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 03d2895..74d20db 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -374,6 +374,7 @@ Objective-C and Objective-C++ Dialects}.
 @item Debugging Options
 @xref{Debugging Options,,Options for Debugging Your Program}.
 @gccoptlist{-g  -g@var{level}  -gdwarf  -gdwarf-@var{version} @gol
+-gt  -gt@var{level} @gol
 -ggdb  -grecord-gcc-switches  -gno-record-gcc-switches @gol
 -gstabs  -gstabs+  -gstrict-dwarf  -gno-strict-dwarf @gol
 -gas-loc-support  -gno-as-loc-support @gol
@@ -7798,6 +7799,21 @@ other DWARF-related options such as
 @option{-fno-dwarf2-cfi-asm}) retain a reference to DWARF Version 2
 in their names, but apply to all currently-supported versions of DWARF.
 
+@item -gt
+@itemx -gt@var{level}
+@opindex gt
+Request CTF debug information and use level to specify how much CTF debug
+information should be produced.  If -gt is specified without a value for level,
+the default level of CTF debug information is 2.
+
+Level 0 produces no CTF debug information at all.  Thus, -gt0 negates -gt.
+
+Level 1 produces CTF information for tracebacks only.  This includes callsite
+information, but does not include type information.
+
+Level 2 produces type information for entities (functions, data objects etc.)
+at file-scope or global-scope only.
+
 @item -gstabs
 @opindex gstabs
 Produce debugging information in stabs format (if that is supported),
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index a210328..61a1432 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -105,6 +105,19 @@ enum dwarf_gnat_encodings
 				       Emit GNAT encodings for the rest.  */
 };
 
+/* CTF debug info levels.
+   CTF debug info levels are untied with DWARF debug info levels because CTF
+   may co-exist with DWARF.  */
+enum ctf_debug_info_levels
+{
+  CTFINFO_LEVEL_NONE = 0,     /* Write no CTF debug info.  */
+  CTFINFO_LEVEL_TERSE = 1,    /* Write CTF information to support tracebacks
+				 only.  Not Implemented.  */
+  CTFINFO_LEVEL_NORMAL = 2    /* Write CTF type information for all entities
+				 (functions, data objects, variables etc.)
+				 at file-scope or global-scope only.  */
+};
+
 /* Enumerate Objective-c instance variable visibility settings. */
 
 enum ivar_visibility
diff --git a/gcc/opts.c b/gcc/opts.c
index b38bfb1..03346ec 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -195,6 +195,8 @@ static void set_debug_level (enum debug_info_type type, int extended,
 			     const char *arg, struct gcc_options *opts,
 			     struct gcc_options *opts_set,
 			     location_t loc);
+static void set_ctf_debug_level (const char *arg,
+				 struct gcc_options *opts, location_t loc);
 static void set_fast_math_flags (struct gcc_options *opts, int set);
 static void decode_d_option (const char *arg, struct gcc_options *opts,
 			     location_t loc, diagnostic_context *dc);
@@ -2684,6 +2686,10 @@ common_handle_option (struct gcc_options *opts,
       opts->x_flag_stack_usage_info = value != 0;
       break;
 
+    case OPT_gt:
+      set_ctf_debug_level (arg, opts, loc);
+      break;
+
     case OPT_g:
       set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
                        loc);
@@ -3006,6 +3012,26 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
     }
 }
 
+/* Handle a debug output -gt switch for options OPTS.  */
+static void
+set_ctf_debug_level (const char *arg,
+		     struct gcc_options *opts, location_t loc)
+{
+  /* CTF debug flag without a level defaults to level 2.  */
+  if (*arg == '\0')
+    opts->x_ctf_debug_info_level = CTFINFO_LEVEL_NORMAL;
+  else
+    {
+      int argval = integral_argument (arg);
+      if (argval == -1)
+	error_at (loc, "unrecognized ctf debug output level %qs", arg);
+      else if (argval > CTFINFO_LEVEL_NORMAL)
+	error_at (loc, "ctf debug output level %qs is too high", arg);
+      else
+	opts->x_ctf_debug_info_level = (enum ctf_debug_info_levels) argval;
+    }
+}
+
 /* Arrange to dump core on error for diagnostic context DC.  (The
    regular error message is still printed first, except in the case of
    abort ().)  */
-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-06-27  6:37 [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
                   ` (4 preceding siblings ...)
  2019-06-27  6:37 ` [PATCH,RFC,V3 2/5] Add CTF command line options : -gtLEVEL Indu Bhagat
@ 2019-07-02 17:43 ` Indu Bhagat
  2019-07-03  3:18   ` Jeff Law
  5 siblings, 1 reply; 24+ messages in thread
From: Indu Bhagat @ 2019-07-02 17:43 UTC (permalink / raw)
  To: gcc-patches; +Cc: Indu Bhagat

Ping.
Can someone please review these patches ? We would like to get the
support for CTF integrated soon.
Thanks
Indu

On Wed, Jun 26, 2019 at 11:38 PM Indu Bhagat <indu.bhagat@oracle.com> wrote:
>
> Hello,
>
> This patch series adds support for CTF generation in GCC.
>
> [Changes from V2]
>  - Patch 1, 2, and 3 have minor edits if any.
>  - Patch 4 is a new addition.
>  - Patch 5 is a new addition.
>
> Summary of the GCC RFC V3 patch set :
> Patch 1, 2, and 3 do the preparatory work of adding the CTF command line options
> and setting up the framework for CTF generation and emission.  More details on
> these patches can be seen in the previous posting
> https://gcc.gnu.org/ml/gcc-patches/2019-06/msg00718.html
>
> With Patch 4 in the current set, the compiler can generate a .ctf section for a
> single compilation unit if -gt (when unspecified, LEVEL defaults to 2) or -gt2
> is specified.  Recall that -gt2 produces type information for entities
> (functions, variables etc.) at file-scope or global-scope.
>
> For each translation unit, a CTF container (ctf_container_t) is used to
> keep the generated CTF.  Two hash_map structures are kept to hold the generated
> CTF for type and variables.  CTF does need pre-processing before emission into
> a section; there are code comments in ctfout.c to help understand this.
>
> There are a couple of TBDs and FIXMEs in Patch 4 which will be resolved as I
> progress further; Inputs on some of which will be very helpful :
>
> - ctf_dtdef_hash : The compiler uses a hashing scheme to keep track of whether
>   CTF has been generated for a type of decl.  For a type, the hashing scheme
>   uses TYPE_UID, but for a decl it uses htab_hash_pointer (decl).  Is there a
>   better way to do this ? (See hash_dtd_tree_decl in ctfout.c)
>
> - delete_ctf_container routine in ctfout.c : I have used the GTY (()) tags in
>   the CTF container structs.  Does this ensure that if I set the CTF container
>   global variable (ctfc) to NULL, the garbage collection machinery will take
>   care of cleaning up the the internals of the container (including hash_map).
>   Haven't been able to get a definitive answer looking at the code in
>   hash-map.h and the generated code in gtype-desc.c.
>
> Testing :
> - Bootstrapped and regression tested on x86_64/linux and aarch64/linux.
>   Also bootstrapped on SPARC64/linux with some testing.
> - Parsed .ctf sections of libdtrace-ctf files via a CTF dumping utility on
>   x86_64/linux.  This simply ensures that the CTF sections are well-formed.
> - Interaction with an internally available GDB looks promising.  Basic whatis
>   and ptype tests work.  GDB patches to uptake CTF debug info are in the works
>   and will be upstreamed soon.
>
> In the subsequent patches, I intend to close some open ends in the current
> patch and add LTO support.
>
> Thanks,
>
> Indu Bhagat (5):
>   Add new function lang_GNU_GIMPLE
>   Add CTF command line options : -gtLEVEL
>   Setup for CTF generation and emission
>   CTF generation for a single compilation unit
>   Update CTF testsuite
>
>  gcc/ChangeLog                                      |   91 +
>  gcc/Makefile.in                                    |    5 +
>  gcc/cgraphunit.c                                   |   12 +-
>  gcc/common.opt                                     |    9 +
>  gcc/ctfcreate.c                                    |  526 ++++++
>  gcc/ctfout.c                                       | 1739 ++++++++++++++++++++
>  gcc/ctfout.h                                       |  359 ++++
>  gcc/ctfutils.c                                     |  198 +++
>  gcc/doc/invoke.texi                                |   16 +
>  gcc/flag-types.h                                   |   13 +
>  gcc/gengtype.c                                     |    4 +-
>  gcc/langhooks.c                                    |    9 +
>  gcc/langhooks.h                                    |    1 +
>  gcc/opts.c                                         |   26 +
>  gcc/passes.c                                       |    7 +-
>  gcc/testsuite/ChangeLog                            |   35 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c             |    6 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c             |   10 +
>  .../gcc.dg/debug/ctf/ctf-anonymous-struct-1.c      |   23 +
>  .../gcc.dg/debug/ctf/ctf-anonymous-union-1.c       |   26 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c       |   31 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c   |   30 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c   |   39 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c   |   44 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c   |   30 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c   |   41 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c        |   21 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c       |   16 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c     |   36 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c     |   16 +
>  .../gcc.dg/debug/ctf/ctf-function-pointers-1.c     |   24 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c   |   34 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c         |   17 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c    |   26 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c    |   11 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c   |   26 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c      |   25 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c      |   30 +
>  .../gcc.dg/debug/ctf/ctf-struct-array-1.c          |   36 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c     |   23 +
>  .../gcc.dg/debug/ctf/ctf-typedef-struct-1.c        |   12 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c       |   14 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c   |   25 +
>  gcc/testsuite/gcc.dg/debug/ctf/ctf.exp             |   41 +
>  gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c          |    7 +
>  gcc/toplev.c                                       |   18 +
>  include/ChangeLog                                  |    8 +
>  include/ctf.h                                      |  487 ++++++
>  48 files changed, 4277 insertions(+), 6 deletions(-)
>  create mode 100644 gcc/ctfcreate.c
>  create mode 100644 gcc/ctfout.c
>  create mode 100644 gcc/ctfout.h
>  create mode 100644 gcc/ctfutils.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-struct-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-anonymous-union-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-functions-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-preamble-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-str-table-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp
>  create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c
>  create mode 100644 include/ctf.h
>
> --
> 1.8.3.1
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-02 17:43 ` [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
@ 2019-07-03  3:18   ` Jeff Law
  2019-07-03 12:39     ` Richard Biener
  2019-07-04  0:36     ` Indu Bhagat
  0 siblings, 2 replies; 24+ messages in thread
From: Jeff Law @ 2019-07-03  3:18 UTC (permalink / raw)
  To: Indu Bhagat, gcc-patches; +Cc: Indu Bhagat

On 7/2/19 11:54 AM, Indu Bhagat wrote:
> Ping.
> Can someone please review these patches ? We would like to get the
> support for CTF integrated soon.
I'm not sure there's really even consensus that we want CTF support in
GCC.  Though I think that the changes you've made in the last several
weeks do make it somewhat more palatable.  But ultimately the first step
is to get that consensus.

I'd hazard a guess that Jakub in particular isn't on board as he's been
pushing to some degree for post-processing or perhaps doing it via a
plug in.

Richi has been guiding you a bit through how to make the changes easier
to integrate, but I haven't seen him state one way or the other his
preference on whether or not CTF support is something we want.

I'm hesitant to add CTF support in GCC, but can understand how it might
be useful given the kernel's aversion to everything dwarf.  But if the
kernel is the primary consumer than I'd lean towards post-processing.

Jeff

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-03  3:18   ` Jeff Law
@ 2019-07-03 12:39     ` Richard Biener
  2019-07-04  1:49       ` Indu Bhagat
  2019-07-04  0:36     ` Indu Bhagat
  1 sibling, 1 reply; 24+ messages in thread
From: Richard Biener @ 2019-07-03 12:39 UTC (permalink / raw)
  To: Jeff Law; +Cc: Indu Bhagat, GCC Patches, Indu Bhagat

On Wed, Jul 3, 2019 at 5:18 AM Jeff Law <law@redhat.com> wrote:
>
> On 7/2/19 11:54 AM, Indu Bhagat wrote:
> > Ping.
> > Can someone please review these patches ? We would like to get the
> > support for CTF integrated soon.
> I'm not sure there's really even consensus that we want CTF support in
> GCC.  Though I think that the changes you've made in the last several
> weeks do make it somewhat more palatable.  But ultimately the first step
> is to get that consensus.
>
> I'd hazard a guess that Jakub in particular isn't on board as he's been
> pushing to some degree for post-processing or perhaps doing it via a
> plug in.
>
> Richi has been guiding you a bit through how to make the changes easier
> to integrate, but I haven't seen him state one way or the other his
> preference on whether or not CTF support is something we want.

I'm mostly worried about the lack of a specification and the appearant
restriction on a subset of C (the patches have gcc_unreachable ()
in paths that can be reached by VECTOR_TYPE or COMPLEX_TYPE
not to mention FIXED_POINT_TYPE, etc...).

While CTF might be easy and fast to parse and small I fear it will
go the STABS way of being not extensible and bitrotten.

Given it appears to generate only debug info for symbols and no locations
or whatnot it should be sufficient to introspect the compilation to generate
the CTF info on the side and then merge it in at link-time.  Which makes
me wonder if this shouldn't be a plugin for now until it is more complete
and can be evaluated better (comments in the patches indicate even the
on-disk format is in flux?).  Adding plugin hook invocations to the three
places the CTF info generation hooks off should be easy.

That said, the patch series isn't ready for integration since it will
crash left and right -- did you bootstrap and run the testsuite
with -gt?

Richard.

> I'm hesitant to add CTF support in GCC, but can understand how it might
> be useful given the kernel's aversion to everything dwarf.  But if the
> kernel is the primary consumer than I'd lean towards post-processing.
>
> Jeff
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-03  3:18   ` Jeff Law
  2019-07-03 12:39     ` Richard Biener
@ 2019-07-04  0:36     ` Indu Bhagat
  1 sibling, 0 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-07-04  0:36 UTC (permalink / raw)
  To: Jeff Law, Indu Bhagat, gcc-patches



On 07/02/2019 08:18 PM, Jeff Law wrote:
> On 7/2/19 11:54 AM, Indu Bhagat wrote:
>> Ping.
>> Can someone please review these patches ? We would like to get the
>> support for CTF integrated soon.
> I'm not sure there's really even consensus that we want CTF support in
> GCC.  Though I think that the changes you've made in the last several
> weeks do make it somewhat more palatable.  But ultimately the first step
> is to get that consensus.

Thanks for your message.  Absolutely, consensus is the first step.  We are
happy to take all the constructive feedback and answer all the concerns to make
certain that CTF support in toolchain will be a useful and worthwhile
contribution.

>
> I'd hazard a guess that Jakub in particular isn't on board as he's been
> pushing to some degree for post-processing or perhaps doing it via a
> plug in.
>
> Richi has been guiding you a bit through how to make the changes easier
> to integrate, but I haven't seen him state one way or the other his
> preference on whether or not CTF support is something we want.
>
> I'm hesitant to add CTF support in GCC, but can understand how it might
> be useful given the kernel's aversion to everything dwarf.  But if the
> kernel is the primary consumer than I'd lean towards post-processing.
>
Kernel is just *one* of the consumers. There are other applications, external
and internal to Oracle, that have shown interest. Not just that, a couple of
distro and package maintainers have shown interest in enabling CTF by default.

Post-processing in kernel and other internally available large applications has
been a deterrent for adoption because of high space and compile-time costs. I
answered some of Jakub's concerns in the post here
https://gcc.gnu.org/ml/gcc-patches/2019-06/msg00131.html.

I would even argue that the usecases will only grow if CTF is properly
supported in the toolchain.

Thanks

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-03 12:39     ` Richard Biener
@ 2019-07-04  1:49       ` Indu Bhagat
  2019-07-04 10:47         ` Richard Biener
  0 siblings, 1 reply; 24+ messages in thread
From: Indu Bhagat @ 2019-07-04  1:49 UTC (permalink / raw)
  To: Richard Biener, Jeff Law; +Cc: Indu Bhagat, GCC Patches


On 07/03/2019 05:31 AM, Richard Biener wrote:
> On Wed, Jul 3, 2019 at 5:18 AM Jeff Law <law@redhat.com> wrote:
>> On 7/2/19 11:54 AM, Indu Bhagat wrote:
>>> Ping.
>>> Can someone please review these patches ? We would like to get the
>>> support for CTF integrated soon.
>> I'm not sure there's really even consensus that we want CTF support in
>> GCC.  Though I think that the changes you've made in the last several
>> weeks do make it somewhat more palatable.  But ultimately the first step
>> is to get that consensus.
>>
>> I'd hazard a guess that Jakub in particular isn't on board as he's been
>> pushing to some degree for post-processing or perhaps doing it via a
>> plug in.
>>
>> Richi has been guiding you a bit through how to make the changes easier
>> to integrate, but I haven't seen him state one way or the other his
>> preference on whether or not CTF support is something we want.
> I'm mostly worried about the lack of a specification and the appearant
> restriction on a subset of C (the patches have gcc_unreachable ()
> in paths that can be reached by VECTOR_TYPE or COMPLEX_TYPE
> not to mention FIXED_POINT_TYPE, etc...).

RE lack of specification : I cannot agree more; This does need to absolutely exist
if we envision CTF support in toolchain to be useful to the community.
We plan on getting to this task once the Linker changes are scoped and closer
to done (~ a couple of weeks from now). Will this work ?

RE subset of C : It is true that CTF format currently does leave out a very
small subset of C like FIXED_POINT as you noted ( CTF does have representation
for COMPLEX_TYPE, if my code paths culminate to gcc_unreachable () for that, I
should fix them ).  The end goal is to make it support all of C, and not just a
subset.

Meanwhile, I intend to make the compiler skip types when a C construct is not
supported instead of crashing because of gcc_unreachable (). (You may have also
noted stubs with "TBD WARN instead" notes in the patch series I sent.)	


>
> While CTF might be easy and fast to parse and small I fear it will
> go the STABS way of being not extensible and bitrotten.

FWIW, I can understand this. We will maintain it. And I hope it will also be a
community effort thereafter with active consumers, so there is a positive
feedback loop.

>
> Given it appears to generate only debug info for symbols and no locations
> or whatnot it should be sufficient to introspect the compilation to generate
> the CTF info on the side and then merge it in at link-time.  Which makes
> me wonder if this shouldn't be a plugin for now until it is more complete
> and can be evaluated better (comments in the patches indicate even the
> on-disk format is in flux?).  Adding plugin hook invocations to the three
> places the CTF info generation hooks off should be easy.

Yes, some bits of the on-disk format are being adapted to make it easier to
adopt the CTF format across the board. E.g., we recently added CU name in the
CTF header. As another example, we added CTF_K_SLICE type because there existed
no way in CTF to represent enum bitfields. For the most part though, CTF format
has stayed as is.

Hmm...a GCC plugin for CTF generation at compile-time may work out for a single
compilation unit.  But I am not sure how will LTO be supported in that case.
Basically, for LTO and -gtLEVEL to work together, I need the lto-wrapper to be
aware of the presence of .ctf sections (so I think). I will need to combine the
.ctf sections from multiple compilation units into a CTF archive, which the
linker can then de-duplicate.

Even if I assume that the technical hurdle in the above paragraph is solvable
within the purview of a plugin, I fear worse problems of adoption, maintenance
and distribution in the long run, if CTF support unfortunately ever remains to be
done via a plugin for reasons unforeseen.

Going the plugin route for the short term, will continue to suffer similar
problems of distribution and support.

- Is the plugin infrastructure supported on most platforms ? Also, I see that
   the plugin infrastructure supports all gcc versions from 4.5 onwards.
   Can someone confirm ? ( We minimally want the toolchain support with
   GCC 4.8.5 and GCC 8 and later, for now. )

- How will the plugin be distributed for a variety of platforms and
   architectures outside of what Oracle Linux commits to support ?

   Unless you are suggesting that the GCC plugin be distributed within GCC,
   meanwhile ? Well, that may be acceptable in the short term, depending on how
   I resolve some points raised above.


>
> That said, the patch series isn't ready for integration since it will
> crash left and right -- did you bootstrap and run the testsuite
> with -gt?
>
>
Bootstrap and Testsuite : Yes, I have.  On x86_64/linux, sparc64/linux,
                           aarch64/linux.
Run testsuite with -gt : Not yet. Believe me, it's on my plate. And I already
                          regret not having done it sooner :)
Bootstrap with -gt : Not yet. I should try soon.

(I have compiled libdtrace-ctf with -gt and parsed the .ctf sections with the
patch set.)

About the patch being not ready for integration : Yes, you're right.
That's why I chose to retain 'RFC' for this patch series as well. I am working
on issues, testing the compiler, and closing on the open ends in the
implementation.

I will refresh the patch series when I have made a meaningful stride ahead. Any
further suggestions on functional/performance testing will be helpful too.

Thanks again for your reviews.

Indu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-04  1:49       ` Indu Bhagat
@ 2019-07-04 10:47         ` Richard Biener
  2019-07-04 22:44           ` Indu Bhagat
  2019-07-09 17:32           ` Indu Bhagat
  0 siblings, 2 replies; 24+ messages in thread
From: Richard Biener @ 2019-07-04 10:47 UTC (permalink / raw)
  To: Indu Bhagat; +Cc: Jeff Law, Indu Bhagat, GCC Patches

On Thu, Jul 4, 2019 at 2:36 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
>
>
> On 07/03/2019 05:31 AM, Richard Biener wrote:
> > On Wed, Jul 3, 2019 at 5:18 AM Jeff Law <law@redhat.com> wrote:
> >> On 7/2/19 11:54 AM, Indu Bhagat wrote:
> >>> Ping.
> >>> Can someone please review these patches ? We would like to get the
> >>> support for CTF integrated soon.
> >> I'm not sure there's really even consensus that we want CTF support in
> >> GCC.  Though I think that the changes you've made in the last several
> >> weeks do make it somewhat more palatable.  But ultimately the first step
> >> is to get that consensus.
> >>
> >> I'd hazard a guess that Jakub in particular isn't on board as he's been
> >> pushing to some degree for post-processing or perhaps doing it via a
> >> plug in.
> >>
> >> Richi has been guiding you a bit through how to make the changes easier
> >> to integrate, but I haven't seen him state one way or the other his
> >> preference on whether or not CTF support is something we want.
> > I'm mostly worried about the lack of a specification and the appearant
> > restriction on a subset of C (the patches have gcc_unreachable ()
> > in paths that can be reached by VECTOR_TYPE or COMPLEX_TYPE
> > not to mention FIXED_POINT_TYPE, etc...).
>
> RE lack of specification : I cannot agree more; This does need to absolutely exist
> if we envision CTF support in toolchain to be useful to the community.
> We plan on getting to this task once the Linker changes are scoped and closer
> to done (~ a couple of weeks from now). Will this work ?

Sure - just keep in mind that it's difficult to give feedback to
something without
a specification.

> RE subset of C : It is true that CTF format currently does leave out a very
> small subset of C like FIXED_POINT as you noted ( CTF does have representation
> for COMPLEX_TYPE, if my code paths culminate to gcc_unreachable () for that, I
> should fix them ).  The end goal is to make it support all of C, and not just a
> subset.

What about other languages?  GCC supports C++, Ada, Objective-C, Go, D,
Fortran, Modula-2, BRIG (this list is not necessarily complete and may change
in the future).

> Meanwhile, I intend to make the compiler skip types when a C construct is not
> supported instead of crashing because of gcc_unreachable (). (You may have also
> noted stubs with "TBD WARN instead" notes in the patch series I sent.)
>
>
> >
> > While CTF might be easy and fast to parse and small I fear it will
> > go the STABS way of being not extensible and bitrotten.
>
> FWIW, I can understand this. We will maintain it. And I hope it will also be a
> community effort thereafter with active consumers, so there is a positive
> feedback loop.
>
> >
> > Given it appears to generate only debug info for symbols and no locations
> > or whatnot it should be sufficient to introspect the compilation to generate
> > the CTF info on the side and then merge it in at link-time.  Which makes
> > me wonder if this shouldn't be a plugin for now until it is more complete
> > and can be evaluated better (comments in the patches indicate even the
> > on-disk format is in flux?).  Adding plugin hook invocations to the three
> > places the CTF info generation hooks off should be easy.
>
> Yes, some bits of the on-disk format are being adapted to make it easier to
> adopt the CTF format across the board. E.g., we recently added CU name in the
> CTF header. As another example, we added CTF_K_SLICE type because there existed
> no way in CTF to represent enum bitfields. For the most part though, CTF format
> has stayed as is.

I hope the format is versioned at least.

> Hmm...a GCC plugin for CTF generation at compile-time may work out for a single
> compilation unit.  But I am not sure how will LTO be supported in that case.
> Basically, for LTO and -gtLEVEL to work together, I need the lto-wrapper to be
> aware of the presence of .ctf sections (so I think). I will need to combine the
> .ctf sections from multiple compilation units into a CTF archive, which the
> linker can then de-duplicate.

True.  lto-wrapper does this kind of dancing for the much more complex set of
DWARF sections already.

> Even if I assume that the technical hurdle in the above paragraph is solvable
> within the purview of a plugin, I fear worse problems of adoption, maintenance
> and distribution in the long run, if CTF support unfortunately ever remains to be
> done via a plugin for reasons unforeseen.
>
> Going the plugin route for the short term, will continue to suffer similar
> problems of distribution and support.
>
> - Is the plugin infrastructure supported on most platforms ? Also, I see that
>    the plugin infrastructure supports all gcc versions from 4.5 onwards.
>    Can someone confirm ? ( We minimally want the toolchain support with
>    GCC 4.8.5 and GCC 8 and later, for now. )

The infrastructure is quite old but you'd need new invocation hooks so this
won't help.

> - How will the plugin be distributed for a variety of platforms and
>    architectures outside of what Oracle Linux commits to support ?
>
>    Unless you are suggesting that the GCC plugin be distributed within GCC,
>    meanwhile ? Well, that may be acceptable in the short term, depending on how
>    I resolve some points raised above.
>
> >
> > That said, the patch series isn't ready for integration since it will
> > crash left and right -- did you bootstrap and run the testsuite
> > with -gt?
> >
> >
> Bootstrap and Testsuite : Yes, I have.  On x86_64/linux, sparc64/linux,
>                            aarch64/linux.
> Run testsuite with -gt : Not yet. Believe me, it's on my plate. And I already
>                           regret not having done it sooner :)
> Bootstrap with -gt : Not yet. I should try soon.
>
> (I have compiled libdtrace-ctf with -gt and parsed the .ctf sections with the
> patch set.)
>
> About the patch being not ready for integration : Yes, you're right.
> That's why I chose to retain 'RFC' for this patch series as well. I am working
> on issues, testing the compiler, and closing on the open ends in the
> implementation.
>
> I will refresh the patch series when I have made a meaningful stride ahead. Any
> further suggestions on functional/performance testing will be helpful too.

What's the functional use of CTF?  Print nice backtraces (without showing
function argument values)?

Richard.

> Thanks again for your reviews.
>
> Indu
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-04 10:47         ` Richard Biener
@ 2019-07-04 22:44           ` Indu Bhagat
  2019-07-05 11:25             ` Richard Biener
  2019-07-09 17:32           ` Indu Bhagat
  1 sibling, 1 reply; 24+ messages in thread
From: Indu Bhagat @ 2019-07-04 22:44 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jeff Law, Indu Bhagat, GCC Patches

On 07/04/2019 03:43 AM, Richard Biener wrote:
> On Thu, Jul 4, 2019 at 2:36 AM Indu Bhagat<indu.bhagat@oracle.com>  wrote:
>> [...]
>> RE subset of C : It is true that CTF format currently does leave out a very
>> small subset of C like FIXED_POINT as you noted ( CTF does have representation
>> for COMPLEX_TYPE, if my code paths culminate to gcc_unreachable () for that, I
>> should fix them ).  The end goal is to make it support all of C, and not just a
>> subset.
> What about other languages?  GCC supports C++, Ada, Objective-C, Go, D,
> Fortran, Modula-2, BRIG (this list is not necessarily complete and may change
> in the future).

The format supports C only at this time. Other languages are not on the radar
yet. However, we have no intrinsic objection to them. Although, languages
that already have fully-fledged type introspection and interpreted/
managed languages are probably out of scope, since they already have
what CTF provides.

>
>>
>>> Given it appears to generate only debug info for symbols and no locations
>>> or whatnot it should be sufficient to introspect the compilation to generate
>>> the CTF info on the side and then merge it in at link-time.  Which makes
>>> me wonder if this shouldn't be a plugin for now until it is more complete
>>> and can be evaluated better (comments in the patches indicate even the
>>> on-disk format is in flux?).  Adding plugin hook invocations to the three
>>> places the CTF info generation hooks off should be easy.
>> Yes, some bits of the on-disk format are being adapted to make it easier to
>> adopt the CTF format across the board. E.g., we recently added CU name in the
>> CTF header. As another example, we added CTF_K_SLICE type because there existed
>> no way in CTF to represent enum bitfields. For the most part though, CTF format
>> has stayed as is.
> I hope the format is versioned at least.

Yes, the format is versioned. The current version is CTF_VERSION_3.  All these
format changes I talked about above are a part of CTF_VERSION_3.

libctf handles backward compatibility for users of CTF in the toolchain; all
transparently to the user. This means that, in future, when CTF version needs
to be bumped, libctf will either support older version and/or transparently
upgrade to the new version for further consumers.

It also means that the compiler does not always need to change merely because
the format has changed: (depending on the change) the linker can transparently
adjust, as will all consumers if they try to read unlinked object files.

>
>>> That said, the patch series isn't ready for integration since it will
>>> crash left and right -- did you bootstrap and run the testsuite
>>> with -gt?
>>>
>>>
>> Bootstrap and Testsuite : Yes, I have.  On x86_64/linux, sparc64/linux,
>>                             aarch64/linux.
>> Run testsuite with -gt : Not yet. Believe me, it's on my plate. And I already
>>                            regret not having done it sooner :)
>> Bootstrap with -gt : Not yet. I should try soon.
>>
>> (I have compiled libdtrace-ctf with -gt and parsed the .ctf sections with the
>> patch set.)
>>
>> About the patch being not ready for integration : Yes, you're right.
>> That's why I chose to retain 'RFC' for this patch series as well. I am working
>> on issues, testing the compiler, and closing on the open ends in the
>> implementation.
>>
>> I will refresh the patch series when I have made a meaningful stride ahead. Any
>> further suggestions on functional/performance testing will be helpful too.
> What's the functional use of CTF?  Print nice backtraces (without showing
> function argument values)?
>
CTF, at this time, is type information for entities at global or file scope.
This can be used by online debuggers, program tracers (dynamic tracing); More
generally, it provides type introspection for C programs, with an optional
library API to allow them to get at their own types quite more easily than
DWARF. So, the umbrella usecases are - all C programs that want to introspect
their own types quickly; and applications that want to introspect other
programs's types quickly.

(Even with the exception of its embedded string table, it is already small
  enough to  be kept around in stripped binaries so that it can be relied upon
  to be present.)

We are also extending the format so it is useful for other on-line debugging
tools, such as backtracers.

Indu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-04 22:44           ` Indu Bhagat
@ 2019-07-05 11:25             ` Richard Biener
  2019-07-05 18:28               ` Nix
  0 siblings, 1 reply; 24+ messages in thread
From: Richard Biener @ 2019-07-05 11:25 UTC (permalink / raw)
  To: Indu Bhagat; +Cc: Jeff Law, Indu Bhagat, GCC Patches

On Fri, Jul 5, 2019 at 12:21 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
>
> On 07/04/2019 03:43 AM, Richard Biener wrote:
>
> On Thu, Jul 4, 2019 at 2:36 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
>
> [...]
>
> RE subset of C : It is true that CTF format currently does leave out a very
> small subset of C like FIXED_POINT as you noted ( CTF does have representation
> for COMPLEX_TYPE, if my code paths culminate to gcc_unreachable () for that, I
> should fix them ).  The end goal is to make it support all of C, and not just a
> subset.
>
> What about other languages?  GCC supports C++, Ada, Objective-C, Go, D,
> Fortran, Modula-2, BRIG (this list is not necessarily complete and may change
> in the future).
>
> The format supports C only at this time. Other languages are not on the radar
> yet. However, we have no intrinsic objection to them. Although, languages
> that already have fully-fledged type introspection and interpreted/
> managed languages are probably out of scope, since they already have
> what CTF provides.
>
>
>
> Given it appears to generate only debug info for symbols and no locations
> or whatnot it should be sufficient to introspect the compilation to generate
> the CTF info on the side and then merge it in at link-time.  Which makes
> me wonder if this shouldn't be a plugin for now until it is more complete
> and can be evaluated better (comments in the patches indicate even the
> on-disk format is in flux?).  Adding plugin hook invocations to the three
> places the CTF info generation hooks off should be easy.
>
> Yes, some bits of the on-disk format are being adapted to make it easier to
> adopt the CTF format across the board. E.g., we recently added CU name in the
> CTF header. As another example, we added CTF_K_SLICE type because there existed
> no way in CTF to represent enum bitfields. For the most part though, CTF format
> has stayed as is.
>
> I hope the format is versioned at least.
>
> Yes, the format is versioned. The current version is CTF_VERSION_3.  All these
> format changes I talked about above are a part of CTF_VERSION_3.
>
> libctf handles backward compatibility for users of CTF in the toolchain; all
> transparently to the user. This means that, in future, when CTF version needs
> to be bumped, libctf will either support older version and/or transparently
> upgrade to the new version for further consumers.
>
> It also means that the compiler does not always need to change merely because
> the format has changed: (depending on the change) the linker can transparently
> adjust, as will all consumers if they try to read unlinked object files.
>
>
> That said, the patch series isn't ready for integration since it will
> crash left and right -- did you bootstrap and run the testsuite
> with -gt?
>
>
> Bootstrap and Testsuite : Yes, I have.  On x86_64/linux, sparc64/linux,
>                            aarch64/linux.
> Run testsuite with -gt : Not yet. Believe me, it's on my plate. And I already
>                           regret not having done it sooner :)
> Bootstrap with -gt : Not yet. I should try soon.
>
> (I have compiled libdtrace-ctf with -gt and parsed the .ctf sections with the
> patch set.)
>
> About the patch being not ready for integration : Yes, you're right.
> That's why I chose to retain 'RFC' for this patch series as well. I am working
> on issues, testing the compiler, and closing on the open ends in the
> implementation.
>
> I will refresh the patch series when I have made a meaningful stride ahead. Any
> further suggestions on functional/performance testing will be helpful too.
>
> What's the functional use of CTF?  Print nice backtraces (without showing
> function argument values)?
>
> CTF, at this time, is type information for entities at global or file scope.
> This can be used by online debuggers, program tracers (dynamic tracing); More
> generally, it provides type introspection for C programs, with an optional
> library API to allow them to get at their own types quite more easily than
> DWARF. So, the umbrella usecases are - all C programs that want to introspect
> their own types quickly; and applications that want to introspect other
> programs's types quickly.

What makes it superior to DWARF stripped down to the above feature set?

> (Even with the exception of its embedded string table, it is already small
>  enough to  be kept around in stripped binaries so that it can be relied upon
>  to be present.)

So for distributing a program/library for SUSE we usually split the
distribution into two pieces - the binaries and separated debug information.
With CTF we'd then create both, continue stripping out the DWARF information
but keep the CTF in the binaries?

When a program contains CTF only, can gdb do anything to help debugging
of a running program or a core file?  Do you have gdb support in the works?

> We are also extending the format so it is useful for other on-line debugging
> tools, such as backtracers.

So you become more complex similar to DWARF?

Richard.

>
> Indu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-05 11:25             ` Richard Biener
@ 2019-07-05 18:28               ` Nix
  2019-07-05 19:37                 ` Jakub Jelinek
                                   ` (2 more replies)
  0 siblings, 3 replies; 24+ messages in thread
From: Nix @ 2019-07-05 18:28 UTC (permalink / raw)
  To: Richard Biener; +Cc: Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

On 5 Jul 2019, Richard Biener said:

> On Fri, Jul 5, 2019 at 12:21 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
>> CTF, at this time, is type information for entities at global or file scope.
>> This can be used by online debuggers, program tracers (dynamic tracing); More
>> generally, it provides type introspection for C programs, with an optional
>> library API to allow them to get at their own types quite more easily than
>> DWARF. So, the umbrella usecases are - all C programs that want to introspect
>> their own types quickly; and applications that want to introspect other
>> programs's types quickly.
>
> What makes it superior to DWARF stripped down to the above feature set?

Increased compactness. DWARF fundamentally trades off compactness in
favour of its regular structure, which makes it easier to parse (but not
easier to interpret) but very hard to make it much smaller than it is
now. Where DWARF uses word-sized and larger entities for everything, CTF
packs everything much more tightly -- and this is quite visible in the
resulting file sizes, once deduplicated. (CTF for the entire Linux
kernel is about 6MiB after gzipping, and that includes not only complete
descriptions of its tens of thousands of types but also type and string
table entries for every structure and union member name, every
enumeration member, and every global variable. More conventional
programs will be able to eschew spending space on some of these because
the ELF string table already contains their names, and we reuse those
where possible. Insofar as it is possible to tell, the DWARF type info
for the entire kernel, even after deduplication, would be many times
larger: it is certainly much larger as it comes out of the compiler. You
could define a "restricted DWARF" with smaller tags etc that is smaller,
but frankly that would no longer be DWARF at all.)

(I'm using the kernel as an example a lot not because CTF is
kernel-specific but because our *existing deduplicator* happens to be
targetted at the kernel. This is already an annoying limitation: we want
to be able to use CTF in userspace more easily and more widely, without
kludges and without incurring huge costs to generate gigabytes of DWARF
we otherwise aren't using: hence this project.)

When programs try to consume DWARF from large programs the size of the
kernel, even with indexes I observe a multi-second lag and significant
memory usage: no program I have tried has increased its RSS by less than
100MiB. CTF consumers can suck in the CTF for the core kernel in well
under a third of a second, and can traverse the CTF for the kernel and
all modules (multiple CTF sections in an archive, sharing common types
wiht a parent section) in about a second and a half (from a cold cache):
RSS goes up by about 15MiB. If DWARF usage can impose a burden that low
on consumers, it's the first I've ever heard of it.

>> (Even with the exception of its embedded string table, it is already small
>>  enough to  be kept around in stripped binaries so that it can be relied upon
>>  to be present.)
>
> So for distributing a program/library for SUSE we usually split the
> distribution into two pieces - the binaries and separated debug information.
> With CTF we'd then create both, continue stripping out the DWARF information
> but keep the CTF in the binaries?
>
> When a program contains CTF only, can gdb do anything to help debugging
> of a running program or a core file?  Do you have gdb support in the works?

Yes, and it works well enough already to extract types from programs
(going all the way from symbols to types requires some code on the GCC
and linker side that is being written right now, and we can't test the
GDB code that relies on that until then: equally, I'm still working on
the linker so this is a demo on a randomly-chosen object file. This also
means you don't see any benefits from strtab reuse with the containing
ELF object, CTF section compression or deduplication in the following
example's .ctf section size):

[nix@ca-tools3 libiberty]$ /home/ibhagat/GCC/install/gcc-ctf/bin/gcc -c -DHAVE_CONFIG_H -gt -O2  -I. -I../../libiberty/../include  -W -Wall -Wwrite-strings -Wc++-compat -Wstrict-prototypes -Wshadow=local -pedantic  -D_GNU_SOURCE ../../libiberty/hashtab.c -o hashtab.o

[nix@ca-tools3 libiberty]$ size -A hashtab.o
hashtab.o  :
section            size   addr
.text              4112      0
.data                16      0
.bss                  0      0
.ctf              11907      0
.rodata.str1.8       40      0
.rodata.cst8          8      0
.rodata             480      0
.comment             43      0
.note.GNU-stack       0      0
Total             16606

[nix@ca-tools3 libiberty]$ ../gdb/gdb hashtab.o 
GNU gdb (GDB) 8.2.50.20190214-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "sparc64-unknown-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from hashtab.o...
(gdb) info types
All defined types:

File /home/nix/binutils-gdb/foo/libiberty/hashtab.o:
	struct {
    unsigned char __arr[8];
};
	typedef struct <unknown> FILE;
	typedef struct {
    long __pos;
    struct {...} __state;
} _G_fpos64_t;
	typedef struct {
    long __pos;
    struct {...} __state;
} _G_fpos_t;
	typedef short _G_int16_t;
	typedef int _G_int32_t;
	typedef unsigned short _G_uint16_t;
	typedef unsigned int _G_uint32_t;
	typedef struct <unknown> _IO_FILE;
	typedef struct {
    long (*read)();
    long (*write)();
    int (*seek)();
    int (*close)();
} _IO_cookie_io_functions_t;
	typedef void _IO_lock_t;
	typedef struct <unknown> __FILE;
	typedef struct {
    unsigned char __arr[2];
} __STRING2_COPY_ARR2;
	typedef struct {
    unsigned char __arr[3];
} __STRING2_COPY_ARR3;
	typedef struct {
    unsigned char __arr[4];
} __STRING2_COPY_ARR4;
	typedef struct {
    unsigned char __arr[5];
} __STRING2_COPY_ARR5;
	typedef struct {
    unsigned char __arr[6];
} __STRING2_COPY_ARR6;
	typedef struct {
    unsigned char __arr[7];
} __STRING2_COPY_ARR7;
	typedef struct {
    unsigned char __arr[8];
} __STRING2_COPY_ARR8;
	typedef union {
    union wait *__uptr;
    int *__iptr;
} __WAIT_STATUS;
	typedef long __blkcnt64_t;
	typedef long __blkcnt_t;
	typedef long __blksize_t;
	typedef char * __caddr_t;
	typedef long __clock_t;
	typedef int __clockid_t;
	typedef int (*)() __compar_d_fn_t;
	typedef int (*)() __compar_fn_t;
	typedef int __daddr_t;
	typedef unsigned long __dev_t;
	typedef long __fd_mask;
	typedef unsigned long __fsblkcnt64_t;
	typedef unsigned long __fsblkcnt_t;
	typedef unsigned long __fsfilcnt64_t;
	typedef unsigned long __fsfilcnt_t;
	typedef struct {
    int __val[2];
} __fsid_t;
	typedef unsigned int __gid_t;
	typedef void * __gnuc_va_list;
	typedef int __gwchar_t;
	typedef unsigned int __id_t;
	typedef unsigned long __ino64_t;
[... and on and on...]

gdb support, like everything other than GCC, uses the libctf library in
the binutils-gdb repo, which will soon enough be made a public,
versioned shared library so that other consumers can pitch in (I just
don't want to do that before the linker changes are upstreamed).

>> We are also extending the format so it is useful for other on-line debugging
>> tools, such as backtracers.
>
> So you become more complex similar to DWARF?

Simplicity of types is not the goal. Compactness is the goal, and ease
of parsing by end users once the format itself has been decoded (so
nothing like the exprloc interpreter exists). We have simple data
structures, sure, but they are not regular: rather they are tuned for
the type system they are describing, and in some cases tuned further to
maximize compactness for types that are more likely to be referenced
often or occur frequently and types in the majority of non-huge programs
(types used by many other types, etc).

As an example (a lengthy one, sorry!), types themselves have two
overlapping core representations shared by all types, with a sentinel
indicating which is in use for any given type:

typedef struct ctf_stype
{
  uint32_t ctt_name;		/* Reference to name in string table.  */
  uint32_t ctt_info;		/* Encoded kind, variant length (see below).  */
  union
  {
    uint32_t ctt_size;		/* Size of entire type in bytes.  */
    uint32_t ctt_type;		/* Reference to another type.  */
  };
} ctf_stype_t;

typedef struct ctf_type
{
  uint32_t ctt_name;		/* Reference to name in string table.  */
  uint32_t ctt_info;		/* Encoded kind, variant length.  */
  union
  {
    uint32_t ctt_size;		/* Always CTF_LSIZE_SENT.  */
    uint32_t ctt_type;		/* Do not use.  */
  };
  uint32_t ctt_lsizehi;		/* High 32 bits of type size in bytes.  */
  uint32_t ctt_lsizelo;		/* Low 32 bits of type size in bytes.  */
} ctf_type_t;

So the (very rare!) huge types pay the space in the type vector for a
64-bit type word (without requiring all users to have a uint64_t type):
smaller types do not pay.

You might say types so huge are so rare that this adds nothing -- but a
future format extension planned well before the end of this year will
add *another* layer to this, giving us three core representations, and
the third one is notably smaller:

typedef struct ctf_ttype
{
  uint32_t ctt_name;            /* Reference to name in string table.  */
  uint16_t ctt_info;            /* Encoded kind, variant length.  */
  union
  {
    uint16_t ctt_size;          /* Size of entire type in bytes.  */
    uint16_t ctt_type;          /* Reference to another type.  */
  };
} ctf_ttype_t;

(there is another sentinel hiding inside ctt_info to indicate when a
type is represented using one of these). The compiler will not need to
adapt to any of this because libctf will transparently upgrade the older
format into the newer one at link time. The compiler only needs to
change if the format becomes more expressive -- e.g. when support for
the GNU C types you mentioned is added.

This change will allow "smaller" programs (the majority of C programs)
to encode types in only eight bytes per type plus similarly compact
per-type variable-length data for things like structure members, down
from twelve bytes now, and I can probably shrink it further, down to six
bytes per type. Obviously not all types can be this compact: things like
complex types fall back to the larger form, as do huge types and types
that reference types with high IDs. But DWARF needs really quite a lot
more, even for simple types, and there can be many thousands of them.

Structure and union members use similar trickery: as a result of all
this, even now, our biggest space consumer is the strtab giving the
names of the structure members! The backtrace section, when it is
designed, will follow a similar philosophy.

Surprisingly, this sort of bit-shaving actually saves significant space
even when the section is compressed: it seems Huffman dictionaries can't
always elide small runs of high-byte zeroes...

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-05 18:28               ` Nix
@ 2019-07-05 19:37                 ` Jakub Jelinek
  2019-07-08 14:16                   ` Nix
  2019-07-09 23:25                 ` Mike Stump
  2019-07-09 23:46                 ` Segher Boessenkool
  2 siblings, 1 reply; 24+ messages in thread
From: Jakub Jelinek @ 2019-07-05 19:37 UTC (permalink / raw)
  To: Nix; +Cc: Richard Biener, Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

On Fri, Jul 05, 2019 at 07:28:12PM +0100, Nix wrote:
> > What makes it superior to DWARF stripped down to the above feature set?
> 
> Increased compactness. DWARF fundamentally trades off compactness in
> favour of its regular structure, which makes it easier to parse (but not
> easier to interpret) but very hard to make it much smaller than it is
> now. Where DWARF uses word-sized and larger entities for everything, CTF
> packs everything much more tightly -- and this is quite visible in the

That is just not true, most of the data in DWARF are uleb128/sleb128
encoded, or often even present just in the abbreviation table
(DW_FORM_flag_present, DW_FORM_implicit_const), word-sized is typically only
stuff that needs relocations (at assembly time and more importantly at link
time).

> could define a "restricted DWARF" with smaller tags etc that is smaller,
> but frankly that would no longer be DWARF at all.)

You can certainly decide what kind of information you emit and what you
don't, it is done already (look at -g1 vs. -g2 vs. -g3), and can be done for
other stuff, say if you aren't interested in any locations,
DW_AT_{decl,call}_{file,line,column} can be omitted, if you aren't
interested in debug info within functions, a lot of debug info can be
emitted etc.  And it still will be DWARF.
For DWARF you also have various techniques at reducing size and optimizing
redundancies away, look e.g. at the dwz utility.

	Jakub

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-05 19:37                 ` Jakub Jelinek
@ 2019-07-08 14:16                   ` Nix
  0 siblings, 0 replies; 24+ messages in thread
From: Nix @ 2019-07-08 14:16 UTC (permalink / raw)
  To: Jakub Jelinek
  Cc: Richard Biener, Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

On 5 Jul 2019, Jakub Jelinek outgrape:

> On Fri, Jul 05, 2019 at 07:28:12PM +0100, Nix wrote:
>> > What makes it superior to DWARF stripped down to the above feature set?
>> 
>> Increased compactness. DWARF fundamentally trades off compactness in
>> favour of its regular structure, which makes it easier to parse (but not
>> easier to interpret) but very hard to make it much smaller than it is
>> now. Where DWARF uses word-sized and larger entities for everything, CTF
>> packs everything much more tightly -- and this is quite visible in the
>
> That is just not true, most of the data in DWARF are uleb128/sleb128
> encoded, or often even present just in the abbreviation table
> (DW_FORM_flag_present, DW_FORM_implicit_const), word-sized is typically only
> stuff that needs relocations (at assembly time and more importantly at link
> time).

Hm. I may have misread the spec.

The fact remains that DWARF is (in typical usage) both large and slow to
use: it is not entirely untrue to say that you can spot a DWARF consumer
because it takes ten seconds to start up. This may be something that can
be avoided with sufficiently clever implementations, but I've never seen
any such implementation and we don't appear to be approaching one
terribly fast :( meanwhile, in CTF we already have a working system that
can reduce multigigabyte DWARF input down to 6MiB of compressed CTF
loading in fractions of a second, though it is true that not all of that
input was global-scope type info, so a large portion of that
multigigabyte input would simply have been dropped and should not be
considered relevant. I'm not sure how to determine how much of the input
is type DIEs at global scope... (The 6MiB figure is slightly misleading,
too, since only 1439845 bytes of that is type data: the rest is mostly
compressed string table.)

Possibly sufficiently clever deduplication can do a similar scrunching
job for DWARF, but I note that what DWARF deduplication GCC did in
earlier releases has subsequently been removed because it never really
worked very well. (Having written code that deduplicates DWARF, I can
see why: it's a complex job when you just have C to think about. Doing
it for C++ as well must have made people's brains dribble out of their
ears).

Type signatures in DWARF 4 were supposed to provide this sort of thing,
too, but yet again the promise does not seem to have been borne out:
DWARF debuginfo remains immense and there is no discussion of leaving
unstripped binaries on production systems for the sake of continuous
tracing tools or introspection, because the debuginfo in those binaries
would still be many times the size of the binaries they relate to, and
obviously leaving it unstripped in that case is ridiculous. Meanwhile,
FreeBSD has a leg-up in continuous debugging because they generate (an
older form of) CTF for everything and deduplicate it, and it's small
enough that they can leave it linked into the binaries rather than
stripping it out, and tracers can and do use it. I'm trying to give us
all that advantage, while not leaving us tied to a format with as many
limitations as FreeBSD's CTF.


As a side note, I tried switching to ULEB128 for the representations of
unsigned integers in CTF a while back, but never even pushed it anywhere
because while it shrank the output a little, the compressed sizes
worsened noticeably, by about 10%, and we don't want to hurt the
compressed sizes any more than we do the uncompressed ones. I found this
quite annoying. So I'm not convinced that ULEB actually buys you
much of anything once compressors get into the mix.

Something similar happened when I tried to do clever things with string
tables last month, sharing common string suffixes, slicing strtabs up on
underscores and changes of case and replacing strings where beneficial
with offset tables pointing into the sliced-up pieces: the uncompressed
size shrank by about 50% and the compressed size grew by 20%... I found
this *very* annoying. :)

> For DWARF you also have various techniques at reducing size and optimizing
> redundancies away, look e.g. at the dwz utility.

... interesting! I'll be looking through this and seeing if any of it is
applicable to CTF as well, that's for sure.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-04 10:47         ` Richard Biener
  2019-07-04 22:44           ` Indu Bhagat
@ 2019-07-09 17:32           ` Indu Bhagat
  1 sibling, 0 replies; 24+ messages in thread
From: Indu Bhagat @ 2019-07-09 17:32 UTC (permalink / raw)
  To: Richard Biener; +Cc: Jeff Law, Indu Bhagat, GCC Patches



On 07/04/2019 03:43 AM, Richard Biener wrote:
>> Hmm...a GCC plugin for CTF generation at compile-time may work out for a single
>> compilation unit.  But I am not sure how will LTO be supported in that case.
>> Basically, for LTO and -gtLEVEL to work together, I need the lto-wrapper to be
>> aware of the presence of .ctf sections (so I think). I will need to combine the
>> .ctf sections from multiple compilation units into a CTF archive, which the
>> linker can then de-duplicate.
> True.  lto-wrapper does this kind of dancing for the much more complex set of
> DWARF sections already.
>
>> Even if I assume that the technical hurdle in the above paragraph is solvable
>> within the purview of a plugin, I fear worse problems of adoption, maintenance
>> and distribution in the long run, if CTF support unfortunately ever remains to be
>> done via a plugin for reasons unforeseen.
>>
>> Going the plugin route for the short term, will continue to suffer similar
>> problems of distribution and support.
>>
>> - Is the plugin infrastructure supported on most platforms ? Also, I see that
>>     the plugin infrastructure supports all gcc versions from 4.5 onwards.
>>     Can someone confirm ? ( We minimally want the toolchain support with
>>     GCC 4.8.5 and GCC 8 and later, for now. )
> The infrastructure is quite old but you'd need new invocation hooks so this
> won't help.
>

OK then.  I will continue to focus on my current implementation without
exploring the plugin option at this time.  Thanks for confirming.

Indu

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-05 18:28               ` Nix
  2019-07-05 19:37                 ` Jakub Jelinek
@ 2019-07-09 23:25                 ` Mike Stump
  2019-07-11 12:25                   ` Nix
  2019-07-09 23:46                 ` Segher Boessenkool
  2 siblings, 1 reply; 24+ messages in thread
From: Mike Stump @ 2019-07-09 23:25 UTC (permalink / raw)
  To: Nix; +Cc: Richard Biener, Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

On Jul 5, 2019, at 11:28 AM, Nix <nix@esperi.org.uk> wrote:
> ICTF for the entire Linux kernel is about 6MiB

Any reason why not add CTF to the next dwarf standard?  Then, we just support the next dwarf standard.  If not, have you started talks with them to add it?

Long term, this is a better solution, as we then get more interoperability, more support, more tools and more goodness.

To me this is the obvious solution to the problem.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-05 18:28               ` Nix
  2019-07-05 19:37                 ` Jakub Jelinek
  2019-07-09 23:25                 ` Mike Stump
@ 2019-07-09 23:46                 ` Segher Boessenkool
  2019-07-10  0:50                   ` Jeff Law
  2019-07-11 12:59                   ` Nix
  2 siblings, 2 replies; 24+ messages in thread
From: Segher Boessenkool @ 2019-07-09 23:46 UTC (permalink / raw)
  To: Nix; +Cc: Richard Biener, Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

On Fri, Jul 05, 2019 at 07:28:12PM +0100, Nix wrote:
> On 5 Jul 2019, Richard Biener said:
> 
> > On Fri, Jul 5, 2019 at 12:21 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
> >> CTF, at this time, is type information for entities at global or file scope.
> >> This can be used by online debuggers, program tracers (dynamic tracing); More
> >> generally, it provides type introspection for C programs, with an optional
> >> library API to allow them to get at their own types quite more easily than
> >> DWARF. So, the umbrella usecases are - all C programs that want to introspect
> >> their own types quickly; and applications that want to introspect other
> >> programs's types quickly.
> >
> > What makes it superior to DWARF stripped down to the above feature set?
> 
> Increased compactness.

Does CTF support something like -fasynchronous-unwind-tables?  You need
that to have any sane debugging on many platforms.  Without it, you
even have only partial backtraces, on most architectures/ABIs anyway.


Segher

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-09 23:46                 ` Segher Boessenkool
@ 2019-07-10  0:50                   ` Jeff Law
  2019-07-11 12:59                   ` Nix
  1 sibling, 0 replies; 24+ messages in thread
From: Jeff Law @ 2019-07-10  0:50 UTC (permalink / raw)
  To: Segher Boessenkool, Nix
  Cc: Richard Biener, Indu Bhagat, Indu Bhagat, GCC Patches

On 7/9/19 5:25 PM, Segher Boessenkool wrote:
> On Fri, Jul 05, 2019 at 07:28:12PM +0100, Nix wrote:
>> On 5 Jul 2019, Richard Biener said:
>>
>>> On Fri, Jul 5, 2019 at 12:21 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
>>>> CTF, at this time, is type information for entities at global or file scope.
>>>> This can be used by online debuggers, program tracers (dynamic tracing); More
>>>> generally, it provides type introspection for C programs, with an optional
>>>> library API to allow them to get at their own types quite more easily than
>>>> DWARF. So, the umbrella usecases are - all C programs that want to introspect
>>>> their own types quickly; and applications that want to introspect other
>>>> programs's types quickly.
>>>
>>> What makes it superior to DWARF stripped down to the above feature set?
>>
>> Increased compactness.
> 
> Does CTF support something like -fasynchronous-unwind-tables?  You need
> that to have any sane debugging on many platforms.  Without it, you
> even have only partial backtraces, on most architectures/ABIs anyway.
I'd be suprised if it did since you need location information.  FWIW,
low level libraries like glibc depend on this stuff to support cancellation.

jeff

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-09 23:25                 ` Mike Stump
@ 2019-07-11 12:25                   ` Nix
  0 siblings, 0 replies; 24+ messages in thread
From: Nix @ 2019-07-11 12:25 UTC (permalink / raw)
  To: Mike Stump
  Cc: Richard Biener, Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

[Sorry for delay: head down in linker plus having nice food poisoning
 bouts]

On 9 Jul 2019, Mike Stump verbalised:

> On Jul 5, 2019, at 11:28 AM, Nix <nix@esperi.org.uk> wrote:
>> ICTF for the entire Linux kernel is about 6MiB
>
> Any reason why not add CTF to the next dwarf standard? Then, we just
> support the next dwarf standard. If not, have you started talks with
> them to add it?

A mixture of impostor syndrome, the fact that CTF is really very
non-DWARFish in all sorts of ways, and the fact that CTF-the-format is
changing quite fast right now means that... well, if it is to be added,
now is not the time. I haven't even documented it in texi yet :)

(Just suggestions for improvement I've had on the binutils list will
lead to a good few changes :) ).

Right now, the rule for compatibility is that libctf will always be able
to read all earlier versions written by any released binutils or
libdtrace-ctf, and rewrite them as the latest version -- and one
improvement I have planned is that it will eventually be able to *write*
older versions as well, as long as doing so doesn't lose information or
run into limitations of the older format (like trying to write >2^16
types to a format v1 container, or add an enum bitfield to a v2
container).

I'm doing this in the obvious fashion: every time the format written by
binutils libctf changes, it keeps the ability to upgrade all older CTF
formats any release of binutils ever accepted to the latest format.
Every binutils release after such a change constitutes a boundary: the
next format change after that will bump the CTF format version, and the
just-released format will be upgraded to be compatible with any new
stuff that gets added. If CTF generation support lands in GCC, I'll
treat compiler releases the same way, nailing the format any released
GCC emits into binutils libctf at release time and ensuring binutils
libctf can always accept it (and thus binutils ld can always link it and
gdb can always use it).

(I do not plan to ever drop support for any older CTF formats: indeed I
plan to extend it so that the FreeBSD/Solaris CTF can be read as well,
and hopefully eventually written too.)

This should suffice to ensure that the CTF emitted by any released
compiler and any released binutils can always be accepted by newer
releases, and is probably the right approach until format evolution
slows and we can start to actually standardize this.

> Long term, this is a better solution, as we then get more
> interoperability, more support, more tools and more goodness.

Agreed! I do hope libctf remains flexible and useful enough that
everyone can use it as a "format oracle", but I would welcome other
implementations: the more the merrier! (It's just that now might be too
early and too annoying for the other implementors, since the format is
evolving faster than it ever has, thanks to all the lovely suggestions
on the binutils list).

If libctf *does* gain the ability to downgrade as well as upgrade
formats, we can keep evolving the format even after standardization,
with libctf translating the standardized version to newer versions and
back down again as needed, restandardizing at intervals so the other
tools can catch up: this seems like a fairly strong reason to gain the
ability to write out old versions as well as new ones. (But I'm getting
way ahead of myself here: the internal intermediate representation
inside libctf that will make this sort of format ubiquity possible only
exists inside my head right now, after all.)

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-09 23:46                 ` Segher Boessenkool
  2019-07-10  0:50                   ` Jeff Law
@ 2019-07-11 12:59                   ` Nix
  2019-07-11 16:54                     ` Segher Boessenkool
  1 sibling, 1 reply; 24+ messages in thread
From: Nix @ 2019-07-11 12:59 UTC (permalink / raw)
  To: Segher Boessenkool
  Cc: Richard Biener, Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

On 10 Jul 2019, Segher Boessenkool spake thusly:

> On Fri, Jul 05, 2019 at 07:28:12PM +0100, Nix wrote:
>> On 5 Jul 2019, Richard Biener said:
>> 
>> > On Fri, Jul 5, 2019 at 12:21 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
>> >> CTF, at this time, is type information for entities at global or file scope.
>> >> This can be used by online debuggers, program tracers (dynamic tracing); More
>> >> generally, it provides type introspection for C programs, with an optional
>> >> library API to allow them to get at their own types quite more easily than
>> >> DWARF. So, the umbrella usecases are - all C programs that want to introspect
>> >> their own types quickly; and applications that want to introspect other
>> >> programs's types quickly.
>> >
>> > What makes it superior to DWARF stripped down to the above feature set?
>> 
>> Increased compactness.
>
> Does CTF support something like -fasynchronous-unwind-tables?  You need
> that to have any sane debugging on many platforms.  Without it, you
> even have only partial backtraces, on most architectures/ABIs anyway.

The backtrace section is still being designed, so it could! There is
certainly nothing intrinsically preventing it. Am I right that this
stuff works by ensuring that the arg->location picture is consistent at
all times, between every instruction, rather than just at function
calls, i.e. tracking all register moves done by the compiler, even
transiently? Because that sounds doable, given that the compiler is
doing the hard work of identifying such locations anyway (it has to for
DWARF -fasynchronous-unwind-tables, right?).

It seems essential to do this in any case if you want to get correct
args for the function the user is actually stopped at: there's no
requirement that the user is stopped at a function call!

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH,RFC,V3 0/5] Support for CTF in GCC
  2019-07-11 12:59                   ` Nix
@ 2019-07-11 16:54                     ` Segher Boessenkool
  0 siblings, 0 replies; 24+ messages in thread
From: Segher Boessenkool @ 2019-07-11 16:54 UTC (permalink / raw)
  To: Nix; +Cc: Richard Biener, Indu Bhagat, Jeff Law, Indu Bhagat, GCC Patches

On Thu, Jul 11, 2019 at 01:25:18PM +0100, Nix wrote:
> On 10 Jul 2019, Segher Boessenkool spake thusly:
> 
> > On Fri, Jul 05, 2019 at 07:28:12PM +0100, Nix wrote:
> >> On 5 Jul 2019, Richard Biener said:
> >> 
> >> > On Fri, Jul 5, 2019 at 12:21 AM Indu Bhagat <indu.bhagat@oracle.com> wrote:
> >> >> CTF, at this time, is type information for entities at global or file scope.
> >> >> This can be used by online debuggers, program tracers (dynamic tracing); More
> >> >> generally, it provides type introspection for C programs, with an optional
> >> >> library API to allow them to get at their own types quite more easily than
> >> >> DWARF. So, the umbrella usecases are - all C programs that want to introspect
> >> >> their own types quickly; and applications that want to introspect other
> >> >> programs's types quickly.
> >> >
> >> > What makes it superior to DWARF stripped down to the above feature set?
> >> 
> >> Increased compactness.
> >
> > Does CTF support something like -fasynchronous-unwind-tables?  You need
> > that to have any sane debugging on many platforms.  Without it, you
> > even have only partial backtraces, on most architectures/ABIs anyway.
> 
> The backtrace section is still being designed, so it could! There is
> certainly nothing intrinsically preventing it. Am I right that this
> stuff works by ensuring that the arg->location picture is consistent at
> all times, between every instruction, rather than just at function
> calls, i.e. tracking all register moves done by the compiler, even
> transiently?

Yes, something like that.  You get unwind tables that are valid at each
instruction boundary.  This is esp. important for the return address,
without that backtraces are broken.

> Because that sounds doable, given that the compiler is
> doing the hard work of identifying such locations anyway (it has to for
> DWARF -fasynchronous-unwind-tables, right?).

Yes, every backend outputs DWARF info semi-manually for this.  You have
some work to do if you want to use this for CTF.

> It seems essential to do this in any case if you want to get correct
> args for the function the user is actually stopped at: there's no
> requirement that the user is stopped at a function call!

Yes.  You need the asynchronous option only if you need this info at
any possible point in a program -- but quite a few things do need it
everywhere ;-)


Segher

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2019-07-11 16:48 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-27  6:37 [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
2019-06-27  6:37 ` [PATCH,RFC,V3 3/5] Setup for CTF generation and emission Indu Bhagat
2019-06-27  6:37 ` [PATCH,RFC,V3 5/5] Update CTF testsuite Indu Bhagat
2019-06-27  6:37 ` [PATCH,RFC,V3 4/5] CTF generation for a single compilation unit Indu Bhagat
2019-06-27  6:37 ` [PATCH,RFC,V3 1/5] Add new function lang_GNU_GIMPLE Indu Bhagat
2019-06-27  6:37 ` [PATCH,RFC,V3 2/5] Add CTF command line options : -gtLEVEL Indu Bhagat
2019-07-02 17:43 ` [PATCH,RFC,V3 0/5] Support for CTF in GCC Indu Bhagat
2019-07-03  3:18   ` Jeff Law
2019-07-03 12:39     ` Richard Biener
2019-07-04  1:49       ` Indu Bhagat
2019-07-04 10:47         ` Richard Biener
2019-07-04 22:44           ` Indu Bhagat
2019-07-05 11:25             ` Richard Biener
2019-07-05 18:28               ` Nix
2019-07-05 19:37                 ` Jakub Jelinek
2019-07-08 14:16                   ` Nix
2019-07-09 23:25                 ` Mike Stump
2019-07-11 12:25                   ` Nix
2019-07-09 23:46                 ` Segher Boessenkool
2019-07-10  0:50                   ` Jeff Law
2019-07-11 12:59                   ` Nix
2019-07-11 16:54                     ` Segher Boessenkool
2019-07-09 17:32           ` Indu Bhagat
2019-07-04  0:36     ` Indu Bhagat

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).