public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 0/4] Support for the CTF debug format
@ 2021-01-22 11:01 Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 1/4] Add new function lang_GNU_GIMPLE Jose E. Marchesi
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Jose E. Marchesi @ 2021-01-22 11:01 UTC (permalink / raw)
  To: gcc-patches

Hi people!

Last year we submitted a first patch series introducing support for
the CTF debugging format in GCC [1].  We got a lot of feedback that
prompted us to change the approach used to generate the debug info,
and this patch series is the result of that.

This implementation works, but there are several points that need
discussion and agreement with the upstream community, as they impact
the way debugging options work.  We are also proposing a way to add
additional debugging formats (such as BTF) in the future.  See below
for more details.

[1] https://gcc.gnu.org/legacy-ml/gcc-patches/2019-05/msg01297.html

About CTF
=========

CTF is a debugging format designed in order to express C types in a
very compact way.  The key is compactness and simplicity.  For more
information see:

- CTF specification
  http://www.esperi.org.uk/~oranix/ctf/ctf-spec.pdf

- Compact C-Type support in the GNU toolchain (talk + slides)
  https://linuxplumbersconf.org/event/4/contributions/396/

- On type de-duplication in CTF (talk + slides)
  https://linuxplumbersconf.org/event/7/contributions/725/

CTF in the GNU Toolchain
========================

During the last year we have been working in adding support for CTF to
several components of the GNU toolchain:

- binutils support is already upstream.  It supports linking objects
  with CTF information with full type de-duplication.

- GDB support is to be sent upstream very shortly.  It makes the
  debugger capable to use the CTF information whenever available.
  This is useful in cases where DWARF has been stripped out but CTF is
  kept.

- GCC support is being discussed and submitted in this series.

From debug hooks to debug formats
=================================

Our first attempt in adding CTF to GCC used the obvious approach of
adding a new set of debug hooks as defined in gcc/debug.h.

During our first interaction with the upstream community we were told
to _not_ use debug hooks, because these are to be obsoleted at some
point.  We were suggested to instead hook our handlers (which
processed type TREE nodes producing CTF types from them) somewhere
else.  So we did.

However at the time we were also facing the need to support BTF, which
is another type-related debug format needed by the BPF GCC backend.
Hooking here and there doesn't sound like such a good idea when it
comes to support several debug formats.

Therefore we thought about how to make GCC support diverse debugging
formats in a better way.  This led to a proposal we tried to discuss
at the GNU Tools Track in LPC2020:

- Update of the BPF support in the GNU Toolchain
  https://linuxplumbersconf.org/event/7/contributions/724/

Basically, the current situation in terms of diversity of debugging
formats in GCC can be summarized in the following like:

     tree     --+                  +--> dwarf2out
     rtl      --+                  +--> dbxout
                +--> debug_hooks --+--> vmsdbgout
     backends --+                  +--> xcoffout
     lto      --+                  +--> godump

i.e. each debug format materializes in a set of debug hooks, as in
gcc/debug.h.  The installed hooks are then invoked from many different
areas of the compiler including front-end, middle-end, back-end and
also lto.  Most of the hooks get TREE objects, from which they are
supposed to extract/infer whatever information they need to express.

This approach has several problems, some of which were raised by you
people when we initially submitted the CTF support:

- The handlers depend on the TREE nodes, so if new TREE nodes are
  added to cover new languages, or functionality in existing
  languages, all the debug hooks may need to be updated to reflect it.

- This also happens when the contents of existing TREE node types
  change or get expanded.

- The semantics encoded in TREE nodes usually are not in the best form
  to be used by debug formats.  This implies that the several sets of
  debug hooks need to do very similar transformations, which again
  will have to be adjusted/corrected if the TREE nodes change.

- And more...

In contrast, this is how LLVM supports several debug formats:

                                     +--> DWARF
     IR --> class DebugHandlerBase --+--> CodeView
                                     +--> BTF    

i.e. LLVM gets debugging information as part of the IR, and then has
debug info backends in the form of instances of DebugHandlerBase,
which process that subset of the IR to produce whatever debug output.

To overcome the problems above, we thought about introducing a new set
of debug hooks, resulting in something like this:

                   +--> godump
                   +--> xcoffout
      debug_hooks -+--> vmsdbgout
                   +--> dbxout                        +--> DWARF
                   +--> dwarf2out --> n_debug_hooks --+--> BTF
                                        (walk)        +--> CTF
                                                      ... more ...

See how these "new debug hooks" are intended to be called by the DWARF
old debug hooks.  In this way:

- The internal DWARF representation becomes the canonical (and only)
  IR for debugging information in the compiler.  This is similar to
  what LLVM uses to implement support for DWARF, BTF and the Microsoft
  debug format.

- Debug formats (like CTF, BTF, stabs, etc) are implemented to provide
  a very simple API that traverses the DWARF DIE trees available in
  dwarf2out.

- The semantics expressed in the DWARF DIEs, which have been already
  extracted from the TREE nodes, are free of many internal details and
  more suitable to be easily translated into whatever abstractions the
  debug formats require.
  
To avoid misunderstandings, we got to refer to these "new debug hooks"
simply as "debug formats".

In this patch series we are using this later approach in order to
support CTF, and we can say we are happy about using the internal
DWARF DIEs as a source instead of TREE nodes: it led to a more natural
implementation, much easier to understand.  This sort of confirms in
practice that the approach is sound.
   
The debug format API
====================

As you can see in the patch series, we hooked CTF in dwarf2out_early_finish
like this:

     /* Emit CTF debug info.  */
     if (ctf_debug_info_level > CTFINFO_LEVEL_NONE && lang_GNU_C ())
      {
        ctf_debug_init ();
        debug_format_do_cu (comp_unit_die ());
        for (limbo_die_node *node = limbo_die_list; node; node = node->next) 
          debug_format_do_cu (node->die);
        ctf_debug_finalize (filename);
       }

In turn, debug_format_do_cu traverses the tree of DIEs passed to it calling
ctf_do_die on them.

This conforms the debug format API:

   FOO_debug_init ()
     Initialize the debug format FOO.

   FOO_debug_finalize (FILENAME)
     Possibly write out, cleanup and finalization for debug format FOO.

   FOO_do_die (DIE)
     Process the given DIE.
  
Note how the emission of DWARF is interrupted after that point, if no
DWARF was requested by the user.

dwarf2out - dwarf2ctf
=====================

The functions ctf_debug_init, ctf_do_die and ctf_debug_finalize, that
implement the API described above, are all in gcc/dwarf2ctf.c.

Obviously, these routines need access to the dwarf DIE data
structures, and several functions which are defined in dwarf2out.[ch],
many (most?) of which are private to that file: dw_die_ref, get_AT,
etc.

Therefore, in this implementation we opted by writing dwarf2ctf.c in a
way it can just be #included in dwarf2ctf.c.

A question remains: would it be better to abstract these types and
functions in an API in dwarf2out.h?

Command line options for debug formats
======================================

This implementation adds the following command-line options to select the
emission of CTF:

     -gt[123]

These options mimic the -g[123...] options for DWARF.

This involved adding new entries for debug_info_type:

     CTF_DEBUG            - Write CTF debug info.
     CTF_AND_DWARF2_DEBUG - Write both CTF and DWARF info.
   
Doing this, we just followed the trend initiated by vmsdbgout.c, which
added VMS_DEBUG and VMS_AND_DWARF2_DEBUG.

This approach is not very good, because debug_info_type was designed
to cover different debug hook implementations; debug formats, in
contrast, are a different thing.

This translates to problems and fragile behavior:

- Everywhere write_symbols is checked we have to expand the logic to
  take the CTF values into account.  You can see that is the case in
  this patch series.  This is very fragile and doesn't scale well: we
  are most probably missing some checks.

- The CTF debug format needs certain DWARF debug level (2) in order to
  work, since otherwise not enough type DIEs get generated.  This will
  probably happen with some other formats as well.

- Therefore, -gt implicitly sets the DWARF debug level to 2.  But if
  the user uses -gt -g1, the CTF information will be incomplete
  because -g1 resets the DWARF debug level to 1.  -gtoggle also
  presents difficulties.
  
- Backends select what debug hooks to use by defining constants like
  DWARF2_DEBUGGING_INFO.  Since the new debug formats are based on the
  DWARF debug hooks, that is the constant to define by the backends
  wanting to support DWARF + debug infos.
     
  However, some backends may want to use one of the debug formats by
  default, i.e. for -g.  This is the case of the BPF backend, that
  needs to generate BTF instead of DWARF.  Currently, there is no way
  to specify this.

  We could add a new optional backend hook/constant to select the
  desired default debug format, like:

       #define DWARF2_DEBUGGING_INFO /* Selects the dwarf debug hooks */

       /* Selects the default debug format to emit with -g.  */
       #define CTF_DEBUGGING_FORMAT
       #define BTF_DEBUGGING_FORMAT
       #define DWARF_DEBUGGING_FORMAT /* The default */

  Regardless of what debug format is defined as the default, the other
  formats are also available with -gdwarf, -gctf, -gbtf, etc.

-gt or -gctf
============

This patch series uses -gt to trigger the generation of CTF debug
data, but if we agree on the approach outlined in the last section for
supporting debug formats in the backends, most likely we will want to
use -gctf instead of -gt.

Work in progress: BTF as a debug format
=======================================

We are already working in adding support for the BTF debug format to
GCC.  This is needed by the BPF backend, which should generate BTF
instead of DWARF.  This is absolutely needed in order to compile BPF
programs that work in the Linux kernel, as explained in the "Update of
the BPF support in the GNU Toolchain" talk mentioned above.

Since BTF is very similar to CTF, we are just adding support for BTF
to the CTF implementation.  In this way, ctfout.[ch] and dwarf2ctf.c
provide two debug formats.

Indu Bhagat (4):
  Add new function lang_GNU_GIMPLE
  CTF debug format
  CTF testsuite
  CTF documentation

 gcc/Makefile.in                               |    3 +
 gcc/common.opt                                |    9 +
 gcc/ctfout.c                                  | 1579 +++++++++++++++++
 gcc/ctfout.h                                  |  322 ++++
 gcc/doc/invoke.texi                           |   16 +
 gcc/dwarf2cfi.c                               |    3 +-
 gcc/dwarf2ctf.c                               |  816 +++++++++
 gcc/dwarf2out.c                               |   32 +-
 gcc/final.c                                   |    5 +-
 gcc/flag-types.h                              |   19 +-
 gcc/gengtype.c                                |    2 +-
 gcc/langhooks.c                               |    9 +
 gcc/langhooks.h                               |    1 +
 gcc/opts.c                                    |   65 +-
 gcc/targhooks.c                               |    3 +-
 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  |   38 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-3.c  |   17 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-4.c  |   13 +
 .../gcc.dg/debug/ctf/ctf-attr-mode-1.c        |   22 +
 .../gcc.dg/debug/ctf/ctf-attr-used-1.c        |   22 +
 .../gcc.dg/debug/ctf/ctf-bitfields-1.c        |   30 +
 .../gcc.dg/debug/ctf/ctf-bitfields-2.c        |   39 +
 .../gcc.dg/debug/ctf/ctf-bitfields-3.c        |   16 +
 .../gcc.dg/debug/ctf/ctf-bitfields-4.c        |   19 +
 .../gcc.dg/debug/ctf/ctf-complex-1.c          |   22 +
 .../gcc.dg/debug/ctf/ctf-cvr-quals-1.c        |   65 +
 .../gcc.dg/debug/ctf/ctf-cvr-quals-2.c        |   30 +
 .../gcc.dg/debug/ctf/ctf-cvr-quals-3.c        |   25 +
 .../gcc.dg/debug/ctf/ctf-cvr-quals-4.c        |   23 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c   |   21 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c   |   27 +
 .../gcc.dg/debug/ctf/ctf-file-scope-1.c       |   25 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c  |   16 +
 .../gcc.dg/debug/ctf/ctf-forward-1.c          |   40 +
 .../gcc.dg/debug/ctf/ctf-forward-2.c          |   16 +
 .../gcc.dg/debug/ctf/ctf-func-index-1.c       |   25 +
 .../debug/ctf/ctf-function-pointers-1.c       |   24 +
 .../debug/ctf/ctf-function-pointers-2.c       |   22 +
 .../debug/ctf/ctf-function-pointers-3.c       |   21 +
 .../gcc.dg/debug/ctf/ctf-functions-1.c        |   34 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c    |   17 +
 .../gcc.dg/debug/ctf/ctf-objt-index-1.c       |   30 +
 .../gcc.dg/debug/ctf/ctf-pointers-1.c         |   26 +
 .../gcc.dg/debug/ctf/ctf-pointers-2.c         |   25 +
 .../gcc.dg/debug/ctf/ctf-preamble-1.c         |   11 +
 .../gcc.dg/debug/ctf/ctf-skip-types-1.c       |   33 +
 .../gcc.dg/debug/ctf/ctf-skip-types-2.c       |   17 +
 .../gcc.dg/debug/ctf/ctf-skip-types-3.c       |   20 +
 .../gcc.dg/debug/ctf/ctf-skip-types-4.c       |   19 +
 .../gcc.dg/debug/ctf/ctf-skip-types-5.c       |   19 +
 .../gcc.dg/debug/ctf/ctf-skip-types-6.c       |   18 +
 .../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 |   32 +
 .../gcc.dg/debug/ctf/ctf-struct-array-1.c     |   65 +
 .../gcc.dg/debug/ctf/ctf-struct-pointer-1.c   |   21 +
 .../gcc.dg/debug/ctf/ctf-struct-pointer-2.c   |   22 +
 .../gcc.dg/debug/ctf/ctf-typedef-1.c          |   68 +
 .../gcc.dg/debug/ctf/ctf-typedef-2.c          |   20 +
 .../gcc.dg/debug/ctf/ctf-typedef-3.c          |   24 +
 .../gcc.dg/debug/ctf/ctf-typedef-struct-1.c   |   14 +
 .../gcc.dg/debug/ctf/ctf-typedef-struct-2.c   |   17 +
 .../gcc.dg/debug/ctf/ctf-typedef-struct-3.c   |   32 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c  |   14 +
 .../gcc.dg/debug/ctf/ctf-variables-1.c        |   25 +
 .../gcc.dg/debug/ctf/ctf-variables-2.c        |   16 +
 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp        |   41 +
 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c     |    7 +
 gcc/toplev.c                                  |   21 +-
 include/ctf.h                                 |  513 ++++++
 libiberty/simple-object.c                     |    3 +
 76 files changed, 4862 insertions(+), 11 deletions(-)
 create mode 100644 gcc/ctfout.c
 create mode 100644 gcc/ctfout.h
 create mode 100644 gcc/dwarf2ctf.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-array-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-used-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-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-file-scope-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-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-function-pointers-3.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-pointers-2.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-skip-types-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-5.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-6.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-struct-pointer-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-pointer-2.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-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-3.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-typedef-struct-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-3.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-variables-2.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

