This patch updates btfout.cc to be aware of BTF_KIND_DECL_TAG types and output them appropriately.
gcc/ * btfout.cc (funcs_map): New hash map. (btf_emit_preprocess): ... Initialize it here... (btf_collect_datasec): ... Populate it here... (btf_finalize): ... And free it here. (get_btf_kind): Handle BTF_KIND_DECL_TAG. (calc_num_vbytes): Likewise. (btf_asm_type): Likewise. (output_asm_btf_vlen_bytes): Likewise. (btf_asm_type_ref): Update comment. --- gcc/btfout.cc | 79 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 3 deletions(-) diff --git a/gcc/btfout.cc b/gcc/btfout.cc index e6acf4e51a5..087d0b40e0a 100644 --- a/gcc/btfout.cc +++ b/gcc/btfout.cc @@ -104,6 +104,9 @@ static vec<ctf_id_t> voids; created. This vector holds them. */ static GTY (()) vec<ctf_dtdef_ref, va_gc> *funcs; +/* Maps FUNC_PROTO types to the IDs of the corresponding FUNC types. */ +static GTY (()) hash_map <ctf_dtdef_ref, unsigned> *funcs_map; + /* The number of BTF variables added to the TU CTF container. */ static unsigned int num_vars_added = 0; @@ -153,6 +156,7 @@ 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 CTFC_INT_K_DECL_TAG: return BTF_KIND_DECL_TAG; default:; } return BTF_KIND_UNKN; @@ -316,6 +320,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; } @@ -425,13 +433,15 @@ btf_collect_datasec (ctf_container_ref ctfc) func_dtd->dtd_data = dtd->dtd_data; func_dtd->dtd_data.ctti_type = dtd->dtd_type; func_dtd->linkage = dtd->linkage; - func_dtd->dtd_type = num_types_added + num_types_created; + /* +1 for the sentinel type not in the types map. */ + func_dtd->dtd_type = num_types_added + num_types_created + 1; /* Only the BTF_KIND_FUNC type actually references the name. The BTF_KIND_FUNC_PROTO is always anonymous. */ dtd->dtd_data.ctti_name = 0; vec_safe_push (funcs, func_dtd); + funcs_map->put (dtd, func_dtd->dtd_type); num_types_created++; /* Mark any 'extern' funcs and add DATASEC entries for them. */ @@ -449,7 +459,7 @@ btf_collect_datasec (ctf_container_ref ctfc) struct btf_var_secinfo info; /* +1 for the sentinel type not in the types map. */ - info.type = func_dtd->dtd_type + 1; + info.type = func_dtd->dtd_type; /* Both zero at compile time. */ info.size = 0; @@ -653,6 +663,7 @@ btf_emit_preprocess (ctf_container_ref ctfc) } btf_var_ids = hash_map<ctf_dvdef_ref, unsigned int>::create_ggc (100); + funcs_map = hash_map<ctf_dtdef_ref, unsigned int>::create_ggc (100); if (num_ctf_vars) { @@ -709,7 +720,8 @@ btf_asm_type_ref (const char *prefix, ctf_container_ref ctfc, ctf_id_t ref_id) else if (ref_id >= num_types_added + 1 && ref_id < num_types_added + num_vars_added + 1) { - /* Ref to a variable. Should only appear in DATASEC entries. */ + /* Ref to a variable. + Should only appear in DATASEC entries or DECL_TAGs. */ ctf_id_t var_id = btf_relative_var_id (ref_id); ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[var_id]; dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_VAR '%s')", @@ -831,6 +843,59 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd) and should write 0. */ dw2_asm_output_data (4, 0, "(unused)"); return; + case BTF_KIND_DECL_TAG: + { + /* A decl tag might refer to (be the child DIE of) a variable. Try to + lookup the parent DIE's CTF variable, and if it exists point to the + corresponding BTF variable. This is an odd construction - we have a + 'type' which refers to a variable, rather than the reverse. */ + dw_die_ref parent = get_die_parent (dtd->dtd_key); + ctf_dvdef_ref ref_dvd = ctf_dvd_lookup (ctfc, parent); + ctf_dtdef_ref ref_dtd = ctf_dtd_lookup (ctfc, parent); + if (ref_dvd) + { + /* The decl tag is on a variable. */ + unsigned int *var_id = btf_var_ids->get (ref_dvd); + gcc_assert (var_id); + btf_asm_type_ref ("btt_type", ctfc, + btf_absolute_var_id (*var_id)); + return; + } + else if (ref_dtd) + { + /* Decl tags on functions refer to the FUNC_PROTO record as a + result of how they are created. But we want them in the output + to refer to the synthesized FUNC record instead. */ + unsigned int *func_id = funcs_map->get (ref_dtd); + gcc_assert (func_id); + btf_asm_type_ref ("btt_type", ctfc, *func_id); + return; + } + else if (parent && dw_get_die_tag (parent) == DW_TAG_formal_parameter) + { + /* The decl tag is on a function argument. In this case we refer + to the FUNC record, and component_index indicates to which + parameter the tag applies. */ + ref_dtd = ctf_dtd_lookup (ctfc, get_die_parent (parent)); + unsigned int *func_id = funcs_map->get (ref_dtd); + gcc_assert (func_id); + btf_asm_type_ref ("btt_type", ctfc, *func_id); + return; + } + else if (parent && dw_get_die_tag (parent) == DW_TAG_member) + { + /* The decl tag is on a struct/union member. In this case we refer + to the struct/union record, and component_index indicates to + which member the tag applies. */ + ref_dtd = ctf_dtd_lookup (ctfc, get_die_parent (parent)); + ctf_id_t ref_id = get_btf_id (ref_dtd->dtd_type); + btf_asm_type_ref ("btt_type", ctfc, ref_id); + return; + } + + /* There are no other valid places for decl tag to appear. */ + gcc_unreachable (); + } default: break; } @@ -1177,6 +1242,11 @@ 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_btfnote.component_idx, + "decltag_compidx"); + break; + default: /* All other BTF type kinds have no variable length data. */ break; @@ -1384,6 +1454,9 @@ btf_finalize (void) btf_var_ids->empty (); btf_var_ids = NULL; + funcs_map->empty (); + funcs_map = NULL; + free (btf_id_map); btf_id_map = NULL; -- 2.40.1