]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
vla: add stride support to fortran arrays.
authorKeven Boell <keven.boell@intel.com>
Wed, 28 May 2014 13:44:11 +0000 (14:44 +0100)
committerBernhard Heckel <bernhard.heckel@intel.com>
Wed, 7 Sep 2016 10:08:25 +0000 (12:08 +0200)
2014-05-28  Bernhard Heckel  <bernhard.heckel@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

gdb/Changelog:
* dwarf2read.c (read_subrange_type): Read dynamic
stride attributes.
* gdbtypes.c (create_array_type_with_stride): Add
stride support
(create_range_type): Add stride parameter.
(create_static_range_type): Pass default stride
parameter.
(resolve_dynamic_range): Evaluate stride baton.
* gdbtypes.h (TYPE_BYTE_STRIDE): New macro.
(TYPE_BYTE_STRIDE_BLOCK): New macro.
(TYPE_BYTE_STRIDE_LOCLIST): New macro.
(TYPE_BYTE_STRIDE_KIND): New macro.
* valarith.c (value_subscripted_rvalue): Use stride.

gdb/testsuite/Changelog:
* vla-stride.exp: New file.
* vla-stride.f90: New file.

Change-Id: I3cd90c5514dc8ea8c0f7b67f450d9a45822257dc

gdb/dwarf2read.c
gdb/f-valprint.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/testsuite/gdb.fortran/vla-stride.exp [new file with mode: 0644]
gdb/testsuite/gdb.fortran/vla-stride.f90 [new file with mode: 0644]
gdb/valarith.c

index 6658a386ec9a20851308d14545f1077714668ffa..a1ac659ff6b76fa3ad98358cb89223361b42ffba 100644 (file)
@@ -14952,7 +14952,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   struct type *base_type, *orig_base_type;
   struct type *range_type;
   struct attribute *attr;
-  struct dynamic_prop low, high;
+  struct dynamic_prop low, high, stride;
   int low_default_is_valid;
   int high_bound_is_count = 0;
   const char *name;
@@ -14972,7 +14972,9 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 
   low.kind = PROP_CONST;
   high.kind = PROP_CONST;
+  stride.kind = PROP_CONST;
   high.data.const_val = 0;
+  stride.data.const_val = 0;
 
   /* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
      omitting DW_AT_lower_bound.  */
@@ -15006,6 +15008,13 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
       break;
     }
 
+  attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
+  if (attr)
+    if (!attr_to_dynamic_prop (attr, die, cu, &stride))
+        complaint (&symfile_complaints, _("Missing DW_AT_byte_stride "
+                  "- DIE at 0x%x [in module %s]"),
+             die->offset.sect_off, objfile_name (cu->objfile));
+
   attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
   if (attr)
     attr_to_dynamic_prop (attr, die, cu, &low);
@@ -15082,7 +15091,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
       && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask))
     high.data.const_val |= negative_mask;
 
-  range_type = create_range_type (NULL, orig_base_type, &low, &high);
+  range_type = create_range_type (NULL, orig_base_type, &low, &high, &stride);
 
   if (high_bound_is_count)
     TYPE_RANGE_DATA (range_type)->flag_upper_bound_is_count = 1;