-- 
2.25.0.2.g232378479e


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

* [PATCH 1/4] Add new function lang_GNU_GIMPLE
  2021-01-22 11:01 [PATCH 0/4] Support for the CTF debug format Jose E. Marchesi
@ 2021-01-22 11:01 ` Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 2/4] CTF debug format Jose E. Marchesi
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jose E. Marchesi @ 2021-01-22 11:01 UTC (permalink / raw)
  To: gcc-patches

2021-01-22  Indu Bhagat  <indu.bhagat@oracle.com>

	* langhooks.c (lang_GNU_GIMPLE): New Function.
	* langhooks.h: New Prototype.
---
 gcc/langhooks.c | 9 +++++++++
 gcc/langhooks.h | 1 +
 2 files changed, 10 insertions(+)

diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 2354386f7b4..0082ee9f350 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -929,3 +929,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 842e605c439..f9c82eff0cb 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -638,5 +638,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 */
-- 
2.25.0.2.g232378479e


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

* [PATCH 2/4] CTF debug format
  2021-01-22 11:01 [PATCH 0/4] Support for the CTF debug format Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 1/4] Add new function lang_GNU_GIMPLE Jose E. Marchesi
@ 2021-01-22 11:01 ` Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 3/4] CTF testsuite Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 4/4] CTF documentation Jose E. Marchesi
  3 siblings, 0 replies; 5+ messages in thread
From: Jose E. Marchesi @ 2021-01-22 11:01 UTC (permalink / raw)
  To: gcc-patches

This commit introduces support for generating CTF debugging
information from GCC.

2021-01-22  Indu Bhagat  <indu.bhagat@oracle.com>
	    Jose E. Marchesi  <jose.marchesi@oracle.com>
	    Weimin Pan  <weimin.pan@oracle.com>

gcc/

	* Makefile.in: Add ctfout.* files to GTFILES.  Add new object files.
	* common.opt: Add CTF debug info options.
	* ctfout.c: New file.
	* ctfout.h: Likewise.
	* dwarf2cfi.c (dwarf2out_do_frame): Acknowledge CTF_DEBUG.
	* dwarf2ctf.c: New file.
	* dwarf2out.c (dwarf2out_source_line): Acknowledge CTF_DEBUG.
	(dwarf2out_finish): Skip emitting DWARF if CTF is to be generated.
	(debug_format_do_cu): New function.
	(dwarf2out_early_finish): Traverse DIEs and emit CTF for them if
	requested.
	Include dwarf2ctf.c.
	* final.c (dwarf2_debug_info_emitted_p): Acknowledge CTF_DEBUG and
	CTF_AND_DWARF2_DEBUG.
	(final_scan_insn_1): Likewise.
	(final_scan_insn_1): Likewise.
	* flag-types.h (enum debug_info_type): Add CTF_DEBUG and
	CTF_AND_DWARF2_DEBUG.
	(enum ctf_debug_info_levels): New enum.
	* gengtype.c (open_base_files): Handle ctfout.h.
	* opts.c (debug_type_names): Add ctf.
	(set_ctf_debug_level): New function.
	(set_debug_level): Set CTF_DEBUG and CTF_AND_DWARF2_DEBUG whenever
	appropriate.
	* targhooks.c (default_debug_unwind_info): Likewise.
	* toplev.c (process_options): Inform the user and ignore -gtLEVEL if
	frontend is not C.

include/

	* ctf.h: Import from binutils.

libiberty/

	* simple-object.c (handle_lto_debug_sections): Copy over .ctf
	sections.
---
 gcc/Makefile.in           |    3 +
 gcc/common.opt            |    9 +
 gcc/ctfout.c              | 1579 +++++++++++++++++++++++++++++++++++++
 gcc/ctfout.h              |  322 ++++++++
 gcc/dwarf2cfi.c           |    3 +-
 gcc/dwarf2ctf.c           |  816 +++++++++++++++++++
 gcc/dwarf2out.c           |   32 +-
 gcc/final.c               |    5 +-
 gcc/flag-types.h          |   19 +-
 gcc/gengtype.c            |    2 +-
 gcc/opts.c                |   65 +-
 gcc/targhooks.c           |    3 +-
 gcc/toplev.c              |   21 +-
 include/ctf.h             |  513 ++++++++++++
 libiberty/simple-object.c |    3 +
 15 files changed, 3384 insertions(+), 11 deletions(-)
 create mode 100644 gcc/ctfout.c
 create mode 100644 gcc/ctfout.h
 create mode 100644 gcc/dwarf2ctf.c
 create mode 100644 include/ctf.h

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index a63c5d9cab6..a3d2b5202c6 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1317,6 +1317,7 @@ OBJS = \
 	cfgloopanal.o \
 	cfgloopmanip.o \
 	cfgrtl.o \
+	ctfout.o \
 	symtab.o \
 	symtab-thunks.o \
 	symtab-clones.o \
@@ -2655,6 +2656,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)/gimple-isel.cc \
   $(srcdir)/dojump.c $(srcdir)/emit-rtl.h \
