@@ -2253,6 +2253,10 @@ flto-partition=
Common Joined RejectNegative Enum(lto_partition_model) Var(flag_lto_partition) Init(LTO_PARTITION_BALANCED)
Specify the algorithm to partition symbols and vars at linktime.
+flto-debuginfo-assume-unique-filepaths
+Common Var(flag_lto_debuginfo_assume_unique_filepaths) Init(0)
+Assume all linked source files have unique filepaths.
+
; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h.
flto-compression-level=
Common Joined RejectNegative UInteger Var(flag_lto_compression_level) Init(-1) IntegerRange(0, 19)
@@ -8015,9 +8015,17 @@ compute_comp_unit_symbol (dw_die_ref unit_die)
the name filename of the unit. */
md5_init_ctx (&ctx);
- mark = 0;
- die_checksum (unit_die, &ctx, &mark);
- unmark_all_dies (unit_die);
+ if (flag_lto_debuginfo_assume_unique_filepaths)
+ {
+ gcc_assert (die_name);
+ md5_process_bytes (die_name, strlen (die_name), &ctx);
+ }
+ else
+ {
+ mark = 0;
+ die_checksum (unit_die, &ctx, &mark);
+ unmark_all_dies (unit_die);
+ }
md5_finish_ctx (&ctx, checksum);
/* When we this for comp_unit_die () we have a DW_AT_name that might
@@ -33119,6 +33127,110 @@ ctf_debug_do_cu (dw_die_ref die)
FOR_EACH_CHILD (die, c, ctf_do_die (c));
}
+/* Recursively compute die symbols from DIE's attributes.
+ Not all symbols can be computed this way. */
+static void
+compute_die_symbols_from_die (dw_die_ref die)
+{
+ dw_attr_node *a;
+ int i;
+ const char* name = NULL;
+
+ if (!die->die_attr)
+ return;
+
+ switch (die->die_tag)
+ {
+ /* Assumed that each die parent has at most single children namespace
+ with the same name. */
+ case DW_TAG_namespace:
+ case DW_TAG_module:
+
+ FOR_EACH_VEC_ELT (*die->die_attr, i, a)
+ {
+ if (a->dw_attr == DW_AT_name)
+ name = AT_string (a);
+ /* Ignored DW_AT_abstract_origin, leads to duplicates. */
+ }
+ break;
+
+ default: break;
+ }
+
+ if (name)
+ {
+ gcc_assert (!die->die_id.die_symbol);
+ gcc_assert (die->die_parent);
+
+ const char* parent_symbol = die->die_parent->die_id.die_symbol;
+ /* Prefix with parent symbol to guarantee uniqueness. Important for
+ namespaces. Toplevel functions and variables can and do use just
+ comp_unit's symbol as prefix. Die symbols of these toplevel symbols
+ may overlap. Use the 'r' to differentiate. */
+ die->die_id.die_symbol = concat (parent_symbol, ".r.", name, NULL);
+ }
+
+ /* Splitting functions has little to no benefit. */
+ if (die->die_tag == DW_TAG_subprogram)
+ return;
+
+ dw_die_ref c;
+ if (!die->comdat_type_p && die->die_id.die_symbol)
+ FOR_EACH_CHILD (die, c, compute_die_symbols_from_die (c));
+}
+
+/* Compute die symbols and insert them into their DIEs.
+ All die symbols must be unique across compilation units. */
+static void
+compute_die_symbols ()
+{
+ dw_die_ref comp_unit = comp_unit_die ();
+ compute_comp_unit_symbol (comp_unit);
+
+ /* For Incremental LTO we are interested in stable 'die_symbol+offset'.
+ By computing and emmiting die_symbols for more DIEs we get more local
+ and stable offsets. */
+ if (flag_generate_lto && flag_lto_debuginfo_assume_unique_filepaths)
+ {
+ /* Information about functions is not fully contained in DIEs. Must be
+ done separatelly.
+ DIE might not contain DW_AT_linkage_name and DW_AT_name may be not
+ unique. Even when contained, DW_AT_linkage_name does not have to be
+ unique. */
+ const char* base = comp_unit->die_id.die_symbol;
+ symtab_node *node;
+ FOR_EACH_SYMBOL (node)
+ {
+ /* There may be multiple functions with the same asm_name.
+ This is rare, so we don't handle them. */
+ if (node->next_sharing_asm_name || node->previous_sharing_asm_name)
+ continue;
+
+ const char* asm_name = node->asm_name ();
+ /* Mimic what assemble_name_raw does with a leading '*'. */
+ if (asm_name[0] == '*')
+ asm_name = &asm_name[1];
+
+ dw_die_ref decl_die = lookup_decl_die (node->decl);
+ if (decl_die)
+ decl_die->die_id.die_symbol = concat (base, ".s.", asm_name, NULL);
+
+ tree origin = DECL_ABSTRACT_ORIGIN (node->decl);
+ dw_die_ref origin_die = origin ? lookup_decl_die (origin) : NULL;
+ if (origin_die)
+ {
+ asm_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (origin));
+ origin_die->die_id.die_symbol = concat (base, ".s.", asm_name,
+ NULL);
+ }
+ }
+
+ /* Other needed die symbols can be computed from DIE informatation
+ alone. */
+ compute_die_symbols_from_die (comp_unit);
+ }
+}
+
/* Perform any cleanups needed after the early debug generation pass
has run. */
@@ -33338,7 +33450,7 @@ dwarf2out_early_finish (const char *filename)
}
/* Stick a unique symbol to the main debuginfo section. */
- compute_comp_unit_symbol (comp_unit_die ());
+ compute_die_symbols ();
/* Output the main compilation unit. We always need it if only for
the CU symbol. */
new file mode 100644
@@ -0,0 +1,12 @@
+/* { dg-lto-do assemble } */
+/* { dg-lto-options { { -O2 -g -flto -flto-debuginfo-assume-unique-filepaths } } } */
+
+/* DIE symbols computed from names might conflict. */
+
+namespace foo {
+ void foo () asm ("foo");
+}
+
+int main () {
+ foo::foo ();
+}