gdb: introduce symtab_create_debug_printf
[binutils-gdb.git] / gdb / dwarf2 / cooked-index.h
index 0a38fc88e52bca428c19c4fae968a76ee5998063..f3c26480a81e2507d0cd3927b8b90dd893170c3d 100644 (file)
 #include "gdbsupport/gdb_obstack.h"
 #include "addrmap.h"
 #include "gdbsupport/iterator-range.h"
+#include "gdbsupport/thread-pool.h"
+#include "dwarf2/mapped-index.h"
+#include "dwarf2/tag.h"
+#include "gdbsupport/range-chain.h"
 
 struct dwarf2_per_cu_data;
 
@@ -105,11 +109,13 @@ struct cooked_index_entry : public allocate_on_obstack
     switch (kind)
       {
       case VARIABLES_DOMAIN:
-       return tag == DW_TAG_variable;
+       return (tag == DW_TAG_variable
+               || tag == DW_TAG_constant
+               || tag == DW_TAG_enumerator);
       case FUNCTIONS_DOMAIN:
        return tag == DW_TAG_subprogram;
       case TYPES_DOMAIN:
-       return tag == DW_TAG_typedef || tag == DW_TAG_structure_type;
+       return tag_is_type (tag);
       case MODULES_DOMAIN:
        return tag == DW_TAG_module;
       }
@@ -155,6 +161,8 @@ private:
   void write_scope (struct obstack *storage, const char *sep) const;
 };
 
+class cooked_index_vector;
+
 /* An index of interesting DIEs.  This is "cooked", in contrast to a
    mapped .debug_names or .gdb_index, which are "raw".  An entry in
    the index is of type cooked_index_entry.
@@ -166,9 +174,7 @@ class cooked_index
 {
 public:
   cooked_index () = default;
-  explicit cooked_index (cooked_index &&other) = default;
   DISABLE_COPY_AND_ASSIGN (cooked_index);
-  cooked_index &operator= (cooked_index &&other) = default;
 
   /* Create a new cooked_index_entry and register it with this object.
      Entries are owned by this object.  The new item is returned.  */
@@ -178,56 +184,57 @@ public:
                                 const cooked_index_entry *parent_entry,
                                 dwarf2_per_cu_data *per_cu);
 
-  /* Return the entry that is believed to represent the program's
-     "main".  This will return NULL if no such entry is available.  */
-  const cooked_index_entry *get_main () const
-  {
-    return m_main;
-  }
-
   /* Install a new fixed addrmap from the given mutable addrmap.  */
-  void install_addrmap (addrmap *map)
+  void install_addrmap (addrmap_mutable *map)
   {
     gdb_assert (m_addrmap == nullptr);
-    m_addrmap = addrmap_create_fixed (map, &m_storage);
-  }
-
-  /* Look up ADDR in the address map, and return either the
-     corresponding CU, or nullptr if the address could not be
-     found.  */
-  dwarf2_per_cu_data *lookup (CORE_ADDR addr)
-  {
-    return (dwarf2_per_cu_data *) addrmap_find (m_addrmap, addr);
+    m_addrmap = new (&m_storage) addrmap_fixed (&m_storage, map);
   }
 
   /* Finalize the index.  This should be called a single time, when
      the index has been fully populated.  It enters all the entries
-     into the internal hash table.  */
+     into the internal table.  */
   void finalize ();
 
+  /* Wait for this index's finalization to be complete.  */
+  void wait ()
+  {
+    m_future.wait ();
+  }
+
+  friend class cooked_index_vector;
+
   /* A simple range over part of m_entries.  */
   typedef iterator_range<std::vector<cooked_index_entry *>::iterator> range;
 
-  /* Look up an entry by name.  Returns a range of all matching
-     results.  If COMPLETING is true, then a larger range, suitable
-     for completion, will be returned.  */
-  range find (gdb::string_view name, bool completing);
-
   /* Return a range of all the entries.  */
   range all_entries ()
   {
+    wait ();
     return { m_entries.begin (), m_entries.end () };
   }
 
+  /* Look up an entry by name.  Returns a range of all matching
+     results.  If COMPLETING is true, then a larger range, suitable
+     for completion, will be returned.  */
+  range find (gdb::string_view name, bool completing);
+
 private:
 
-  /* GNAT only emits mangled ("encoded") names in the DWARF, and does
-     not emit the module structure.  However, we need this structure
-     to do lookups.  This function recreates that structure for an
-     existing entry.  It returns the base name (last element) of the
-     full decoded name.  */
-  gdb::unique_xmalloc_ptr<char> handle_gnat_encoded_entry
-       (cooked_index_entry *entry, htab_t gnat_entries);
+  /* Return the entry that is believed to represent the program's
+     "main".  This will return NULL if no such entry is available.  */
+  const cooked_index_entry *get_main () const
+  {
+    return m_main;
+  }
+
+  /* Look up ADDR in the address map, and return either the
+     corresponding CU, or nullptr if the address could not be
+     found.  */
+  dwarf2_per_cu_data *lookup (CORE_ADDR addr)
+  {
+    return (dwarf2_per_cu_data *) m_addrmap->find (addr);
+  }
 
   /* Create a new cooked_index_entry and register it with this object.
      Entries are owned by this object.  The new item is returned.  */
@@ -243,6 +250,17 @@ private:
                                                per_cu);
   }
 
+  /* GNAT only emits mangled ("encoded") names in the DWARF, and does
+     not emit the module structure.  However, we need this structure
+     to do lookups.  This function recreates that structure for an
+     existing entry.  It returns the base name (last element) of the
+     full decoded name.  */
+  gdb::unique_xmalloc_ptr<char> handle_gnat_encoded_entry
+       (cooked_index_entry *entry, htab_t gnat_entries);
+
+  /* A helper method that does the work of 'finalize'.  */
+  void do_finalize ();
+
   /* Storage for the entries.  */
   auto_obstack m_storage;
   /* List of all entries.  */
@@ -250,11 +268,95 @@ private:
   /* If we found "main" or an entry with 'is_main' set, store it
      here.  */
   cooked_index_entry *m_main = nullptr;
-  /* Storage for canonical names.  */
-  std::vector<gdb::unique_xmalloc_ptr<char>> m_names;
   /* The addrmap.  This maps address ranges to dwarf2_per_cu_data
      objects.  */
   addrmap *m_addrmap = nullptr;
+  /* Storage for canonical names.  */
+  std::vector<gdb::unique_xmalloc_ptr<char>> m_names;
+  /* A future that tracks when the 'finalize' method is done.  Note
+     that the 'get' method is never called on this future, only
+     'wait'.  */
+  gdb::future<void> m_future;
+};
+
+/* The main index of DIEs.  The parallel DIE indexers create
+   cooked_index objects.  Then, these are all handled to a
+   cooked_index_vector for storage and final indexing.  The index is
+   made by iterating over the entries previously created.  */
+
+class cooked_index_vector : public dwarf_scanner_base
+{
+public:
+
+  /* A convenience typedef for the vector that is contained in this
+     object.  */
+  typedef std::vector<std::unique_ptr<cooked_index>> vec_type;
+
+  explicit cooked_index_vector (vec_type &&vec);
+  DISABLE_COPY_AND_ASSIGN (cooked_index_vector);
+
+  /* Wait until the finalization of the entire cooked_index_vector is
+     done.  */
+  void wait ()
+  {
+    for (auto &item : m_vector)
+      item->wait ();
+  }
+
+  ~cooked_index_vector ()
+  {
+    /* The 'finalize' methods may be run in a different thread.  If
+       this object is destroyed before these complete, then one will
+       end up writing to freed memory.  Waiting for finalization to
+       complete avoids this problem; and the cost seems ignorable
+       because creating and immediately destroying the debug info is a
+       relatively rare thing to do.  */
+    wait ();
+  }
+
+  /* A range over a vector of subranges.  */
+  typedef range_chain<cooked_index::range> range;
+
+  /* Look up an entry by name.  Returns a range of all matching
+     results.  If COMPLETING is true, then a larger range, suitable
+     for completion, will be returned.  */
+  range find (gdb::string_view name, bool completing);
+
+  /* Return a range of all the entries.  */
+  range all_entries ()
+  {
+    std::vector<cooked_index::range> result_range;
+    result_range.reserve (m_vector.size ());
+    for (auto &entry : m_vector)
+      result_range.push_back (entry->all_entries ());
+    return range (std::move (result_range));
+  }
+
+  /* Look up ADDR in the address map, and return either the
+     corresponding CU, or nullptr if the address could not be
+     found.  */
+  dwarf2_per_cu_data *lookup (CORE_ADDR addr);
+
+  /* Return a new vector of all the addrmaps used by all the indexes
+     held by this object.  */
+  std::vector<addrmap *> get_addrmaps ();
+
+  /* Return the entry that is believed to represent the program's
+     "main".  This will return NULL if no such entry is available.  */
+  const cooked_index_entry *get_main () const;
+
+  cooked_index_vector *index_for_writing () override
+  {
+    return this;
+  }
+
+  quick_symbol_functions_up make_quick_functions () const override;
+
+private:
+
+  /* The vector of cooked_index objects.  This is stored because the
+     entries are stored on the obstacks in those objects.  */
+  vec_type m_vector;
 };
 
 #endif /* GDB_DWARF2_COOKED_INDEX_H */