On 2/24/25 11:04, Indu Bhagat wrote:
> On 2/6/25 11:54 AM, David Faust wrote:
>> Translate DW_TAG_GNU_annotation DIEs created for C attributes
>> btf_decl_tag and btf_type_tag into an in-memory representation in the
>> CTF/BTF container.  They will be output in BTF as BTF_KIND_DECL_TAG and
>> BTF_KIND_TYPE_TAG records.
>>
>> The new CTF kinds used to represent these annotations, CTF_K_DECL_TAG
>> and CTF_K_TYPE_TAG, are expected to be formalized in the next version of
>> the CTF specification.  For now they only exist in memory as a
>> translation step to BTF, and are not emitted when generating CTF
>> information.
>>
> 
> The patch overall looks OK to me.  Some comments inlined below.
> 
>> gcc/
>>      * ctfc.cc (ctf_dtu_d_union_selector): Handle CTF_K_DECL_TAG and
>>      CTF_K_TYPE_TAG.
>>      (ctf_add_type_tag, ctf_add_decl_tag): New.
>>      (ctf_add_variable): Return the new ctf_dvdef_ref rather than zero.
>>      (new_ctf_container): Initialize new members.
>>      (ctfc_delete_container): Deallocate new members.
>>      * ctfc.h (ctf_dvdef, ctf_dvdef_t, ctf_dvdef_ref): Move forward
>>      declarations earlier in file.
>>      (ctf_decl_tag_t): New typedef.
>>      (ctf_dtdef): Add ctf_decl_tag_t member to dtd_u union.
>>      (ctf_dtu_d_union_enum): Add new CTF_DTU_D_TAG enumerator.
>>      (ctf_container): Add ctfc_tags vector and ctfc_type_tags_map hash_map
>>      members.
>>      (ctf_add_type_tag, ctf_add_decl_tag): New function protos.
>>      (ctf_add_variable): Change prototype return type to ctf_dvdef_ref.
>>      * dwarf2ctf.cc (gen_ctf_type_tags, gen_ctf_decl_tags)
>>      (gen_ctf_decl_tags_for_var): New static functions.
>>      (gen_ctf_sou_type): Handle decl tags.
>>      (gen_ctf_function_type): Likewise.
>>      (gen_ctf_variable): Likewise.
>>      (gen_ctf_function): Likewise.
>>      (gen_ctf_type): Handle type tags.
>>
>> gcc/testsuite
>>      * gcc.dg/debug/ctf/ctf-decl-tag-1.c: New test.
>>      * gcc.dg/debug/ctf/ctf-type-tag-1.c: New test.
>>
>> include/
>>      * ctf.h (CTF_K_DECL_TAG, CTF_K_TYPE_TAG): New defines.
>> ---
>>   gcc/ctfc.cc                                   |  70 +++++++-
>>   gcc/ctfc.h                                    |  41 ++++-
>>   gcc/dwarf2ctf.cc                              | 152 +++++++++++++++++-
>>   .../gcc.dg/debug/ctf/ctf-decl-tag-1.c         |  31 ++++
>>   .../gcc.dg/debug/ctf/ctf-type-tag-1.c         |  19 +++
>>   include/ctf.h                                 |   4 +
>>   6 files changed, 303 insertions(+), 14 deletions(-)
>>   create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-decl-tag-1.c
>>   create mode 100644 gcc/testsuite/gcc.dg/debug/ctf/ctf-type-tag-1.c
>>
>> diff --git a/gcc/ctfc.cc b/gcc/ctfc.cc
>> index 51511d69baa..c478fa0a136 100644
>> --- a/gcc/ctfc.cc
>> +++ b/gcc/ctfc.cc
>> @@ -107,6 +107,9 @@ ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype)
>>         return CTF_DTU_D_ARGUMENTS;
>>       case CTF_K_SLICE:
>>         return CTF_DTU_D_SLICE;
>> +    case CTF_K_DECL_TAG:
>> +    case CTF_K_TYPE_TAG:
>> +      return CTF_DTU_D_TAG;
>>       default:
>>         /* The largest member as default.  */
>>         return CTF_DTU_D_ARRAY;
>> @@ -445,6 +448,58 @@ ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, 
>> ctf_dtdef_ref ref,
>>     return dtd;
>>   }
>>   
>> +ctf_dtdef_ref
>> +ctf_add_type_tag (ctf_container_ref ctfc, uint32_t flag, const char *value,
>> +              ctf_dtdef_ref ref_dtd)
>> +{
>> +  ctf_dtdef_ref dtd;
>> +   /* Create a DTD for the tag, but do not place it in the regular types 
>> list;
>> +      CTF format does not (yet) encode tags.  */
>> +  dtd = ggc_cleared_alloc<ctf_dtdef_t> ();
>> +
>> +  dtd->dtd_name = ctf_add_string (ctfc, value, &(dtd->dtd_data.ctti_name),
>> +                              CTF_AUX_STRTAB);
>> +  /* A single DW_TAG_GNU_annotation DIE may be referenced by multiple DIEs,
>> +     e.g. when multiple distinct types specify the same type tag.  We will
>> +     synthesize multiple CTF DTD records in that case, so we cannot tie them
>> +     all to the same key (the DW_TAG_GNU_annotation DIE) in ctfc_types.  */
>> +  dtd->dtd_key = NULL;
>> +  dtd->ref_type = ref_dtd;
>> +  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_TYPE_TAG, flag, 0);
>> +  dtd->dtd_u.dtu_tag.ref_var = NULL; /* Not used for type tags.  */
>> +  dtd->dtd_u.dtu_tag.component_idx = 0; /* Not used for type tags.  */
>> +
>> +  /* Insert tag directly into the tag list.  Type ID will be assigned 
>> later.  */
>> +  vec_safe_push (ctfc->ctfc_tags, dtd);
>> +  return dtd;
>> +}
>> +
>> +ctf_dtdef_ref
>> +ctf_add_decl_tag (ctf_container_ref ctfc, uint32_t flag, const char *value,
>> +              ctf_dtdef_ref ref_dtd, uint32_t comp_idx)
>> +{
>> +   ctf_dtdef_ref dtd;
>> +   /* Create a DTD for the tag, but do not place it in the regular types 
>> list;
>> +      ctf format does not (yet) encode tags.  */
>> +  dtd = ggc_cleared_alloc<ctf_dtdef_t> ();
>> +
>> +  dtd->dtd_name = ctf_add_string (ctfc, value, &(dtd->dtd_data.ctti_name),
>> +                              CTF_AUX_STRTAB);
>> +  /* A single DW_TAG_GNU_annotation DIE may be referenced by multiple DIEs,
>> +     e.g. when multiple distinct declarations specify the same decl tag.
>> +     We will synthesize multiple CTF DTD records in that case, so we cannot 
>> tie
>> +     them all to the same key (the DW_TAG_GNU_annotation DIE) in 
>> ctfc_types.  */
>> +  dtd->dtd_key = NULL;
>> +  dtd->ref_type = ref_dtd;
>> +  dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_DECL_TAG, flag, 0);
>> +  dtd->dtd_u.dtu_tag.ref_var = NULL;
>> +  dtd->dtd_u.dtu_tag.component_idx = comp_idx;
>> +
>> +  /* Insert tag directly into the tag list.  Type ID will be assigned 
>> later.  */
>> +  vec_safe_push (ctfc->ctfc_tags, dtd);
>> +  return dtd;
>> +}
>> +
>>   ctf_dtdef_ref
>>   ctf_add_forward (ctf_container_ref ctfc, uint32_t flag, const char * name,
>>               uint32_t kind, dw_die_ref die)
>> @@ -691,12 +746,12 @@ ctf_add_member_offset (ctf_container_ref ctfc, 
>> dw_die_ref sou,
>>     return 0;
>>   }
>>   
>> -int
>> +ctf_dvdef_ref
>>   ctf_add_variable (ctf_container_ref ctfc, const char * name, ctf_dtdef_ref 
>> ref,
>>                dw_die_ref die, unsigned int external_vis,
>>                dw_die_ref die_var_decl)
>>   {
>> -  ctf_dvdef_ref dvd, dvd_ignore;
>> +  ctf_dvdef_ref dvd = NULL, dvd_ignore;
>>   
>>     gcc_assert (name);
>>   
>> @@ -732,7 +787,7 @@ ctf_add_variable (ctf_container_ref ctfc, const char * 
>> name, ctf_dtdef_ref ref,
>>      ctfc->ctfc_strlen += strlen (name) + 1;
>>       }
>>   
>> -  return 0;
>> +  return dvd;
>>   }
>>   
>>   int
>> @@ -949,6 +1004,10 @@ new_ctf_container (void)
>>     tu_ctfc->ctfc_ignore_vars
>>       = hash_table<ctfc_dvd_hasher>::create_ggc (10);
>>   
>> +  vec_alloc (tu_ctfc->ctfc_tags, 100);
>> +  tu_ctfc->ctfc_type_tags_map
>> +    = hash_map<ctf_dtdef_ref, ctf_dtdef_ref>::create_ggc (100);
>> +
>>     return tu_ctfc;
>>   }
>>   
>> @@ -1003,6 +1062,11 @@ ctfc_delete_container (ctf_container_ref ctfc)
>>         ctfc->ctfc_ignore_vars->empty ();
>>         ctfc->ctfc_ignore_vars = NULL;
>>   
>> +      ctfc->ctfc_tags = NULL;
>> +
>> +      ctfc->ctfc_type_tags_map->empty ();
>> +      ctfc->ctfc_type_tags_map = NULL;
>> +
>>         ctfc_delete_strtab (&ctfc->ctfc_strtable);
>>         ctfc_delete_strtab (&ctfc->ctfc_aux_strtable);
>>         if (ctfc->ctfc_vars_list)
>> diff --git a/gcc/ctfc.h b/gcc/ctfc.h
>> index 32c73be6a41..756f17f0a9b 100644
>> --- a/gcc/ctfc.h
>> +++ b/gcc/ctfc.h
>> @@ -52,6 +52,10 @@ struct ctf_dtdef;
>>   typedef struct ctf_dtdef ctf_dtdef_t;
>>   typedef ctf_dtdef_t * ctf_dtdef_ref;
>>   
>> +struct ctf_dvdef;
>> +typedef struct ctf_dvdef ctf_dvdef_t;
>> +typedef ctf_dvdef_t * ctf_dvdef_ref;
>> +
>>   /* CTF string table element (list node).  */
>>   
>>   typedef struct GTY ((chain_next ("%h.cts_next"))) ctf_string
>> @@ -155,6 +159,14 @@ typedef struct GTY (()) ctf_func_arg
>>   
>>   #define ctf_farg_list_next(elem) ((ctf_func_arg_t *)((elem)->farg_next))
>>   
>> +/* Declaration Tag.  */
>> +
> 
> Perhaps another one liner will be meaningful here.  Something like:
> 
> Declaration tags may be used for struct or union members, variable and 
> function declarations, and function arguments.

OK

> 
>> +typedef struct GTY (()) ctf_decl_tag
>> +{
>> +  uint32_t component_idx;  /* Index of component to which tag applies.  */
>> +  ctf_dvdef_ref ref_var;   /* Non-null iff this tag applies to a variable.  
>> */
>> +} ctf_decl_tag_t;
>> +
>>   /* Type definition for CTF generation.  */
>>   
>>   struct GTY ((for_user)) ctf_dtdef
>> @@ -184,6 +196,8 @@ struct GTY ((for_user)) ctf_dtdef
>>       ctf_func_arg_t * GTY ((tag ("CTF_DTU_D_ARGUMENTS"))) dtu_argv;
>>       /* slice.  */
>>       ctf_sliceinfo_t GTY ((tag ("CTF_DTU_D_SLICE"))) dtu_slice;
>> +    /* decl tag.  */
>> +    ctf_decl_tag_t GTY ((tag ("CTF_DTU_D_TAG"))) dtu_tag;
>>     } dtd_u;
>>   };
>>   
>> @@ -201,9 +215,6 @@ struct GTY ((for_user)) ctf_dvdef
>>     ctf_id_t dvd_id;         /* ID of this variable.  Only used for BTF.  */
>>   };
>>   
>> -typedef struct ctf_dvdef ctf_dvdef_t;
>> -typedef ctf_dvdef_t * ctf_dvdef_ref;
>> -
>>   /* Location information for CTF Types and CTF Variables.  */
>>   
>>   typedef struct GTY (()) ctf_srcloc
>> @@ -222,7 +233,8 @@ enum ctf_dtu_d_union_enum {
>>     CTF_DTU_D_ARRAY,
>>     CTF_DTU_D_ENCODING,
>>     CTF_DTU_D_ARGUMENTS,
>> -  CTF_DTU_D_SLICE
>> +  CTF_DTU_D_SLICE,
>> +  CTF_DTU_D_TAG,
>>   };
>>   
>>   enum ctf_dtu_d_union_enum
>> @@ -287,6 +299,17 @@ typedef struct GTY (()) ctf_container
>>     /* CTF variables to be ignored.  */
>>     hash_table <ctfc_dvd_hasher> * GTY (()) ctfc_ignore_vars;
>>   
>> +  /* BTF type and decl tags.  Not yet represented in CTF.  These tags also
>> +     uniquely have a one-to-many relation with DIEs, meaning a single DIE
>> +     may translate to multiple CTF/BTF records.  For both of these reasons,
>> +     they cannot be stored in the regular types table.  */
>> +  vec <ctf_dtdef_ref, va_gc> * GTY (()) ctfc_tags;
>> +  /* Type tags logically form part of the type chain similar to cv-quals.
>> +     Therefore references to types need to know if the referred-to type has
>> +     any type tags, and if so to refer to the outermost type tag.  This map
>> +     maps a type to the outermost type tag created for it, if any.  */
>> +  hash_map <ctf_dtdef_ref, ctf_dtdef_ref> * GTY (()) ctfc_type_tags_map;
>> +
>>     /* CTF string table.  */
>>     ctf_strtable_t ctfc_strtable;
>>     /* Auxilliary string table.  At this time, used for keeping func arg 
>> names
>> @@ -440,15 +463,19 @@ extern ctf_dtdef_ref ctf_add_function 
>> (ctf_container_ref, uint32_t,
>>                                     dw_die_ref, bool, int);
>>   extern ctf_dtdef_ref ctf_add_sou (ctf_container_ref, uint32_t, const char 
>> *,
>>                                uint32_t, size_t, dw_die_ref);
>> -
>> +extern ctf_dtdef_ref ctf_add_type_tag (ctf_container_ref, uint32_t,
>> +                                   const char *, ctf_dtdef_ref);
>> +extern ctf_dtdef_ref ctf_add_decl_tag (ctf_container_ref, uint32_t,
>> +                                   const char *, ctf_dtdef_ref, uint32_t);
>>   extern int ctf_add_enumerator (ctf_container_ref, ctf_dtdef_ref, const 
>> char *,
>>                             HOST_WIDE_INT, dw_die_ref);
>>   extern int ctf_add_member_offset (ctf_container_ref, dw_die_ref, const 
>> char *,
>>                                ctf_dtdef_ref, uint64_t);
>>   extern int ctf_add_function_arg (ctf_container_ref, dw_die_ref,
>>                               const char *, ctf_dtdef_ref);
>> -extern int ctf_add_variable (ctf_container_ref, const char *, ctf_dtdef_ref,
>> -                         dw_die_ref, unsigned int, dw_die_ref);
>> +extern ctf_dvdef_ref ctf_add_variable (ctf_container_ref, const char *,
>> +                                   ctf_dtdef_ref, dw_die_ref, unsigned int,
>> +                                   dw_die_ref);
>>   
>>   extern ctf_dtdef_ref ctf_lookup_tree_type (ctf_container_ref, const tree);
>>   
>> diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
>> index 7de3696a4d7..33432a1038c 100644
>> --- a/gcc/dwarf2ctf.cc
>> +++ b/gcc/dwarf2ctf.cc
>> @@ -32,6 +32,15 @@ along with GCC; see the file COPYING3.  If not see
>>   static ctf_dtdef_ref
>>   gen_ctf_type (ctf_container_ref, dw_die_ref);
>>   
>> +static ctf_dtdef_ref
>> +gen_ctf_type_tags (ctf_container_ref, dw_die_ref, ctf_dtdef_ref);
>> +
>> +static void
>> +gen_ctf_decl_tags (ctf_container_ref, dw_die_ref, ctf_dtdef_ref, uint32_t);
>> +
>> +static void
>> +gen_ctf_decl_tags_for_var (ctf_container_ref, dw_die_ref, ctf_dvdef_ref);
>> +
>>   /* All the DIE structures we handle come from the DWARF information
>>      generated by GCC.  However, there are three situations where we need
>>      to create our own created DIE structures because GCC doesn't
>> @@ -532,6 +541,7 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref 
>> sou, uint32_t kind)
>>     /* Now process the struct members.  */
>>     {
>>       dw_die_ref c;
>> +    uint32_t idx = 0;
>>   
>>       c = dw_get_die_child (sou);
>>       if (c)
>> @@ -616,6 +626,9 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref 
>> sou, uint32_t kind)
>>                               field_name,
>>                               field_dtd,
>>                               field_location);
>> +
>> +      gen_ctf_decl_tags (ctfc, c, sou_dtd, idx);
>> +      idx++;
>>      }
>>         while (c != dw_get_die_child (sou));
>>     }
>> @@ -699,14 +712,18 @@ gen_ctf_function_type (ctf_container_ref ctfc, 
>> dw_die_ref function,
>>            gcc_assert (i == num_args - 1);
>>            /* Add an argument with type 0 and no name.  */
>>            ctf_add_function_arg (ctfc, function, "", NULL);
>> +          /* Handle any declaration tags on the argument.  */
>> +          gen_ctf_decl_tags (ctfc, c, function_dtd, i);
>>          }
>>        else if (dw_get_die_tag (c) == DW_TAG_formal_parameter)
>>          {
>> -          i++;
>>            arg_name = get_AT_string (c, DW_AT_name);
>>            arg_type = gen_ctf_type (ctfc, ctf_get_AT_type (c));
>>            /* Add the argument to the existing CTF function type.  */
>>            ctf_add_function_arg (ctfc, function, arg_name, arg_type);
>> +          /* Handle any declaration tags on the argument.  */
>> +          gen_ctf_decl_tags (ctfc, c, function_dtd, i);
>> +          i++;
>>          }
>>        else
>>          /* This is a local variable.  Ignore.  */
>> @@ -797,6 +814,7 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
>>     dw_die_ref var_type = ctf_get_AT_type (die);
>>     unsigned int external_vis = get_AT_flag (die, DW_AT_external);
>>     ctf_dtdef_ref var_dtd;
>> +  ctf_dvdef_ref dvd;
>>   
>>     /* Avoid duplicates.  */
>>     if (ctf_dvd_lookup (ctfc, die))
>> @@ -817,10 +835,13 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref 
>> die)
>>     var_dtd = gen_ctf_type (ctfc, var_type);
>>   
>>     /* Generate the new CTF variable and update global counter.  */
>> -  (void) ctf_add_variable (ctfc, var_name, var_dtd, die, external_vis, 
>> decl);
>> +  dvd = ctf_add_variable (ctfc, var_name, var_dtd, die, external_vis, decl);
>>     /* Skip updating the number of global objects at this time.  This is 
>> updated
>>        later after pre-processing as some CTF variable records although
>>        generated now, will not be emitted later.  [PR105089].  */
>> +
>> +  /* Handle declaration tags on the variable.  */
>> +  gen_ctf_decl_tags_for_var (ctfc, die, dvd);
>>   }
>>   
>>   /* Add a CTF function record for the given input DWARF DIE.  */
>> @@ -838,8 +859,119 @@ gen_ctf_function (ctf_container_ref ctfc, dw_die_ref 
>> die)
>>        counter.  Note that DWARF encodes function types in both
>>        DW_TAG_subroutine_type and DW_TAG_subprogram in exactly the same
>>        way.  */
>> -  (void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
>> +  function_dtd = gen_ctf_function_type (ctfc, die, true /* from_global_func 
>> */);
>>     ctfc->ctfc_num_global_funcs += 1;
>> +
>> +  /* Handle declaration tags on the function.  */
>> +  gen_ctf_decl_tags (ctfc, die, function_dtd, -1U);
>> +}
>> +
>> +/* Handle any DW_AT_GNU_annotation on type DIE by constructing a 
>> CTF_K_TYPE_TAG
>> +   type for the DW_TAG_GNU_annotation DIE to which it points, if this has 
>> not
>> +   previously been constructed.  There may be multiple annotations chained
>> +   together by further occurances of DW_AT_GNU_annotation in the annotation
>> +   DIEs themselves, in which case a corresponding chain of CTF_K_TYPE_TAG
>> +   records is created.  The final TYPE_TAG in the chain refers to the dtd 
>> for
>> +   the annotated type, which should be supplied in REF_DTD.
>> +
>> +   Return the ctf_dtdef_t for the outermost TYPE_TAG created, since anything
>> +   referring to this type should refer to it via the chain of type tags.  */
>> +
>> +static ctf_dtdef_ref
>> +gen_ctf_type_tags (ctf_container_ref ctfc, dw_die_ref die,
>> +               ctf_dtdef_ref ref_dtd)
>> +{
>> +  if (!btf_debuginfo_p ())
>> +    return ref_dtd;
>> +  if (!die || !ref_dtd)
>> +    return NULL;
>> +
>> +  ctf_dtdef_ref *existing = ctfc->ctfc_type_tags_map->get (ref_dtd);
>> +  if (existing)
>> +    return *existing;
>> +
>> +  dw_die_ref annot_die = get_AT_ref (die, DW_AT_GNU_annotation);
>> +  ctf_dtdef_ref tag_dtd = ref_dtd;
>> +
>> +  /* Recurse first; build the chain from back to front.  */
>> +  if (annot_die)
>> +    tag_dtd = gen_ctf_type_tags (ctfc, annot_die, ref_dtd);
>> +
>> +  /* If this is an annotation die, make the tag.  */
>> +  if (dw_get_die_tag (die) == DW_TAG_GNU_annotation)
>> +    {
>> +      const char *name = get_AT_string (die, DW_AT_name);
>> +      const char *value = get_AT_string (die, DW_AT_const_value);
>> +      if (strcmp (name, "btf_type_tag") == 0)
>> +    {
>> +      tag_dtd = ctf_add_type_tag (ctfc, CTF_ADD_ROOT, value, tag_dtd);
>> +      ctfc->ctfc_type_tags_map->put (ref_dtd, tag_dtd);
>> +    }
>> +    }
>> +
>> +  return tag_dtd;
>> +}
>> +
>> +/* Handle any DW_AT_GNU_annotation on decl DIE by constructing a 
>> CTF_K_DECL_TAG
>> +   type for the DW_TAG_GNU_annotation DIE to which it points, if this has 
>> not
>> +   been previously constructed.  There may be multiple annotations chained
>> +   together by further occurances of DW_AT_GNU_annotation in the annoation 
>> DIEs
>> +   themselves, in which case a corresponding CTF_K_DECL_TAG type is created 
>> for
>> +   each.  Unlike TYPE_TAGs, which form a chain, each DECL_TAG individually
>> +   refers directly to the annotated decl, which should be supplied in 
>> REF_DTD.
> 
> Which is why they cannot be deduplicated across usages.

Right.

> 
> I see that you mention this aspect also in ctf_add_decl_tag (), but I 
> think its worthwhile to mention it explicitly here again.

Makes sense to me, I'll add a note to the comment.

> 
>> +   IDX is the zero-based component index indicating to which function 
>> parameter
>> +   or struct or union member the DECL_TAG refers, or (uint32_t) -1 if it 
>> refers
>> +   to a function decl or sou itself.  */
>> +> +static void
>> +gen_ctf_decl_tags (ctf_container_ref ctfc, dw_die_ref die,
>> +               ctf_dtdef_ref ref_dtd, uint32_t idx)
>> +{
>> +  if (!btf_debuginfo_p () || !die || !ref_dtd)
>> +    return;
>> +
>> +  dw_die_ref annot_die = get_AT_ref (die, DW_AT_GNU_annotation);
>> +  while (annot_die)
>> +    {
>> +      const char *name = get_AT_string (annot_die, DW_AT_name);
>> +      const char *value = get_AT_string (annot_die, DW_AT_const_value);
>> +
>> +      if (strcmp (name, "btf_decl_tag") == 0)
>> +    (void) ctf_add_decl_tag (ctfc, CTF_ADD_ROOT, value, ref_dtd, idx);
>> +
>> +      annot_die = get_AT_ref (annot_die, DW_AT_GNU_annotation);
>> +    }
>> +}
>> +
>> +/* Like gen_ctf_decl_tags above, but specifically for variables.  
>> Declaration
>> +   tags may appear on variables or other declarations like functions, but 
>> due
>> +   to the distinction in CTF between variables and types the processing in
>> +   each case is slightly different.  REF_DVD is the CTF record for the 
>> variable
>> +   which is annotated.  */
>> +
>> +static void
>> +gen_ctf_decl_tags_for_var (ctf_container_ref ctfc, dw_die_ref die,
>> +                       ctf_dvdef_ref ref_dvd)
>> +{
>> +  if (!btf_debuginfo_p () || !die || !ref_dvd)
>> +    return;
>> +
>> +  ctf_dtdef_ref tag_dtd = NULL;
>> +
>> +  dw_die_ref annot_die = get_AT_ref (die, DW_AT_GNU_annotation);
>> +  while (annot_die)
>> +    {
>> +      const char *name = get_AT_string (annot_die, DW_AT_name);
>> +      const char *value = get_AT_string (annot_die, DW_AT_const_value);
>> +
>> +      if (strcmp (name, "btf_decl_tag") == 0)
>> +    {
>> +      tag_dtd = ctf_add_decl_tag (ctfc, CTF_ADD_ROOT, value, NULL, -1U);
>> +      tag_dtd->dtd_u.dtu_tag.ref_var = ref_dvd;
>> +    }
>> +
>> +      annot_die = get_AT_ref (annot_die, DW_AT_GNU_annotation);
>> +    }
>>   }
>>   
>>   /* Add CTF type record(s) for the given input DWARF DIE and return its 
>> type id.
>> @@ -857,7 +989,12 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
>>     int unrecog_die = false;
>>   
>>     if (ctf_type_exists (ctfc, die, &dtd))
>> -    return dtd;
>> +    {
>> +      if (btf_debuginfo_p ())
>> +    return gen_ctf_type_tags (ctfc, die, dtd);
>> +      else
>> +    return dtd;
>> +    }
>>   
>>     switch (dw_get_die_tag (die))
>>       {
>> @@ -906,6 +1043,10 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
>>   
>>      break;
>>         }
>> +    case DW_TAG_GNU_annotation:
>> +      dtd = NULL;
>> +      unrecog_die = true;
>> +      break;
> 
> Hmm... this can be confusing later.  The DW_TAG_GNU_annotation is now 
> represented in CTF, albeit only in-memory representation.
> 
> Should we add a comment that these dies are traversed explicitly in 
> dwarf2ctf by following the DW_AT_GNU_annotation ?

OK

> 
>>       case DW_TAG_reference_type:
>>         dtd = NULL;
>>         break;
>> @@ -916,6 +1057,9 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
>>         break;
>>       }
>>   
>> +  if (dtd)
>> +    dtd = gen_ctf_type_tags (ctfc, die, dtd);
>> +
> 
> Nit: I see that gen_ctf_type_tags () has an early exit if 
> !btf_debuginfo_p(), but just to keep this invocation of 
> gen_ctf_type_tags () similar looking as the one above (it does help 
> readability IMO), perhaps include a check for btf_debuginfo_p () here too ?

You're right. Thanks for catching the inconsistency, will fix it.

> 
>>     /* For all types unrepresented in CTF, use an explicit CTF type of kind
>>        CTF_K_UNKNOWN.  */
>>     if ((dtd == NULL) && (!unrecog_die))
>> diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-decl-tag-1.c 
>> b/gcc/testsuite/gcc.dg/debug/ctf/ctf-decl-tag-1.c
>> new file mode 100644
>> index 00000000000..564bbc76468
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-decl-tag-1.c
>> @@ -0,0 +1,31 @@
>> +/* CTF generation for btf_decl_tag attribute.
>> +
>> +   CTF does not encode these attributes and no CTF_K_DECL_TAG record should 
>> be
>> +   emitted; these records only exist internally to facilitate translation
>> +   to BTF.  */
>> +
>> +/* { dg-do compile } */
>> +/* { dg-options "-O0 -gctf -dA" } */
>> +
>> +int x __attribute__((btf_decl_tag ("some_tag")));
>> +
>> +struct S {
>> +  int a;
>> +  int b __attribute__((btf_decl_tag ("_b")));
>> +  int c;
>> +};
>> +
>> +struct S some_S;
>> +
>> +void
>> +__attribute__((btf_decl_tag ("__func")))
>> +foo (int *ptr __attribute__((btf_decl_tag ("w"))), int val)
>> +{
>> +  *ptr = val;
>> +}
>> +
>> +/* Expect 5 CTF types: int, struct, void, int*, void (int*, int).  */
>> +/* { dg-final { scan-assembler-times "ctt_info" 5 } } */
>> +/* Ensure no CTF_K_DECL_TAG record is emitted.  */
>> +/* { dg-final { scan-assembler-not "\[\t \]0x3c*\[\t \]+\[^\n\]*ctt_info" } 
>> } */
>> +/* { dg-final { scan-assembler-not "\[\t \]0x3e*\[\t \]+\[^\n\]*ctt_info" } 
>> } */
>> diff --git a/gcc/testsuite/gcc.dg/debug/ctf/ctf-type-tag-1.c 
>> b/gcc/testsuite/gcc.dg/debug/ctf/ctf-type-tag-1.c
>> new file mode 100644
>> index 00000000000..ca37ef44fe2
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/debug/ctf/ctf-type-tag-1.c
>> @@ -0,0 +1,19 @@
>> +/* CTF generation for btf_type_tag attribute.
>> +
>> +   CTF does not encode these attributes and no CTF_K_TYPE_TAG record should 
>> be
>> +   emitted; these records only exist internally to facilitate translation
>> +   to BTF.  */
>> +
>> +/* { dg-do compile } */
>> +/* { dg-options "-O0 -gctf -dA" } */
>> +
>> +int * __attribute__((btf_type_tag ("some_tag"))) x;
>> +
>> +typedef unsigned int __attribute__((btf_type_tag ("other_tag"))) uint;
>> +const uint u;
>> +
>> +/* Expect 5 CTF types: int, int*, unsigned int, typedef, const.  */
>> +/* { dg-final { scan-assembler-times "ctt_info" 5 } } */
>> +/* Ensure no CTF_K_TYPE_TAG record is emitted.  */
>> +/* { dg-final { scan-assembler-not "\[\t \]0x40*\[\t \]+\[^\n\]*ctt_info" } 
>> } */
>> +/* { dg-final { scan-assembler-not "\[\t \]0x42*\[\t \]+\[^\n\]*ctt_info" } 
>> } */
>> diff --git a/include/ctf.h b/include/ctf.h
>> index 72a639ac9b4..f75e337ba0f 100644
>> --- a/include/ctf.h
>> +++ b/include/ctf.h
>> @@ -423,6 +423,10 @@ union
>>   #define CTF_K_CONST        12      /* ctt_type is base type.  */
>>   #define CTF_K_RESTRICT     13      /* ctt_type is base type.  */
>>   #define CTF_K_SLICE        14      /* Variant data is a ctf_slice_t.  */
>> +#define CTF_K_DECL_TAG      15      /* Declaration tag.  Internal use only.
>> +                               Not valid externally until CTF V4.  */
>> +#define CTF_K_TYPE_TAG      16      /* Type tag.  Internal use only.
>> +                               Not valid externally until CTF V4.  */
>>   
>>   #define CTF_K_MAX  63      /* Maximum possible (V2) CTF_K_* value.  */
>>   
> 


Reply via email to