public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH,RFC,V5 2/6] Add CTF command line options : -gtLEVEL
  2019-09-09  4:28 [PATCH,RFC,V5 0/6] Support for CTF in GCC Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 6/6] Handle CTF sections when LTO is enabled Indu Bhagat
@ 2019-09-09  4:28 ` Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 5/6] Update CTF testsuite Indu Bhagat
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Indu Bhagat @ 2019-09-09  4:28 UTC (permalink / raw)
  To: gcc-patches

-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 f2214ed..283a959 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
@@ -3011,6 +3016,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 bfcd76e..af42da9 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -378,6 +378,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
@@ -7823,6 +7824,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 07f701c..db3711c 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -196,6 +196,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);
@@ -2759,6 +2761,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);
@@ -3088,6 +3094,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] 7+ messages in thread

* [PATCH,RFC,V5 0/6] Support for CTF in GCC
@ 2019-09-09  4:28 Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 6/6] Handle CTF sections when LTO is enabled Indu Bhagat
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Indu Bhagat @ 2019-09-09  4:28 UTC (permalink / raw)
  To: gcc-patches

Hello,

This patch series adds support for CTF generation in GCC.

[Changes from V4]

1. Patch 4 brings in a number of bug fixes and enhancements. Few of them are:
   - Use DECL_UID () instead of htab_hash_pointer () for _DECL
   - Handle boolean and zero-sized bitfields
   - Do not inform () when skipping types.  Arguably this was intended for the
     GCC developer and not for the end user.
   - Other bugfixes around de-dupilication at the time of CTF Array or CTF
     function generation.

2. Patch 5 has added testcases.

3. Patch 6 is a new patch added for handling CTF section when LTO is enabled.

Work on CTF spec document is also in progress; will share something very soon.
In the interim, https://sourceware.org/ml/binutils/2019-04/msg00277.html may be
helpful.

For more context, please also see previous posting
https://gcc.gnu.org/ml/gcc-patches/2019-07/msg01209.html

NickA recently posted a changeset to the binutils mailing list that adds initial
support for linking CTF sections. Please see
https://sourceware.org/ml/binutils/2019-09/msg00045.html

( This current GCC  patch set has the ctf.h in sync with the above-mentioned
   binutils patch set. )

I will be connecting online to talk about the CTF support in GNU toolchain at
Cauldron 2019.  Posting these patches so that there is added context.

Testing :
Apart from the usual bootstrap and regression testing on x86_64/linux,
sparc64/linux, I have now compiled more codebases with -gt.

Thanks

Indu Bhagat (6):
  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
  Handle CTF sections when LTO is enabled

 gcc/ChangeLog                                      |   97 +
 gcc/Makefile.in                                    |    5 +
 gcc/cgraphunit.c                                   |   12 +-
 gcc/common.opt                                     |    9 +
 gcc/ctfcreate.c                                    |  557 ++++++
 gcc/ctfout.c                                       | 1941 ++++++++++++++++++++
 gcc/ctfout.h                                       |  364 ++++
 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                            |   46 +
 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-array-2.c       |   39 +
 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-bitfields-3.c   |   16 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c   |   22 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c     |   22 +
 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-cvr-quals-4.c   |   21 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c        |   21 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c        |   26 +
 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/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c     |   21 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c  |   25 +
 .../gcc.dg/debug/ctf/ctf-function-pointers-1.c     |   24 +
 .../gcc.dg/debug/ctf/ctf-function-pointers-2.c     |   18 +
 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-objt-index-1.c  |   29 +
 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-skip-types-1.c  |   33 +
 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                                  |    9 +
 include/ctf.h                                      |  510 +++++
 libiberty/ChangeLog                                |    5 +
 libiberty/simple-object.c                          |    3 +
 61 files changed, 4836 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-array-2.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-bitfields-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.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-cvr-quals-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.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-forward-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.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-function-pointers-2.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-objt-index-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-skip-types-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] 7+ messages in thread

* [PATCH,RFC,V5 6/6] Handle CTF sections when LTO is enabled
  2019-09-09  4:28 [PATCH,RFC,V5 0/6] Support for CTF in GCC Indu Bhagat
@ 2019-09-09  4:28 ` Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 2/6] Add CTF command line options : -gtLEVEL Indu Bhagat
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Indu Bhagat @ 2019-09-09  4:28 UTC (permalink / raw)
  To: gcc-patches

libiberty/ChangeLog:

	* simple-object.c (handle_lto_debug_sections): Copy CTF section.

---
 libiberty/ChangeLog       | 5 +++++
 libiberty/simple-object.c | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c
index b00c265..96bdcf8 100644
--- a/libiberty/simple-object.c
+++ b/libiberty/simple-object.c
@@ -298,6 +298,9 @@ handle_lto_debug_sections (const char *name, int rename)
      COMDAT sections in objects produced by GCC.  */
   else if (strcmp (name, ".comment") == 0)
     return strcpy (newname, name);
+  /* Copy over .ctf section under the same name if present.  */
+  else if (strcmp (name, ".ctf") == 0)
+    return strcpy (newname, name);
   free (newname);
   return NULL;
 }
-- 
1.8.3.1

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

* [PATCH,RFC,V5 3/6] Setup for CTF generation and emission
  2019-09-09  4:28 [PATCH,RFC,V5 0/6] Support for CTF in GCC Indu Bhagat
                   ` (3 preceding siblings ...)
  2019-09-09  4:28 ` [PATCH,RFC,V5 1/6] Add new function lang_GNU_GIMPLE Indu Bhagat
@ 2019-09-09  4:28 ` Indu Bhagat
  2019-09-09  4:29 ` [PATCH,RFC,V5 4/6] CTF generation for a single compilation unit Indu Bhagat
  5 siblings, 0 replies; 7+ messages in thread
