[gdb] Skip imports of c++ CUs
authorTom de Vries <tdevries@suse.de>
Tue, 17 Mar 2020 07:56:36 +0000 (08:56 +0100)
committerTom de Vries <tdevries@suse.de>
Tue, 17 Mar 2020 07:56:36 +0000 (08:56 +0100)
The DWARF standard appendix E.1 describes techniques that can be used for
compression and deduplication: DIEs can be factored out into a new compilation
unit, and referenced using DW_FORM_ref_addr.

Such a new compilation unit can either use a DW_TAG_compile_unit or
DW_TAG_partial_unit.  If a DW_TAG_compile_unit is used, its contents is
evaluated by consumers as though it were an ordinary compilation unit.  If a
DW_TAG_partial_unit is used, it's only considered by consumers in the context
of a DW_TAG_imported_unit.

An example of when DW_TAG_partial_unit is required is when the factored out
DIEs are not top-level, f.i. because they were children of a namespace.  In
such a case the corresponding DW_TAG_imported_unit will occur as child of the
namespace.

In the case of factoring out DIEs from c++ compilation units, we can factor
out into a new DW_TAG_compile_unit, and no DW_TAG_imported_unit is required.

This begs the question how to interpret a top-level DW_TAG_imported_unit of a
c++ DW_TAG_compile_unit compilation unit.  The semantics of
DW_TAG_imported_unit describe that the imported unit logically appears at the
point of the DW_TAG_imported_unit entry.  But it's not clear what the effect
should be in this case, since all the imported DIEs are already globally
visible anyway, due to the use of DW_TAG_compile_unit.

So, skip top-level imports of c++ DW_TAG_compile_unit compilation units in
process_imported_unit_die.

Using the cc1 binary from PR23710 comment 1 and setting a breakpoint on do_rpo_vn:
...
$ gdb \
    -batch \
    -iex "maint set dwarf max-cache-age 316" \
    -iex "set language c++" \
    -ex "b do_rpo_vn" \
    cc1
...
we get a 8.1% reduction in execution time, due to reducing the number of
partial symtabs expanded into full symtabs from 212 to 175.

Build and reg-tested on x86_64-linux.

gdb/ChangeLog:

2020-03-17  Tom de Vries  <tdevries@suse.de>

PR gdb/23710
* dwarf2/read.h (struct dwarf2_per_cu_data): Add unit_type and lang
fields.
* dwarf2/read.c (process_psymtab_comp_unit): Initialize unit_type and lang
fields.
(process_imported_unit_die): Skip import of c++ CUs.

gdb/ChangeLog
gdb/dwarf2/read.c
gdb/dwarf2/read.h

index cfd8c5b9d245ccd11513f6f6ee1644af8421f851..3c9215060a93c12469ababe932be382efecce662 100644 (file)
@@ -1,3 +1,12 @@
+2020-03-17  Tom de Vries  <tdevries@suse.de>
+
+       PR gdb/23710
+       * dwarf2/read.h (struct dwarf2_per_cu_data): Add unit_type and lang
+       fields.
+       * dwarf2/read.c (process_psymtab_comp_unit): Initialize unit_type and lang
+       fields.
+       (process_imported_unit_die): Skip import of c++ CUs.
+
 2020-03-16  Tom Tromey  <tom@tromey.com>
 
        * p-valprint.c (pascal_object_print_value): Initialize
index 88a60c1c73bb20543cd54e8ee9d2b7231c439688..0e879e08a0c0ba02c7dbafee7250eaf372f64287 100644 (file)
@@ -7425,6 +7425,18 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
 
   cutu_reader reader (this_cu, NULL, 0, false);
 
+  switch (reader.comp_unit_die->tag)
+    {
+    case DW_TAG_compile_unit:
+      this_cu->unit_type = DW_UT_compile;
+      break;
+    case DW_TAG_partial_unit:
+      this_cu->unit_type = DW_UT_partial;
+      break;
+    default:
+      abort ();
+    }
+
   if (reader.dummy_p)
     {
       /* Nothing.  */
@@ -7438,6 +7450,8 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
                                      reader.comp_unit_die,
                                      pretend_language);
 
+  this_cu->lang = this_cu->cu->language;
+
   /* Age out any secondary CUs.  */
   age_cached_comp_units (this_cu->dwarf2_per_objfile);
 }
@@ -9759,6 +9773,14 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
        = dwarf2_find_containing_comp_unit (sect_off, is_dwz,
                                            cu->per_cu->dwarf2_per_objfile);
 
+      /* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
+        into another compilation unit, at root level.  Regard this as a hint,
+        and ignore it.  */
+      if (die->parent && die->parent->parent == NULL
+         && per_cu->unit_type == DW_UT_compile
+         && per_cu->lang == language_cplus)
+       return;
+
       /* If necessary, add it to the queue and load its DIEs.  */
       if (maybe_queue_comp_unit (cu, per_cu, cu->language))
        load_full_comp_unit (per_cu, false, cu->language);
index 00652c2b45a71dec209167c1df67bb6006bd35bc..f0e3d6bb7238e60ddc20c7b845bc80b005cb88bc 100644 (file)
@@ -323,6 +323,12 @@ struct dwarf2_per_cu_data
      dummy CUs (a CU header, but nothing else).  */
   struct dwarf2_cu *cu;
 
+  /* The unit type of this CU.  */
+  enum dwarf_unit_type unit_type;
+
+  /* The language of this CU.  */
+  enum language lang;
+
   /* The corresponding dwarf2_per_objfile.  */
   struct dwarf2_per_objfile *dwarf2_per_objfile;