mirror of git://gcc.gnu.org/git/gcc.git
btf: generate and output DECL_TAG and TYPE_TAG records
Support the btf_decl_tag and btf_type_tag attributes in BTF by creating and emitting BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG records, respectively, for them. Some care is required when -gprune-btf is in effect to avoid emitting decl or type tags for declarations or types which have been pruned and will not be emitted in BTF. gcc/ * btfout.cc (get_btf_kind): Handle DECL_TAG and TYPE_TAG kinds. (btf_calc_num_vbytes): Likewise. (btf_asm_type): Likewise. (output_asm_btf_vlen_bytes): Likewise. (output_btf_tags): New. (btf_output): Call it here. (btf_add_used_type): Replace with simple wrapper around... (btf_add_used_type_1): ...the implementation. Handle BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG. (btf_add_vars): Update btf_add_used_type call. (btf_assign_tag_ids): New. (btf_mark_type_used): Update btf_add_used_type call. (btf_collect_pruned_types): Likewise. Handle type and decl tags. (btf_finish): Call btf_assign_tag_ids. gcc/testsuite/ * gcc.dg/debug/btf/btf-decl-tag-1.c: New test. * gcc.dg/debug/btf/btf-decl-tag-2.c: New test. * gcc.dg/debug/btf/btf-decl-tag-3.c: New test. * gcc.dg/debug/btf/btf-decl-tag-4.c: New test. * gcc.dg/debug/btf/btf-type-tag-1.c: New test. * gcc.dg/debug/btf/btf-type-tag-2.c: New test. * gcc.dg/debug/btf/btf-type-tag-3.c: New test. * gcc.dg/debug/btf/btf-type-tag-4.c: New test. * gcc.dg/debug/btf/btf-type-tag-c2x-1.c: New test. include/ * btf.h (BTF_KIND_DECL_TAG, BTF_KIND_TYPE_TAG) New defines. (struct btf_decl_tag): New.
This commit is contained in:
parent
9c862a593b
commit
43dcea48b8
171
gcc/btfout.cc
171
gcc/btfout.cc
|
@ -141,6 +141,8 @@ get_btf_kind (uint32_t ctf_kind)
|
|||
case CTF_K_VOLATILE: return BTF_KIND_VOLATILE;
|
||||
case CTF_K_CONST: return BTF_KIND_CONST;
|
||||
case CTF_K_RESTRICT: return BTF_KIND_RESTRICT;
|
||||
case CTF_K_DECL_TAG: return BTF_KIND_DECL_TAG;
|
||||
case CTF_K_TYPE_TAG: return BTF_KIND_TYPE_TAG;
|
||||
default:;
|
||||
}
|
||||
return BTF_KIND_UNKN;
|
||||
|
@ -217,6 +219,7 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
|
|||
case BTF_KIND_CONST:
|
||||
case BTF_KIND_RESTRICT:
|
||||
case BTF_KIND_FUNC:
|
||||
case BTF_KIND_TYPE_TAG:
|
||||
/* These kinds have no vlen data. */
|
||||
break;
|
||||
|
||||
|
@ -256,6 +259,10 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
|
|||
vlen_bytes += vlen * sizeof (struct btf_var_secinfo);
|
||||
break;
|
||||
|
||||
case BTF_KIND_DECL_TAG:
|
||||
vlen_bytes += sizeof (struct btf_decl_tag);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -452,6 +459,20 @@ btf_asm_type (ctf_dtdef_ref dtd)
|
|||
and should write 0. */
|
||||
dw2_asm_output_data (4, 0, "(unused)");
|
||||
return;
|
||||
case BTF_KIND_DECL_TAG:
|
||||
{
|
||||
if (dtd->ref_type)
|
||||
break;
|
||||
else if (dtd->dtd_u.dtu_tag.ref_var)
|
||||
{
|
||||
/* ref_type is NULL for decl tag attached to a variable. */
|
||||
ctf_dvdef_ref dvd = dtd->dtd_u.dtu_tag.ref_var;
|
||||
dw2_asm_output_data (4, dvd->dvd_id,
|
||||
"btt_type: (BTF_KIND_VAR '%s')",
|
||||
dvd->dvd_name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -801,6 +822,12 @@ output_asm_btf_vlen_bytes (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
|
|||
at this point. */
|
||||
gcc_unreachable ();
|
||||
|
||||
case BTF_KIND_DECL_TAG:
|
||||
dw2_asm_output_data (4, dtd->dtd_u.dtu_tag.component_idx,
|
||||
"component_idx=%d",
|
||||
dtd->dtd_u.dtu_tag.component_idx);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* All other BTF type kinds have no variable length data. */
|
||||
break;
|
||||
|
@ -851,6 +878,20 @@ output_btf_func_types (void)
|
|||
btf_asm_func_type (ref);
|
||||
}
|
||||
|
||||
static void
|
||||
output_btf_tags (ctf_container_ref ctfc)
|
||||
{
|
||||
/* If pruning, tags which are not pruned have already been added to
|
||||
the used list and output by output_btf_types. */
|
||||
if (debug_prune_btf)
|
||||
return;
|
||||
|
||||
ctf_dtdef_ref dtd;
|
||||
unsigned i;
|
||||
FOR_EACH_VEC_ELT (*ctfc->ctfc_tags, i, dtd)
|
||||
output_asm_btf_type (ctfc, dtd);
|
||||
}
|
||||
|
||||
/* Output all BTF_KIND_DATASEC records. */
|
||||
|
||||
static void
|
||||
|
@ -869,6 +910,7 @@ btf_output (ctf_container_ref ctfc)
|
|||
output_btf_types (ctfc);
|
||||
output_btf_vars (ctfc);
|
||||
output_btf_func_types ();
|
||||
output_btf_tags (ctfc);
|
||||
output_btf_datasec_types ();
|
||||
output_btf_strs (ctfc);
|
||||
}
|
||||
|
@ -985,7 +1027,8 @@ static vec<struct btf_fixup> fixups;
|
|||
is created and emitted. This vector stores them. */
|
||||
static GTY (()) vec<ctf_dtdef_ref, va_gc> *forwards;
|
||||
|
||||
/* Recursively add type DTD and any types it references to the used set.
|
||||
/* Implementation of btf_add_used_type.
|
||||
Recursively add type DTD and any types it references to the used set.
|
||||
Return a type that should be used for references to DTD - usually DTD itself,
|
||||
but may be NULL if DTD corresponds to a type which will not be emitted.
|
||||
CHECK_PTR is true if one of the predecessors in recursive calls is a struct
|
||||
|
@ -996,8 +1039,8 @@ static GTY (()) vec<ctf_dtdef_ref, va_gc> *forwards;
|
|||
CREATE_FIXUPS is false. */
|
||||
|
||||
static ctf_dtdef_ref
|
||||
btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
||||
bool check_ptr, bool seen_ptr, bool create_fixups)
|
||||
btf_add_used_type_1 (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
||||
bool check_ptr, bool seen_ptr, bool create_fixups)
|
||||
{
|
||||
if (dtd == NULL)
|
||||
return NULL;
|
||||
|
@ -1029,8 +1072,9 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
fixups.unordered_remove (i);
|
||||
|
||||
/* Add the concrete base type. */
|
||||
dtd->ref_type = btf_add_used_type (ctfc, dtd->ref_type, check_ptr,
|
||||
seen_ptr, create_fixups);
|
||||
dtd->ref_type = btf_add_used_type_1 (ctfc, dtd->ref_type,
|
||||
check_ptr, seen_ptr,
|
||||
create_fixups);
|
||||
return dtd;
|
||||
}
|
||||
default:
|
||||
|
@ -1044,8 +1088,8 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
the reference to the bitfield. The slice type won't be emitted,
|
||||
but we need the information in it when writing out the bitfield
|
||||
encoding. */
|
||||
btf_add_used_type (ctfc, dtd->dtd_u.dtu_slice.cts_type,
|
||||
check_ptr, seen_ptr, create_fixups);
|
||||
btf_add_used_type_1 (ctfc, dtd->dtd_u.dtu_slice.cts_type,
|
||||
check_ptr, seen_ptr, create_fixups);
|
||||
return dtd;
|
||||
}
|
||||
|
||||
|
@ -1069,7 +1113,11 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
case BTF_KIND_INT:
|
||||
case BTF_KIND_FLOAT:
|
||||
case BTF_KIND_FWD:
|
||||
/* Leaf kinds which do not refer to any other types. */
|
||||
case BTF_KIND_DECL_TAG:
|
||||
/* Leaf kinds which do not refer to any other types.
|
||||
BTF_KIND_DECL_TAG is a special case: we treat it as though it does not
|
||||
refer to any other types, since we only want the DECL_TAG to be added
|
||||
if the type to which it refers has already been added. */
|
||||
break;
|
||||
|
||||
case BTF_KIND_FUNC:
|
||||
|
@ -1082,6 +1130,7 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
case BTF_KIND_CONST:
|
||||
case BTF_KIND_VOLATILE:
|
||||
case BTF_KIND_RESTRICT:
|
||||
case BTF_KIND_TYPE_TAG:
|
||||
{
|
||||
/* These type kinds refer to exactly one other type. */
|
||||
if (check_ptr && !seen_ptr)
|
||||
|
@ -1106,18 +1155,18 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
}
|
||||
|
||||
/* Add the type to which this type refers. */
|
||||
dtd->ref_type = btf_add_used_type (ctfc, dtd->ref_type, check_ptr,
|
||||
seen_ptr, create_fixups);
|
||||
dtd->ref_type = btf_add_used_type_1 (ctfc, dtd->ref_type, check_ptr,
|
||||
seen_ptr, create_fixups);
|
||||
break;
|
||||
}
|
||||
case BTF_KIND_ARRAY:
|
||||
{
|
||||
/* Add element and index types. */
|
||||
ctf_arinfo_t *arr = &(dtd->dtd_u.dtu_arr);
|
||||
arr->ctr_contents = btf_add_used_type (ctfc, arr->ctr_contents, false,
|
||||
false, create_fixups);
|
||||
arr->ctr_index = btf_add_used_type (ctfc, arr->ctr_index, false, false,
|
||||
create_fixups);
|
||||
arr->ctr_contents = btf_add_used_type_1 (ctfc, arr->ctr_contents,
|
||||
false, false, create_fixups);
|
||||
arr->ctr_index = btf_add_used_type_1 (ctfc, arr->ctr_index, false,
|
||||
false, create_fixups);
|
||||
break;
|
||||
}
|
||||
case BTF_KIND_STRUCT:
|
||||
|
@ -1133,8 +1182,8 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
/* Add member type for struct/union members. For enums, only the
|
||||
enumerator names are needed. */
|
||||
if (kind == BTF_KIND_STRUCT || kind == BTF_KIND_UNION)
|
||||
dmd->dmd_type = btf_add_used_type (ctfc, dmd->dmd_type, true,
|
||||
false, create_fixups);
|
||||
dmd->dmd_type = btf_add_used_type_1 (ctfc, dmd->dmd_type, true,
|
||||
false, create_fixups);
|
||||
ctf_add_string (ctfc, dmd->dmd_name, &(dmd->dmd_name_offset),
|
||||
CTF_STRTAB);
|
||||
}
|
||||
|
@ -1143,16 +1192,17 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
case BTF_KIND_FUNC_PROTO:
|
||||
{
|
||||
/* Add return type. */
|
||||
dtd->ref_type = btf_add_used_type (ctfc, dtd->ref_type, false, false,
|
||||
create_fixups);
|
||||
dtd->ref_type = btf_add_used_type_1 (ctfc, dtd->ref_type, false, false,
|
||||
create_fixups);
|
||||
|
||||
/* Add arg types. */
|
||||
ctf_func_arg_t * farg;
|
||||
for (farg = dtd->dtd_u.dtu_argv;
|
||||
farg != NULL; farg = (ctf_func_arg_t *) ctf_farg_list_next (farg))
|
||||
{
|
||||
farg->farg_type = btf_add_used_type (ctfc, farg->farg_type, false,
|
||||
false, create_fixups);
|
||||
farg->farg_type = btf_add_used_type_1 (ctfc, farg->farg_type,
|
||||
false, false,
|
||||
create_fixups);
|
||||
/* Note: argument names are stored in the auxilliary string table,
|
||||
since CTF does not include arg names. That table has not been
|
||||
cleared, so no need to re-add argument names here. */
|
||||
|
@ -1166,6 +1216,16 @@ btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd,
|
|||
return dtd;
|
||||
}
|
||||
|
||||
/* Recursively add type DTD and any types it references to the used set.
|
||||
Return a type that should be used for references to DTD - usually DTD itself,
|
||||
but may be NULL if DTD corresponds to a type which will not be emitted. */
|
||||
|
||||
static ctf_dtdef_ref
|
||||
btf_add_used_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
|
||||
{
|
||||
return btf_add_used_type_1 (ctfc, dtd, false, false, true);
|
||||
}
|
||||
|
||||
/* Initial entry point of BTF generation, called at early_finish () after
|
||||
CTF information has possibly been output. Translate all CTF information
|
||||
to BTF, and do any processing that must be done early, such as creating
|
||||
|
@ -1402,7 +1462,7 @@ btf_add_vars (ctf_container_ref ctfc)
|
|||
ctf_dmdef_t *dmd;
|
||||
for (dmd = dtd->dtd_u.dtu_members;
|
||||
dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
|
||||
btf_add_used_type (ctfc, dmd->dmd_type, false, false, true);
|
||||
btf_add_used_type (ctfc, dmd->dmd_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1488,6 +1548,39 @@ btf_assign_var_ids (ctf_container_ref ctfc)
|
|||
}
|
||||
}
|
||||
|
||||
/* Assign BTF IDs for type and decl tags and account for their size. */
|
||||
|
||||
static void
|
||||
btf_assign_tag_ids (ctf_container_ref ctfc)
|
||||
{
|
||||
size_t num_tags = vec_safe_length (ctfc->ctfc_tags);
|
||||
if (num_tags == 0)
|
||||
return;
|
||||
|
||||
unsigned int i;
|
||||
ctf_dtdef_ref dtd;
|
||||
FOR_EACH_VEC_ELT (*ctfc->ctfc_tags, i, dtd)
|
||||
{
|
||||
/* Assign BTF id. */
|
||||
ctf_id_t id = ctfc->ctfc_nextid++;
|
||||
gcc_assert (id <= BTF_MAX_TYPE);
|
||||
dtd->dtd_type = id;
|
||||
|
||||
/* Tags on functions will have a ref_type pointing to the
|
||||
FUNC_PROTO, we want them to point the FUNC record instead. */
|
||||
ctf_dtdef_ref *pdtd = NULL;
|
||||
if (dtd->ref_type && (pdtd = func_map->get (dtd->ref_type)) != NULL)
|
||||
dtd->ref_type = *pdtd;
|
||||
|
||||
/* Strings for tags are stored in the auxiliary strtab, which is
|
||||
concatenated after the regular strtab. ctti_name only accounts
|
||||
for offset in the auxiliary strtab until this point. */
|
||||
dtd->dtd_data.ctti_name += ctfc_get_strtab_len (ctfc, CTF_STRTAB);
|
||||
ctfc->ctfc_num_types++;
|
||||
ctfc->ctfc_num_vlen_bytes += btf_calc_num_vbytes (dtd);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign BTF IDs for datasec records and account for their size. */
|
||||
|
||||
static void
|
||||
|
@ -1522,7 +1615,7 @@ btf_mark_type_used (tree t)
|
|||
if (!dtd)
|
||||
return;
|
||||
|
||||
btf_add_used_type (ctfc, dtd, false, false, true);
|
||||
btf_add_used_type (ctfc, dtd);
|
||||
}
|
||||
|
||||
/* Callback used for assembling the only-used-types list. Note that this is
|
||||
|
@ -1549,7 +1642,7 @@ btf_collect_pruned_types (ctf_container_ref ctfc)
|
|||
size_t i;
|
||||
FOR_EACH_VEC_ELT (*funcs, i, dtd)
|
||||
{
|
||||
btf_add_used_type (ctfc, dtd->ref_type, false, false, true);
|
||||
btf_add_used_type (ctfc, dtd->ref_type);
|
||||
ctf_add_string (ctfc, dtd->dtd_name, &(dtd->dtd_data.ctti_name),
|
||||
CTF_STRTAB);
|
||||
}
|
||||
|
@ -1558,10 +1651,33 @@ btf_collect_pruned_types (ctf_container_ref ctfc)
|
|||
for (i = 0; i < ctfc->ctfc_vars_list_count; i++)
|
||||
{
|
||||
ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[i];
|
||||
btf_add_used_type (ctfc, dvd->dvd_type, false, false, true);
|
||||
btf_add_used_type (ctfc, dvd->dvd_type);
|
||||
ctf_add_string (ctfc, dvd->dvd_name, &(dvd->dvd_name_offset), CTF_STRTAB);
|
||||
}
|
||||
|
||||
/* Used type tags will be added by recursive btf_add_used_type calls above.
|
||||
For decl tags, scan the list and only add those decl tags whose referent
|
||||
types are marked as used. We may have pruned a struct type with members
|
||||
annotated by a decl tag. */
|
||||
FOR_EACH_VEC_ELT (*ctfc->ctfc_tags, i, dtd)
|
||||
{
|
||||
/* Only add decl tags whose referent types have not been pruned.
|
||||
Variables are never pruned, so decl tags on variables are always
|
||||
used. */
|
||||
if (btf_dtd_kind (dtd) == BTF_KIND_DECL_TAG
|
||||
&& ((dtd->ref_type && btf_used_types->contains (dtd->ref_type))
|
||||
|| (dtd->dtd_u.dtu_tag.ref_var)))
|
||||
btf_add_used_type (ctfc, dtd);
|
||||
|
||||
/* Tags on functions or function args will have a ref_type pointing to the
|
||||
FUNC_PROTO, we want them to point the FUNC record instead. */
|
||||
ctf_dtdef_ref *pdtd = NULL;
|
||||
if (dtd->ref_type
|
||||
&& btf_used_types->contains (dtd->ref_type)
|
||||
&& (pdtd = func_map->get (dtd->ref_type)) != NULL)
|
||||
dtd->ref_type = *pdtd;
|
||||
}
|
||||
|
||||
/* Process fixups. If the base type was never added, create a forward for it
|
||||
and adjust the reference to point to that. If it was added, then nothing
|
||||
needs to change. */
|
||||
|
@ -1634,6 +1750,13 @@ btf_finish (void)
|
|||
|
||||
btf_assign_var_ids (tu_ctfc);
|
||||
btf_assign_func_ids (tu_ctfc);
|
||||
|
||||
/* Both decl and type tags may be pruned if the types/decls to which they
|
||||
refer are pruned. This is handled in btf_collect_pruned_types, and
|
||||
through that process they have also been assigned ids already. */
|
||||
if (!debug_prune_btf)
|
||||
btf_assign_tag_ids (tu_ctfc);
|
||||
|
||||
btf_assign_datasec_ids (tu_ctfc);
|
||||
|
||||
/* Finally, write out the complete .BTF section. */
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/* Test simple BTF decl tag generation for variables. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA" } */
|
||||
|
||||
#define __tag1 __attribute__((btf_decl_tag ("decl1")))
|
||||
#define __tag2 __attribute__((btf_decl_tag ("decl2")))
|
||||
#define __tag3 __attribute__((btf_decl_tag ("decl3")))
|
||||
|
||||
int x __tag1 __tag2;
|
||||
int y __tag1;
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'x'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'x'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'y'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
|
@ -0,0 +1,22 @@
|
|||
/* Test BTF decl tag generation for structs. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA" } */
|
||||
|
||||
#define __tag1 __attribute__((btf_decl_tag ("decl1")))
|
||||
#define __tag2 __attribute__((btf_decl_tag ("decl2")))
|
||||
#define __tag3 __attribute__((btf_decl_tag ("decl3")))
|
||||
|
||||
struct Foo {
|
||||
int a;
|
||||
int b __tag3 __tag2;
|
||||
char *z __tag1;
|
||||
};
|
||||
|
||||
struct Foo f __tag1 __tag2;
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'Foo'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl3'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'Foo'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'Foo'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=2" 1} } */
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'f'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 'f'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
|
@ -0,0 +1,22 @@
|
|||
/* Test BTF decl tag generation for functions and function args. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA" } */
|
||||
|
||||
#define __tag1 __attribute__((btf_decl_tag ("decl1")))
|
||||
#define __tag2 __attribute__((btf_decl_tag ("decl2")))
|
||||
#define __tag3 __attribute__((btf_decl_tag ("decl3")))
|
||||
|
||||
int __tag1 __tag2 func (int arg_a __tag3 __tag1, int arg_b __tag2)
|
||||
{
|
||||
return arg_a * arg_b;
|
||||
}
|
||||
|
||||
int foo (int x) {
|
||||
return func (x, x + 1);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_FUNC 'func'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_FUNC 'func'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_FUNC 'func'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=0" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl3'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_FUNC 'func'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=0" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_FUNC 'func'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=1" 1} } */
|
|
@ -0,0 +1,34 @@
|
|||
/* Test BTF decl tag generation with BTF pruning. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -gprune-btf -dA" } */
|
||||
|
||||
#define __decl1 __attribute__((btf_decl_tag ("decl1")))
|
||||
#define __decl2 __attribute__((btf_decl_tag ("decl2")))
|
||||
#define __decl3 __attribute__((btf_decl_tag ("decl3")))
|
||||
|
||||
struct S {
|
||||
/* This tag on S.v shall not be emitted, because struct S is pruned and
|
||||
replaced with a FWD, which does not hold any member info. */
|
||||
int v __decl3;
|
||||
int w;
|
||||
};
|
||||
|
||||
struct T {
|
||||
int a;
|
||||
struct S *s __decl1;
|
||||
int c __decl2;
|
||||
};
|
||||
|
||||
struct T t __decl1;
|
||||
|
||||
int __decl1 func (struct T *t __decl2)
|
||||
{
|
||||
return t->a + t->c;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-not " BTF_KIND_DECL_TAG 'decl3'" } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'T'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT 'T'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=2" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VAR 't'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_FUNC 'func'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=-1" 1} } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 'decl2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_FUNC 'func'\\)\[\\r\\n\]+\[^\\r\\n\]*component_idx=0" 1} } */
|
|
@ -0,0 +1,26 @@
|
|||
/* Test simple generation of BTF type tags. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA" } */
|
||||
|
||||
#define __tag1 __attribute__((btf_type_tag("1")))
|
||||
#define __tag2 __attribute__((btf_type_tag("2")))
|
||||
|
||||
/* var("kp") -> ptr -> type_tag("1") -> int */
|
||||
int * __tag1 kp;
|
||||
|
||||
struct Foo {
|
||||
char a;
|
||||
int b;
|
||||
};
|
||||
|
||||
/* var("f") -> ptr -> type_tag("2") -> type_tag("1") -> struct("Foo") */
|
||||
struct Foo * __tag1 __tag2 f;
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_VAR 'kp'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_INT" 1 } } */
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_VAR 'f'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '1'\\)" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_STRUCT" 1 } } */
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG" 2 } } */
|
|
@ -0,0 +1,13 @@
|
|||
/* Test generation of BTF type tags with cv-quals. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA" } */
|
||||
|
||||
#define __tag __attribute__((btf_type_tag("1")))
|
||||
|
||||
/* var("pci") -> const -> ptr -> type_tag("1") -> int */
|
||||
int __tag *const pci;
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_VAR 'pci'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_CONST" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_CONST ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_INT" 1 } } */
|
|
@ -0,0 +1,28 @@
|
|||
/* Test generation of BTF type tags with typedefs. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA" } */
|
||||
|
||||
#define __tag1 __attribute__((btf_type_tag("1")))
|
||||
#define __tag2 __attribute__((btf_type_tag("2")))
|
||||
|
||||
typedef int *const cp;
|
||||
typedef int __tag1 *tp;
|
||||
|
||||
/* var("x") -> ptr -> type_tag("2") -> typedef("cp") -> const -> ptr -> int */
|
||||
cp __tag2 * x;
|
||||
|
||||
/* var("y") -> const -> typedef("tp") -> ptr -> type_tag("1") -> int */
|
||||
const tp y;
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_VAR 'x'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '2'\\)" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPEDEF 'cp'\\)" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPEDEF 'cp'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_CONST" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_CONST ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_INT" 1 } } */
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_VAR 'y'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_CONST" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_CONST ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPEDEF 'tp'\\)" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPEDEF 'tp'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '1'\\)" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_INT" 1 } } */
|
|
@ -0,0 +1,24 @@
|
|||
/* Test generation of BTF type tag when applied to function prototypes. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA" } */
|
||||
|
||||
#define __tag1 __attribute__((btf_type_tag("1")))
|
||||
#define __tag2 __attribute__((btf_type_tag("2")))
|
||||
|
||||
int * __tag1
|
||||
dothing (void __tag2 *ptr, int __tag2 __tag1 *xi)
|
||||
{
|
||||
if (xi)
|
||||
{
|
||||
int *tmp = (int *) ptr;
|
||||
return tmp + (*xi);
|
||||
}
|
||||
|
||||
return (int *) ptr;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '2'(\[\\r\\n\]+\[^\\r\\n\]*){2} btt_type: void" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_INT" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '1'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '2'" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '1'" 2 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '2'" 1 } } */
|
|
@ -0,0 +1,22 @@
|
|||
/* Test BTF type tag generation using C2x standard attribute syntax.
|
||||
C2x attribute syntax does not allow attributes to "slide around". */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O0 -gbtf -dA -std=c23" } */
|
||||
|
||||
#define __tag1 [[gnu::btf_type_tag ("1")]]
|
||||
#define __tag2 [[gnu::btf_type_tag ("2")]]
|
||||
#define __tag3 [[gnu::btf_type_tag ("3")]]
|
||||
|
||||
/* Note that the BTF format still only allows to represent type tags on
|
||||
pointer types, so we do not get any type_tag("1") from the below, as
|
||||
it applies to the 'volatile int' type and cannot be represented. */
|
||||
|
||||
/* var(z) -> const -> ptr -> type_tag(2) -> type_tag(3) -> ptr -> type_tag(2) -> volatile -> int */
|
||||
volatile int __tag1 * __tag2 * __tag3 __tag2 const z;
|
||||
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_VAR 'z'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_CONST" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_CONST ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_PTR ''(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '2'\\)" 2 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_TYPE_TAG '3'\\)" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '3'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_PTR" 1 } } */
|
||||
/* { dg-final { scan-assembler-times " BTF_KIND_TYPE_TAG '2'(\[\\r\\n\]+\[^\\r\\n\]*){2}\\(BTF_KIND_VOLATILE" 1 } } */
|
|
@ -114,6 +114,8 @@ struct btf_type
|
|||
#define BTF_KIND_VAR 14 /* Variable. */
|
||||
#define BTF_KIND_DATASEC 15 /* Section such as .bss or .data. */
|
||||
#define BTF_KIND_FLOAT 16 /* Floating point. */
|
||||
#define BTF_KIND_DECL_TAG 17 /* Declaration tag. */
|
||||
#define BTF_KIND_TYPE_TAG 18 /* Type tag. */
|
||||
#define BTF_KIND_ENUM64 19 /* Enumeration up to 64 bits. */
|
||||
#define BTF_KIND_MAX BTF_KIND_ENUM64
|
||||
#define NR_BTF_KINDS (BTF_KIND_MAX + 1)
|
||||
|
@ -227,6 +229,18 @@ struct btf_enum64
|
|||
uint32_t val_hi32; /* high 32-bit value for a 64-bit value Enumerator */
|
||||
};
|
||||
|
||||
/* BTF_KIND_DECL_TAG is followed by a single struct btf_decl_tag, which
|
||||
describes the item to which the tag applies:
|
||||
- If component_idx == (uint32_t) -1, then the tag applies to item referred
|
||||
to by the type_id.
|
||||
- Otherwise, the tag applies to the struct or union member, or function
|
||||
argument of the type referred to by type_id with the 0-based index
|
||||
given by component_idx. */
|
||||
struct btf_decl_tag
|
||||
{
|
||||
uint32_t component_idx;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue