* ada-lang.c (decode_packed_array): If the value is a pointer to

an array, then use value_ind to dereference it, not ada_value_ind.
        (ada_template_to_fixed_record_type_1): Handle the case where a
        dynamic field is an aligner type.
        (to_fixed_array_type): Add handling for packed array types.
        (ada_get_base_type): Do not follow the XVS type if the type is
        an aligner type.
        (ada_evaluate_subexp): Split a few statements up for clarity
        and debuggability.
        <OP_FUNCALL>: Add handling of the case of a packed array that
        has already been fixed.
This commit is contained in:
Joel Brobecker 2009-06-23 16:43:24 +00:00
parent 4b27a62068
commit 284614f01a
2 changed files with 328 additions and 23 deletions

View File

@ -1,3 +1,17 @@
2009-06-23 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (decode_packed_array): If the value is a pointer to
an array, then use value_ind to dereference it, not ada_value_ind.
(ada_template_to_fixed_record_type_1): Handle the case where a
dynamic field is an aligner type.
(to_fixed_array_type): Add handling for packed array types.
(ada_get_base_type): Do not follow the XVS type if the type is
an aligner type.
(ada_evaluate_subexp): Split a few statements up for clarity
and debuggability.
<OP_FUNCALL>: Add handling of the case of a packed array that
has already been fixed.
2009-06-23 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (evaluate_subexp): Delete. Use the version from eval.c.

View File

