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. 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. */ + +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. + 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; 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); + /* 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. */ -- 2.45.2