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