From 729efb13174d6522fba4aa7ab273e7f25a253c47 Mon Sep 17 00:00:00 2001 From: Sanimir Agovic Date: Tue, 8 Oct 2013 15:04:49 +0100 Subject: [PATCH] vla: introduce new bound type abstraction adapt uses The rational behind this patch is to get started to implement the feature described in dwarf4 standard (2.19) Static and Dynamic Values of Attributes. It adds new BOUND_PROP to store either a constant, exprloc, or reference to describe an upper-/lower bound of a subrange. Other than that no new features are introduced. * dwarf2read.c (read_subrange_type): Use struct bound_prop for declaring high/low bounds and change uses accordingly. Call create_range_type instead of create_static_range_type. * gdbtypes.c (create_range_type): New function. (create_range_type): Convert bounds into struct bound_prop and pass them to create_range_type. * gdbtypes.h (struct bound_prop): New struct. (create_range_type): New function prototype. (struct range_bounds): Use struct bound_prop instead of LONGEST for high/low bounds. Remove low_undefined/high_undefined and adapt all uses. (TYPE_LOW_BOUND,TYPE_HIGH_BOUND): Adapt macros to refer to the static part of the bound. * parse.c (follow_types): Set high bound kind to BOUND_UNDEFINED. --- gdb/ChangeLog | 16 +++++++++++++ gdb/dwarf2read.c | 43 ++++++++++++++++++++--------------- gdb/gdbtypes.c | 50 +++++++++++++++++++++++++++++------------ gdb/gdbtypes.h | 58 ++++++++++++++++++++++++++++++++++++------------ gdb/parse.c | 3 ++- 5 files changed, 123 insertions(+), 47 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 47230c5a3d2..a26d590d02c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2014-04-11 Sanimir Agovic + + * dwarf2read.c (read_subrange_type): Use struct bound_prop for + declaring high/low bounds and change uses accordingly. Call + create_range_type instead of create_static_range_type. + * gdbtypes.c (create_range_type): New function. + (create_range_type): Convert bounds into struct bound_prop and pass + them to create_range_type. + * gdbtypes.h (struct bound_prop): New struct. + (create_range_type): New function prototype. + (struct range_bounds): Use struct bound_prop instead of LONGEST for + high/low bounds. Remove low_undefined/high_undefined and adapt all uses. + (TYPE_LOW_BOUND,TYPE_HIGH_BOUND): Adapt macros to refer to the static + part of the bound. + * parse.c (follow_types): Set high bound kind to BOUND_UNDEFINED. + 2014-04-11 Sanimir Agovic * gdbtypes.c (create_static_range_type): Renamed from create_range_type. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index a575b8210f9..152c8d24b86 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -14413,7 +14413,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; - LONGEST low, high; + struct dynamic_prop low, high; int low_default_is_valid; const char *name; LONGEST negative_mask; @@ -14430,33 +14430,37 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) if (range_type) return range_type; + low.kind = PROP_CONST; + high.kind = PROP_CONST; + high.data.const_val = 0; + /* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow omitting DW_AT_lower_bound. */ switch (cu->language) { case language_c: case language_cplus: - low = 0; + low.data.const_val = 0; low_default_is_valid = 1; break; case language_fortran: - low = 1; + low.data.const_val = 1; low_default_is_valid = 1; break; case language_d: case language_java: case language_objc: - low = 0; + low.data.const_val = 0; low_default_is_valid = (cu->header.version >= 4); break; case language_ada: case language_m2: case language_pascal: - low = 1; + low.data.const_val = 1; low_default_is_valid = (cu->header.version >= 4); break; default: - low = 0; + low.data.const_val = 0; low_default_is_valid = 0; break; } @@ -14466,7 +14470,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) but we don't know how to handle it. */ attr = dwarf2_attr (die, DW_AT_lower_bound, cu); if (attr) - low = dwarf2_get_attr_constant_value (attr, low); + low.data.const_val + = dwarf2_get_attr_constant_value (attr, low.data.const_val); else if (!low_default_is_valid) complaint (&symfile_complaints, _("Missing DW_AT_lower_bound " "- DIE at 0x%x [in module %s]"), @@ -14488,10 +14493,10 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) either; we just represent them as zero-length arrays. Choose an appropriate upper bound given the lower bound we've computed above. */ - high = low - 1; + high.data.const_val = low.data.const_val - 1; } else - high = dwarf2_get_attr_constant_value (attr, 1); + high.data.const_val = dwarf2_get_attr_constant_value (attr, 1); } else { @@ -14499,12 +14504,12 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) if (attr) { int count = dwarf2_get_attr_constant_value (attr, 1); - high = low + count - 1; + high.data.const_val = low.data.const_val + count - 1; } else { /* Unspecified array length. */ - high = low - 1; + high.data.const_val = low.data.const_val - 1; } } @@ -14555,22 +14560,24 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) the base type is signed. */ negative_mask = (LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1); - if (!TYPE_UNSIGNED (base_type) && (low & negative_mask)) - low |= negative_mask; - if (!TYPE_UNSIGNED (base_type) && (high & negative_mask)) - high |= negative_mask; + if (low.kind == PROP_CONST + && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask)) + low.data.const_val |= negative_mask; + if (high.kind == PROP_CONST + && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask)) + high.data.const_val |= negative_mask; - range_type = create_static_range_type (NULL, orig_base_type, low, high); + range_type = create_range_type (NULL, orig_base_type, &low, &high); /* Mark arrays with dynamic length at least as an array of unspecified length. GDB could check the boundary but before it gets implemented at least allow accessing the array elements. */ if (attr && attr_form_is_block (attr)) - TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1; + TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED; /* Ada expects an empty array on no boundary attributes. */ if (attr == NULL && cu->language != language_ada) - TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1; + TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED; name = dwarf2_name (die, cu); if (name) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 7f1645a049b..231139be777 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -798,19 +798,13 @@ allocate_stub_method (struct type *type) return mtype; } -/* Create a range type using either a blank type supplied in - RESULT_TYPE, or creating a new type, inheriting the objfile from - INDEX_TYPE. - - Indices will be of type INDEX_TYPE, and will range from LOW_BOUND - to HIGH_BOUND, inclusive. - - FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make - sure it is TYPE_CODE_UNDEF before we bash it into a range type? */ +/* Create a range type with a dynamic range from LOW_BOUND to + HIGH_BOUND, inclusive. See create_range_type for further details. */ struct type * -create_static_range_type (struct type *result_type, struct type *index_type, - LONGEST low_bound, LONGEST high_bound) +create_range_type (struct type *result_type, struct type *index_type, + const struct dynamic_prop *low_bound, + const struct dynamic_prop *high_bound) { if (result_type == NULL) result_type = alloc_type_copy (index_type); @@ -820,17 +814,45 @@ create_static_range_type (struct type *result_type, struct type *index_type, TYPE_TARGET_STUB (result_type) = 1; else TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type)); + TYPE_RANGE_DATA (result_type) = (struct range_bounds *) TYPE_ZALLOC (result_type, sizeof (struct range_bounds)); - TYPE_LOW_BOUND (result_type) = low_bound; - TYPE_HIGH_BOUND (result_type) = high_bound; + TYPE_RANGE_DATA (result_type)->low = *low_bound; + TYPE_RANGE_DATA (result_type)->high = *high_bound; - if (low_bound >= 0) + if (low_bound->kind == PROP_CONST && low_bound->data.const_val >= 0) TYPE_UNSIGNED (result_type) = 1; return result_type; } +/* Create a range type using either a blank type supplied in + RESULT_TYPE, or creating a new type, inheriting the objfile from + INDEX_TYPE. + + Indices will be of type INDEX_TYPE, and will range from LOW_BOUND + to HIGH_BOUND, inclusive. + + FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make + sure it is TYPE_CODE_UNDEF before we bash it into a range type? */ + +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; + + low.kind = PROP_CONST; + low.data.const_val = low_bound; + + high.kind = PROP_CONST; + high.data.const_val = high_bound; + + result_type = create_range_type (result_type, index_type, &low, &high); + + return result_type; +} + /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type TYPE. Return 1 if type is a range type, 0 if it is discrete (and bounds will fit in LONGEST), or -1 otherwise. */ diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index b5fb5640c9a..e91ab977251 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -399,6 +399,33 @@ enum type_instance_flag_value #define TYPE_ADDRESS_CLASS_ALL(t) (TYPE_INSTANCE_FLAGS(t) \ & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL) +/* * Used to store a dynamic property. */ + +struct dynamic_prop +{ + /* Determine which field of the union dynamic_prop.data is used. */ + enum + { + PROP_UNDEFINED, /* Not defined. */ + PROP_CONST, /* Constant. */ + PROP_LOCEXPR, /* Location expression. */ + PROP_LOCLIST /* Location list. */ + } kind; + + /* Storage for dynamic or static value. */ + union data + { + /* Storage for constant property. */ + + LONGEST const_val; + + /* Storage for dynamic property. */ + + void *baton; + } data; +}; + + /* * Determine which field of the union main_type.fields[x].loc is used. */ @@ -630,19 +657,11 @@ struct main_type { /* * Low bound of range. */ - LONGEST low; + struct dynamic_prop low; /* * High bound of range. */ - LONGEST high; - - /* * Flags indicating whether the values of low and high are - valid. When true, the respective range value is - undefined. Currently used only for FORTRAN arrays. */ - - char low_undefined; - char high_undefined; - + struct dynamic_prop high; } *bounds; } flds_bnds; @@ -1155,12 +1174,18 @@ extern void allocate_gnat_aux_type (struct type *); #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0) #define TYPE_RANGE_DATA(thistype) TYPE_MAIN_TYPE(thistype)->flds_bnds.bounds -#define TYPE_LOW_BOUND(range_type) TYPE_RANGE_DATA(range_type)->low -#define TYPE_HIGH_BOUND(range_type) TYPE_RANGE_DATA(range_type)->high +#define TYPE_LOW_BOUND(range_type) \ + TYPE_RANGE_DATA(range_type)->low.data.const_val +#define TYPE_HIGH_BOUND(range_type) \ + TYPE_RANGE_DATA(range_type)->high.data.const_val #define TYPE_LOW_BOUND_UNDEFINED(range_type) \ - TYPE_RANGE_DATA(range_type)->low_undefined + (TYPE_RANGE_DATA(range_type)->low.kind == PROP_UNDEFINED) #define TYPE_HIGH_BOUND_UNDEFINED(range_type) \ - TYPE_RANGE_DATA(range_type)->high_undefined + (TYPE_RANGE_DATA(range_type)->high.kind == PROP_UNDEFINED) +#define TYPE_HIGH_BOUND_KIND(range_type) \ + TYPE_RANGE_DATA(range_type)->high.kind +#define TYPE_LOW_BOUND_KIND(range_type) \ + TYPE_RANGE_DATA(range_type)->low.kind /* Moto-specific stuff for FORTRAN arrays. */ @@ -1628,9 +1653,14 @@ extern struct type *lookup_function_type_with_arguments (struct type *, extern struct type *create_static_range_type (struct type *, struct type *, LONGEST, LONGEST); + 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 *); + extern struct type *create_array_type (struct type *, struct type *, struct type *); diff --git a/gdb/parse.c b/gdb/parse.c index b0da2efac86..105d0cd8971 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -1692,7 +1692,8 @@ follow_types (struct type *follow_type) lookup_array_range_type (follow_type, 0, array_size >= 0 ? array_size - 1 : 0); if (array_size < 0) - TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (follow_type) = 1; + TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (follow_type)) + = PROP_UNDEFINED; break; case tp_function: /* FIXME-type-allocation: need a way to free this type when we are -- 2.30.2