dwarf2out: Fix up add_scalar_info not to create invalid DWARF
authorJakub Jelinek <jakub@redhat.com>
Wed, 2 Dec 2020 23:29:46 +0000 (00:29 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 2 Dec 2020 23:41:47 +0000 (00:41 +0100)
As discussed in https://sourceware.org/bugzilla/show_bug.cgi?id=26987 ,
for very large bounds (which don't fit into HOST_WIDE_INT) GCC emits invalid
DWARF.
In DWARF2, DW_AT_{lower,upper}_bound were constant reference class.
In DWARF3 they are block constant reference and the
Static and Dynamic Properties of Types
chapter says:
"For a block, the value is interpreted as a DWARF expression; evaluation of the expression
yields the value of the attribute."
In DWARF4/5 they are constant exprloc reference class.
Now, for add_AT_wide we use DW_FORM_data16 (valid in constant class)
when -gdwarf-5, but otherwise just use DW_FORM_block1, which is not constant
class, but block.
For DWARF3 this means emitting clearly invalid DWARF, because the
DW_FORM_block1 should contain a DWARF expression, not random bytes
containing the constant directly.
For DWARF2/DWARF4/5 it could be considered a GNU extension, but a very badly
designed one when it means something different in DWARF3.

The following patch uses add_AT_wide only if we know we'll be using
DW_FORM_data16, and otherwise wastes 2 extra bytes and emits in there
DW_OP_implicit_value <size> before the constant.

2020-12-03  Jakub Jelinek  <jakub@redhat.com>

* dwarf2out.c (add_scalar_info): Only use add_AT_wide for 128-bit
constants and only in dwarf-5 or later, where DW_FORM_data16 is
available.  Otherwise use DW_FORM_block*/DW_FORM_exprloc with
DW_OP_implicit_value to describe the constant.

gcc/dwarf2out.c

index 0a0a7ea..c23a3ca 100644 (file)
@@ -20775,12 +20775,23 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
          else
            add_AT_int (die, attr, TREE_INT_CST_LOW (value));
        }
-      else
+      else if (dwarf_version >= 5
+              && TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (value))) == 128)
        /* Otherwise represent the bound as an unsigned value with
           the precision of its type.  The precision and signedness
           of the type will be necessary to re-interpret it
           unambiguously.  */
        add_AT_wide (die, attr, wi::to_wide (value));
+      else
+       {
+         rtx v = immed_wide_int_const (wi::to_wide (value),
+                                       TYPE_MODE (TREE_TYPE (value)));
+         dw_loc_descr_ref loc
+           = loc_descriptor (v, TYPE_MODE (TREE_TYPE (value)),
+                             VAR_INIT_STATUS_INITIALIZED);
+         if (loc)
+           add_AT_loc (die, attr, loc);
+       }
       return;
     }