diff --git a/gcc/common.opt b/gcc/common.opt
index bde1711870d..adaddaa19ef 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -122,6 +122,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
@@ -3174,6 +3179,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/ctfout.c b/gcc/ctfout.c
new file mode 100644
index 00000000000..7895d864666
--- /dev/null
+++ b/gcc/ctfout.c
@@ -0,0 +1,1579 @@
+/* Output CTF format from GCC.
+   Copyright (C) 2019,2020 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 "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.  */
+
+GTY (()) ctf_container_ref tu_ctfc;
+
+ctf_container_ref
+ctf_get_tu_ctfc (void)
+{
+  return 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.  */
+
+/* CTF debug info section.  */
+
+#ifndef CTF_INFO_SECTION_NAME
+#define CTF_INFO_SECTION_NAME  ".ctf"
+#endif
+
+/* Section flags for the 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 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;
+    }
+}
+
+/* Functions to create CTF types.
+
+   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.  */
+
+static void
+ctf_dtd_insert (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
+{
+  bool existed = ctfc->ctfc_types->put (dtd->dtd_key, dtd);
+  /* Duplicate CTF type records not expected to be inserted.  And dtd_decl
+     cannot be NULL.  */
+  gcc_assert (!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.  */
+
+static ctf_dtdef_ref
+ctf_dtd_lookup (const ctf_container_ref ctfc, const dw_die_ref type)
+{
+  ctf_dtdef_ref *dtdef_ref = ctfc->ctfc_types->get (type);
+  if (dtdef_ref)
+    return *dtdef_ref;
+  else
+    return NULL;
+}
+
+static void
+ctf_dvd_insert (ctf_container_ref ctfc, ctf_dvdef_ref dvd)
+{
+  bool existed = ctfc->ctfc_vars->put (dvd->dvd_key, dvd);
+  /* Duplicate variable records not expected to be inserted.  And dvd_decl
+     cannot be NULL.  */
+  gcc_assert (!existed);
+}
+
+/* Lookup CTF variable given a decl node.  */
+
+ctf_dvdef_ref
+ctf_dvd_lookup (const ctf_container_ref ctfc, dw_die_ref die)
+{
+  ctf_dvdef_ref * slot;
+
+  slot = ctfc->ctfc_vars->get (die);
+
+  if (slot)
+    return (ctf_dvdef_ref) (*slot);
+
+  return NULL;
+}
+
+/* Append member definition to the list.  Member list is a singly-linked list
+   with list start pointing to the head.  */
+
+#define ctf_dmd_list_next(elem) ((ctf_dmdef_t *)((elem)->dmd_next))
+
+static 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;
+}
+
+/* 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;
+}
+
+static 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;
+}
+
+static ctf_id_t
+ctf_add_generic (ctf_container_ref ctfc, uint32_t flag, const char * name,
+		 ctf_dtdef_ref * rp, dw_die_ref die)
+{
+  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 = die;
+
+  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, dw_die_ref die)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, die);
+
+  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;
+}
+
+ctf_id_t
+ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+		 uint32_t kind, dw_die_ref die)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  gcc_assert (ref <= CTF_MAX_TYPE);
+
+  type = ctf_add_generic (ctfc, flag, NULL, &dtd, die);
+  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, dw_die_ref die)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type = 0;
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, die);
+
+  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, dw_die_ref die)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+
+  gcc_assert (ref <= CTF_MAX_TYPE);
+
+  type = ctf_add_generic (ctfc, flag, name, &dtd, die);
+  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,
+	       uint32_t bit_offset, uint32_t bit_size, dw_die_ref die)
+{
+  ctf_dtdef_ref dtd;
+  ctf_id_t type;
+  uint32_t roundup_nbytes;
+
+  gcc_assert ((bit_size <= 255) && (bit_offset <= 255));
+
+  gcc_assert (ref <= CTF_MAX_TYPE);
+
+  type = ctf_add_generic (ctfc, flag, NULL, &dtd, die);
+
+  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_SLICE, flag, 0);
+
+  roundup_nbytes = (ROUND_UP (bit_size, 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 = bit_size;
+  dtd->dtd_u.dtu_slice.cts_offset = bit_offset;
+
+  ctfc->ctfc_num_stypes++;
+
+  return type;
+}
+
+ctf_id_t
+ctf_add_float (ctf_container_ref ctfc, uint32_t flag,
+	       const char * name, const ctf_encoding_t * ep, dw_die_ref die)
+{
+  return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_FLOAT, die));
+}
+
+ctf_id_t
+ctf_add_integer (ctf_container_ref ctfc, uint32_t flag,
+		 const char * name, const ctf_encoding_t * ep, dw_die_ref die)
+{
+  return (ctf_add_encoded (ctfc, flag, name, ep, CTF_K_INTEGER, die));
+}
+
+ctf_id_t
+ctf_add_pointer (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
+		 dw_die_ref die)
+{
+  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_POINTER, die));
+}
+
+ctf_id_t
+ctf_add_array (ctf_container_ref ctfc, uint32_t flag, const ctf_arinfo_t * arp,
+	       dw_die_ref die)
+{
+  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, die);
+
+  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, dw_die_ref die)
+{
+  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 (ctfc, die);
+  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, die);
+
+  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, dw_die_ref die)
+{
+  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, die);
+  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, dw_die_ref 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);
+
+  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,
+		  dw_die_ref die)
+{
+  ctf_dvdef_ref dvd;
+
+  gcc_assert (name);
+
+  if (name != NULL)
+    {
+      dvd = ggc_cleared_alloc<ctf_dvdef_t> ();
+      dvd->dvd_key = die;
+      /* Buffer the strings in the CTF string table.  */
+      dvd->dvd_name = ctf_add_string (ctfc, name, &(dvd->dvd_name_offset));
+      dvd->dvd_type = ref;
+      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,
+		  dw_die_ref die, bool from_global_func)
+{
+  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, die);
+
+  dtd->from_global_func = from_global_func;
+  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, dw_die_ref die)
+{
+  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 (ctfc, die);
+  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, die);
+
+  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;
+}
+
+/* Compare two CTF variable definition entries.  Currently used for sorting
+   by name.  */
+
+static 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;
+}
+
+/* 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.  */
+
+static 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;
+}
+
+static 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;
+}
+
+/* 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;
+}
+
+/* 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.  */
+
+bool
+ctf_type_exists (ctf_container_ref ctfc, dw_die_ref type,
+		 ctf_id_t * type_id)
+{
+  bool exists = false;
+  ctf_dtdef_ref ctf_type_seen = ctf_dtd_lookup (ctfc, type);
+
+  if (ctf_type_seen)
+    {
+      exists = true;
+      /* CTF type for this type exists.  */
+      *type_id = ctf_type_seen->dtd_type;
+    }
+
+  return exists;
+}
+
+/* CTF container setup and teardown routines.  */
+
+/* Initialize the CTF string table.
+   The first entry in the CTF string table (empty string) is added.  */
+
+static void
+init_ctf_string_table (ctf_container_ref ctfc)
+{
+  ctfc->ctfc_strtable.ctstab_head = NULL;
+  ctfc->ctfc_strtable.ctstab_tail = NULL;
+  ctfc->ctfc_strtable.ctstab_num = 0;
+  ctfc->ctfc_strtable.ctstab_len = 0;
+
+  /* The first entry in the CTF string table is an empty string.  E.g., CTF
+     type records with no name (like CTF_K_CONST, CTF_K_VOLATILE etc) point to
+     this string.  */
+  uint32_t estr_offset = 0;
+  ctfc->ctfc_strtable.ctstab_estr = ctf_add_string (ctfc, "", &estr_offset);
+  ctfc->ctfc_strlen++;
+}
+
+/* Allocate a new CTF container with the desired flags.  */
+
+static inline ctf_container_ref
+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;
+  tu_ctfc->ctfc_nextid = CTF_INIT_TYPEID;
+
+  tu_ctfc->ctfc_types
+    = hash_map<dw_die_ref, ctf_dtdef_ref>::create_ggc (100);
+
+  tu_ctfc->ctfc_vars
+    = hash_map<dw_die_ref, ctf_dvdef_ref>::create_ggc (100);
+
+  init_ctf_string_table (tu_ctfc);
+
+  return tu_ctfc;
+}
+
+/* Initialize a CTF container per translation unit.  */
+
+static void
+init_ctf_containers (void)
+{
+  tu_ctfc = new_ctf_container (CTF_F_NEWFUNCINFO);
+}
+
+/* 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)
+    {
+      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;
+    }
+}
+
+/* Initialize the various sections and labels for CTF output.  */
+
+void
+init_ctf_sections (void)
+{
+  /* 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++);
+}
+
+#if 0
+/* Add CTF qualifier record.
+
+   If there are multiple qualifiers, the recommended ordering for CTF qualifier
+   records is const, volatile, restrict (from top-most to bottom-most).  */
+
+static ctf_id_t
+gen_ctf_cvrquals (ctf_container_ref ctfc, tree type, ctf_id_t type_id)
+{
+  tree qualified_type;
+  int flags;
+  uint32_t cvrint = 0;
+  int quals_index = 0;
+
+  ctf_id_t qual_type_id = type_id;
+  int cvr_quals = get_cvr_quals_for_type (type);
+
+  int quals_order[3] = { TYPE_QUAL_RESTRICT,
+			 TYPE_QUAL_VOLATILE,
+			 TYPE_QUAL_CONST };
+  ctf_id_t (*func_ptrs[3]) (ctf_container_ref, uint32_t, ctf_id_t, tree,
+			    uint32_t) = { ctf_add_restrict,
+					  ctf_add_volatile,
+					  ctf_add_const };
+  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_MAIN_VARIANT (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 (ctfc, type);
+	  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;
+}
+#endif
+
+/* 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 (dw_die_ref const & ARG_UNUSED (key), ctf_dvdef_ref * slot,
+		       void * arg)
+{
+  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.  */
+  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 (dw_die_ref const & ARG_UNUSED (key),
+		       ctf_dtdef_ref * slot, void * arg)
+{
+  uint32_t kind;
+
+  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 and the type
+     was generated from a function object.  */
+  kind = CTF_V2_INFO_KIND (ctftype->dtd_data.ctti_info);
+  if (kind == CTF_K_FUNCTION && ctftype->from_global_func)
+    {
+      arg_ctfc->ctfc_gfuncs_list[dtd_arg->dtd_global_func_idx] = ctftype;
+      dtd_arg->dtd_global_func_idx++;
+    }
+
+  /* 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);
+    }
+
+  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 + ctfc->ctfc_num_global_funcs * sizeof (uint32_t);
+      /* 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;
+  ctf_dtdef_ref ctftype;
+
+  if (!ctfc->ctfc_num_global_funcs) return;
+
+  /* The CTF funcinfo section is simply an array of CTF_K_FUNCTION type IDs in
+     the type section.  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];
+      dw2_asm_output_data (4, ctftype->dtd_type, "funcinfo_func_type");
+    }
+}
+
+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]);
+    }
+}
+
+/* CTF routines interfacing to the compiler.  */
+
+void
+ctf_init (void)
+{
+  init_ctf_containers ();
+}
+
+void
+ctf_output (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));
+}
+
+/* Reset all state within ctfout.c so that we can rerun the compiler
+   within the same process.  */
+
+void
+ctf_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
new file mode 100644
index 00000000000..d9a620461b2
--- /dev/null
+++ b/gcc/ctfout.h
@@ -0,0 +1,322 @@
+/* ctfout.h - Various declarations for functions found in ctfout.c
+   Copyright (C) 2019,2020 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 "config.h"
+#include "system.h"
+#include "tree.h"
+#include "fold-const.h"
+#include "dwarf2out.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;
+
+/* Type definition for CTF generation.  */
+
+typedef struct GTY (()) ctf_dtdef
+{
+  dw_die_ref 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.  */
+  bool from_global_func; /* Whether this type was added from a global
+                            function.  */
+  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;
+
+/* Variable definition for CTF generation.  */
+
+typedef struct GTY (()) ctf_dvdef
+{
+  dw_die_ref dvd_key;		/* DWARF DIE 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);
+
+/* 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;
+  unsigned int ctfc_cuname_offset;
+
+  /* CTF types.  */
+  hash_map <dw_die_ref, ctf_dtdef_ref> * GTY ((skip)) ctfc_types;
+  /* CTF variables.  */
+  hash_map <dw_die_ref, ctf_dvdef_ref> * GTY ((skip)) 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;
+
+  /* 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)
+
+/* 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.  */
+
+/* These APIs allow to initialize and finalize the CTF machinery and
+   to add types to the CTF container associated to the current
+   translation unit.  Used in dwarf2ctf.c.  */
+
+extern void ctf_init (void);
+extern void ctf_output (const char * filename);
+extern void ctf_finalize (void);
+
+extern ctf_container_ref ctf_get_tu_ctfc (void);
+
+extern bool ctf_type_exists (ctf_container_ref ctfc, dw_die_ref type,
+                             ctf_id_t * type_id);
+
+extern ctf_dvdef_ref ctf_dvd_lookup (const ctf_container_ref ctfc,
+                                     dw_die_ref die);
+
+extern ctf_id_t ctf_add_reftype (ctf_container_ref, uint32_t, ctf_id_t,
+                                 uint32_t, dw_die_ref);
+extern ctf_id_t ctf_add_enum (ctf_container_ref, uint32_t, const char *,
+			      HOST_WIDE_INT, dw_die_ref);
+extern ctf_id_t ctf_add_slice (ctf_container_ref, uint32_t, ctf_id_t,
+			       uint32_t bit_offset, uint32_t bit_size, dw_die_ref);
+extern ctf_id_t ctf_add_float (ctf_container_ref, uint32_t, const char *,
+			       const ctf_encoding_t *, dw_die_ref);
+extern ctf_id_t ctf_add_integer (ctf_container_ref, uint32_t, const char *,
+				 const ctf_encoding_t *, dw_die_ref);
+extern ctf_id_t ctf_add_pointer (ctf_container_ref, uint32_t flag, ctf_id_t,
+				 dw_die_ref);
+extern ctf_id_t ctf_add_array (ctf_container_ref, uint32_t,
+			       const ctf_arinfo_t *, dw_die_ref);
+extern ctf_id_t ctf_add_forward (ctf_container_ref, uint32_t, const char *,
+				 uint32_t, dw_die_ref);
+extern ctf_id_t ctf_add_typedef (ctf_container_ref, uint32_t, const char *,
+				 ctf_id_t, dw_die_ref);
+extern ctf_id_t ctf_add_function (ctf_container_ref, uint32_t, const char *,
+				  const ctf_funcinfo_t *, ctf_func_arg_t *,
+				  dw_die_ref, bool);
+extern ctf_id_t ctf_add_sou (ctf_container_ref, uint32_t, const char *,
+			     uint32_t, size_t, dw_die_ref);
+
+extern int ctf_add_enumerator (ctf_container_ref, ctf_id_t, const char *,
+			       HOST_WIDE_INT, dw_die_ref);
+extern int ctf_add_member_offset (ctf_container_ref, dw_die_ref, const char *,
+				  ctf_id_t, unsigned long);
+extern int ctf_add_variable (ctf_container_ref, const char *, ctf_id_t, dw_die_ref);
+
+/* Debug Format Interface.  Used in dwarf2out.c  */
+
+extern void ctf_debug_init (void);
+extern bool ctf_do_die (dw_die_ref die);
+extern void ctf_debug_finalize (const char *filename);
+
+#endif /* GCC_CTFOUT_H */
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index c2533b091b2..c0d01de7728 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -3531,7 +3531,8 @@ dwarf2out_do_frame (void)
   /* We want to emit correct CFA location expressions or lists, so we
      have to return true if we're going to output debug info, even if
      we're not going to output frame or unwind info.  */
-  if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
+  if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG
+      || write_symbols == CTF_DEBUG || write_symbols == CTF_AND_DWARF2_DEBUG)
     return true;
 
   if (saved_do_cfi_asm > 0)
diff --git a/gcc/dwarf2ctf.c b/gcc/dwarf2ctf.c
new file mode 100644
index 00000000000..20a37e5af54
--- /dev/null
+++ b/gcc/dwarf2ctf.c
@@ -0,0 +1,816 @@
+/* Generate CTF types and objects from the GCC DWARF.
+   Copyright (C) 2020 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 is meant to be included in dwarf2out.c */
+
+#include "ctfout.h"
+
+/* Forward declarations for some routines defined in this file.  */
+
+static ctf_id_t gen_ctf_type (ctf_container_ref, dw_die_ref);
+
+/* All the DIE structures we handle come from the DWARF information
+   generated by GCC.  However, there are two situations where we need
+   to create our own created DIE structures because GCC doesn't
+   provide them.
+
+   The DWARF spec suggests using a DIE with DW_tag_unspecified_type
+   and name "void" in order to denote the void type.  But GCC doesn't
+   follow this advice.  Still we need a DIE to act as a key for void
+   types, we use ctf_void_die.
+
+   Also, if a subrange type corresponding to an array index does not
+   specify a type then we assume it is `int'.
+
+   The variables below are initialized in ctf_debug_init and hold
+   references to the proper DIEs.  */
+
+dw_die_ref ctf_void_die;
+dw_die_ref ctf_array_index_die;
+
+/* Some DIEs have a type description attribute, stored in a DW_AT_type
+   attribute.  However, GCC generates no attribute to signify a `void'
+   type.
+
+   This can happen in many contexts (return type of a function,
+   pointed or qualified type, etc) so we use the `ctf_get_AT_type'
+   function below abstracts this.  */
+
+static dw_die_ref ctf_get_AT_type (dw_die_ref die)
+{
+  dw_die_ref type_die = get_AT_ref (die, DW_AT_type);
+  return (type_die ? type_die : ctf_void_die);
+}
+
+/* Generate CTF for the void type.  */
+
+static ctf_id_t
+gen_ctf_void_type (ctf_container_ref ctfc)
+{
+  ctf_encoding_t ctf_encoding = {0, 0, 0};
+
+  /* In CTF the void type is encoded as a 0-byte signed integer
+     type.  */
+
+  ctf_encoding.cte_bits = 0;
+  ctf_encoding.cte_format = CTF_INT_SIGNED;
+
+  gcc_assert (ctf_void_die != NULL);
+  return ctf_add_integer (ctfc, CTF_ADD_ROOT, "void",
+			  &ctf_encoding, ctf_void_die);
+}
+
+/* Sizes of entities can be given in bytes or bits.  This function
+   abstracts this by returning the size in bits of the given entity.
+   If no DW_AT_byte_size nor DW_AT_bit_size are defined, this function
+   returns 0.  */
+
+static uint32_t ctf_die_bitsize (dw_die_ref die)
+{
+  dw_attr_node *attr_byte_size = get_AT (die, DW_AT_byte_size);
+  dw_attr_node *attr_bit_size = get_AT (die, DW_AT_bit_size);
+
+  if (attr_bit_size)
+    return AT_unsigned (attr_bit_size);
+  else if (attr_byte_size)
+    return (AT_unsigned (attr_byte_size) * 8);
+  else
+    return 0;
+}
+
+/* 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, dw_die_ref type)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+
+  ctf_encoding_t ctf_encoding = {0, 0, 0};
+
+  unsigned int encoding = get_AT_unsigned (type, DW_AT_encoding);
+  unsigned int bit_size = ctf_die_bitsize (type);
+  const char * name_string = get_AT_string (type, DW_AT_name);
+
+  switch (encoding)
+    {
+    case DW_ATE_void:
+
+      ctf_encoding.cte_format = CTF_INT_SIGNED;
+      ctf_encoding.cte_bits = 0;
+
+      gcc_assert (name_string);
+      type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
+				 &ctf_encoding, type);
+
+      break;
+    case DW_ATE_boolean:
+
+      ctf_encoding.cte_format = CTF_INT_BOOL;
+      ctf_encoding.cte_bits = bit_size;
+
+      gcc_assert (name_string);
+      type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
+				 &ctf_encoding, type);
+      break;
+    case DW_ATE_float:
+      {
+	unsigned int float_bit_size
+	  = tree_to_uhwi (TYPE_SIZE (float_type_node));
+	unsigned int double_bit_size
+	  = tree_to_uhwi (TYPE_SIZE (double_type_node));
+	unsigned int long_double_bit_size
+	  = tree_to_uhwi (TYPE_SIZE (long_double_type_node));
+
+	if (bit_size == float_bit_size)
+	  ctf_encoding.cte_format = CTF_FP_SINGLE;
+	else if (bit_size == double_bit_size)
+	  ctf_encoding.cte_format = CTF_FP_DOUBLE;
+	else if (bit_size == long_double_bit_size)
+	  ctf_encoding.cte_format = CTF_FP_LDOUBLE;
+	else
+	  gcc_unreachable ();
+
+        ctf_encoding.cte_bits = bit_size;
+	type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
+				 &ctf_encoding, type);
+
+	break;
+      }
+    case DW_ATE_signed_char:
+      /* FALLTHROUGH */
+    case DW_ATE_unsigned_char:
+      /* FALLTHROUGH */
+    case DW_ATE_signed:
+      /* FALLTHROUGH */
+    case DW_ATE_unsigned:
+
+      if (encoding == DW_ATE_signed_char
+	  || encoding == DW_ATE_unsigned_char)
+	ctf_encoding.cte_format |= CTF_INT_CHAR;
+
+      if (encoding == DW_ATE_signed
+	  || encoding == DW_ATE_signed_char)
+	ctf_encoding.cte_format |= CTF_INT_SIGNED;
+
+      ctf_encoding.cte_bits = bit_size;
+      type_id = ctf_add_integer (ctfc, CTF_ADD_ROOT, name_string,
+				 &ctf_encoding, type);
+      break;
+
+    case DW_ATE_complex_float:
+      {
+	unsigned int float_bit_size
+	  = tree_to_uhwi (TYPE_SIZE (float_type_node));
+	unsigned int double_bit_size
+	  = tree_to_uhwi (TYPE_SIZE (double_type_node));
+	unsigned int long_double_bit_size
+	  = tree_to_uhwi (TYPE_SIZE (long_double_type_node));
+
+	if (bit_size == float_bit_size * 2)
+	  ctf_encoding.cte_format = CTF_FP_CPLX;
+	else if (bit_size == double_bit_size * 2)
+	  ctf_encoding.cte_format = CTF_FP_DCPLX;
+	else if (bit_size == long_double_bit_size * 2)
+	    ctf_encoding.cte_format = CTF_FP_LDCPLX;
+	else
+	  gcc_unreachable ();
+
+	ctf_encoding.cte_bits = bit_size;
+	type_id = ctf_add_float (ctfc, CTF_ADD_ROOT, name_string,
+				 &ctf_encoding, type);
+	break;
+      }
+    default:
+      /* Ignore.  */
+      break;
+    }
+
+  return type_id;
+}
+
+/* Generate CTF for a pointer type.  */
+
+static ctf_id_t
+gen_ctf_pointer_type (ctf_container_ref ctfc, dw_die_ref ptr_type)
+{
+  ctf_id_t type_id = CTF_NULL_TYPEID;
+  ctf_id_t ptr_type_id = CTF_NULL_TYPEID;
+  dw_die_ref pointed_type_die = ctf_get_AT_type (ptr_type);
+
+  type_id = gen_ctf_type (ctfc, pointed_type_die);
+
+  /* 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.  */
+  if (ctf_type_exists (ctfc, ptr_type, &ptr_type_id))
+    return ptr_type_id;
+
+  ptr_type_id = ctf_add_pointer (ctfc, CTF_ADD_ROOT, type_id, ptr_type);
+  return ptr_type_id;
+}
+
+/* Generate CTF for an array type.  */
+
+static ctf_id_t
+gen_ctf_array_type (ctf_container_ref ctfc, dw_die_ref array_type)
+{
+  dw_die_ref c;
+  ctf_id_t array_elems_type_id;
+  dw_die_ref array_elems_type = ctf_get_AT_type (array_type);
+
+  /* First, register the type of the array elements if needed.  */
+  array_elems_type_id = gen_ctf_type (ctfc, array_elems_type);
+
+  /* DWARF array types pretend C supports multi-dimensional arrays.
+     So for the type int[N][M], the array type DIE contains two
+     subrange_type children, the first iwth upper bound N-1 and the
+     second with upper bound M-1.
+
+     CTF, on the other hand, just encodes each array type in its own
+     array type CTF struct.  Therefore we have to iterate on the
+     children and create all the needed types.  */
+
+  c = array_type->die_child;
+  gcc_assert (c);
+  do
+    {
+      ctf_arinfo_t arinfo;
+      dw_die_ref array_index_type;
+      uint32_t array_num_elements;
+
+      c = c->die_sib;
+
+      if (c->die_tag == DW_TAG_subrange_type)
+	{
+	  dw_attr_node *upper_bound_at;
+
+	  array_index_type = ctf_get_AT_type (c);
+
+	  /* When DW_AT_upper_bound is used to specify the size of an
+	     array in DWARF, it is usually an unsigned constant
+	     specifying the upper bound index of the array.  However,
+	     for unsized arrays, such as foo[] or bar[0],
+	     DW_AT_upper_bound is a signed integer constant
+	     instead.  */
+
+	  upper_bound_at = get_AT (c, DW_AT_upper_bound);
+	  if (upper_bound_at
+	      && AT_class (upper_bound_at) == dw_val_class_unsigned_const)
+	    /* This is the upper bound index.  */
+	    array_num_elements = get_AT_unsigned (c, DW_AT_upper_bound) + 1;
+	  else if (get_AT (c, DW_AT_count))
+	    array_num_elements = get_AT_unsigned (c, DW_AT_count);
+	  else
+	    {
+	      /* This is a VLA of some kind.  */
+	      array_num_elements = 0;
+	    }
+	}
+      else if (c->die_tag == DW_TAG_enumeration_type)
+	{
+	  array_index_type = 0;
+	  array_num_elements = 0;
+	  /* XXX writeme. */
+	  gcc_assert (1);
+	}
+      else
+	gcc_unreachable ();
+
+      /* Ok, mount and register the array type.  Note how the array
+	 type we register here is the type of the elements in
+	 subsequent "dimensions", if there are any.  */
+
+      arinfo.ctr_nelems = array_num_elements;
+      if (array_index_type)
+	arinfo.ctr_index = gen_ctf_type (ctfc, array_index_type);
+      else
+	arinfo.ctr_index = gen_ctf_type (ctfc, ctf_array_index_die);
+
+      arinfo.ctr_contents = array_elems_type_id;
+      if (!ctf_type_exists (ctfc, c, &array_elems_type_id))
+	array_elems_type_id = ctf_add_array (ctfc, CTF_ADD_ROOT, &arinfo,
+					     c);
+    }
+  while (c != array_type->die_child);
+
+#if 0
+  /* 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);
+#endif
+
+  return array_elems_type_id;
+}
+
+/* Generate CTF for a typedef.  */
+
+static ctf_id_t
+gen_ctf_typedef (ctf_container_ref ctfc, dw_die_ref tdef)
+{
+  ctf_id_t tdef_type_id, tid;
+  const char *tdef_name = get_AT_string (tdef, DW_AT_name);
+  dw_die_ref tdef_type = ctf_get_AT_type (tdef);
+
+  tid = gen_ctf_type (ctfc, tdef_type);
+
+  /* Type de-duplication.
+     This is necessary because the ctf for the typedef may have been already
+     added due to the gen_ctf_type call above.  */
+  if (!ctf_type_exists (ctfc, tdef, &tdef_type_id))
+  {
+    tdef_type_id = ctf_add_typedef (ctfc, CTF_ADD_ROOT,
+				    tdef_name,
+				    tid,
+				    tdef);
+  }
+  return tdef_type_id;
+}
+
+/* Generate CTF for a type modifier.
+
+   If the given DIE doesn't represent a modifier supported by CTF then
+   this function returns CTF_NULL_TYPEID.  */
+
+static ctf_id_t
+gen_ctf_modifier_type (ctf_container_ref ctfc, dw_die_ref modifier)
+{
+  int kind;
+  ctf_id_t modifier_type_id, qual_type_id;
+  dw_die_ref qual_type = ctf_get_AT_type (modifier);
+
+  switch (modifier->die_tag)
+    {
+    case DW_TAG_const_type: kind = CTF_K_CONST; break;
+    case DW_TAG_volatile_type: kind = CTF_K_VOLATILE; break;
+    case DW_TAG_restrict_type: kind = CTF_K_RESTRICT; break;
+    default:
+      return CTF_NULL_TYPEID;
+    }
+
+  /* Register the type for which this modifier applies.  */
+  qual_type_id = gen_ctf_type (ctfc, qual_type);
+
+  /* Now register the modifier itself.  */
+  if (!ctf_type_exists (ctfc, modifier, &modifier_type_id))
+    modifier_type_id = ctf_add_reftype (ctfc, CTF_ADD_ROOT,
+					qual_type_id, kind,
+					modifier);
+
+  return modifier_type_id;
+}
+
+/* Generate CTF for a struct type.  */
+
+static ctf_id_t
+gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, int kind)
+{
+  uint32_t bit_size = ctf_die_bitsize (sou);
+  int declaration_p = get_AT_flag (sou, DW_AT_declaration);
+  const char *sou_name = get_AT_string (sou, DW_AT_name);
+
+  ctf_id_t sou_type_id;
+
+  /* An incomplete structure or union type is represented in DWARF by
+     a structure or union DIE that does not have a size attribute and
+     that has a DW_AT_declaration attribute.  This corresponds to a
+     CTF forward type with kind CTF_K_STRUCT.  */
+  if (bit_size == 0 && declaration_p)
+    return ctf_add_forward (ctfc, CTF_ADD_ROOT,
+			    sou_name, kind, sou);
+
+  /* This is a complete struct or union type.  Generate a CTF type for
+     it if it doesn't exist already.  */
+  if (!ctf_type_exists (ctfc, sou, &sou_type_id))
+    sou_type_id = ctf_add_sou (ctfc, CTF_ADD_ROOT,
+			       sou_name, kind, bit_size / 8,
+			       sou);
+
+  /* Now process the struct members.  */
+  {
+    dw_die_ref c;
+
+    c = sou->die_child;
+    if (c)
+      do
+	{
+	  const char *field_name;
+	  dw_die_ref field_type;
+	  HOST_WIDE_INT field_location;
+	  ctf_id_t field_type_id;
+
+	  c = c->die_sib;
+
+	  field_name = get_AT_string (c, DW_AT_name);
+	  field_type = ctf_get_AT_type (c);
+
+	  /* The field location (in bits) can be determined from
+	     either a DW_AT_data_member_location attribute or a
+	     DW_AT_data_bit_offset attribute.  */
+	  if (get_AT (c, DW_AT_data_bit_offset))
+	    field_location = get_AT_unsigned (c, DW_AT_data_bit_offset);
+	  else
+	    field_location = (get_AT_unsigned (c,
+					       DW_AT_data_member_location)
+			      * 8);
+
+	  /* Generate the field type.  */
+	  field_type_id = gen_ctf_type (ctfc, field_type);
+
+	  /* If this is a bit-field, then wrap the field type
+	     generated above with a CTF slice.  */
+	  if (get_AT (c, DW_AT_bit_offset)
+	      || get_AT (c, DW_AT_data_bit_offset))
+	    {
+	      dw_attr_node *attr;
+	      HOST_WIDE_INT bitpos = 0;
+	      HOST_WIDE_INT bitsize = ctf_die_bitsize (c);
+	      HOST_WIDE_INT bit_offset;
+
+	      /* The bit offset is given in bits and it may be
+		 negative.  */
+	      attr = get_AT (c, DW_AT_bit_offset);
+	      if (attr)
+		{
+		  if (AT_class (attr) == dw_val_class_unsigned_const)
+		    bit_offset = AT_unsigned (attr);
+		  else
+		    bit_offset = AT_int (attr);
+
+		  if (BYTES_BIG_ENDIAN)
+		    bitpos = field_location + bit_offset;
+		  else
+		    {
+		      HOST_WIDE_INT bit_size;
+
+		      attr = get_AT (c, DW_AT_byte_size);
+		      if (attr)
+			/* Explicit size given in bytes.  */
+			bit_size = AT_unsigned (attr) * 8;
+		      else
+			/* Infer the size from the member type.  */
+			bit_size = ctf_die_bitsize (field_type);
+
+		      bitpos = (field_location
+				+ bit_size
+				- bit_offset
+				- bitsize);
+		    }
+		}
+
+	      /* In DWARF5 a data_bit_offset attribute is given with
+		 the offset of the data from the beginning of the
+		 struct.  Acknowledge it if present.  */
+	      attr = get_AT (c, DW_AT_data_bit_offset);
+	      if (attr)
+		bitpos += AT_unsigned (attr);
+
+	      field_type_id = ctf_add_slice (ctfc, CTF_ADD_NONROOT,
+					     field_type_id,
+					     bitpos - field_location,
+					     bitsize,
+					     c);
+	    }
+
+	  /* Add the field type to the struct or union type.  */
+	  ctf_add_member_offset (ctfc, sou,
+				 field_name,
+				 field_type_id,
+				 field_location);
+	}
+      while (c != sou->die_child);
+  }
+
+  return sou_type_id;
+}
+
+/* Generate CTF for a function type.  */
+
+static ctf_id_t
+gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref function,
+		       bool from_global_func)
+{
+  const char *function_name = get_AT_string (function, DW_AT_name);
+  dw_die_ref return_type = ctf_get_AT_type (function);
+
+  ctf_func_arg_t * argv_ids;
+  ctf_funcinfo_t func_info;
+  uint32_t num_args = 0;
+
+  ctf_id_t return_type_id;
+  ctf_id_t function_type_id;
+
+  /* First, add the return type.  */
+  return_type_id = gen_ctf_type (ctfc, return_type);
+  func_info.ctc_return = return_type_id;
+
+  /* Do a first pass on the formals to determine the number of
+     arguments, and whether the function type gets a varargs.  */
+  {
+    dw_die_ref c;
+
+    c = function->die_child;
+    if (c)
+      do
+	{
+	  c = c->die_sib;
+
+	  if (c->die_tag == DW_TAG_formal_parameter)
+	    num_args += 1;
+	  else if (c->die_tag == DW_TAG_unspecified_parameters)
+	    {
+	      func_info.ctc_flags |= CTF_FUNC_VARARG;
+	      num_args += 1;
+	    }
+	}
+      while (c != function->die_child);
+  }
+
+  /* Note the number of typed arguments _includes_ the vararg.  */
+  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);
+
+  /* Second pass on formals: generate the CTF types corresponding to
+     them and add them to `argv_ids'.  */
+  {
+    dw_die_ref c;
+    unsigned int i = 0;
+
+    c = function->die_child;
+    if (c)
+      do
+	{
+	  c = c->die_sib;
+
+	  if (c->die_tag == DW_TAG_unspecified_parameters)
+	    {
+	      gcc_assert (i == num_args - 1);
+	      argv_ids[i++].farg_type = 0;
+	    }
+	  else if (c->die_tag == DW_TAG_formal_parameter)
+	    {
+	      argv_ids[i++].farg_type = gen_ctf_type (ctfc,
+						      ctf_get_AT_type (c));
+	    }
+	  else
+	    /* This is a local variable.  Ignore.  */
+	    continue;
+	}
+      while (c != function->die_child);
+  }
+
+  /* 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.  */
+  if (ctf_type_exists (ctfc, function, &function_type_id))
+    argv_ids = NULL;
+  else
+    function_type_id = ctf_add_function (ctfc, CTF_ADD_ROOT,
+					 function_name,
+					 (const ctf_funcinfo_t *)&func_info,
+					 argv_ids,
+					 function,
+					 from_global_func);
+
+  return function_type_id;
+}
+
+/* Generate CTF for an enumeration type.  */
+
+static ctf_id_t
+gen_ctf_enumeration_type (ctf_container_ref ctfc, dw_die_ref enumeration)
+{
+  const char *enum_name = get_AT_string (enumeration, DW_AT_name);
+  unsigned int bit_size = ctf_die_bitsize (enumeration);
+  int declaration_p = get_AT_flag (enumeration, DW_AT_declaration);
+
+  ctf_id_t enumeration_type_id;
+
+  /* If this is an incomplete enum, generate a CTF forward for it and
+     be done.  */
+  if (declaration_p)
+    {
+      gcc_assert (enum_name);
+      return ctf_add_forward (ctfc, CTF_ADD_ROOT, enum_name,
+			      CTF_K_ENUM, enumeration);
+    }
+
+  /* If the size the enumerators is not specified then use the size of
+     the underlying type, which must be a base type.  */
+  if (bit_size == 0)
+    {
+      dw_die_ref type = ctf_get_AT_type (enumeration);
+      bit_size = ctf_die_bitsize (type);
+    }
+
+  /* Generate a CTF type for the enumeration.  */
+  enumeration_type_id = ctf_add_enum (ctfc, CTF_ADD_ROOT,
+				      enum_name, bit_size / 8, enumeration);
+
+  /* Process the enumerators.  */
+  {
+    dw_die_ref c;
+
+    c = enumeration->die_child;
+    if (c)
+      do
+	{
+	  const char *enumerator_name;
+	  dw_attr_node *enumerator_value;
+	  HOST_WIDE_INT value_wide_int;
+
+	  c = c->die_sib;
+
+	  enumerator_name = get_AT_string (c, DW_AT_name);
+	  enumerator_value = get_AT (c, DW_AT_const_value);
+
+	  /* enumerator_value can be either a signed or an unsigned
+	     constant value.  */
+	  if (AT_class (enumerator_value) == dw_val_class_unsigned_const
+	      || AT_class (enumerator_value) == dw_val_class_unsigned_const_implicit)
+	    value_wide_int = AT_unsigned (enumerator_value);
+	  else
+	    value_wide_int = AT_int (enumerator_value);
+
+	  ctf_add_enumerator (ctfc, enumeration_type_id,
+			      enumerator_name, value_wide_int, enumeration);
+	}
+      while (c != enumeration->die_child);
+  }
+
+  return enumeration_type_id;
+}
+
+/* Add a CTF variable record for the given input DWARF DIE.  */
+
+static void
+gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
+{
+  const char *var_name = get_AT_string (die, DW_AT_name);
+  dw_die_ref var_type = ctf_get_AT_type (die);
+  ctf_id_t var_type_id;
+
+  /* Avoid duplicates.  */
+  if (ctf_dvd_lookup (ctfc, die))
+    return;
+
+  /* Add the type of the variable.  */
+  var_type_id = gen_ctf_type (ctfc, var_type);
+
+  /* Generate the new CTF variable and update global counter.  */
+  (void) ctf_add_variable (ctfc, var_name, var_type_id, die);
+  ctfc->ctfc_num_global_objts += 1;
+}
+
+/* Add a CTF function record for the given input DWARF DIE.  */
+
+static void
+gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die)
+{
+  /* Add the type of the function and update the global functions
+     counter.  Note that DWARF encodes function types in both
+     DW_tag_subroutine_type and DW_tag_subprogram in exactly the same
+     way.  */
+  (void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
+  ctfc->ctfc_num_global_funcs += 1;
+}
+
+/* Add CTF type record(s) for the given input DWARF DIE and return its type id.
+
+   If there is already a CTF type corresponding to the given DIE, then
+   this function returns the type id of the existing type.
+
+   If the given DIE is not recognized as a type, then this function
+   returns CTF_NULL_TYPEID.  */
+
+static ctf_id_t
+gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
+{
+  ctf_id_t type_id;
+
+  if (ctf_type_exists (ctfc, die, &type_id))
+    return type_id;
+
+  switch (die->die_tag)
+    {
+    case DW_TAG_base_type:
+      type_id = gen_ctf_base_type (ctfc, die);
+      break;
+    case DW_TAG_pointer_type:
+      type_id = gen_ctf_pointer_type (ctfc, die);
+      break;
+    case DW_TAG_typedef:
+      type_id = gen_ctf_typedef (ctfc, die);
+      break;
+    case DW_TAG_array_type:
+      type_id = gen_ctf_array_type (ctfc, die);
+      break;
+    case DW_TAG_structure_type:
+      type_id = gen_ctf_sou_type (ctfc, die, CTF_K_STRUCT);
+      break;
+    case DW_TAG_union_type:
+      type_id = gen_ctf_sou_type (ctfc, die, CTF_K_UNION);
+      break;
+    case DW_TAG_subroutine_type:
+      type_id = gen_ctf_function_type (ctfc, die,
+				       false /* from_global_func */);
+      break;
+    case DW_TAG_enumeration_type:
+      type_id = gen_ctf_enumeration_type (ctfc, die);
+      break;
+    case DW_TAG_const_type:
+      /* FALLTHROUGH */
+    case DW_TAG_restrict_type:
+      /* FALLTHROUGH */
+    case DW_TAG_volatile_type:
+      type_id = gen_ctf_modifier_type (ctfc, die);
+      break;
+    case DW_TAG_unspecified_type:
+      {
+	const char *name = get_AT_string (die, DW_AT_name);
+
+	if (name && strcmp (name, "void") == 0)
+	  type_id = gen_ctf_void_type (ctfc);
+	else
+	  type_id = CTF_NULL_TYPEID;
+
+	break;
+      }
+    default:
+      /* Unrecognized DIE.  */
+      type_id = CTF_NULL_TYPEID;
+      break;
+    }
+
+  return type_id;
+}
+
+bool
+ctf_do_die (dw_die_ref die)
+{
+  ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
+
+  /* Note how we tell the caller to continue traversing children DIEs
+     if this DIE didn't result in CTF records being added.  */
+  if (die->die_tag == DW_TAG_variable)
+    {
+      gen_ctf_variable (tu_ctfc, die);
+      return false;
+    }
+  else if (die->die_tag == DW_TAG_subprogram)
+    {
+      gen_ctf_function (tu_ctfc, die);
+      return false;
+    }
+  else
+    return gen_ctf_type (tu_ctfc, die) == CTF_NULL_TYPEID;
+}
+
+void
+ctf_debug_init (void)
+{
+  /* First, initialize the CTF subsystem.  */
+  ctf_init ();
+
+  /* Create a couple of DIE structures that we may need.  */
+  ctf_void_die = new_die_raw (DW_TAG_unspecified_type);
+  add_name_attribute (ctf_void_die, "void");
+  ctf_array_index_die
+    = base_type_die (integer_type_node, 0 /* reverse */);
+  add_name_attribute (ctf_array_index_die, "int");
+}
+
+void
+ctf_debug_finalize (const char *filename)
+{
+  /* Emit the collected CTF information.  */
+  ctf_output (filename);
+
+  /* Reset the CTF state.  */
+  ctf_finalize ();
+}
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 77ea4948d5e..e8865faeac0 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -79,6 +79,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "expr.h"
 #include "dwarf2out.h"
+#include "ctfout.h"
 #include "dwarf2asm.h"
 #include "toplev.h"
 #include "md5.h"
@@ -27889,7 +27890,7 @@ dwarf2out_source_line (unsigned int line, unsigned int column,
   dw_line_info_table *table;
   static var_loc_view lvugid;
 
-  if (debug_info_level < DINFO_LEVEL_TERSE)
+  if (debug_info_level < DINFO_LEVEL_TERSE || write_symbols == CTF_DEBUG)
     return;
 
   table = cur_line_info_table;
@@ -31366,6 +31367,10 @@ dwarf2out_finish (const char *filename)
   unsigned char checksum[16];
   char dl_section_ref[MAX_ARTIFICIAL_LABEL_BYTES];
 
+  /* Skip emitting DWARF if CTF is to be generated.  */
+  if (write_symbols == CTF_DEBUG)
+    return;
+
   /* Flush out any latecomers to the limbo party.  */
   flush_limbo_die_list ();
 
@@ -32091,6 +32096,17 @@ note_variable_value (dw_die_ref die)
   FOR_EACH_CHILD (die, c, note_variable_value (c));
 }
 
+static void
+debug_format_do_cu (dw_die_ref die)
+{
+  dw_die_ref c;
+
+  if (!ctf_do_die (die))
+    return;
+
+  FOR_EACH_CHILD (die, c, ctf_do_die (c));
+}
+
 /* Perform any cleanups needed after the early debug generation pass
    has run.  */
 
@@ -32213,6 +32229,16 @@ dwarf2out_early_finish (const char *filename)
       print_die (comp_unit_die (), dump_file);
     }
 
