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.
This commit is contained in:
Sanimir Agovic
2013-10-08 15:04:49 +01:00
parent 0c9c347402
commit 729efb1317
5 changed files with 123 additions and 47 deletions

View File

@ -1,3 +1,19 @@
2014-04-11 Sanimir Agovic <sanimir.agovic@intel.com>
* 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 <sanimir.agovic@intel.com> 2014-04-11 Sanimir Agovic <sanimir.agovic@intel.com>
* gdbtypes.c (create_static_range_type): Renamed from create_range_type. * gdbtypes.c (create_static_range_type): Renamed from create_range_type.

View File

@ -14413,7 +14413,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
struct type *base_type, *orig_base_type; struct type *base_type, *orig_base_type;
struct type *range_type; struct type *range_type;
struct attribute *attr; struct attribute *attr;
LONGEST low, high; struct dynamic_prop low, high;
int low_default_is_valid; int low_default_is_valid;
const char *name; const char *name;
LONGEST negative_mask; LONGEST negative_mask;
@ -14430,33 +14430,37 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
if (range_type) if (range_type)
return 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 /* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
omitting DW_AT_lower_bound. */ omitting DW_AT_lower_bound. */
switch (cu->language) switch (cu->language)
{ {
case language_c: case language_c:
case language_cplus: case language_cplus:
low = 0; low.data.const_val = 0;
low_default_is_valid = 1; low_default_is_valid = 1;
break; break;
case language_fortran: case language_fortran:
low = 1; low.data.const_val = 1;
low_default_is_valid = 1; low_default_is_valid = 1;
break; break;
case language_d: case language_d:
case language_java: case language_java:
case language_objc: case language_objc:
low = 0; low.data.const_val = 0;
low_default_is_valid = (cu->header.version >= 4); low_default_is_valid = (cu->header.version >= 4);
break; break;
case language_ada: case language_ada:
case language_m2: case language_m2:
case language_pascal: case language_pascal:
low = 1; low.data.const_val = 1;
low_default_is_valid = (cu->header.version >= 4); low_default_is_valid = (cu->header.version >= 4);
break; break;
default: default:
low = 0; low.data.const_val = 0;
low_default_is_valid = 0; low_default_is_valid = 0;
break; 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. */ but we don't know how to handle it. */
attr = dwarf2_attr (die, DW_AT_lower_bound, cu); attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
if (attr) 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) else if (!low_default_is_valid)
complaint (&symfile_complaints, _("Missing DW_AT_lower_bound " complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
"- DIE at 0x%x [in module %s]"), "- 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 either; we just represent them as zero-length
arrays. Choose an appropriate upper bound given arrays. Choose an appropriate upper bound given
the lower bound we've computed above. */ the lower bound we've computed above. */
high = low - 1; high.data.const_val = low.data.const_val - 1;
} }
else else
high = dwarf2_get_attr_constant_value (attr, 1); high.data.const_val = dwarf2_get_attr_constant_value (attr, 1);
} }
else else
{ {
@ -14499,12 +14504,12 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
if (attr) if (attr)
{ {
int count = dwarf2_get_attr_constant_value (attr, 1); int count = dwarf2_get_attr_constant_value (attr, 1);
high = low + count - 1; high.data.const_val = low.data.const_val + count - 1;
} }
else else
{ {
/* Unspecified array length. */ /* 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. */ the base type is signed. */
negative_mask = negative_mask =
(LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1); (LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1);
if (!TYPE_UNSIGNED (base_type) && (low & negative_mask)) if (low.kind == PROP_CONST
low |= negative_mask; && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask))
if (!TYPE_UNSIGNED (base_type) && (high & negative_mask)) low.data.const_val |= negative_mask;
high |= 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 /* Mark arrays with dynamic length at least as an array of unspecified
length. GDB could check the boundary but before it gets implemented at length. GDB could check the boundary but before it gets implemented at
least allow accessing the array elements. */ least allow accessing the array elements. */
if (attr && attr_form_is_block (attr)) 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. */ /* Ada expects an empty array on no boundary attributes. */
if (attr == NULL && cu->language != language_ada) 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); name = dwarf2_name (die, cu);
if (name) if (name)

View File

@ -798,6 +798,34 @@ allocate_stub_method (struct type *type)
return mtype; return mtype;
} }
/* 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_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);
TYPE_CODE (result_type) = TYPE_CODE_RANGE;
TYPE_TARGET_TYPE (result_type) = index_type;
if (TYPE_STUB (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_RANGE_DATA (result_type)->low = *low_bound;
TYPE_RANGE_DATA (result_type)->high = *high_bound;
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 /* Create a range type using either a blank type supplied in
RESULT_TYPE, or creating a new type, inheriting the objfile from RESULT_TYPE, or creating a new type, inheriting the objfile from
INDEX_TYPE. INDEX_TYPE.
@ -812,21 +840,15 @@ struct type *
create_static_range_type (struct type *result_type, struct type *index_type, create_static_range_type (struct type *result_type, struct type *index_type,
LONGEST low_bound, LONGEST high_bound) LONGEST low_bound, LONGEST high_bound)
{ {
if (result_type == NULL) struct dynamic_prop low, high;
result_type = alloc_type_copy (index_type);
TYPE_CODE (result_type) = TYPE_CODE_RANGE;
TYPE_TARGET_TYPE (result_type) = index_type;
if (TYPE_STUB (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;
if (low_bound >= 0) low.kind = PROP_CONST;
TYPE_UNSIGNED (result_type) = 1; 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; return result_type;
} }

View File

@ -399,6 +399,33 @@ enum type_instance_flag_value
#define TYPE_ADDRESS_CLASS_ALL(t) (TYPE_INSTANCE_FLAGS(t) \ #define TYPE_ADDRESS_CLASS_ALL(t) (TYPE_INSTANCE_FLAGS(t) \
& TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL) & 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 /* * Determine which field of the union main_type.fields[x].loc is
used. */ used. */
@ -630,19 +657,11 @@ struct main_type
{ {
/* * Low bound of range. */ /* * Low bound of range. */
LONGEST low; struct dynamic_prop low;
/* * High bound of range. */ /* * High bound of range. */
LONGEST high; struct dynamic_prop 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;
} *bounds; } *bounds;
} flds_bnds; } 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_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0)
#define TYPE_RANGE_DATA(thistype) TYPE_MAIN_TYPE(thistype)->flds_bnds.bounds #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_LOW_BOUND(range_type) \
#define TYPE_HIGH_BOUND(range_type) TYPE_RANGE_DATA(range_type)->high 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) \ #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) \ #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. */ /* 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 *, extern struct type *create_static_range_type (struct type *, struct type *,
LONGEST, LONGEST); LONGEST, LONGEST);
extern struct type *create_array_type_with_stride extern struct type *create_array_type_with_stride
(struct type *, struct type *, struct type *, unsigned int); (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 *, extern struct type *create_array_type (struct type *, struct type *,
struct type *); struct type *);

View File

@ -1692,7 +1692,8 @@ follow_types (struct type *follow_type)
lookup_array_range_type (follow_type, lookup_array_range_type (follow_type,
0, array_size >= 0 ? array_size - 1 : 0); 0, array_size >= 0 ? array_size - 1 : 0);
if (array_size < 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; break;
case tp_function: case tp_function:
/* FIXME-type-allocation: need a way to free this type when we are /* FIXME-type-allocation: need a way to free this type when we are