@ -1818,8 +1818,15 @@ decode_packed_array (struct value *arr)
struct type *type;
arr = ada_coerce_ref (arr);
/* If our value is a pointer, then dererence it. Make sure that
this operation does not cause the target type to be fixed, as
this would indirectly cause this array to be decoded. The rest
of the routine assumes that the array hasn't been decoded yet,
so we use the basic "value_ind" routine to perform the dereferencing,
as opposed to using "ada_value_ind". */
if (TYPE_CODE (value_type (arr)) == TYPE_CODE_PTR)
arr = ada_value_ind (arr);
arr = value_ind (arr);
type = decode_packed_array_type (value_type (arr));
if (type == NULL)
@ -6780,6 +6787,11 @@ ada_template_to_fixed_record_type_1 (struct type *type,
}
else if (is_dynamic_field (type, f))
{
const gdb_byte *field_valaddr = valaddr;
CORE_ADDR field_address = address;
struct type *field_type =
TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, f));
if (dval0 == NULL)
{
/* rtype's length is computed based on the run-time
@ -6793,18 +6805,36 @@ ada_template_to_fixed_record_type_1 (struct type *type,
else
dval = dval0;
/* Get the fixed type of the field. Note that, in this case, we
do not want to get the real type out of the tag: if the current
field is the parent part of a tagged record, we will get the
tag of the object. Clearly wrong: the real type of the parent
is not the real type of the child. We would end up in an infinite
loop. */
TYPE_FIELD_TYPE (rtype, f) =
ada_to_fixed_type
(ada_get_base_type
(TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, f))),
cond_offset_host (valaddr, off / TARGET_CHAR_BIT),
cond_offset_target (address, off / TARGET_CHAR_BIT), dval, 0);
/* If the type referenced by this field is an aligner type, we need
to unwrap that aligner type, because its size might not be set.
Keeping the aligner type would cause us to compute the wrong
size for this field, impacting the offset of the all the fields
that follow this one. */
if (ada_is_aligner_type (field_type))
{
long field_offset = TYPE_FIELD_BITPOS (field_type, f);
field_valaddr = cond_offset_host (field_valaddr, field_offset);
field_address = cond_offset_target (field_address, field_offset);
field_type = ada_aligned_type (field_type);
}
field_valaddr = cond_offset_host (field_valaddr,
off / TARGET_CHAR_BIT);
field_address = cond_offset_target (field_address,
off / TARGET_CHAR_BIT);
/* Get the fixed type of the field. Note that, in this case,
we do not want to get the real type out of the tag: if
the current field is the parent part of a tagged record,
we will get the tag of the object. Clearly wrong: the real
type of the parent is not the real type of the child. We
would end up in an infinite loop. */
field_type = ada_get_base_type (field_type);
field_type = ada_to_fixed_type (field_type, field_valaddr,
field_address, dval, 0);
TYPE_FIELD_TYPE (rtype, f) = field_type;
TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
bit_incr = fld_bit_len =
TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT;
@ -7130,11 +7160,15 @@ to_fixed_array_type (struct type *type0, struct value *dval,
{
struct type *index_type_desc;
struct type *result;
int packed_array_p;
if (ada_is_packed_array_type (type0) /* revisit? */
|| TYPE_FIXED_INSTANCE (type0))
if (TYPE_FIXED_INSTANCE (type0))
return type0;
packed_array_p = ada_is_packed_array_type (type0);
if (packed_array_p)
type0 = decode_packed_array_type (type0);
index_type_desc = ada_find_parallel_type (type0, "___XA");
if (index_type_desc == NULL)
{
@ -7152,7 +7186,10 @@ to_fixed_array_type (struct type *type0, struct value *dval,
consult the object tag. */
struct type *elt_type = ada_to_fixed_type (elt_type0, 0, 0, dval, 1);
if (elt_type0 == elt_type)
/* Make sure we always create a new array type when dealing with
packed array types, since we're going to fix-up the array
type length and element bitsize a little further down. */
if (elt_type0 == elt_type && !packed_array_p)
result = type0;
else
result = create_array_type (alloc_type (TYPE_OBJFILE (type0)),
@ -7192,6 +7229,21 @@ to_fixed_array_type (struct type *type0, struct value *dval,
error (_("array type with dynamic size is larger than varsize-limit"));
}
if (packed_array_p)
{
/* So far, the resulting type has been created as if the original
type was a regular (non-packed) array type. As a result, the
bitsize of the array elements needs to be set again, and the array
length needs to be recomputed based on that bitsize. */
int len = TYPE_LENGTH (result) / TYPE_LENGTH (TYPE_TARGET_TYPE (result));
int elt_bitsize = TYPE_FIELD_BITSIZE (type0, 0);
TYPE_FIELD_BITSIZE (result, 0) = TYPE_FIELD_BITSIZE (type0, 0);
TYPE_LENGTH (result) = len * elt_bitsize / HOST_CHAR_BIT;
if (TYPE_LENGTH (result) * HOST_CHAR_BIT < len * elt_bitsize)
TYPE_LENGTH (result)++;
}
TYPE_FIXED_INSTANCE (result) = 1;
return result;
}
@ -7615,6 +7667,21 @@ ada_get_base_type (struct type *raw_type)
if (raw_type == NULL || TYPE_CODE (raw_type) != TYPE_CODE_STRUCT)
return raw_type;
if (ada_is_aligner_type (raw_type))
/* The encoding specifies that we should always use the aligner type.
So, even if this aligner type has an associated XVS type, we should
simply ignore it.
According to the compiler gurus, an XVS type parallel to an aligner
type may exist because of a stabs limitation. In stabs, aligner
types are empty because the field has a variable-sized type, and
thus cannot actually be used as an aligner type. As a result,
we need the associated parallel XVS type to decode the type.
Since the policy in the compiler is to not change the internal
representation based on the debugging info format, we sometimes
end up having a redundant XVS type parallel to the aligner type. */
return raw_type;
real_type_namer = ada_find_parallel_type (raw_type, "___XVS");
if (real_type_namer == NULL
|| TYPE_CODE (real_type_namer) != TYPE_CODE_STRUCT
@ -8253,6 +8320,225 @@ ada_value_cast (struct type *type, struct value *arg2, enum noside noside)
return value_cast (type, arg2);
}
/* Evaluating Ada expressions, and printing their result.
------------------------------------------------------
We usually evaluate an Ada expression in order to print its value.
We also evaluate an expression in order to print its type, which
happens during the EVAL_AVOID_SIDE_EFFECTS phase of the evaluation,
but we'll focus mostly on the EVAL_NORMAL phase. In practice, the
EVAL_AVOID_SIDE_EFFECTS phase allows us to simplify certain aspects of
the evaluation compared to the EVAL_NORMAL, but is otherwise very
similar.
Evaluating expressions is a little more complicated for Ada entities
than it is for entities in languages such as C. The main reason for
this is that Ada provides types whose definition might be dynamic.
One example of such types is variant records. Or another example
would be an array whose bounds can only be known at run time.
The following description is a general guide as to what should be
done (and what should NOT be done) in order to evaluate an expression
involving such types, and when. This does not cover how the semantic
information is encoded by GNAT as this is covered separatly. For the
document used as the reference for the GNAT encoding, see exp_dbug.ads
in the GNAT sources.
Ideally, we should embed each part of this description next to its
associated code. Unfortunately, the amount of code is so vast right
now that it's hard to see whether the code handling a particular
situation might be duplicated or not. One day, when the code is
cleaned up, this guide might become redundant with the comments
inserted in the code, and we might want to remove it.
When evaluating Ada expressions, the tricky issue is that they may
reference entities whose type contents and size are not statically
known. Consider for instance a variant record:
type Rec (Empty : Boolean := True) is record
case Empty is
when True => null;
when False => Value : Integer;
end case;
end record;
Yes : Rec := (Empty => False, Value => 1);
No : Rec := (empty => True);
The size and contents of that record depends on the value of the
descriminant (Rec.Empty). At this point, neither the debugging
information nor the associated type structure in GDB are able to
express such dynamic types. So what the debugger does is to create
"fixed" versions of the type that applies to the specific object.
We also informally refer to this opperation as "fixing" an object,
which means creating its associated fixed type.
Example: when printing the value of variable "Yes" above, its fixed
type would look like this:
type Rec is record
Empty : Boolean;
Value : Integer;
end record;
On the other hand, if we printed the value of "No", its fixed type
would become:
type Rec is record
Empty : Boolean;
end record;
Things become a little more complicated when trying to fix an entity
with a dynamic type that directly contains another dynamic type,
such as an array of variant records, for instance. There are
two possible cases: Arrays, and records.
Arrays are a little simpler to handle, because the same amount of
memory is allocated for each element of the array, even if the amount
of space used by each element changes from element to element.
Consider for instance the following array of type Rec:
type Rec_Array is array (1 .. 2) of Rec;
The type structure in GDB describes an array in terms of its
bounds, and the type of its elements. By design, all elements
in the array have the same type. So we cannot use a fixed type
for the array elements in this case, since the fixed type depends
on the actual value of each element.
Fortunately, what happens in practice is that each element of
the array has the same size, which is the maximum size that
might be needed in order to hold an object of the element type.
And the compiler shows it in the debugging information by wrapping
the array element inside a private PAD type. This type should not
be shown to the user, and must be "unwrap"'ed before printing. Note
that we also use the adjective "aligner" in our code to designate
these wrapper types.
These wrapper types should have a constant size, which is the size
of each element of the array. In the case when the size is statically
known, the PAD type will already have the right size, and the array
element type should remain unfixed. But there are cases when
this size is not statically known. For instance, assuming that
"Five" is an integer variable:
type Dynamic is array (1 .. Five) of Integer;
type Wrapper (Has_Length : Boolean := False) is record
Data : Dynamic;
case Has_Length is
when True => Length : Integer;
when False => null;
end case;
end record;
type Wrapper_Array is array (1 .. 2) of Wrapper;
Hello : Wrapper_Array := (others => (Has_Length => True,
Data => (others => 17),
Length => 1));
The debugging info would describe variable Hello as being an
array of a PAD type. The size of that PAD type is not statically
known, but can be determined using a parallel XVZ variable.
In that case, a copy of the PAD type with the correct size should
be used for the fixed array.
However, things are slightly different in the case of dynamic
record types. In this case, in order to compute the associated
fixed type, we need to determine the size and offset of each of
its components. This, in turn, requires us to compute the fixed
type of each of these components.
Consider for instance the example:
type Bounded_String (Max_Size : Natural) is record
Str : String (1 .. Max_Size);
Length : Natural;
end record;
My_String : Bounded_String (Max_Size => 10);
In that case, the position of field "Length" depends on the size
of field Str, which itself depends on the value of the Max_Size
discriminant. In order to fix the type of variable My_String,
we need to fix the type of field Str. Therefore, fixing a variant
record requires us to fix each of its components.
However, if a component does not have a dynamic size, the component
should not be fixed. In particular, fields that use a PAD type
should not fixed. Here is an example where this might happen
(assuming type Rec above):
type Container (Big : Boolean) is record
First : Rec;
After : Integer;
case Big is
when True => Another : Integer;
when False => null;
end case;
end record;
My_Container : Container := (Big => False,
First => (Empty => True),
After => 42);
In that example, the compiler creates a PAD type for component First,
whose size is constant, and then positions the component After just
right after it. The offset of component After is therefore constant
in this case.
The debugger computes the position of each field based on an algorithm
that uses, among other things, the actual position and size of the field
preceding it. Let's now imagine that the user is trying to print the
value of My_Container. If the type fixing was recursive, we would
end up computing the offset of field After based on the size of the
fixed version of field First. And since in our example First has
only one actual field, the size of the fixed type is actually smaller
than the amount of space allocated to that field, and thus we would
compute the wrong offset of field After.
Unfortunately, we need to watch out for dynamic components of variant
records (identified by the ___XVL suffix in the component name).
Even if the target type is a PAD type, the size of that type might
not be statically known. So the PAD type needs to be unwrapped and
the resulting type needs to be fixed. Otherwise, we might end up
with the wrong size for our component. This can be observed with
the following type declarations:
type Octal is new Integer range 0 .. 7;
type Octal_Array is array (Positive range <>) of Octal;
pragma Pack (Octal_Array);
type Octal_Buffer (Size : Positive) is record
Buffer : Octal_Array (1 .. Size);
Length : Integer;
end record;
In that case, Buffer is a PAD type whose size is unset and needs
to be computed by fixing the unwrapped type.
Lastly, when should the sub-elements of a type that remained unfixed
thus far, be actually fixed?
The answer is: Only when referencing that element. For instance
when selecting one component of a record, this specific component
should be fixed at that point in time. Or when printing the value
of a record, each component should be fixed before its value gets
printed. Similarly for arrays, the element of the array should be
fixed when printing each element of the array, or when extracting
one element out of that array. On the other hand, fixing should
not be performed on the elements when taking a slice of an array!
Note that one of the side-effects of miscomputing the offset and
size of each field is that we end up also miscomputing the size
of the containing type. This can have adverse results when computing
the value of an entity. GDB fetches the value of an entity based
on the size of its type, and thus a wrong size causes GDB to fetch
the wrong amount of memory. In the case where the computed size is
too small, GDB fetches too little data to print the value of our
entiry. Results in this case as unpredicatble, as we usually read
past the buffer containing the data =:-o. */
/* Implement the evaluate_exp routine in the exp_descriptor structure
for the Ada language. */
static struct value *
ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
int *pos, enum noside noside)
@ -8525,9 +8811,8 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
}
else
{
arg1 =
unwrap_value (evaluate_subexp_standard
(expect_type, exp, pos, noside));
arg1 = evaluate_subexp_standard (expect_type, exp, pos, noside);
arg1 = unwrap_value (arg1);
return ada_to_fixed_value (arg1);
}
@ -8556,6 +8841,12 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
if (ada_is_packed_array_type (desc_base_type (value_type (argvec[0]))))
argvec[0] = ada_coerce_to_simple_array (argvec[0]);
else if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_ARRAY
&& TYPE_FIELD_BITSIZE (value_type (argvec[0]), 0) != 0)
/* This is a packed array that has already been fixed, and
therefore already coerced to a simple array. Nothing further
to do. */
;
else if (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_REF
|| (TYPE_CODE (value_type (argvec[0])) == TYPE_CODE_ARRAY
&& VALUE_LVAL (argvec[0]) == lval_memory))
@ -9126,10 +9417,10 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp,
return value_zero (ada_aligned_type (type), lval_memory);
}
else
return
ada_to_fixed_value (unwrap_value
(ada_value_struct_elt
(arg1, &exp->elts[pc + 2].string, 0)));
arg1 = ada_value_struct_elt (arg1, &exp->elts[pc + 2].string, 0);
arg1 = unwrap_value (arg1);
return ada_to_fixed_value (arg1);
case OP_TYPE:
/* The value is not supposed to be used. This is here to make it
easier to accommodate expressions that contain types. */