+  /* Emit CTF debug info.  */
+  if (ctf_debug_info_level > CTFINFO_LEVEL_NONE && lang_GNU_C ())
+    {
+      ctf_debug_init ();
+      debug_format_do_cu (comp_unit_die ());
+      for (limbo_die_node *node = limbo_die_list; node; node = node->next) 
+	debug_format_do_cu (node->die);
+      ctf_debug_finalize (filename);
+    }
+
   /* Do not generate DWARF assembler now when not producing LTO bytecode.  */
   if ((!flag_generate_lto && !flag_generate_offload)
       /* FIXME: Disable debug info generation for (PE-)COFF targets since the
@@ -32431,4 +32457,8 @@ dwarf2out_c_finalize (void)
   init_sections_and_labels_generation = 0;
 }
 
+/* Include debug format support.  */
+
+#include "dwarf2ctf.c"
+
 #include "gt-dwarf2out.h"
diff --git a/gcc/final.c b/gcc/final.c
index daae115fef5..0e8af842597 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1442,7 +1442,8 @@ asm_str_count (const char *templ)
 static bool
 dwarf2_debug_info_emitted_p (tree decl)
 {
-  if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG)
+  if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
+      && write_symbols != CTF_DEBUG && write_symbols != CTF_AND_DWARF2_DEBUG)
     return false;
 
   if (DECL_IGNORED_P (decl))
