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

Reply via email to