From: Indu Bhagat @ 2019-09-09  4:28 UTC (permalink / raw)
  To: gcc-patches

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): Inform the user 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 99d88a4..62d9256 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1256,6 +1256,7 @@ OBJS = \
 	cfgloopanal.o \
 	cfgloopmanip.o \
 	cfgrtl.o \
+	ctfout.o \
 	symtab.o \
 	cgraph.o \
 	cgraphbuild.o \
@@ -2534,6 +2535,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 cb08efe..e8130a1 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
@@ -2851,17 +2852,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..471cf80
--- /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 the CTF debug info 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 f715c67..93ebef4 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 d741a66..4422508 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"
@@ -1293,6 +1294,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;
@@ -1465,6 +1468,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)
+    {
+      inform (UNKNOWN_LOCATION,
+	      "CTF debug info requested, but not supported for %qs 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");
@@ -1537,6 +1551,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.  */
@@ -2348,6 +2365,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] 7+ messages in thread

* [PATCH,RFC,V5 5/6] Update CTF testsuite
  2019-09-09  4:28 [PATCH,RFC,V5 0/6] Support for CTF in GCC Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 6/6] Handle CTF sections when LTO is enabled Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 2/6] Add CTF command line options : -gtLEVEL Indu Bhagat
@ 2019-09-09  4:28 ` Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 1/6] Add new function lang_GNU_GIMPLE Indu Bhagat
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Indu Bhagat @ 2019-09-09  4:28 UTC (permalink / raw)
  To: gcc-patches

[Changes from V4]
Added new testcases
 - gcc.dg/debug/ctf/ctf-bitfields-3.c
 - gcc.dg/debug/ctf/ctf-bitfields-4.c
 - gcc.dg/debug/ctf/ctf-cvr-quals-4.c
 - gcc.dg/debug/ctf/ctf-forward-3.c
 - gcc.dg/debug/ctf/ctf-function-pointers-2.c

gcc/testsuite/ChangeLog:

	* gcc.dg/debug/ctf/ctf-2.c: New test.
	* gcc.dg/debug/ctf/ctf-anonymous-struct-1.c: New test.
	* gcc.dg/debug/ctf/ctf-anonymous-union-1.c: New test.
	* gcc.dg/debug/ctf/ctf-array-1.c: New test.
	* gcc.dg/debug/ctf/ctf-array-2.c: New test.
	* gcc.dg/debug/ctf/ctf-bitfields-1.c: New test.
	* gcc.dg/debug/ctf/ctf-bitfields-2.c: New test.
	* gcc.dg/debug/ctf/ctf-bitfields-3.c: New test.
	* gcc.dg/debug/ctf/ctf-bitfields-4.c: New test.
	* gcc.dg/debug/ctf/ctf-complex-1.c: New test.
	* gcc.dg/debug/ctf/ctf-cvr-quals-1.c: New test.
	* gcc.dg/debug/ctf/ctf-cvr-quals-2.c: New test.
	* gcc.dg/debug/ctf/ctf-cvr-quals-3.c: New test.
	* gcc.dg/debug/ctf/ctf-cvr-quals-4.c: New test.
	* gcc.dg/debug/ctf/ctf-enum-1.c: New test.
	* gcc.dg/debug/ctf/ctf-enum-2.c: New test.
	* gcc.dg/debug/ctf/ctf-float-1.c: New test.
	* gcc.dg/debug/ctf/ctf-forward-1.c: New test.
	* gcc.dg/debug/ctf/ctf-forward-2.c: New test.
	* gcc.dg/debug/ctf/ctf-forward-3.c: New test.
	* gcc.dg/debug/ctf/ctf-func-index-1.c: New test.
	* gcc.dg/debug/ctf/ctf-function-pointers-1.c: New test.
	* gcc.dg/debug/ctf/ctf-function-pointers-2.c: New test.
	* gcc.dg/debug/ctf/ctf-functions-1.c: New test.
	* gcc.dg/debug/ctf/ctf-int-1.c: New test.
	* gcc.dg/debug/ctf/ctf-objt-index-1.c: New test.
	* gcc.dg/debug/ctf/ctf-pointers-1.c: New test.
	* gcc.dg/debug/ctf/ctf-skip-types-1.c: New test.
	* gcc.dg/debug/ctf/ctf-str-table-1.c: New test.
	* gcc.dg/debug/ctf/ctf-struct-1.c: New test.
	* gcc.dg/debug/ctf/ctf-struct-2.c: New test.
	* gcc.dg/debug/ctf/ctf-struct-array-1.c: New test.
	* gcc.dg/debug/ctf/ctf-typedef-1.c: New test.
	* gcc.dg/debug/ctf/ctf-typedef-struct-1.c: New test.
	* gcc.dg/debug/ctf/ctf-union-1.c: New test.
	* gcc.dg/debug/ctf/ctf-variables-1.c: New test.

---
 gcc/testsuite/ChangeLog                            | 39 +++++++++++++++++++
 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-array-2.c       | 39 +++++++++++++++++++
 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-bitfields-3.c   | 16 ++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c   | 22 +++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c     | 22 +++++++++++
 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-cvr-quals-4.c   | 21 +++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c        | 21 +++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c        | 26 +++++++++++++
 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/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c     | 21 +++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c  | 25 ++++++++++++
 .../gcc.dg/debug/ctf/ctf-function-pointers-1.c     | 24 ++++++++++++
 .../gcc.dg/debug/ctf/ctf-function-pointers-2.c     | 18 +++++++++
 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-objt-index-1.c  | 29 ++++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-1.c    | 26 +++++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c  | 33 ++++++++++++++++
 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 ++++++++++++
 37 files changed, 966 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-array-2.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-bitfields-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.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-cvr-quals-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.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-forward-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.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-function-pointers-2.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-objt-index-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-skip-types-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-array-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c
new file mode 100644
index 0000000..744f15e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c
@@ -0,0 +1,39 @@
+/* CTF generation for unsized arrays.
+
+   Unsized arrays are encoded with a 0 for the number of elements.  The type
+   of array index is the INT type.
+
+   TBD_CTF_FORMAT_OPEN_ISSUES (1) - 
+   This testcase makes a note of the case of a probable misrepresentation.
+   See Note 1 and Note 2 below.
+
+   In the CTF section, these types are encoded as :
+
+     Variables:
+      _CTF_NEWSTR ->  7: const char [0] (size 0x0)
+      _CTF_SECTION ->  6: const char [5] (size 0x5)
+      b1 ->  2: int [0] (size 0x0)
+      b2 ->  3: int [0] (size 0x0)
+
+    Note 1 : There is misrepresentation in that b1 and b2 are specified
+    differently by the user.
+    Note 2 : It is arguable though whether the representation for
+    _CTF_NEWSTR is incorrect.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "0x12000000\[\t \]+\[^\n\]*ctt_info" 4 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*cta_index" 4 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*cta_nelems" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x5\[\t \]+\[^\n\]*cta_nelems" 1 } } */
+
+static int b1[] = {};
+
+int b2[0];
+
+const char _CTF_SECTION[] = ".ctf";
+
+extern const char _CTF_NEWSTR[];
+const char _CTF_NEWSTR[] = "ctfinfo"; 
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-bitfields-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-3.c
new file mode 100644
index 0000000..dcb6a2a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-3.c
@@ -0,0 +1,16 @@
+/* The bool bitfield type.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_type" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*cts_bits" 2 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"_Bool.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+#include <stdbool.h>
+
+struct open_file {
+  bool mmapped:1;
+  bool released:1;
+} of;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c
new file mode 100644
index 0000000..4fa4764
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c
@@ -0,0 +1,22 @@
+/* The zero sized bitfield.
+
+   In this testcase, three slices are expected - two of which correspond to
+   type int, and one corresponds to unsigned int.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*cts_type" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*cts_type" 1 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x5\[\t \]+\[^\n\]*cts_bits" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xa\[\t \]+\[^\n\]*cts_bits" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*cts_bits" 1 } } */
+
+/* { dg-final { scan-assembler-times "ctm_name" 3 } } */
+struct foo
+{
+  int a:5;
+  unsigned:0;
+  int b:10;
+} foome;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c
new file mode 100644
index 0000000..3d02b87
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-complex-1.c
@@ -0,0 +1,22 @@
+/* Tests for CTF complex base types.
+
+   CTF does not have representation for COMPLEX integer types.
+   
+   This testcase has a mix of C constructs containing COMPLEX_TYPE.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0xa000000\[\t \]+\[^\n\]*ctt_info" 3 } } */
+
+/* { dg-final { scan-assembler-times "ascii \"complex double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"complex long double.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"complex float.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+#include <complex.h>
+
+double complex z1 = I * I;
+
+const long double complex z2 = I * I;
+
+float complex z4 = 1+2.11*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-cvr-quals-4.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c
new file mode 100644
index 0000000..f1aeedc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c
@@ -0,0 +1,21 @@
+/* Test compilation of stubs with various qualifiers - const, restrict and
+   volatile.
+
+   CTF records for CVR qualifiers are no-name records.  In this testcase, there
+   is 1 const qualifier. 1 more no-name CTF record corresponds to the CTF
+   pointer record.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*ctt_name" 2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+typedef const struct howto_struct howto_type;
+
+typedef struct entry
+{
+  int addend;
+  howto_type *howto;
+} how_ent;
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-enum-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c
new file mode 100644
index 0000000..ef87691
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c
@@ -0,0 +1,26 @@
+/* CTF generation for enums.
+
+   CTF represents enum values with an int32_t.  The compiler skips adding these
+   enum values into the CTF for the enum type.  This will be fixed soon in the
+   format.  TBD_CTF_REPRESENTATION_LIMIT.
+   
+   In this testcase, CTF for enumerator GFS_MONOTONIC will not be generated.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"GFS_MONOTONIC.0\"\[\t \]+\[^\n\]*ctf_string" 0 } } */
+/* { dg-final { scan-assembler-times "ascii \"GFS_RUNTIME.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"GFS_STATIC.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "cte_value" 2} } */
+
+
+enum gomp_schedule_type
+{
+  GFS_RUNTIME,
+  GFS_STATIC,
+  GFS_MONOTONIC = 0x80000000U
+};
+
+enum gomp_schedule_type gsch_type;
+
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-forward-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c
new file mode 100644
index 0000000..cdb740b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-3.c
@@ -0,0 +1,21 @@
+/* A compilation unit may have a forward declation of a type and the definition
+   of the type at a later point.
+
+   CTF forward type is generated for forward declarations of types in C.
+
+   Once the type is defined, the CTF generated for the forward declaration is
+   updated to non-root type.
+   
+   In this testcase, one CTF_K_FORWARD type and two CTF_K_STRUCT types are
+   expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x24000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x6\[\t \]+\[^\n\]*ctt_size or ctt_type" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x8\[\t \]+\[^\n\]*ctt_size or ctt_type" 2 } } */
+/* { dg-final { scan-assembler-times "ascii \"afoo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"bfoo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+struct bar { struct foo * a; } barbar;
+struct foo { int afoo; int bfoo; } foofoo;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c
new file mode 100644
index 0000000..4215615
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c
@@ -0,0 +1,25 @@
+/* CTF function index sub-section.
+
+   A function index sub-section in the CTF section contains the offset to the
+   string name of the global function symbols.  The number of entries in the
+   func info section and the func index section are always the same.
+
+   In this testcase, 2 records in the function index section are expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "funcinfo_name" 2 } } */
+/* { dg-final { scan-assembler-times "funcinfo_func_type" 2 } } */
+/* { dg-final { scan-assembler-times "ascii \"bar.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"foo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+int foo (void)
+{
+  return 0;
+}
+
+int bar (int a)
+{
+  return 33 + a;
+}
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-function-pointers-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-2.c
new file mode 100644
index 0000000..4a88af4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-2.c
@@ -0,0 +1,18 @@
+/* CTF generation of function pointers.
+
+   In this testcase,  there is a single function type expected for two
+   different function pointer types.  */
+
+/* { 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 "ascii \"rcu_callback_t.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"func.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+struct callback_head {
+      struct callback_head *next;
+        void (*func) (struct callback_head *head);
+} __attribute__ (( aligned (sizeof (void *))));
+#define rcu_head callback_head
+
+typedef void (*rcu_callback_t) (struct rcu_head *head);
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-objt-index-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c
new file mode 100644
index 0000000..8d380d8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c
@@ -0,0 +1,29 @@
+/* CTF objext index sub-section.
+
+   An object index sub-section in the CTF section contains the offset to the
+   string name of the global object symbols.  The number of entries in the
+   obj info section and objt index section are always the same. 
+
+   In this testcase, 3 records in the object index section are expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "objtinfo_name" 3 } } */
+/* { dg-final { scan-assembler-times "objtinfo_var_type" 3 } } */
+/* { dg-final { scan-assembler-times "ascii \"a.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"a1.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"d_instance.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+static int b = 33;
+
+int a = 44;
+int a1[2] = {22, 33};
+
+struct d
+{
+  int d1;
+  int d2;
+};
+
+struct d d_instance;
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-skip-types-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c
new file mode 100644
index 0000000..bd2935d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c
@@ -0,0 +1,33 @@
+/* CTF does not have representation for some types at this time.  These types
+   are skipped in the CTF generation phase in the compiler.
+   
+   This testcase does NOT cover all skipped types exhaustively.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+
+#include <complex.h>
+
+typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
+La_x86_64_xmm a1;
+
+/* GCC also supports complex integer data types.  */
+complex char a;
+complex signed char b;
+complex unsigned char c;
+complex short int d;
+complex short unsigned int e;
+complex int f;
+complex unsigned int g;
+complex long int h;
+complex long unsigned int i;
+complex long long int j;
+
+enum gomp_schedule_type
+{
+  GFS_RUNTIME,
+  GFS_STATIC,
+  GFS_MONOTONIC = 0x80000000U
+};
+
+enum gomp_schedule_type gsch_type;
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] 7+ messages in thread

* [PATCH,RFC,V5 1/6] Add new function lang_GNU_GIMPLE
  2019-09-09  4:28 [PATCH,RFC,V5 0/6] Support for CTF in GCC Indu Bhagat
                   ` (2 preceding siblings ...)
  2019-09-09  4:28 ` [PATCH,RFC,V5 5/6] Update CTF testsuite Indu Bhagat
@ 2019-09-09  4:28 ` Indu Bhagat
  2019-09-09  4:28 ` [PATCH,RFC,V5 3/6] Setup for CTF generation and emission Indu Bhagat
  2019-09-09  4:29 ` [PATCH,RFC,V5 4/6] CTF generation for a single compilation unit Indu Bhagat
  5 siblings, 0 replies; 7+ messages in thread
