From 28c85d6c4b53aca80e4b00525a89fa213705690c Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Mon, 17 May 2010 16:55:31 +0000 Subject: [PATCH] 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 * 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. --- gdb/ChangeLog | 14 +++++++++ gdb/ada-lang.c | 83 ++++++++++++++++++++++++++++++++++++++++++++--------- gdb/ada-lang.h | 2 ++ gdb/ada-typeprint.c | 29 ++++++++++--------- 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 + + * 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 * 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; -- 2.7.4