aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Brobecker <brobecker@gnat.com>2010-05-17 16:55:31 +0000
committerJoel Brobecker <brobecker@gnat.com>2010-05-17 16:55:31 +0000
commit28c85d6c4b53aca80e4b00525a89fa213705690c (patch)
treeea2b98cdc7d99cae7d17e937953b4556fd6c95f1
parent3872d37d18fb4e3c92df4c5816876e651e1fd3bf (diff)
downloadgdb-28c85d6c4b53aca80e4b00525a89fa213705690c.zip
gdb-28c85d6c4b53aca80e4b00525a89fa213705690c.tar.gz
gdb-28c85d6c4b53aca80e4b00525a89fa213705690c.tar.bz2
Avoid global lookup when decoding XA type.
This patch enhances GDB to take advantage of a recent change in the GNAT encoding regarding XA types. A detailed description of the logic has been added at the start of ada_fixup_array_indexes_type to give the context behind this enhancement. 2010-05-17 Joel Brobecker <brobecker@adacore.com> * ada-lang.c (to_fixed_range_type): The the raw index type as argument instead of the raw type name. Remove orig_type parameter. Update calls throughout. (ada_fixup_array_indexes_type): New function. (ada_array_bound_from_type): Add call to ada_fixup_array_indexes_type. * ada-lang.h (ada_fixup_array_indexes_type): Add declaration. * ada-typeprint.c (print_range_type): Renames print_range_type_named. Remove name parameter. (print_array_type): Add call to ada_fixup_array_indexes_type. Update calls to print_range_type. (ada_print_type): Update calls to print_range_type.
-rw-r--r--gdb/ChangeLog14
-rw-r--r--gdb/ada-lang.c83
-rw-r--r--gdb/ada-lang.h2
-rw-r--r--gdb/ada-typeprint.c29
4 files changed, 100 insertions, 28 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 92fe6fb..852b6c0 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -4,6 +4,20 @@
* c-lang.c (c_printstr): Compute real length of NUL terminated
string at first.
+2010-05-17 Joel Brobecker <brobecker@adacore.com>
+
+ * ada-lang.c (to_fixed_range_type): The the raw index type as
+ argument instead of the raw type name. Remove orig_type parameter.
+ Update calls throughout.
+ (ada_fixup_array_indexes_type): New function.
+ (ada_array_bound_from_type): Add call to ada_fixup_array_indexes_type.
+ * ada-lang.h (ada_fixup_array_indexes_type): Add declaration.
+ * ada-typeprint.c (print_range_type): Renames print_range_type_named.
+ Remove name parameter.
+ (print_array_type): Add call to ada_fixup_array_indexes_type.
+ Update calls to print_range_type.
+ (ada_print_type): Update calls to print_range_type.
+
2010-05-17 Pierre Muller <muller@ics.u-strasbg.fr>
* dwarf2read.c (read_set_type): Set type length if
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3b3894c..83f7cf3 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -165,8 +165,7 @@ static struct type *to_fixed_variant_branch_type (struct type *,
static struct type *to_fixed_array_type (struct type *, struct value *, int);
-static struct type *to_fixed_range_type (char *, struct value *,
- struct type *);
+static struct type *to_fixed_range_type (struct type *, struct value *);
static struct type *to_static_fixed_type (struct type *);
static struct type *static_unwrap_type (struct type *type);
@@ -1204,6 +1203,61 @@ ada_match_name (const char *sym_name, const char *name, int wild)
/* Arrays */
+/* Assuming that INDEX_DESC_TYPE is an ___XA structure, a structure
+ generated by the GNAT compiler to describe the index type used
+ for each dimension of an array, check whether it follows the latest
+ known encoding. If not, fix it up to conform to the latest encoding.
+ Otherwise, do nothing. This function also does nothing if
+ INDEX_DESC_TYPE is NULL.
+
+ The GNAT encoding used to describle the array index type evolved a bit.
+ Initially, the information would be provided through the name of each
+ field of the structure type only, while the type of these fields was
+ described as unspecified and irrelevant. The debugger was then expected
+ to perform a global type lookup using the name of that field in order
+ to get access to the full index type description. Because these global
+ lookups can be very expensive, the encoding was later enhanced to make
+ the global lookup unnecessary by defining the field type as being
+ the full index type description.
+
+ The purpose of this routine is to allow us to support older versions
+ of the compiler by detecting the use of the older encoding, and by
+ fixing up the INDEX_DESC_TYPE to follow the new one (at this point,
+ we essentially replace each field's meaningless type by the associated
+ index subtype). */
+
+void
+ada_fixup_array_indexes_type (struct type *index_desc_type)
+{
+ int i;
+
+ if (index_desc_type == NULL)
+ return;
+ gdb_assert (TYPE_NFIELDS (index_desc_type) > 0);
+
+ /* Check if INDEX_DESC_TYPE follows the older encoding (it is sufficient
+ to check one field only, no need to check them all). If not, return
+ now.
+
+ If our INDEX_DESC_TYPE was generated using the older encoding,
+ the field type should be a meaningless integer type whose name
+ is not equal to the field name. */
+ if (TYPE_NAME (TYPE_FIELD_TYPE (index_desc_type, 0)) != NULL
+ && strcmp (TYPE_NAME (TYPE_FIELD_TYPE (index_desc_type, 0)),
+ TYPE_FIELD_NAME (index_desc_type, 0)) == 0)
+ return;
+
+ /* Fixup each field of INDEX_DESC_TYPE. */
+ for (i = 0; i < TYPE_NFIELDS (index_desc_type); i++)
+ {
+ char *name = TYPE_FIELD_NAME (index_desc_type, i);
+ struct type *raw_type = ada_check_typedef (ada_find_any_type (name));
+
+ if (raw_type)
+ TYPE_FIELD_TYPE (index_desc_type, i) = raw_type;
+ }
+}
+
/* Names of MAX_ADA_DIMENS bounds in P_BOUNDS fields of array descriptors. */
static char *bound_name[] = {
@@ -2530,9 +2584,10 @@ ada_array_bound_from_type (struct type * arr_type, int n, int which)
elt_type = TYPE_TARGET_TYPE (type);
index_type_desc = ada_find_parallel_type (type, "___XA");
+ ada_fixup_array_indexes_type (index_type_desc);
if (index_type_desc != NULL)
- index_type = to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, n - 1),
- NULL, TYPE_INDEX_TYPE (elt_type));
+ index_type = to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, n - 1),
+ NULL);
else
index_type = TYPE_INDEX_TYPE (elt_type);
@@ -7150,6 +7205,7 @@ to_fixed_array_type (struct type *type0, struct value *dval,
type0 = decode_constrained_packed_array_type (type0);
index_type_desc = ada_find_parallel_type (type0, "___XA");
+ ada_fixup_array_indexes_type (index_type_desc);
if (index_type_desc == NULL)
{
struct type *elt_type0 = ada_check_typedef (TYPE_TARGET_TYPE (type0));
@@ -7202,8 +7258,7 @@ to_fixed_array_type (struct type *type0, struct value *dval,
for (i = TYPE_NFIELDS (index_type_desc) - 1; i >= 0; i -= 1)
{
struct type *range_type =
- to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i),
- dval, TYPE_INDEX_TYPE (elt_type0));
+ to_fixed_range_type (TYPE_FIELD_TYPE (index_type_desc, i), dval);
result = create_array_type (alloc_type_copy (elt_type0),
result, range_type);
elt_type0 = TYPE_TARGET_TYPE (elt_type0);
@@ -9182,7 +9237,7 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
char *name = ada_type_name (type_arg);
range_type = NULL;
if (name != NULL && TYPE_CODE (type_arg) != TYPE_CODE_ENUM)
- range_type = to_fixed_range_type (name, NULL, type_arg);
+ range_type = to_fixed_range_type (type_arg, NULL);
if (range_type == NULL)
range_type = type_arg;
switch (op)
@@ -9704,21 +9759,21 @@ get_int_var_value (char *name, int *flag)
in NAME, the base type given in the named range type. */
static struct type *
-to_fixed_range_type (char *name, struct value *dval, struct type *orig_type)
+to_fixed_range_type (struct type *raw_type, struct value *dval)
{
- struct type *raw_type = ada_find_any_type (name);
+ char *name;
struct type *base_type;
char *subtype_info;
- /* Fall back to the original type if symbol lookup failed. */
- if (raw_type == NULL)
- raw_type = orig_type;
+ gdb_assert (raw_type != NULL);
+ gdb_assert (TYPE_NAME (raw_type) != NULL);
if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
base_type = TYPE_TARGET_TYPE (raw_type);
else
base_type = raw_type;
+ name = TYPE_NAME (raw_type);
subtype_info = strstr (name, "___XD");
if (subtype_info == NULL)
{
@@ -9727,7 +9782,7 @@ to_fixed_range_type (char *name, struct value *dval, struct type *orig_type)
if (L < INT_MIN || U > INT_MAX)
return raw_type;
else
- return create_range_type (alloc_type_copy (orig_type), raw_type,
+ return create_range_type (alloc_type_copy (raw_type), raw_type,
ada_discrete_type_low_bound (raw_type),
ada_discrete_type_high_bound (raw_type));
}
@@ -9790,7 +9845,7 @@ to_fixed_range_type (char *name, struct value *dval, struct type *orig_type)
}
}
- type = create_range_type (alloc_type_copy (orig_type), base_type, L, U);
+ type = create_range_type (alloc_type_copy (raw_type), base_type, L, U);
TYPE_NAME (type) = name;
return type;
}
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index 3d60f8f..f6b613f 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -187,6 +187,8 @@ struct value *ada_convert_actual (struct value *actual,
extern struct value *ada_value_subscript (struct value *, int,
struct value **);
+extern void ada_fixup_array_indexes_type (struct type *index_desc_type);
+
extern struct type *ada_array_element_type (struct type *, int);
extern int ada_array_arity (struct type *);
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
index 17d3594..b69deab 100644
--- a/gdb/ada-typeprint.c
+++ b/gdb/ada-typeprint.c
@@ -55,7 +55,7 @@ static void
print_dynamic_range_bound (struct type *, const char *, int,
const char *, struct ui_file *);
-static void print_range_type_named (char *, struct type *, struct ui_file *);
+static void print_range_type (struct type *, struct ui_file *);
@@ -212,19 +212,19 @@ print_dynamic_range_bound (struct type *type, const char *name, int name_len,
fprintf_filtered (stream, "?");
}
-/* Print the range type named NAME. If symbol lookup fails, fall back
- to ORIG_TYPE as base type. */
+/* Print RAW_TYPE as a range type, using any bound information
+ following the GNAT encoding (if available). */
static void
-print_range_type_named (char *name, struct type *orig_type,
- struct ui_file *stream)
+print_range_type (struct type *raw_type, struct ui_file *stream)
{
- struct type *raw_type = ada_find_any_type (name);
+ char *name;
struct type *base_type;
char *subtype_info;
- if (raw_type == NULL)
- raw_type = orig_type;
+ gdb_assert (raw_type != NULL);
+ name = TYPE_NAME (raw_type);
+ gdb_assert (name != NULL);
if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
base_type = TYPE_TARGET_TYPE (raw_type);
@@ -341,10 +341,12 @@ print_array_type (struct type *type, struct ui_file *stream, int show,
{
if (ada_is_simple_array_type (type))
{
- struct type *range_desc_type =
- ada_find_parallel_type (type, "___XA");
+ struct type *range_desc_type;
struct type *arr_type;
+ range_desc_type = ada_find_parallel_type (type, "___XA");
+ ada_fixup_array_indexes_type (range_desc_type);
+
bitsize = 0;
if (range_desc_type == NULL)
{
@@ -368,9 +370,8 @@ print_array_type (struct type *type, struct ui_file *stream, int show,
{
if (k > 0)
fprintf_filtered (stream, ", ");
- print_range_type_named (TYPE_FIELD_NAME
- (range_desc_type, k),
- TYPE_INDEX_TYPE (arr_type), stream);
+ print_range_type (TYPE_FIELD_TYPE (range_desc_type, k),
+ stream);
if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
}
@@ -786,7 +787,7 @@ ada_print_type (struct type *type0, char *varstring, struct ui_file *stream,
else
{
fprintf_filtered (stream, "range ");
- print_range_type_named (name, type, stream);
+ print_range_type (type, stream);
}
}
break;