gdb/dwarf: remove type_unit_group

The type_unit_group is an indirection between a stmt_list_hash (possible
dwo_unit + line table section offset) and a type_unit_group_unshareable
that provides no real value.  In dwarf2_per_objfile, we maintain a
stmt_list_hash -> type_unit_group mapping, and in dwarf2_per_objfile, we
maintain a type_unit_group_unshareable mapping.  The type_unit_group
type is empty and only exists to have an identity and to be a link
between the two mappings.

This patch changes it so that we have a single stmt_list_hash ->
type_unit_group_unshareable mapping.

Regression tested on Debian 12 amd64 with a bunch of DWARF target
boards.

Change-Id: I9c5778ecb18963f353e9dd058e0f8152f7d8930c
Approved-By: Tom Tromey <tom@tromey.com>
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 68bba49..b9040a5 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -265,29 +265,6 @@ struct loclists_rnglists_header
   unsigned int offset_entry_count;
 };
 
-/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
-   This includes type_unit_group and quick_file_names.  */
-
-struct stmt_list_hash
-{
-  bool operator== (const stmt_list_hash &other) const noexcept;
-
-  /* The DWO unit this table is from or NULL if there is none.  */
-  struct dwo_unit *dwo_unit;
-
-  /* Offset in .debug_line or .debug_line.dwo.  */
-  sect_offset line_sect_off;
-};
-
-/* Each element of dwarf2_per_bfd->type_unit_groups is a pointer to
-   an object of this type.  This contains elements of type unit groups
-   that can be shared across objfiles.  The non-shareable parts are in
-   type_unit_group_unshareable.  */
-
-struct type_unit_group
-{
-};
-
 /* These sections are what may appear in a (real or virtual) DWO file.  */
 
 struct dwo_sections
@@ -2552,7 +2529,7 @@ fill_in_sig_entry_from_dwo_entry (dwarf2_per_objfile *per_objfile,
   gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0
 	      || (to_underlying (sig_entry->type_offset_in_section)
 		  == to_underlying (dwo_entry->type_offset_in_tu)));
-  gdb_assert (sig_entry->type_unit_group == NULL);
+  gdb_assert (!sig_entry->type_unit_group_key.has_value ());
   gdb_assert (sig_entry->dwo_unit == NULL
 	      || sig_entry->dwo_unit == dwo_entry);
 
@@ -3279,14 +3256,13 @@ cutu_reader::cutu_reader (dwarf2_per_cu *this_cu,
 #define NO_STMT_LIST_TYPE_UNIT_PSYMTAB (1 << 31)
 #define NO_STMT_LIST_TYPE_UNIT_PSYMTAB_SIZE 10
 
-/* Look up the type_unit_group for type unit CU, and create it if necessary.
-   STMT_LIST is a DW_AT_stmt_list attribute.  */
+/* Get the type unit group key for type unit CU.  STMT_LIST is a DW_AT_stmt_list
+   attribute.  */
 
-static struct type_unit_group *
-get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
+static stmt_list_hash
+get_type_unit_group_key (struct dwarf2_cu *cu, const struct attribute *stmt_list)
 {
   dwarf2_per_objfile *per_objfile = cu->per_objfile;
-  dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
   struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
   unsigned int line_offset;
 
@@ -3310,16 +3286,7 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
       ++tu_stats->nr_stmt_less_type_units;
     }
 
-  stmt_list_hash key {cu->dwo_unit, static_cast<sect_offset> (line_offset)};
-  auto [it, inserted] = per_bfd->type_unit_groups.emplace (key, nullptr);
-
-  if (inserted)
-    {
-      (*it).second = std::make_unique<type_unit_group> ();
-      ++tu_stats->nr_symtabs;
-    }
-
-  return it->second.get ();
+  return {cu->dwo_unit, static_cast<sect_offset> (line_offset)};
 }
 
 /* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
@@ -3424,9 +3391,6 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
   abbrev_table_up abbrev_table;
   sect_offset abbrev_offset;
 
-  /* It's up to the caller to not call us multiple times.  */
-  gdb_assert (per_objfile->per_bfd->type_unit_groups.empty ());
-
   if (per_objfile->per_bfd->all_type_units.size () == 0)
     return;
 
@@ -4753,16 +4717,15 @@ rust_union_quirks (struct dwarf2_cu *cu)
 /* See read.h.  */
 
 type_unit_group_unshareable *
-dwarf2_per_objfile::get_type_unit_group_unshareable (type_unit_group *tu_group)
+dwarf2_per_objfile::get_type_unit_group_unshareable
+  (stmt_list_hash tu_group_key)
 {
-  auto iter = m_type_units.find (tu_group);
-  if (iter != m_type_units.end ())
-    return iter->second.get ();
+  auto [it, inserted] = m_type_units.emplace (tu_group_key, nullptr);
 
-  type_unit_group_unshareable_up uniq (new type_unit_group_unshareable);
-  type_unit_group_unshareable *result = uniq.get ();
-  m_type_units[tu_group] = std::move (uniq);
-  return result;
+  if (inserted)
+    it->second = std::make_unique<type_unit_group_unshareable> ();
+
+  return it->second.get ();
 }
 
 struct type *
@@ -5034,7 +4997,7 @@ process_full_type_unit (dwarf2_cu *cu)
      of it with end_expandable_symtab.  Otherwise, complete the addition of
      this TU's symbols to the existing symtab.  */
   type_unit_group_unshareable *tug_unshare =