@@ -2333,6 +2334,7 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 	  if (debug_info_level == DINFO_LEVEL_NORMAL
 	      || debug_info_level == DINFO_LEVEL_VERBOSE
 	      || write_symbols == DWARF2_DEBUG
+	      || write_symbols == CTF_AND_DWARF2_DEBUG
 	      || write_symbols == VMS_AND_DWARF2_DEBUG
 	      || write_symbols == VMS_DEBUG)
 	    {
@@ -2371,6 +2373,7 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 	  if (debug_info_level == DINFO_LEVEL_NORMAL
 	      || debug_info_level == DINFO_LEVEL_VERBOSE
 	      || write_symbols == DWARF2_DEBUG
+	      || write_symbols == CTF_AND_DWARF2_DEBUG
 	      || write_symbols == VMS_AND_DWARF2_DEBUG
 	      || write_symbols == VMS_DEBUG)
 	    {
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index a038c8fb738..d3b3b1a9fd2 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -29,8 +29,10 @@ enum debug_info_type
   DWARF2_DEBUG,	    /* Write Dwarf v2 debug info (using dwarf2out.c).  */
   XCOFF_DEBUG,	    /* Write IBM/Xcoff debug info (using dbxout.c).  */
   VMS_DEBUG,        /* Write VMS debug info (using vmsdbgout.c).  */
-  VMS_AND_DWARF2_DEBUG /* Write VMS debug info (using vmsdbgout.c).
-                          and DWARF v2 debug info (using dwarf2out.c).  */
+  CTF_DEBUG,	    /* Write CTF debug info (using ctfout.c).  */
+  VMS_AND_DWARF2_DEBUG, /* Write VMS debug info (using vmsdbgout.c).
+                           and DWARF v2 debug info (using dwarf2out.c).  */
+  CTF_AND_DWARF2_DEBUG /* Write both CTF and DWARF v2 debug info.  */
 };
 
 enum debug_info_levels
@@ -107,6 +109,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/gengtype.c b/gcc/gengtype.c
index 5f50242e857..131dc703637 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1727,7 +1727,7 @@ open_base_files (void)
       "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", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
-      "symtab-clones.h",
+      "symtab-clones.h", "ctfout.h",
       NULL
     };
     const char *const *ifp;
