Hi,

I'm working on improvements for the DWARF information produced by GCC for Ada, and I have hit the following issue:

In Ada, it is possible to define array types inside structures (that are called records). The size of such array types can then depend on members of such records. For instance:

   type Array_Type is array (Integer range <>) of Integer;
   type Record_Type (N : Integer) is record
      A : Array_Type (1 .. N);
   end record;

Here, A's type is a "subtype" of Array_Type. It is an array whose upper bound is the special record member "N". I'm wondering how such bounds should be translated into DW_AT_{lower,upper}_bound attributes. The DWARFv4 specification (Appendix D, subsection 2.2 Ada Example) suggests the following DIEs (I'm stripping a few attributes that are not relevant for this issue):

 1$: DW_TAG_structure_type
         DW_AT_name("Record_Type")

 2$:   DW_TAG_member
           DW_AT_name("N")
           DW_AT_type(reference to Integer)

 3$:   DW_TAG_array_type
           DW_AT_type(reference to Integer)

 4$:     DW_TAG_subrange_type
             DW_AT_type(reference to Integer)
             DW_AT_lower_bound(constant 1)
             DW_AT_upper_bound(reference to member N at 2$)

 5$:   DW_TAG_member
           DW_AT_name("A")
           DW_AT_type(reference to array type at 4$)

With this debug info, the upper bound of "A" indeed completely mirrors the value of "N". In GCC, however, computing the upper bound of "A" is more subtle: it is internally represented as: max(0, <record>.N) so that when "N" is negative, 0 is returned.

While it is straightforward to reference a DIE from the DW_AT_upper_bound attribute, I struggle doing so inside a DWARF expression, and I do need a DWARF expression to correctly describe the computation of the upper bound. I guess I need an operation sequence that looks like:

   # Push N, then 0
   ??? Get the value of the "N" member;
   DW_OP_lit0;

   # Is N > 0?
   DW_OP_over; DW_OP_over;
   DW_OP_gt;
   DW_OP_bra: 1;

   # If not then return 0, else return N.
   DW_OP_swap
   DW_OP_drop

So the issue for me is to know what to put instead of the "???" part. It looks like the DW_OP_push_object_address (defined in section 2.5.1.3 Stack Operations) was introduced specifically for this kind of computation, but I'm not sure what it is supposed to mean in this context. Indeed, this operation would appear as part of a DWARF expression under a DW_TAG_subrange_type DIE, itself under a DW_TAG_array_type DIE, itself under a DW_TAG_structure_type. So what address would this operation push on top of the stack? The address of the "A" member, or the address of the embedding record?

The offsets of discriminants (the special record members that can be used to determine the size of regular record members) inside the record are statically known, so getting the address of the embedding record would be enough to be able to fetch the value of the discriminant. On the other hand, getting the address of the "A" member would not be sufficient: in more complex cases, the offset of the "A" member can depend on discriminants!

I tried to look at the implementation of DW_OP_push_object_address in GDB, but it looks like it's not implemented yet. What do you think about its expected behavior? And if I cannot use this operation for such array bound expressions, what should I use?

Thank you in advance for your answers. :-)

--
Pierre-Marie de Rodat

_______________________________________________
Dwarf-Discuss mailing list
Dwarf-Discuss@lists.dwarfstd.org
http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org

Reply via email to