-    per_objfile->get_type_unit_group_unshareable (sig_type->type_unit_group);
+    per_objfile->get_type_unit_group_unshareable (*sig_type->type_unit_group_key);
   if (tug_unshare->compunit_symtab == NULL)
     {
       buildsym_compunit *builder = cu->get_builder ();
@@ -6222,7 +6185,6 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 void
 dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 {
-  struct type_unit_group *tu_group;
   int first_time;
   struct attribute *attr;
   unsigned int i;
@@ -6235,16 +6197,15 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die)
 
   /* If we're using .gdb_index (includes -readnow) then
      per_cu->type_unit_group may not have been set up yet.  */
-  if (sig_type->type_unit_group == NULL)
-    sig_type->type_unit_group = get_type_unit_group (this, attr);
-  tu_group = sig_type->type_unit_group;
+  if (!sig_type->type_unit_group_key.has_value ())
+    sig_type->type_unit_group_key = get_type_unit_group_key (this, attr);
 
   /* If we've already processed this stmt_list there's no real need to
      do it again, we could fake it and just recreate the part we need
      (file name,index -> symtab mapping).  If data shows this optimization
      is useful we can do it then.  */
   type_unit_group_unshareable *tug_unshare
-    = per_objfile->get_type_unit_group_unshareable (tu_group);
+    = per_objfile->get_type_unit_group_unshareable (*sig_type->type_unit_group_key);
   first_time = tug_unshare->compunit_symtab == NULL;
 
   /* We have to handle the case of both a missing DW_AT_stmt_list or bad
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 44fd7e9..ba2dd07 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -55,7 +55,6 @@ struct dwarf2_per_cu;
 struct mapped_index;
 struct mapped_debug_names;
 struct signatured_type;
-struct type_unit_group;
 
 /* One item on the queue of compilation units to read in full symbols
    for.  */
@@ -74,6 +73,27 @@ struct dwarf2_queue_item
   dwarf2_per_objfile *per_objfile;
 };
 
+/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
+   This includes type_unit_group and quick_file_names.  */
+
+struct stmt_list_hash
+{
+  bool operator== (const stmt_list_hash &other) const noexcept;
+
+  /* The DWO unit this table is from or NULL if there is none.  */
+  struct dwo_unit *dwo_unit;
+
+  /* Offset in .debug_line or .debug_line.dwo.  */
+  sect_offset line_sect_off;
+};
+
+struct stmt_list_hash_hash
+{
+  using is_avalanching = void;
+
+  std::uint64_t operator() (const stmt_list_hash &key) const noexcept;
+};
+
 /* A deleter for dwarf2_per_cu that knows to downcast to signatured_type as
    appropriate.  This approach lets us avoid a virtual destructor, which saves
    a bit of space.  */
@@ -376,8 +396,9 @@ struct signatured_type : public dwarf2_per_cu
   sect_offset type_offset_in_section {};
 
   /* Type units are grouped by their DW_AT_stmt_list entry so that they
-     can share them.  This points to the containing symtab.  */
-  struct type_unit_group *type_unit_group = nullptr;
+     can share them.  This is the key of the group this type unit is part
+     of.  */
+  std::optional<stmt_list_hash> type_unit_group_key;
 
   /* Containing DWO unit.
      This field is valid iff per_cu.reading_dwo_directly.  */
@@ -467,17 +488,6 @@ struct dwp_file;
 
 using dwp_file_up = std::unique_ptr<dwp_file>;
 
-struct stmt_list_hash;
-
-struct stmt_list_hash_hash
-{
-  using is_avalanching = void;
-
-  std::uint64_t operator() (const stmt_list_hash &key) const noexcept;
-};
-
-using type_unit_group_up = std::unique_ptr<type_unit_group>;
-
 /* Some DWARF data can be shared across objfiles who share the same BFD,
    this data is stored in this object.
 
@@ -614,11 +624,6 @@ struct dwarf2_per_bfd
   std::vector<dwarf2_per_cu *> all_comp_units_index_cus;
   std::vector<dwarf2_per_cu *> all_comp_units_index_tus;
 
-  /* Table of struct type_unit_group objects.
-     The hash key is the DW_AT_stmt_list value.  */
-  gdb::unordered_map<stmt_list_hash, type_unit_group_up, stmt_list_hash_hash>
-    type_unit_groups;
-
   /* Set of signatured_types, used to look up by signature.  */
   signatured_type_set signatured_types;
 
@@ -828,10 +833,10 @@ struct dwarf2_per_objfile
   /* Set the compunit_symtab associated to PER_CU.  */
   void set_symtab (const dwarf2_per_cu *per_cu, compunit_symtab *symtab);
 
-  /* Get the type_unit_group_unshareable corresponding to TU_GROUP.  If one
+  /* Get the type_unit_group_unshareable corresponding to TU_GROUP_KEY.  If one
      does not exist, create it.  */
   type_unit_group_unshareable *get_type_unit_group_unshareable
-    (type_unit_group *tu_group);
+    (stmt_list_hash tu_group_key);
 
   struct type *get_type_for_signatured_type (signatured_type *sig_type) const;
 
@@ -898,9 +903,10 @@ struct dwarf2_per_objfile
      expanded yet.  */
   std::vector<compunit_symtab *> m_symtabs;
 
-  /* Map from a type unit group to the corresponding unshared
+  /* Map from a type unit group key to the corresponding unshared
      structure.  */
-  gdb::unordered_map<type_unit_group *, type_unit_group_unshareable_up>
+  gdb::unordered_map<stmt_list_hash, type_unit_group_unshareable_up,
+		     stmt_list_hash_hash>
     m_type_units;
 
   /* Map from signatured types to the corresponding struct type.  */