diff --git a/gcc/opts.c b/gcc/opts.c
index 1f1cf8388f7..031f026fe32 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -40,7 +40,7 @@ static void set_Wstrict_aliasing (struct gcc_options *opts, int onoff);
 /* Indexed by enum debug_info_type.  */
 const char *const debug_type_names[] =
 {
-  "none", "stabs", "dwarf-2", "xcoff", "vms"
+  "none", "stabs", "dwarf-2", "xcoff", "vms", "ctf"
 };
 
 /* Parse the -femit-struct-debug-detailed option value
@@ -194,6 +194,10 @@ 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,
+				 struct gcc_options *opts_set,
+				 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);
@@ -2776,6 +2780,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, opts_set, loc);
+      break;
+
     case OPT_g:
       set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set,
                        loc);
@@ -3029,7 +3037,10 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
 	  if (extended == 2)
 	    {
 #if defined DWARF2_DEBUGGING_INFO || defined DWARF2_LINENO_DEBUGGING_INFO
-	      opts->x_write_symbols = DWARF2_DEBUG;
+	      if (opts->x_write_symbols == CTF_DEBUG)
+		opts->x_write_symbols = CTF_AND_DWARF2_DEBUG;
+	      else
+		opts->x_write_symbols = DWARF2_DEBUG;
 #elif defined DBX_DEBUGGING_INFO
 	      opts->x_write_symbols = DBX_DEBUG;
 #endif
@@ -3038,9 +3049,25 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
 	  if (opts->x_write_symbols == NO_DEBUG)
 	    warning_at (loc, 0, "target system does not support debug output");
 	}
+      else if (opts->x_write_symbols == CTF_DEBUG)
+	{
+	  opts->x_write_symbols = CTF_AND_DWARF2_DEBUG;
+	  opts_set->x_write_symbols = CTF_AND_DWARF2_DEBUG;
+	}
     }
   else
     {
+      /* Make and retain the choice of CTF_AND_DWARF2_DEBUG if both CTF and
+	 DWARF debug info are to be generated.  */
+      if ((opts->x_write_symbols == CTF_DEBUG
+	   || opts->x_write_symbols == CTF_AND_DWARF2_DEBUG)
+	  && type == DWARF2_DEBUG)
+	{
+	  opts->x_write_symbols = CTF_AND_DWARF2_DEBUG;
+	  opts_set->x_write_symbols = CTF_AND_DWARF2_DEBUG;
+	}
+      else
+	{
       /* Does it conflict with an already selected type?  */
       if (opts_set->x_write_symbols != NO_DEBUG
 	  && opts->x_write_symbols != NO_DEBUG
@@ -3049,6 +3076,7 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg,
 		  debug_type_names[type]);
       opts->x_write_symbols = type;
       opts_set->x_write_symbols = type;
+	}
     }
 
   /* A debug flag without a level defaults to level 2.
@@ -3071,6 +3099,39 @@ 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, struct gcc_options *opts_set,
+		     location_t loc)
+{
+  opts->x_debug_info_level = DINFO_LEVEL_NORMAL;
+  if (opts->x_write_symbols == DWARF2_DEBUG)
+    {
+      opts->x_write_symbols = CTF_AND_DWARF2_DEBUG;
+      opts_set->x_write_symbols = CTF_AND_DWARF2_DEBUG;
+    }
+  else if (opts->x_write_symbols == NO_DEBUG)
+    {
+      opts->x_write_symbols = CTF_DEBUG;
+      opts_set->x_write_symbols = CTF_DEBUG;
+    }
+
+  /* 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 ().)  */
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index d69c9a2d819..f35939b7d80 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -1961,7 +1961,8 @@ default_debug_unwind_info (void)
 
   /* Otherwise, only turn it on if dwarf2 debugging is enabled.  */
 #ifdef DWARF2_DEBUGGING_INFO
-  if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
+  if (write_symbols == DWARF2_DEBUG || write_symbols == CTF_AND_DWARF2_DEBUG
+      || write_symbols == VMS_AND_DWARF2_DEBUG)
     return UI_DWARF2;
 #endif
 
diff --git a/gcc/toplev.c b/gcc/toplev.c
index a8947a735ff..58eed6c455f 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1229,6 +1229,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;
@@ -1409,6 +1411,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");
@@ -1430,7 +1443,8 @@ process_options (void)
 
   /* A lot of code assumes write_symbols == NO_DEBUG if the debugging
      level is 0.  */
-  if (debug_info_level == DINFO_LEVEL_NONE)
+  if (debug_info_level == DINFO_LEVEL_NONE 
+      && ctf_debug_info_level == CTFINFO_LEVEL_NONE)
     write_symbols = NO_DEBUG;
 
   if (write_symbols == NO_DEBUG)
@@ -1446,6 +1460,8 @@ process_options (void)
 #ifdef DWARF2_DEBUGGING_INFO
   else if (write_symbols == DWARF2_DEBUG)
     debug_hooks = &dwarf2_debug_hooks;
+  else if (write_symbols == CTF_DEBUG || write_symbols == CTF_AND_DWARF2_DEBUG)
+    debug_hooks = &dwarf2_debug_hooks;
 #endif
 #ifdef VMS_DEBUGGING_INFO
   else if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
@@ -1462,7 +1478,7 @@ process_options (void)
 
   /* We know which debug output will be used so we can set flag_var_tracking
      and flag_var_tracking_uninit if the user has not specified them.  */
-  if (debug_info_level < DINFO_LEVEL_NORMAL
+  if (debug_info_level < DINFO_LEVEL_NORMAL || write_symbols == CTF_DEBUG
       || debug_hooks->var_location == do_nothing_debug_hooks.var_location)
     {
       if (flag_var_tracking == 1
@@ -1520,6 +1536,7 @@ process_options (void)
       = (optimize
 	 && debug_info_level >= DINFO_LEVEL_NORMAL
 	 && (write_symbols == DWARF2_DEBUG
+	     || write_symbols == CTF_AND_DWARF2_DEBUG
 	     || write_symbols == VMS_AND_DWARF2_DEBUG)
 	 && !(flag_selective_scheduling || flag_selective_scheduling2));
 
diff --git a/include/ctf.h b/include/ctf.h
new file mode 100644
index 00000000000..750f1beb013
--- /dev/null
+++ b/include/ctf.h
@@ -0,0 +1,513 @@
+/* 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 | 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
+   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.
+
+   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.  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.  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
+   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_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.  */
+  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 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
+# define CTF_VERSION_2 3
+
+/* Note: some flags may be valid only in particular format versions.  */
+
+#define CTF_VERSION_3 4
+#define CTF_VERSION CTF_VERSION_3 /* Current version.  */
+
+#define CTF_F_COMPRESS	0x1	/* Data buffer is compressed by libctf.  */
+#define CTF_F_NEWFUNCINFO 0x2	/* New v3 func info section format.  */
+
+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)
+#define CTF_SET_STID(name, stid)	((name) | (stid) << 31)
+
+/* 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.
+
+   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 short cts_offset;
+  unsigned short 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 */
diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c
index 6d70b95a00b..909995dd166 100644
--- a/libiberty/simple-object.c
+++ b/libiberty/simple-object.c
@@ -304,6 +304,9 @@ handle_lto_debug_sections (const char *name, int rename)
   /* Copy over .GCC.command.line section under the same name if present.  */
   else if (strcmp (name, ".GCC.command.line") == 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;
 }
-- 
2.25.0.2.g232378479e


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

* [PATCH 3/4] CTF testsuite
  2021-01-22 11:01 [PATCH 0/4] Support for the CTF debug format Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 1/4] Add new function lang_GNU_GIMPLE Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 2/4] CTF debug format Jose E. Marchesi
@ 2021-01-22 11:01 ` Jose E. Marchesi
  2021-01-22 11:01 ` [PATCH 4/4] CTF documentation Jose E. Marchesi
  3 siblings, 0 replies; 5+ messages in thread
From: Jose E. Marchesi @ 2021-01-22 11:01 UTC (permalink / raw)
  To: gcc-patches

This commit adds a new testsuite for the CTF debug format.

2021-01-22  Indu Bhagat  <indu.bhagat@oracle.com>

gcc/testsuite/

	* gcc.dg/debug/ctf/ctf-1.c: New test.
	* gcc.dg/debug/ctf/ctf-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-anonymous-struct-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-anonymous-union-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-array-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-array-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-array-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-array-4.c: Likewise.
	* gcc.dg/debug/ctf/ctf-attr-mode-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-attr-used-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-bitfields-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-bitfields-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-bitfields-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-bitfields-4.c: Likewise.
	* gcc.dg/debug/ctf/ctf-complex-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-cvr-quals-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-cvr-quals-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-cvr-quals-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-cvr-quals-4.c: Likewise.
	* gcc.dg/debug/ctf/ctf-enum-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-enum-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-file-scope-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-float-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-forward-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-forward-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-func-index-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-function-pointers-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-function-pointers-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-function-pointers-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-functions-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-int-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-objt-index-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-pointers-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-pointers-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-preamble-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-skip-types-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-skip-types-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-skip-types-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-skip-types-4.c: Likewise.
	* gcc.dg/debug/ctf/ctf-skip-types-5.c: Likewise.
	* gcc.dg/debug/ctf/ctf-skip-types-6.c: Likewise.
	* gcc.dg/debug/ctf/ctf-str-table-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-array-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-pointer-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-struct-pointer-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-struct-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-struct-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf-typedef-struct-3.c: Likewise.
	* gcc.dg/debug/ctf/ctf-union-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-variables-1.c: Likewise.
	* gcc.dg/debug/ctf/ctf-variables-2.c: Likewise.
	* gcc.dg/debug/ctf/ctf.exp: Likewise.
	* gcc.dg/debug/dwarf2-ctf-1.c: Likewise.
