https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90778

            Bug ID: 90778
           Summary: Strange differences in D runtime debug-info between
                    builds
           Product: gcc
           Version: 9.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: d
          Assignee: ibuclaw at gdcproject dot org
          Reporter: rguenth at gcc dot gnu.org
  Target Milestone: ---

We see builds of the D runtime be not reproducible when compiling from the
same source multiple times.  This for example shows in
libdruntime/rt/lifetime.d
objects which have

@@ -3853,17 +3853,17 @@
     <2212>   DW_AT_location    : 0x1692 (location list)
     <2216>   DW_AT_GNU_locviews: 0x1684
  <2><221a>: Abbrev Number: 48 (DW_TAG_label)
-    <221b>   DW_AT_name        : (indirect string, offset: 0x22f2): Lcontinue
+    <221b>   DW_AT_name        : (indirect string, offset: 0xcac): Loverflow
     <221f>   DW_AT_decl_file   : 1
-    <2220>   DW_AT_decl_line   : 784
+    <2220>   DW_AT_decl_line   : 781
     <2222>   DW_AT_decl_column : 1
-    <2223>   DW_AT_low_pc      : 0xaaa
+    <2223>   DW_AT_low_pc      : 0xe4e
  <2><222b>: Abbrev Number: 48 (DW_TAG_label)
-    <222c>   DW_AT_name        : (indirect string, offset: 0xcdc): Loverflow
+    <222c>   DW_AT_name        : (indirect string, offset: 0x22f2): Lcontinue
     <2230>   DW_AT_decl_file   : 1
-    <2231>   DW_AT_decl_line   : 781
+    <2231>   DW_AT_decl_line   : 784
     <2233>   DW_AT_decl_column : 1
-    <2234>   DW_AT_low_pc      : 0xe4e
+    <2234>   DW_AT_low_pc      : 0xaaa
  <2><223c>: Abbrev Number: 9 (DW_TAG_variable)
     <223d>   DW_AT_name        : tgt
     <2241>   DW_AT_decl_file   : 1

which appears in

 <1><21b2>: Abbrev Number: 21 (DW_TAG_subprogram)
    <21b3>   DW_AT_external    : 1
    <21b3>   DW_AT_name        : (indirect string, offset: 0x880):
_d_arraysetcapacity
    <21b7>   DW_AT_decl_file   : 1
    <21b8>   DW_AT_decl_line   : 734
    <21ba>   DW_AT_decl_column : 18
    <21bb>   DW_AT_type        : <0x29>
    <21bf>   DW_AT_low_pc      : 0xa00
    <21c7>   DW_AT_high_pc     : 0x46b
    <21cf>   DW_AT_frame_base  : 1 byte block: 9c       (DW_OP_call_frame_cfa)
    <21d1>   DW_AT_GNU_all_call_sites: 1
    <21d1>   DW_AT_sibling     : <0x2609>

it looks like D maintains labels in a hash-map, doing

      /* Pop all the labels declared in the function.  */
      if (d_function_chain->labels)
        d_function_chain->labels->traverse<tree, &pop_label> (block);

and

bool
pop_label (Statement * const &s, d_label_entry *ent, tree block)
{
  if (!ent->bc_label)
    {
      /* Put the labels into the "variables" of the top-level block,
         so debugger can see them.  */
      if (DECL_NAME (ent->label))
        {
          gcc_assert (DECL_INITIAL (ent->label) != NULL_TREE);
          DECL_CHAIN (ent->label) = BLOCK_VARS (block);
          BLOCK_VARS (block) = ent->label;

so the order of labels depend on the order of them appearing in the hashtable
which means depending on virtual addresses and hashtable size.

I suggest to fix this by sorting the labels after DECL_UID (which should
order them after time of creation which should roughly match parsing/source
order) and emit them from there.  This means putting the hashtable
contents into a vector and sorting that, sth GCC does elsewhere to avoid
random code-generation differences with for example address-space
randomization.

grepping for 'traverse' this might be the only place D does this.

I'm also not sure it is safe to remove elements while traversing.

Reply via email to