index 08215e22f88d319525adadcf4f3b7f294c0614ff..e6eca6af14df6a26ca3af43301cdd7affd07f1e7 100644 (file)
@@ -121,8 +121,14 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type,
 
   if (nss != ndimensions)
     {
-      size_t dim_size = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
+      size_t dim_size;
       size_t offs = 0;
+      LONGEST byte_stride = abs (TYPE_BYTE_STRIDE (range_type));
+
+      if (byte_stride)
+        dim_size = byte_stride;
+      else
+        dim_size = TYPE_LENGTH (TYPE_TARGET_TYPE (type));
 
       for (i = lowerbound;
           (i < upperbound + 1 && (*elts) < options->print_max);
index 0a2feac6ca29f201dd780efc4b4ef84a52a11b04..eb83791eb13c6ea49acb25d48ff77e62db6784b8 100644 (file)
@@ -836,7 +836,8 @@ allocate_stub_method (struct type *type)
 struct type *
 create_range_type (struct type *result_type, struct type *index_type,
                   const struct dynamic_prop *low_bound,
-                  const struct dynamic_prop *high_bound)
+                  const struct dynamic_prop *high_bound,
+                  const struct dynamic_prop *stride)
 {
   if (result_type == NULL)
     result_type = alloc_type_copy (index_type);
@@ -851,6 +852,7 @@ create_range_type (struct type *result_type, struct type *index_type,
     TYPE_ZALLOC (result_type, sizeof (struct range_bounds));
   TYPE_RANGE_DATA (result_type)->low = *low_bound;
   TYPE_RANGE_DATA (result_type)->high = *high_bound;
+  TYPE_RANGE_DATA (result_type)->stride = *stride;
 
   if (low_bound->kind == PROP_CONST && low_bound->data.const_val >= 0)
     TYPE_UNSIGNED (result_type) = 1;
@@ -879,7 +881,7 @@ struct type *
 create_static_range_type (struct type *result_type, struct type *index_type,
                          LONGEST low_bound, LONGEST high_bound)
 {
-  struct dynamic_prop low, high;
+  struct dynamic_prop low, high, stride;
 
   low.kind = PROP_CONST;
   low.data.const_val = low_bound;
@@ -887,7 +889,11 @@ create_static_range_type (struct type *result_type, struct type *index_type,
   high.kind = PROP_CONST;
   high.data.const_val = high_bound;
 
-  result_type = create_range_type (result_type, index_type, &low, &high);
+  stride.kind = PROP_CONST;
+  stride.data.const_val = 0;
+
+  result_type = create_range_type (result_type, index_type,
+                                   &low, &high, &stride);
 
   return result_type;
 }
@@ -1084,16 +1090,20 @@ create_array_type_with_stride (struct type *result_type,
       && (!type_not_associated (result_type)
          && !type_not_allocated (result_type)))
     {
-      LONGEST low_bound, high_bound;
+      LONGEST low_bound, high_bound, byte_stride;
 
       if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
        low_bound = high_bound = 0;
       element_type = check_typedef (element_type);
+      byte_stride = abs (TYPE_BYTE_STRIDE (range_type));
+
       /* Be careful when setting the array length.  Ada arrays can be
         empty arrays with the high_bound being smaller than the low_bound.
         In such cases, the array length should be zero.  */
       if (high_bound < low_bound)
        TYPE_LENGTH (result_type) = 0;
+      else if (byte_stride > 0)
+       TYPE_LENGTH (result_type) = byte_stride * (high_bound - low_bound + 1);
       else if (bit_stride > 0)
        TYPE_LENGTH (result_type) =
          (bit_stride * (high_bound - low_bound + 1) + 7) / 8;
@@ -1888,7 +1898,7 @@ resolve_dynamic_range (struct type *dyn_range_type,
   CORE_ADDR value;
   struct type *static_range_type, *static_target_type;
   const struct dynamic_prop *prop;
-  struct dynamic_prop low_bound, high_bound;
+  struct dynamic_prop low_bound, high_bound, stride;
 
   gdb_assert (TYPE_CODE (dyn_range_type) == TYPE_CODE_RANGE);
 
@@ -1920,12 +1930,20 @@ resolve_dynamic_range (struct type *dyn_range_type,
       high_bound.data.const_val = 0;
     }
 
+  prop = &TYPE_RANGE_DATA (dyn_range_type)->stride;
+  if (dwarf2_evaluate_property_signed (prop, NULL, addr_stack, &value, 1))
+    {
+      stride.kind = PROP_CONST;
+      stride.data.const_val = value;
+    }
+
   static_target_type
     = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (dyn_range_type),
                                     addr_stack, 0);
   static_range_type = create_range_type (copy_type (dyn_range_type),
                                         static_target_type,
-                                        &low_bound, &high_bound);
+                                        &low_bound, &high_bound, &stride);
+
   TYPE_RANGE_DATA (static_range_type)->flag_bound_evaluated = 1;
   return static_range_type;
 }
index 2dda074d737b9dbff9a45038edd3a561764b6f65..bcc92000d2fd92bf5ed9e7c1b49c4115f6350682 100644 (file)
@@ -577,6 +577,10 @@ struct range_bounds
 
   struct dynamic_prop high;
 
+  /* * Stride of range.  */
+
+  struct dynamic_prop stride;
+
   /* True if HIGH range bound contains the number of elements in the
      subrange. This affects how the final hight bound is computed.  */
 
@@ -739,7 +743,6 @@ struct main_type
     /* * Union member used for range types.  */
 
     struct range_bounds *bounds;
-
   } flds_bnds;
 
   /* * Slot to point to additional language-specific fields of this
@@ -1255,6 +1258,15 @@ extern void allocate_gnat_aux_type (struct type *);
   TYPE_RANGE_DATA(range_type)->high.kind
 #define TYPE_LOW_BOUND_KIND(range_type) \
   TYPE_RANGE_DATA(range_type)->low.kind
+#define TYPE_BYTE_STRIDE(range_type) \
+  TYPE_RANGE_DATA(range_type)->stride.data.const_val
+#define TYPE_BYTE_STRIDE_BLOCK(range_type) \
+  TYPE_RANGE_DATA(range_type)->stride.data.locexpr
+#define TYPE_BYTE_STRIDE_LOCLIST(range_type) \
+  TYPE_RANGE_DATA(range_type)->stride.data.loclist
+#define TYPE_BYTE_STRIDE_KIND(range_type) \
+  TYPE_RANGE_DATA(range_type)->stride.kind
+
 
 /* Property accessors for the type data location.  */
 #define TYPE_DATA_LOCATION(thistype) \
@@ -1289,6 +1301,9 @@ extern void allocate_gnat_aux_type (struct type *);
    TYPE_HIGH_BOUND_UNDEFINED(TYPE_INDEX_TYPE(arraytype))
 #define TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED(arraytype) \
    TYPE_LOW_BOUND_UNDEFINED(TYPE_INDEX_TYPE(arraytype))
+#define TYPE_ARRAY_STRIDE_IS_UNDEFINED(arraytype) \
+   (TYPE_BYTE_STRIDE(TYPE_INDEX_TYPE(arraytype)) == 0)
+
 
 #define TYPE_ARRAY_UPPER_BOUND_VALUE(arraytype) \
    (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE((arraytype))))
@@ -1782,6 +1797,7 @@ extern struct type *create_array_type_with_stride
   (struct type *, struct type *, struct type *, unsigned int);
 
 extern struct type *create_range_type (struct type *, struct type *,
+                                      const struct dynamic_prop *,
                                       const struct dynamic_prop *,
                                       const struct dynamic_prop *);
 
diff --git a/gdb/testsuite/gdb.fortran/vla-stride.exp b/gdb/testsuite/gdb.fortran/vla-stride.exp
new file mode 100644 (file)
index 0000000..dcf15e5
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright 2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile ".f90"
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
+    {debug f90 quiet}] } {
+    return -1
+}
+
+if ![runto MAIN__] then {
+    perror "couldn't run to breakpoint MAIN__"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "re-reverse-elements"]
+gdb_continue_to_breakpoint "re-reverse-elements"
+gdb_test "print pvla" " = \\\(1, 2, 3, 4, 5, 6, 7, 8, 9, 10\\\)" \
+  "print re-reverse-elements"
+gdb_test "print pvla(1)" " = 1" "print first re-reverse-element"
+gdb_test "print pvla(10)" " = 10" "print last re-reverse-element"
+
+gdb_breakpoint [gdb_get_line_number "odd-elements"]
+gdb_continue_to_breakpoint "odd-elements"
+gdb_test "print pvla" " = \\\(1, 3, 5, 7, 9\\\)" "print odd-elements"
+gdb_test "print pvla(1)" " = 1" "print first odd-element"
+gdb_test "print pvla(5)" " = 9" "print last odd-element"
+
+gdb_breakpoint [gdb_get_line_number "single-element"]
+gdb_continue_to_breakpoint "single-element"
+gdb_test "print pvla" " = \\\(5\\\)" "print single-element"
+gdb_test "print pvla(1)" " = 5" "print one single-element"
diff --git a/gdb/testsuite/gdb.fortran/vla-stride.f90 b/gdb/testsuite/gdb.fortran/vla-stride.f90
new file mode 100644 (file)
index 0000000..8d24252
--- /dev/null
@@ -0,0 +1,29 @@
+! Copyright 2016 Free Software Foundation, Inc.
+!
+! This program is free software; you can redistribute it and/or modify
+! it under the terms of the GNU General Public License as published by
+! the Free Software Foundation; either version 3 of the License, or
+! (at your option) any later version.
+!
+! This program is distributed in the hope that it will be useful,
+! but WITHOUT ANY WARRANTY; without even the implied warranty of
+! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+! GNU General Public License for more details.
+!
+! You should have received a copy of the GNU General Public License
+! along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+program vla_stride
+  integer, target, allocatable :: vla (:)
+  integer, pointer :: pvla (:)
+
+  allocate(vla(10))
+  vla = (/ (I, I = 1,10) /)
+
+  pvla => vla(10:1:-1)
+  pvla => pvla(10:1:-1)
+  pvla => vla(1:10:2)   ! re-reverse-elements
+  pvla => vla(5:4:-2)   ! odd-elements
+
+  pvla => null()        ! single-element
+end program vla_stride
index de6fcfd79abb2f3b6a1b341c36736ac949826cf3..9753506ef84bae8ffc5c89c38c862b9a536a9593 100644 (file)
@@ -193,11 +193,17 @@ value_subscripted_rvalue (struct value *array, LONGEST index, int lowerbound)
   struct type *array_type = check_typedef (value_type (array));
   struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type));
   ULONGEST elt_size = type_length_units (elt_type);
-  ULONGEST elt_offs = elt_size * (index - lowerbound);
+  LONGEST elt_offs = index - lowerbound;
+  LONGEST elt_stride = TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (array_type));
   struct value *v;
 
+  if (elt_stride != 0)
+    elt_offs *= elt_stride;
+  else
+    elt_offs *= elt_size;
+
   if (index < lowerbound || (!TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (array_type)
-                            && elt_offs >= type_length_units (array_type)))
+                            && abs (elt_offs) >= type_length_units (array_type)))
     {
       if (type_not_associated (array_type))
         error (_("no such vector element (vector not associated)"));