From: Indu Bhagat @ 2019-09-09  4:28 UTC (permalink / raw)
  To: gcc-patches

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 89fb5bc..66daa9a 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -821,3 +821,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] 7+ messages in thread

* [PATCH,RFC,V5 4/6] CTF generation for a single compilation unit
  2019-09-09  4:28 [PATCH,RFC,V5 0/6] Support for CTF in GCC Indu Bhagat
                   ` (4 preceding siblings ...)
  2019-09-09  4:28 ` [PATCH,RFC,V5 3/6] Setup for CTF generation and emission Indu Bhagat
@ 2019-09-09  4:29 ` Indu Bhagat
  5 siblings, 0 replies; 7+ messages in thread
From: Indu Bhagat @ 2019-09-09  4:29 UTC (permalink / raw)
  To: gcc-patches

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.

[Changes from V4]
 Bugfixes and Enhancements:
  - Use DECL_UID () instead of htab_hash_pointer () for _DECL
  - Handle boolean and zero-sized bitfields
  - Do not inform () when skipping types.  Arguably this was intended for the
    GCC developer and not for the end user.
  - Other bugfixes around de-dupilication at the time of CTF Array or CTF
    function generation.

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.
	(ctfc_add_cuname): New function to add compilation unit name to CTF
	container.
	(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): Update code comments regarding 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_preamble): 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_obj_info): New function.
	(output_ctf_func_info): Likewise.
	(output_ctf_objtidx): Likewise.
	(output_ctf_funcidx): Likewise.
	(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.  Add CTF obj
	index and func index section.

---
 gcc/ChangeLog     |   70 ++
 gcc/Makefile.in   |    2 +
 gcc/ctfcreate.c   |  557 ++++++++++++++++
 gcc/ctfout.c      | 1828 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gcc/ctfout.h      |  317 +++++++++-
 gcc/ctfutils.c    |  198 ++++++
 include/ChangeLog |    5 +
 include/ctf.h     |   59 +-
 8 files changed, 2986 insertions(+), 50 deletions(-)
 create mode 100644 gcc/ctfcreate.c
 create mode 100644 gcc/ctfutils.c

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 62d9256..38ff0be 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1257,6 +1257,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..52c9821
--- /dev/null
+++ b/gcc/ctfcreate.c
@@ -0,0 +1,557 @@
+/* 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);
+
+  /* FIXME, stay close to what libctf does.  But by getting next power of two,
+     aren't we conveying less precise information.  E.g. floating point mode
+     XF has a size of 12 bytes.  */
+  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 <= 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;
+
+  gcc_assert (!TYPE_SIZE (treetype));
+  /* CTF forward types are inserted with key_flags set to 1 to distinguish them
+     from the actual struct/union/union with a non-zero size which may be added
+     later (the latter will be added with key_flags set to 0).  */
+  uint32_t key_flags = (TYPE_SIZE (treetype) == NULL);
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, treetype, key_flags);
+
+  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 <= 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 <= 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);
+  /* 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 = roundup_nbytes ? (1 << ceil_log2 (roundup_nbytes))
+					   : 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_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.  */
+
+  /* The compiler does, however, update any previously existing forward types
+     to non-root.  CTF does not allow existence of two root types with the same
+     name.  */
+  ctf_dtdef_ref enum_fwd_type = ctf_dtd_lookup_with_flags (ctfc, enum_type, 1);
+  if (enum_fwd_type)
+    {
+      enum_fwd_type->dtd_data.ctti_info
+	= CTF_TYPE_INFO (CTF_K_FORWARD, CTF_ADD_NONROOT, 0);
+    }
+
+  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)
+{
+  ctf_dmdef_t * dmd;
+  uint32_t kind, vlen, root;
+
+  /* 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);
+  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);
+
+  /* Enum value is of type HOST_WIDE_INT in the compiler, dmd_value is int32_t
+     on the other hand.  Check bounds and skip adding this enum value if out of
+     bounds.  */
+  if ((value > INT_MAX) || (value < INT_MIN))
+    {
+      /* FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT.  */
+      return (1);
+    }
+
+  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;
+
+  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.  */
+
+  /* The compiler does, however, update any previously existing forward types
+     to non-root.  CTF does not allow existence of two root types with the same
+     name.  */
+  ctf_dtdef_ref sou_fwd_type = ctf_dtd_lookup_with_flags (ctfc, treetype, 1);
+  if (sou_fwd_type)
+    {
+      sou_fwd_type->dtd_data.ctti_info
+	= CTF_TYPE_INFO (CTF_K_FORWARD, CTF_ADD_NONROOT, 0);
+    }
+
+  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 471cf80..9cee1b7 100644
--- a/gcc/ctfout.c
+++ b/gcc/ctfout.c
@@ -25,11 +25,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "memmodel.h"
 #include "tm_p.h"
+#include "toplev.h"
 #include "varasm.h"
 #include "output.h"
 #include "dwarf2asm.h"
 #include "debug.h"
 #include "ctfout.h"
+#include "diagnostic-core.h"
 
 /* A CTF container object - one per translation unit.  */
 
@@ -43,14 +45,14 @@ static GTY (()) section * ctf_info_section;
 
 /* Section names used to hold CTF debugging information.  */
 
+/* CTF debug info section.  */
+
 #ifndef CTF_INFO_SECTION_NAME
 #define CTF_INFO_SECTION_NAME  ".ctf"
 #endif
 
 /* Section flags for the CTF debug info section.  */
 
-/* CTF debug info section.  */
-
 #define CTF_INFO_SECTION_FLAGS (SECTION_DEBUG)
 
 /* Maximum size (in bytes) of an artificially generated CTF label.  */
@@ -63,8 +65,348 @@ 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
+{
+  unsigned long dvd_global_obj_idx;
+  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;
+    }
+}
+
+/* Add the compilation unit (CU) name string to the the CTF string table.  The
+   CU name has a prepended pwd string if it is a relative path.  Also set the
+   CU name offset in the CTF container.  */
+
+static void
+ctfc_add_cuname (ctf_container_ref ctfc, const char * filename)
+{
+  char * cuname = NULL;
+
+  /* (filename at this point of compilation cannot be null).  */
+
+  if (!IS_DIR_SEPARATOR (filename[0]))
+    {
+      /* Filename is a relative path.  */
+      const char * cu_pwd = get_src_pwd ();
+      const int cu_pwd_len = strlen (cu_pwd);
+
+      /* Add a DIR_SEPARATOR char before the filename.  */
+      const int len = cu_pwd_len + 2 + strlen (filename);
+
+      cuname = (char *) ggc_alloc_atomic (len);
+      memset (cuname, 0, len);
+
+      strcpy (cuname, cu_pwd);
+      cuname[cu_pwd_len] = DIR_SEPARATOR;
+      cuname[cu_pwd_len+1] = 0;
+      strcat (cuname, filename);
+    }
+  else
+    /* Filename is an absolute path.  */
+    cuname = CONST_CAST (char *, ggc_strdup (filename));
+
+  ctf_add_string (ctfc, cuname, &(ctfc->ctfc_cuname_offset));
+  /* Add 1 as CTF strings in the CTF string table are null-terminated
+     strings.  */
+  ctfc->ctfc_strlen += strlen (cuname) + 1;
+
+  /* Mark cuname for garbage collection.  */
+  cuname = NULL;
+}
+
+/* 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) DECL_UID (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 = (DECL_UID (e1_decl) == DECL_UID (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;
+  uint32_t key_flags = 0;
+
+  /* In the same compilation unit, use key_flags to differentiate a forward
+     type from the struct/union/enum definition which may follow later.  Both
+     must be CTF encoded for completeness.  */
+  if (RECORD_OR_UNION_TYPE_P (type) || TREE_CODE (type) == ENUMERAL_TYPE)
+    key_flags = (TYPE_SIZE (type) == NULL);
+
+  ctf_dtdef_ref ctf_type_seen
+    = ctf_dtd_lookup_with_flags (ctfc, type, key_flags);
+
+  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 +417,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,7 +448,28 @@ 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;
+	}
+      if (ctfc->ctfc_gobjts_list)
+	{
+	  ggc_free (ctfc->ctfc_gobjts_list);
+	  ctfc->ctfc_gobjts_list = NULL;
+	}
+
+      ctfc= NULL;
     }
 }
 
@@ -106,59 +478,1452 @@ delete_ctf_container (ctf_container_ref ctfc)
 void
 init_ctf_sections (void)
 {
-  ctf_info_section = get_section (CTF_INFO_SECTION_NAME,
-				  CTF_INFO_SECTION_FLAGS,
+  /* Note : Even in case of LTO, the compiler continues to generate a single
+     CTF section for each compilation unit "early".  Unlike other debug
+     sections, CTF sections are non-LTO sections, and do not take the
+     .gnu.debuglto_ prefix.  The linker will de-duplicate the types in the CTF
+     sections, in case of LTO or  otherwise.  */
+  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.  */
+/* 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).  */
 
-static void
-ctf_asm_preamble (ctf_container_ref ctfc)
+/* 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)
 {
-  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");
+  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.  */
+  /* This assert here fails for "complex char a".  CTF skips these types.  But
+     need to debug why the TYPE_NAME is null.  FIXME - moved the asserts into
+     each respective block below meanwhile.  */
+  // 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 * BITS_PER_UNIT;
+
+	gcc_assert (name_string);
+	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 * BITS_PER_UNIT;
+
+    gcc_assert (name_string);
+    type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
+			       &ctf_encoding, type);
+    break;
+
+  case REAL_TYPE:
+    if (FLOAT_MODE_P (TYPE_MODE (type)))
+      {
+	if (size == int_size_in_bytes (float_type_node))
+	  encoding = CTF_FP_SINGLE;
+	else if (size == int_size_in_bytes (double_type_node))
+	  encoding = CTF_FP_DOUBLE;
+	else if ((size == int_size_in_bytes (long_double_type_node))
+		  || (size == int_size_in_bytes (float128_type_node)))
+	  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 * BITS_PER_UNIT;
+
+	gcc_assert (name_string);
+	type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
+			       &ctf_encoding, type);
+      }
+
+    /* CTF does not have representation for non IEEE float encoding.  Skip
+       this type.  FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT.  */
+    break;
+
+  case FIXED_POINT_TYPE:
+    /* CTF does not have representation for fixed point type.  Skip this type.
+       FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT.  */
+    break;
+
+  case COMPLEX_TYPE:
+    encoding = 0;
+    if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
+      {
+	tree component_type = TREE_TYPE (type);
+	size = int_size_in_bytes (component_type);
+
+	if (size == int_size_in_bytes (float_type_node))
+	  encoding = CTF_FP_CPLX;
+	else if (size == int_size_in_bytes (double_type_node))
+	  encoding = CTF_FP_DCPLX;
+	else if ((size == int_size_in_bytes (long_double_type_node))
+		 || (size == int_size_in_bytes (float128_type_node)))
+	  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 * BITS_PER_UNIT;
+
+	gcc_assert (name_string);
+	type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
+				 &ctf_encoding, type);
+      }
+    /* CTF does not have representation for complex integer type.  Skip this
+       type.  FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT.  */
+    break;
+
+  case VOID_TYPE:
+    encoding = CTF_INT_SIGNED;
+    ctf_encoding.cte_format = encoding;
+    ctf_encoding.cte_bits = 0;
+
+    gcc_assert (name_string);
+    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_CTF_FORMAT_OPEN_ISSUES (1) - see testcase ctf-array-2.c.  */
+  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;
+      if (max_index > 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 > 0 && 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 de-duplication.
+     Consult the ctfc_types hash again before adding the CTF array type because
+     there can be cases where an array_type type may have been added by the
+     gen_ctf_type call above.  */
+  if (!ctf_type_exists (ctfc, array_type, &type_id))
+    type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo, array_type);
+
+  return type_id;
 }
 
-/* Output the CTF header.  */
+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
-output_ctf_header (ctf_container_ref ctfc)
+gen_ctf_enum_const_list (ctf_container_ref ctfc, const tree enum_type,
+			 const ctf_id_t enum_type_id)
 {
-  switch_to_section (ctf_info_section);
-  ASM_OUTPUT_LABEL (asm_out_file, ctf_info_section_label);
+  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));
 
-  ctf_asm_preamble (ctfc);
+      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);
+
+      /* ctf_add_enumerator returns true if addition of the enumeration
+	 constant is skipped if not representable in CTF (int32_t).
+	 FIXME - Note this TBD_CTF_REPRESENTATION_LIMIT.  */
+    }
 }
 
-/* CTF routines interfacing to the compiler.  */
+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;
 
-void
-ctf_debug_init (void)
+  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)
 {
-  init_ctf_containers ();
+  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 de-duplication.
+     Consult the ctfc_types hash again before adding the CTF function type
+     because there can be cases where a function type may have been added by
+     the gen_ctf_type call above.  For example,
+     struct callback_head {
+       struct callback_head *next;
+	void (*func) (struct callback_head *head);
+	} __attribute__ (( aligned (sizeof (void *))));
+       #define rcu_head callback_head
+
+       typedef void (*rcu_callback_t) (struct rcu_head *head);  */
+  if (ctf_type_exists (ctfc, func_decl_or_type, &type_id))
+    argv_ids = NULL;
+  else
+    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;
 }
 
-void
-ctf_early_finish (const char * ARG_UNUSED (filename))
+/* 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)
 {
-  if (ctf_debug_info_level == CTFINFO_LEVEL_NONE)
-    return;
+  tree qualified_type;
+  int flags;
+  uint32_t cvrint = 0;
+  int quals_index = 0;
 
-  init_ctf_sections ();
+  ctf_id_t qual_type_id = type_id;
+  int cvr_quals = get_cvr_quals_for_type (type);
 
-  output_ctf_header (tu_ctfc);
+  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)
+	{
+	  cvrint = (cvr_quals != 0);
+	  /* Reset the corresponding cvr_qual flag so that it is not processed
+	     again.  */
+	  cvr_quals &= ~quals_order[quals_index];
+
+	 /* 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;
 }
 
-void
-ctf_early_global_decl (tree ARG_UNUSED (decl))
+static ctf_id_t
+gen_ctf_sou_type (ctf_container_ref ctfc, tree sou_type)
 {
-  /* Generate CTF type information if appropriate debug level is set
-     (ctf_debug_info_level == CTFINFO_LEVEL_NORMAL).  */
+  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);
+
+      /* Update global objects count.  */
+      if (TREE_PUBLIC (decl))
+	ctfc->ctfc_num_global_objts++;
+    }
+  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 if (TREE_CODE (gen_type) == VECTOR_TYPE)
+	/* CTF does not have representation for vector types.  Skip this type.
+	   FIXME- Note this TBD_CTF_REPRESENTATION_LIMIT.  */
+	;
+
+      else
+	/* No other type is expected for C frontend.  */
+	gcc_unreachable ();
+    }
+
+  /* Add qualifiers if any.  */
+  if ((type_id != CTF_NULL_TYPEID) && (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);
+
+  if (TREE_CODE (type) == INTEGER_TYPE)
+    {
+      /* 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;
+    }
+  else if (TREE_CODE (type) == BOOLEAN_TYPE)
+    encoding = CTF_INT_BOOL;
+  else
+    /* The type of a bit field can be integral or boolean.  */
+    gcc_unreachable ();
+
+  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)
+{
+  tree var_decl;
+
+  ctf_dvd_preprocess_arg_t * dvd_arg =  (ctf_dvd_preprocess_arg_t *)arg;
+  ctf_dvdef_ref var = (ctf_dvdef_ref) *slot;
+  ctf_container_ref arg_ctfc = dvd_arg->dvd_arg_ctfc;
+
+  ctf_preprocess_var (arg_ctfc, var);
+
+  /* Keep track of global objts.  */
+  var_decl = var->dvd_decl;
+  if ((TREE_CODE_CLASS (TREE_CODE (var_decl)) == tcc_declaration)
+      && TREE_PUBLIC (var_decl))
+    {
+      arg_ctfc->ctfc_gobjts_list[dvd_arg->dvd_global_obj_idx] = var;
+      dvd_arg->dvd_global_obj_idx++;
+    }
+
+  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_types = ctfc->ctfc_types->elements ();
+
+  /* Initialize an array to keep track of the CTF variables at global
+     scope.  */
+  size_t num_global_objts = ctfc->ctfc_num_global_objts;
+  if (num_global_objts)
+    {
+      ctfc->ctfc_gobjts_list = ggc_vec_alloc<ctf_dvdef_t*>(num_global_objts);
+      gcc_assert (num_ctf_types);
+    }
+
+  size_t num_ctf_vars = ctfc->ctfc_vars->elements ();
+  if (num_ctf_vars)
+    {
+      ctf_dvd_preprocess_arg_t dvd_arg;
+      dvd_arg.dvd_global_obj_idx = 0;
+      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);
+    }
+
+  /* Initialize an array to keep track of the CTF functions types for global
+     functions 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
+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");
+}
+
+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)
+{
+  switch_to_section (ctf_info_section);
+  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");
+  dw2_asm_output_data (4, ctfc->ctfc_cuname_offset, "cth_cuname");
+
+  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 objtidxoff = 0;
+  uint32_t funcidxoff = 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));
+
+      funcoff = objtoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t);
+      /* Object index appears after function info.  */
+      objtidxoff = funcoff + get_ctfc_num_funcinfo_bytes (ctfc);
+      /* Funxtion index goes next.  */
+      funcidxoff = objtidxoff + ctfc->ctfc_num_global_objts * sizeof (uint32_t);
+      /* Vars appear after function index.  */
+      varoff = funcidxoff + ctfc->ctfc_num_global_funcs * sizeof (uint32_t);
+      /* 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 object index section.  */
+    dw2_asm_output_data (4, objtidxoff, "cth_objtidxoff");
+    /* Offset of function index section.  */
+    dw2_asm_output_data (4, funcidxoff, "cth_funcidxoff");
+
+    /* 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_obj_info (ctf_container_ref ctfc)
+{
+  unsigned long i;
+  ctf_dvdef_ref var;
+
+  if (!ctfc->ctfc_num_global_objts) return;
+
+  /* Compiler spits out the objts (at global scope) in the CTF obj info section.
+     In no specific order.  In an object file, the CTF object index section is
+     used to associate the objts to their corresponding names.  */
+  for (i = 0; i < ctfc->ctfc_num_global_objts; i++)
+    {
+      var = ctfc->ctfc_gobjts_list[i];
+
+      /* CTF type ID corresponding to the type of the variable.  */
+      dw2_asm_output_data (4, var->dvd_type, "objtinfo_var_type");
+    }
+
+}
+
+static void
+output_ctf_func_info (ctf_container_ref ctfc)
+{
+  unsigned long i, j;
+  ctf_dtdef_ref ctftype;
+  uint32_t vlen;
+
+  if (!ctfc->ctfc_num_global_funcs) return;
+
+  /* Compiler spits out the function type, return type, and args of each global
+     function in the CTF funcinfo section.  In no specific order.
+     In an object file, the CTF function index section is used to associate
+     functions to their corresponding 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");
+    }
+}
+
+static void
+output_ctf_objtidx (ctf_container_ref ctfc)
+{
+  unsigned long i;
+  ctf_dvdef_ref var;
+
+  if (!ctfc->ctfc_num_global_objts) return;
+
+  for (i = 0; i < ctfc->ctfc_num_global_objts; i++)
+    {
+      var = ctfc->ctfc_gobjts_list[i];
+      /* Offset to the name in CTF string table.  */
+      dw2_asm_output_data (4, var->dvd_name_offset, "objtinfo_name");
+    }
+}
+
+static void
+output_ctf_funcidx (ctf_container_ref ctfc)
+{
+  unsigned long i;
+  ctf_dtdef_ref ctftype;
+
+  if (!ctfc->ctfc_num_global_funcs) return;
+
+  for (i = 0; i < ctfc->ctfc_num_global_funcs; i++)
+    {
+      ctftype = ctfc->ctfc_gfuncs_list[i];
+      /* Offset to the name in CTF string table.  */
+      dw2_asm_output_data (4, ctftype->dtd_data.ctti_name, "funcinfo_name");
+    }
+}
+
+/* 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:
+      if (TREE_CODE (decl) != PARM_DECL)
+	/* FIXME - Its not clear why PARM_DECL arise here.  */
+	/* No other TREE_CODE is expected at this time.  */
+	gcc_unreachable ();
+    }
+}
+
+/* CTF routines interfacing to the compiler.  */
+
+void
+ctf_debug_init (void)
+{
+  init_ctf_containers ();
+}
+
+void
+ctf_early_finish (const char * filename)
+{
+  if (ctf_debug_info_level == CTFINFO_LEVEL_NONE)
+    return;
+
+  init_ctf_sections ();
+
+  ctfc_add_cuname (tu_ctfc, filename);
+
+  /* Pre-process CTF before generating assembly.  */
+  ctf_preprocess (tu_ctfc);
+
+  output_ctf_header (tu_ctfc);
+  output_ctf_obj_info (tu_ctfc);
+  output_ctf_func_info (tu_ctfc);
+  output_ctf_objtidx (tu_ctfc);
+  output_ctf_funcidx (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 decl)
+{
+  /* Generate CTF type information if appropriate debug level is set
+     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 +1935,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..6a01f82 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,68 @@ 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;
+  unsigned int ctfc_cuname_offset;
+
+  /* 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_global_objts;
+
+  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;
+  /* List of CTF variables at global scope.  The order of global object entries
+     in the CTF objinfo section is undefined by the  compiler.  */
+  ctf_dvdef_t ** GTY ((length ("%h.ctfc_num_global_objts"))) ctfc_gobjts_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 +285,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..afc6e8f 100644
--- a/include/ctf.h
+++ b/include/ctf.h
@@ -52,10 +52,15 @@ extern "C"
 
    The CTF file or section itself has the following structure:
 
-   +--------+--------+---------+----------+----------+-------+--------+
-   |  file  |  type  |  data   | function | variable | data  | string |
-   | header | labels | objects |   info   |   info   | types | table  |
-   +--------+--------+---------+----------+----------+-------+--------+
+   +--------+--------+---------+----------+--------+----------+...
+   |  file  |  type  |  data   | function | object | function |...
+   | header | labels | objects |   info   | index  |  index   |...
+   +--------+--------+---------+----------+--------+----------+...
+
+   ...+----------+-------+--------+
+   ...| variable | data  | string |
+   ...|   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
@@ -74,14 +79,27 @@ extern "C"
    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.
 
+   For situations in which the order of the symbols in the symtab is not known,
+   a pair of optional indexes follow the data object and function info sections:
+   each of these is an array of strtab indexes, mapped 1:1 to the corresponding
+   data object / function info section, giving each entry in those sections a
+   name so that the linker can correlate them with final symtab entries and
+   reorder them accordingly (dropping the indexes in the process).
+
    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.
+   names are sorted into ASCIIbetical order, permitting binary searching.  We do
+   not define how the consumer maps these variable names to addresses or
+   anything else, or indeed what these names represent: they might be names
+   looked up at runtime via dlsym() or names extracted at runtime by a debugger
+   or anything else the consumer likes.
 
    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.
+   denoted by their ID.  Most type nodes are standalone or point backwards to
+   earlier nodes, but this is not required: nodes can point to later nodes,
+   particularly structure and union members.
 
    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
@@ -125,9 +143,12 @@ 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_cuname;		/* Ref to CU name (may be 0).  */
   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_objtidxoff;	/* Offset of object index section.  */
+  uint32_t cth_funcidxoff;	/* Offset of function index 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.  */
@@ -142,13 +163,14 @@ typedef struct ctf_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".) */
+/* v1 upgraded to a later version is not quite the same as the native form,
+   because the boundary between parent and child types is different but not
+   recorded anywhere, 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
@@ -265,6 +287,7 @@ union
 
 #define CTF_NAME_STID(name)		((name) >> 31)
 #define CTF_NAME_OFFSET(name)		((name) & CTF_MAX_NAME)
+#define CTF_SET_STID(name, stid)	((name) | (stid) << 31)
 
 /* V2 only. */
 #define CTF_TYPE_INFO(kind, isroot, vlen) \
@@ -378,13 +401,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] 7+ messages in thread

end of thread, other threads:[~2019-09-09  4:29 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-09  4:28 [PATCH,RFC,V5 0/6] Support for CTF in GCC Indu Bhagat
2019-09-09  4:28 ` [PATCH,RFC,V5 6/6] Handle CTF sections when LTO is enabled Indu Bhagat
2019-09-09  4:28 ` [PATCH,RFC,V5 2/6] Add CTF command line options : -gtLEVEL Indu Bhagat
2019-09-09  4:28 ` [PATCH,RFC,V5 5/6] Update CTF testsuite Indu Bhagat
2019-09-09  4:28 ` [PATCH,RFC,V5 1/6] Add new function lang_GNU_GIMPLE Indu Bhagat
2019-09-09  4:28 ` [PATCH,RFC,V5 3/6] Setup for CTF generation and emission Indu Bhagat
2019-09-09  4:29 ` [PATCH,RFC,V5 4/6] CTF generation for a single compilation unit 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).