---
 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  | 38 +++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-3.c  | 17 +++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-4.c  | 13 ++++
 .../gcc.dg/debug/ctf/ctf-attr-mode-1.c        | 22 ++++++
 .../gcc.dg/debug/ctf/ctf-attr-used-1.c        | 22 ++++++
 .../gcc.dg/debug/ctf/ctf-bitfields-1.c        | 30 ++++++++
 .../gcc.dg/debug/ctf/ctf-bitfields-2.c        | 39 +++++++++++
 .../gcc.dg/debug/ctf/ctf-bitfields-3.c        | 16 +++++
 .../gcc.dg/debug/ctf/ctf-bitfields-4.c        | 19 ++++++
 .../gcc.dg/debug/ctf/ctf-complex-1.c          | 22 ++++++
 .../gcc.dg/debug/ctf/ctf-cvr-quals-1.c        | 65 ++++++++++++++++++
 .../gcc.dg/debug/ctf/ctf-cvr-quals-2.c        | 30 ++++++++
 .../gcc.dg/debug/ctf/ctf-cvr-quals-3.c        | 25 +++++++
 .../gcc.dg/debug/ctf/ctf-cvr-quals-4.c        | 23 +++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-1.c   | 21 ++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c   | 27 ++++++++
 .../gcc.dg/debug/ctf/ctf-file-scope-1.c       | 25 +++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c  | 16 +++++
 .../gcc.dg/debug/ctf/ctf-forward-1.c          | 40 +++++++++++
 .../gcc.dg/debug/ctf/ctf-forward-2.c          | 16 +++++
 .../gcc.dg/debug/ctf/ctf-func-index-1.c       | 25 +++++++
 .../debug/ctf/ctf-function-pointers-1.c       | 24 +++++++
 .../debug/ctf/ctf-function-pointers-2.c       | 22 ++++++
 .../debug/ctf/ctf-function-pointers-3.c       | 21 ++++++
 .../gcc.dg/debug/ctf/ctf-functions-1.c        | 34 ++++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-int-1.c    | 17 +++++
 .../gcc.dg/debug/ctf/ctf-objt-index-1.c       | 30 ++++++++
 .../gcc.dg/debug/ctf/ctf-pointers-1.c         | 26 +++++++
 .../gcc.dg/debug/ctf/ctf-pointers-2.c         | 25 +++++++
 .../gcc.dg/debug/ctf/ctf-preamble-1.c         | 11 +++
 .../gcc.dg/debug/ctf/ctf-skip-types-1.c       | 33 +++++++++
 .../gcc.dg/debug/ctf/ctf-skip-types-2.c       | 17 +++++
 .../gcc.dg/debug/ctf/ctf-skip-types-3.c       | 20 ++++++
 .../gcc.dg/debug/ctf/ctf-skip-types-4.c       | 19 ++++++
 .../gcc.dg/debug/ctf/ctf-skip-types-5.c       | 19 ++++++
 .../gcc.dg/debug/ctf/ctf-skip-types-6.c       | 18 +++++
 .../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 | 32 +++++++++
 .../gcc.dg/debug/ctf/ctf-struct-array-1.c     | 65 ++++++++++++++++++
 .../gcc.dg/debug/ctf/ctf-struct-pointer-1.c   | 21 ++++++
 .../gcc.dg/debug/ctf/ctf-struct-pointer-2.c   | 22 ++++++
 .../gcc.dg/debug/ctf/ctf-typedef-1.c          | 68 +++++++++++++++++++
 .../gcc.dg/debug/ctf/ctf-typedef-2.c          | 20 ++++++
 .../gcc.dg/debug/ctf/ctf-typedef-3.c          | 24 +++++++
 .../gcc.dg/debug/ctf/ctf-typedef-struct-1.c   | 14 ++++
 .../gcc.dg/debug/ctf/ctf-typedef-struct-2.c   | 17 +++++
 .../gcc.dg/debug/ctf/ctf-typedef-struct-3.c   | 32 +++++++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf-union-1.c  | 14 ++++
 .../gcc.dg/debug/ctf/ctf-variables-1.c        | 25 +++++++
 .../gcc.dg/debug/ctf/ctf-variables-2.c        | 16 +++++
 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp        | 41 +++++++++++
 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c     |  7 ++
 58 files changed, 1452 insertions(+)
 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-array-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-array-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-used-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-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-file-scope-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-float-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-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-function-pointers-3.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-pointers-2.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-skip-types-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-5.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-6.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-struct-pointer-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-pointer-2.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-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-3.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-typedef-struct-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-3.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-variables-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf.exp
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2-ctf-1.c

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 00000000000..1be0dfb0e65
--- /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-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-2.c
new file mode 100644
index 00000000000..891f20ed85d
--- /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 00000000000..0973b2b8882
--- /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 00000000000..71b491ab109
--- /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 00000000000..cd342b1b23d
--- /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
+   buf : 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 00000000000..abadc646378
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-2.c
@@ -0,0 +1,38 @@
+/* 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" 5 } } */
+
+/* { 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-array-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-3.c
new file mode 100644
index 00000000000..77a33ada7c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-3.c
@@ -0,0 +1,17 @@
+/* CTF generation for variable length arrays.
+
+   In this testcase, a specific flavor of vla appears in the function
+   signature.
+
+   TBD_CTF_FORMAT_OPEN_ISSUES (1) -
+   This testcase makes a note of another case of a probable misrepresentation.
+   See ctf-array-2.c for some context on how vla's are a case of a probable
+   misrepresentation in CTF.  Nevertheless, compilation should not fail.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+
+int foo (int a, int b[a][a])
+{
+  return b[a-1][a-3];
+}
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-4.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-4.c
new file mode 100644
index 00000000000..042023d75c8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-array-4.c
@@ -0,0 +1,13 @@
+/* CTF generation for array type.
+
+   Test CTF generation for single element arrays.  In this testcase, one CTF
+   record for array is expected with cta_nelems = 1.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "0x12000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*cta_nelems" 1 } } */
+
+int b[1];
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c
new file mode 100644
index 00000000000..4bb67ef67bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-mode-1.c
@@ -0,0 +1,22 @@
+/* Test CTF generation works well with ((mode)) attribute.
+
+   In this testcase, CTF should report type of bqi to be an enum and
+   not an int.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"B1.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"B2.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"B3.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "cte_value" 3} } */
+
+/* There are no better/direct methods to assert that the CTF for typedef of
+   enum has been added.  */
+/* { dg-final { scan-assembler-times "\[\t \]0x22000003\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2a000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t \]+\[^\n\]*ctv_typeidx" 1} } */
+
+typedef enum { B1 = 1, B2 = 2, B3 = 3 } B;
+B __attribute__ ((mode (QI))) bqi;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-used-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-used-1.c
new file mode 100644
index 00000000000..0415f3ec300
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-attr-used-1.c
@@ -0,0 +1,22 @@
+/* Test CTF generation works well with ((used)) function attribute.
+
+   This attribute, attached to a function, means that code must be emitted for
+   the function even if it appears that the function is not referenced.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O2 -gt -dA" } */
+
+/* These should be true for higher optimization levels.  */
+/* { dg-final { scan-assembler-times "ascii \"keep_this.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"lose_this.0\"\[\t \]+\[^\n\]*ctf_string" 0 } } */
+
+static int lose_this(int a)
+{
+    return a + 2;
+}
+
+__attribute__((used))
+static int keep_this(double a)
+{
+    return a * 2;
+}
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 00000000000..5f26629dcdf
--- /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 00000000000..ed85cf3d7f3
--- /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 00000000000..dcb6a2a3e17
--- /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 00000000000..e4be6113d1c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-bitfields-4.c
@@ -0,0 +1,19 @@
+/* The zero sized bitfield.
+
+   In this testcase, two slices are expected.  */
+
+/* { 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 \]0x5\[\t \]+\[^\n\]*cts_bits" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xa\[\t \]+\[^\n\]*cts_bits" 1 } } */
+
+/* { dg-final { scan-assembler-times "ctm_name" 2 } } */
+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 00000000000..3d02b8765d1
--- /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 00000000000..f52dc24d95b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-1.c
@@ -0,0 +1,65 @@
+/* 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 5 qualifiers across constructs.  2 more no-name CTF records correspond to
+   CTF pointer records.
+
+    TYPEID: name string (size) -> ref TYPEID : ref name string (size) -> ...
+
+   Types:
+      1: long int (size 0x8)
+      2: long unsigned int (size 0x8)
+      3: size_t (size 0x8) -> 2: long unsigned int (size 0x8)
+      4: int (size 0x4)
+      5: const int (size 0x4) -> 4: int (size 0x4)
+      6: volatile const int (size 0x4) -> 5: const int (size 0x4) -> 4: int (size 0x4)
+      7: long long int (size 0x8)
+      8: long double (size 0x10)
+      9: int * (size 0x8) -> 4: int (size 0x4)
+      a: int *restrict (size 0x8) -> 9: int * (size 0x8) -> 4: int (size 0x4)
+      b: const int * (size 0x8) -> 5: const int (size 0x4) -> 4: int (size 0x4)
+      c: const int *restrict (size 0x8) -> b: const int * (size 0x8) -> 5: const int (size 0x4) -> 4: int (size 0x4)
+      d: INTP (size 0x8) -> 9: int * (size 0x8) -> 4: int (size 0x4)
+      e: const INTP (size 0x8) -> d: INTP (size 0x8) -> 9: int * (size 0x8) -> 4: int (size 0x4)
+      f: void (size 0x0)
+      10: void (*) (size_t, int *restrict, const int *restrict) (size 0x0)
+    */
+
+/* { 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" 7 } } */
+
+/* type id 9, b have POINTER type.  */
+/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+/* type id 5, e have CONST qualifier.  */
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+/* type id a, c have RESTRICT qualifier.  */
+/* { dg-final { scan-assembler-times "\[\t \]0x36000000\[\t \]+\[^\n\]*ctt_info" 2 } } */
+
+/* type id 6 has VOLATILE qualifier.  */
+/* { dg-final { scan-assembler-times "\[\t \]0x2e000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+#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 00000000000..8ce6676319c
--- /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 00000000000..6d42e00a272
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-3.c
@@ -0,0 +1,25 @@
+/* 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.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"unsigned char.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2e000000\[\t \]+\[^\n\]*ctt_info" 5 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 3 } } */
+/* 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 00000000000..5a1f789a2f7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-cvr-quals-4.c
@@ -0,0 +1,23 @@
+/* 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;
+
+how_ent hent;
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 00000000000..d91a4194221
--- /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 00000000000..bf2a08cda61
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-enum-2.c
@@ -0,0 +1,27 @@
+/* CTF generation for enums.
+
+   CTF represents enum values with an int32_t.  For enum values not
+   representable with int32_t data type, the compiler skips adding CTF for
+   them.  This will be fixed soon in the CTF 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-file-scope-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-file-scope-1.c
new file mode 100644
index 00000000000..5c7ad49392e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-file-scope-1.c
@@ -0,0 +1,25 @@
+/* CTF is not generated for entities not at file-scope.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ascii \"SFOO.0\"\[\t \]+\[^\n\]*ctf_string" 0 } } */
+/* { dg-final { scan-assembler-times "ascii \"gfoo.0\"\[\t \]+\[^\n\]*ctf_string" 0 } } */
+/* { dg-final { scan-assembler-times "ascii \"foo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+int foo (int n)
+{
+  typedef struct { int a[n]; } SFOO;
+
+  SFOO a;
+  __attribute__ ((noinline)) SFOO gfoo (void) { return a; }
+
+  a.a[0] = 1;
+  a.a[9] = 2;
+
+  SFOO b;
+  b = gfoo ();
+
+  return b.a[0] == 1 && b.a[9] == 2;
+}
+
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 00000000000..ae2dfc2e401
--- /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 00000000000..9d9b96d6358
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-forward-1.c
@@ -0,0 +1,40 @@
+/* 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" 2 } } */
+
+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;
+
+locale_t loc;
+
+typedef struct __inter_struct
+{
+  union __inter_data * __inters[13]; /* forward union type.  */
+
+  const int * __ctype_kind;
+} * __inter_t;
+
+typedef __inter_t inter_t;
+
+inter_t inter;
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 00000000000..33080f259a2
--- /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-func-index-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-func-index-1.c
new file mode 100644
index 00000000000..4215615bfc9
--- /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 00000000000..30026ea4349
--- /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 00000000000..26b0ec678db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-2.c
@@ -0,0 +1,22 @@
+/* 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
+
+struct callback_head chead;
+
+typedef void (*rcu_callback_t) (struct rcu_head *head);
+
+rcu_callback_t rcb;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-3.c
new file mode 100644
index 00000000000..c97bb168e86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-function-pointers-3.c
@@ -0,0 +1,21 @@
+/* CTF generation of function pointers.
+
+   In this testcase,  there is a single function type expected.  */
+
+/* { 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 \"foo_init_callback.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"fn.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+struct foo;
+
+typedef void (* foo_init_callback) (struct foo *f1);
+
+struct foo
+{
+  /* Function to call to initialize.  */
+  foo_init_callback fn;
+};
+
+struct foo f;
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 00000000000..20bade108f6
--- /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 00000000000..88f2a3aa066
--- /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 00000000000..9196ce88ae0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-objt-index-1.c
@@ -0,0 +1,30 @@
+/* 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, 4 records in the object index section are expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "objtinfo_name" 4 } } */
+/* { dg-final { scan-assembler-times "objtinfo_var_type" 4 } } */
+/* { dg-final { scan-assembler-times "ascii \"a.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"b.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 00000000000..32da7bdd9bd
--- /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-pointers-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-2.c
new file mode 100644
index 00000000000..f7eb13c342c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-pointers-2.c
@@ -0,0 +1,25 @@
+/* CTF generation for pointer types.
+
+   In this testcase, de-duplication of pointer types is exercised.  The
+   compostition of structs in this testcase is such that when adding CTF for
+   pointer type (link), the pointed-to-type type already adds the pointer to
+   struct link.
+   
+   In this testcase, one CTF pointer type record is expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0xe000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+struct link;
+
+typedef struct items {
+    struct link * link; 
+    int str;
+} itemslist;
+
+itemslist il;
+
+struct link { struct link * next; };
+
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 00000000000..476ca80dd65
--- /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-skip-types-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-1.c
new file mode 100644
index 00000000000..bd2935dbee6
--- /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-skip-types-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-2.c
new file mode 100644
index 00000000000..6e0d39e8373
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-2.c
@@ -0,0 +1,17 @@
+/* CTF does not have representation for some types at this time.  These types
+   are skipped in the CTF generation phase in the compiler.
+
+   Skip IEEE interchange and extended formats for CTF generation.
+
+   In this testcase, CTF records for types are not added as CTF has no
+   representation for IEEE interchange and extended formats.
+
+   CTF records for variables do exist, however.  The referenced type is
+   CTF_TYPE_NULLID.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+
+/* { dg-require-effective-target float16 } */
+
+_Float16 f16;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-3.c
new file mode 100644
index 00000000000..e08d142b63e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-3.c
@@ -0,0 +1,20 @@
+/* CTF does not have representation for some types at this time.  These types
+   are skipped in the CTF generation phase in the compiler.
+
+   Skip IEEE interchange and extended formats for CTF generation.
+
+   In this testcase, CTF records for types are not added as CTF has no
+   representation for IEEE interchange and extended formats.
+
+   CTF records for variables and pointer do exist, however.  The referenced
+   type is CTF_TYPE_NULLID.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+
+/* { dg-require-effective-target float32 } */
+/* { dg-require-effective-target float32x } */
+
+_Float32 f32;
+_Float32x f32x;
+_Float32 * f32p;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c
new file mode 100644
index 00000000000..d29bd8bdf54
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-4.c
@@ -0,0 +1,19 @@
+/* CTF does not have representation for some types at this time.  These types
+   are skipped in the CTF generation phase in the compiler.
+
+   Skip IEEE interchange and extended formats for CTF generation.
+
+   In this testcase, CTF records for types are not added as CTF has no
+   representation for IEEE interchange and extended formats.
+
+   CTF records for variables and pointer do exist, however.  The referenced
+   type is CTF_TYPE_NULLID.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+
+/* { dg-require-effective-target float64 } */
+/* { dg-require-effective-target float64x } */
+
+_Float64 f64;
+_Float64x f64x;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-5.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-5.c
new file mode 100644
index 00000000000..37a2a899c55
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-5.c
@@ -0,0 +1,19 @@
+/* CTF does not have representation for some types at this time.  These types
+   are skipped in the CTF generation phase in the compiler.
+
+   Skip IEEE interchange and extended formats for CTF generation.
+
+   In this testcase, CTF records for types are not added as CTF has no
+   representation for IEEE interchange and extended formats.
+
+   CTF records for variables and pointer do exist, however.  The referenced
+   type is CTF_TYPE_NULLID.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+
+/* { dg-require-effective-target float128 } */
+/* { dg-require-effective-target float128x } */
+
+_Float128 f128;
+_Float128x f128x;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-6.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-6.c
new file mode 100644
index 00000000000..ffdfb017ce1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-skip-types-6.c
@@ -0,0 +1,18 @@
+/* CTF does not have representation for some types at this time.  These types
+   are skipped in the CTF generation phase in the compiler.
+
+   Skip Decimal Floating Point format types for CTF generation.
+
+   In this testcase, CTF records for types are not added as CTF has no
+   representation for Decimal floating point format.
+
+   CTF records for variables do exist, however.  The referenced type is
+   CTF_TYPE_NULLID.  */
+
+/* { dg-do compile } */
+/* { dg-options "-gt" } */
+/* { dg-require-effective-target dfp } */
+
+_Decimal32 d32;
+_Decimal64 d64;
+_Decimal128 d128;
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 00000000000..2c5e3527109
--- /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 00000000000..5d496d83efc
--- /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 00000000000..84b41fd246b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-2.c
@@ -0,0 +1,32 @@
+/* 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;
+
+dmx_bundle_t dbt;
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 00000000000..cb3f8864fb3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-array-1.c
@@ -0,0 +1,65 @@
+/* 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 the time of CTF generation).
+   
+   const qualifier in fields of structs should be processed.  It appears as a
+   no-name CTF record with appropriate ctt_info.  In this testcase, there are
+   two const qualifiers - const char and const struct cmodel.  However, due to
+   way the debug information is represented in DWARF die, 3 const qualifier
+   records appear in the CTF section.
+
+   <1><e1>: Abbrev Number: 14 (DW_TAG_typedef)
+      <e2>   DW_AT_name        : (indirect string, offset: 0x114): cmodel_t
+      <e9>   DW_AT_type        : <0x9a>
+   <1><ed>: Abbrev Number: 13 (DW_TAG_const_type)
+      <ee>   DW_AT_type        : <0xe1>
+   <1><f2>: Abbrev Number: 4 (DW_TAG_array_type)
+      <f3>   DW_AT_type        : <0xed>
+      <f7>   DW_AT_sibling     : <0x102>
+
+   <2><101>: Abbrev Number: 0
+   <1><102>: Abbrev Number: 13 (DW_TAG_const_type)
+      <103>   DW_AT_type        : <0xf2>
+   <1><107>: Abbrev Number: 15 (DW_TAG_variable)
+      <108>   DW_AT_name        : (indirect string, offset: 0x57): _models
+      <10f>   DW_AT_type        : <0x102>
+   <1><11d>: Abbrev Number: 0
+
+   This results in:
+
+   _models ->  e: const const cmodel_t [3] (size 0x30) -> d: const cmodel_t [3] (size 0x30)
+
+   Deemed as acceptable for now.  */
+
+/* { 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 } } */
+
+/* 3 const records are expected.  */
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 3 } } */
+
+struct a
+{
+  int a1[2];
+  struct { int b[3]; } a2;
+};
+
+struct a my_a;
+
+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-struct-pointer-1.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-pointer-1.c
new file mode 100644
index 00000000000..af8c413e77d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-pointer-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* This tests the following scenario:
+
+   1. struct foo;
+   2. struct foo *a_foo;
+   3. struct foo { int bar; };
+   4. void baz (struct foo *f) { f->bar = 0; }
+
+   At 2. a forward for struct foo is generated and at 3. the struct
+   type is fully defined.  When a pointer to foo is encountered at 4.,
+   an additional CTF type for the completed struct shall be emitted as
+   well.  The linker will deduplicate both types.  */
+
+struct foo;
+struct foo *a_foo;
+struct foo { int bar; };
+void baz (struct foo *f) { f->bar = 0; }
+
+/* { dg-final { scan-assembler-times "\[\t \]\"bar.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-pointer-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-pointer-2.c
new file mode 100644
index 00000000000..f7783f04476
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-struct-pointer-2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* This tests the following scenario:
+
+   1. struct foo;
+   2. struct foo *a_foo;
+   3. struct foo { int bar; };
+   4. void baz (struct foo **f) { f->bar = 0; }
+
+   At 2. a forward for struct foo is generated and at 3. the struct
+   type is fully defined.  When a pointer to a pointer to foo is
+   encountered at 4., an additional CTF type for the completed struct
+   shall be emitted as well.  The linker will deduplicate both
+   types.  */
+
+struct foo;
+struct foo *a_foo;
+struct foo { int bar; };
+void baz (struct foo **f) { (*f)->bar = 0; }
+
+/* { dg-final { scan-assembler-times "\[\t \]\"bar.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
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 00000000000..82642b1bc8b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-1.c
@@ -0,0 +1,68 @@
+/* CTF_K_TYPEDEF record generation.
+
+   In this testcase, 7 typedef records are expected.
+
+   Further, the declared variables must be of type typedef
+
+     Variables:
+	a ->  2: my_int (size 0x4) -> 1: int (size 0x4)
+	b ->  3: bar_int (size 0x4) -> 1: int (size 0x4)
+	c ->  4: foo_int (size 0x4) -> 1: int (size 0x4)
+	d ->  7: my_array (size 0x8) -> 5: struct  (size 0x8)
+	e ->  9: CINT (size 0x4) -> 8: const int (size 0x4) -> 1: int (size 0x4)
+	f ->  c: CINTP (size 0x8) -> b: const int * (size 0x8) -> a: const int (size 0x4) -> 1: int (size 0x4)
+	g ->  f: my_node_t (size 0x8) -> d: struct my_node (size 0x8)
+
+    There is no direct way to check that the variables are of type typedef.
+    So in this testcase, we simply check that:
+    1. The typedef records are generated (Check for 7 specific ctt_info, and
+       check for the ascii strings for the typedef names).
+    2. The ctv_typeidx are distinct (each pointing to a specfic unique type).
+       Note that if variables were not of type typedef, ctv_typeidx will not be
+       unique (type of a, b, c will all point to int); hence, the check.
+   */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "0x2a000000\[\t \]+\[^\n\]*ctt_info" 7 } } */
+/* { dg-final { scan-assembler-times "ascii \"my_int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"bar_int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"foo_int.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"my_array.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"CINT.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"CINTP.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"my_node_t.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x5\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x9\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xa\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xc\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0xf\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+
+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;
+
+my_int a;
+bar_int b;
+foo_int c;
+
+my_array d;
+CINT e = 3;
+CINTP f = &e;
+
+my_node_t g;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-2.c
new file mode 100644
index 00000000000..275985c80da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-2.c
@@ -0,0 +1,20 @@
+/* CTF_K_TYPEDEF record generation.
+
+   In this testcase, typedef of type void should be generated.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "0x2a000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"foo_void_type.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"void.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+typedef void foo_void_type;
+
+struct bar
+{
+  int a;
+  foo_void_type *b;
+};
+
+struct bar c;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-3.c
new file mode 100644
index 00000000000..0b7e3aa0857
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-3.c
@@ -0,0 +1,24 @@
+/* Type de-duplication of CTF_K_TYPEDEF records.
+
+   In this testcase, a single CTF record for typedef is expected.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "0x2a000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"foo_type.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"foo.0\"\[\t \]+\[^\n\]*ctf_string" 1 } } */
+
+typedef struct foo foo_type;
+
+struct bar
+{
+  struct foo * f1;
+  foo_type * f2;
+};
+
+struct testme {
+    struct bar * b1;
+};
+
+struct testme * t1;
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 00000000000..a10ce0eca7b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-1.c
@@ -0,0 +1,14 @@
+/* { 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;
+
+my_int_t mit;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-2.c
new file mode 100644
index 00000000000..092c70a0a80
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-2.c
@@ -0,0 +1,17 @@
+/* Test compilation of typedef composition in structs.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+typedef struct
+{
+  int day, month, year;
+} Date;
+
+typedef struct
+{
+  Date filedDate, fixedDate;
+  int severity;
+} BugRef;
+
+BugRef CR2112;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-3.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-3.c
new file mode 100644
index 00000000000..1f88db503e9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-typedef-struct-3.c
@@ -0,0 +1,32 @@
+/* Test CTF generation for a typedef instantiation with CVR quals.
+
+   Caveat: There is no direct way to test that the type of foo is
+   "const my_int_t" via scanning the assembly. This test instead
+   checks for the presence of some of the CTF constructs involved
+   individually. Specifically, it checks for CTF const record and
+   CTF typedef record.
+
+  Variables:
+      foo ->  4: const my_int_t (size 0x8) -> 3: my_int_t (size 0x8) -> 1: struct my_int (size 0x8)
+
+   Types:
+      1: struct my_int (size 0x8)
+      2: int (size 0x4)
+      3: my_int_t (size 0x8) -> 1: struct my_int (size 0x8)
+      4: const my_int_t (size 0x8) -> 3: my_int_t (size 0x8) -> 1: struct my_int (size 0x8)
+*/
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*ctv_typeidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2a000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x32000000\[\t \]+\[^\n\]*ctt_info" 1 } } */
+
+typedef struct my_int
+{
+    int upper;
+      int lower;
+} my_int_t;
+
+const my_int_t foo = {10, 20};
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 00000000000..59b4cb7035c
--- /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 00000000000..a2e25577eee
--- /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;
diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-2.c b/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-2.c
new file mode 100644
index 00000000000..cd9ab510b16
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-variables-2.c
@@ -0,0 +1,16 @@
+/* CTF generation for static variables inside a function.
+
+   In this testcase, CTF record for bstatic is NOT expected.  CTF generation
+   is only carried out for variables at file-scope or global-scope.  */
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gt -dA" } */
+
+/* { dg-final { scan-assembler-times "ctv_name" 0 } } */
+/* { dg-final { scan-assembler-times "ascii \"bstatic.0\"\[\t \]+\[^\n\]*ctf_string" 0 } } */
+
+int foo (int a)
+{
+  static int bstatic = 3;
+  return a + bstatic;
+}
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 00000000000..46055f8a2bf
--- /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 00000000000..4ffa8eed418
--- /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)
+{ }
-- 
2.25.0.2.g232378479e


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

