Avoid global lookup when decoding XA type.
authorJoel Brobecker <brobecker@gnat.com>
Mon, 17 May 2010 16:55:31 +0000 (16:55 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Mon, 17 May 2010 16:55:31 +0000 (16:55 +0000)
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.

gdb/ChangeLog
gdb/ada-lang.c
gdb/ada-lang.h
gdb/ada-typeprint.c

index 92fe6fb..852b6c0 100644 (file)
@@ -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
index 3b3894c..83f7cf3 100644 (file)
@@ -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;
     }
index 3d60f8f..f6b613f 100644 (file)
@@ -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 *);
index 17d3594..b69deab 100644 (file)
@@ -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 *);
 \f
 
 
@@ -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;