* [PATCH 4/4] CTF documentation
  2021-01-22 11:01 [PATCH 0/4] Support for the CTF debug format Jose E. Marchesi
                   ` (2 preceding siblings ...)
  2021-01-22 11:01 ` [PATCH 3/4] CTF testsuite Jose E. Marchesi
@ 2021-01-22 11:01 ` Jose E. Marchesi
  3 siblings, 0 replies; 5+ messages in thread
From: Jose E. Marchesi @ 2021-01-22 11:01 UTC (permalink / raw)
  To: gcc-patches

This commit documents the new command line options introduced by the
CTF debug format.

2021-01-22  Indu Bhagat  <indu.bhagat@oracle.com>

	* doc/invoke.texi: Document the CTF debug info options.
---
 gcc/doc/invoke.texi | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 5f4a06625eb..7c4d70bcdf7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -460,6 +460,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
@@ -9629,6 +9630,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),
-- 
2.25.0.2.g232378479e


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

end of thread, other threads:[~2021-01-22 11:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-22 11:01 [PATCH 0/4] Support for the CTF debug format Jose E. Marchesi
2021-01-22 11:01 ` [PATCH 1/4] Add new function lang_GNU_GIMPLE Jose E. Marchesi
2021-01-22 11:01 ` [PATCH 2/4] CTF debug format Jose E. Marchesi
2021-01-22 11:01 ` [PATCH 3/4] CTF testsuite Jose E. Marchesi
2021-01-22 11:01 ` [PATCH 4/4] CTF documentation Jose E. Marchesi

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).