https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61595

            Bug ID: 61595
           Summary: Inconsistent DWARF information for arrays of vector
                    types
           Product: gcc
           Version: 4.7.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: debug
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gcc-bugzilla at mailhell dot seb7.de

While writing a DWARF parser/interpreter I hit what seems to be inconsistent
DWARF information.
The original source for my example originates from
"libgcc/config/rs6000/linux-unwind.h" of some older gcc-4.1.0 for powerpc, but
I reproduced the issue for the version on my workstation, which is "g++ (SUSE
Linux) 4.7.2 20130108 [gcc-4_7-branch revision 195012]" on x86_64.

Minimal example c++ code:
> struct gcc_vregs
> {
>   __attribute__ ((vector_size (16))) int vr[32];
> };
> 
> typedef int v4si __attribute__ ((vector_size (16)));
> 
> int main (int argc, char** argv) {
>     gcc_vregs testData;
>     for (int i = 0; i < 32; i++) {
>         v4si x = {i,i+32,i+64,i+96};
>         testData.vr[i] = x;
>     }   
> 
>     return 0;
> }

I compiled using "g++ minimal.c -gdwarf-4 -O0 -o minimal" and produced a DWARF
output with "objdump minimal -g > minimal.S".
The interesting snippet there is the type of gcc_vregs:
>  <1><25>: Abbrev Number: 2 (DW_TAG_structure_type)
>     <26>   DW_AT_name        : (indirect string, offset: 0xd7): gcc_vregs 
>     <2a>   DW_AT_byte_size   : 512
>     <2c>   DW_AT_decl_file   : 1  
>     <2d>   DW_AT_decl_line   : 1  
>     <2e>   DW_AT_sibling     : <0x3e> 
>  <2><32>: Abbrev Number: 3 (DW_TAG_member)
>     <33>   DW_AT_name        : vr 
>     <36>   DW_AT_decl_file   : 1  
>     <37>   DW_AT_decl_line   : 3  
>     <38>   DW_AT_type        : <0x3e> 
>     <3c>   DW_AT_data_member_location: 0  
>  <1><3e>: Abbrev Number: 4 (DW_TAG_array_type)
>     <3f>   DW_AT_type        : <0x4e> 
>     <43>   DW_AT_sibling     : <0x4e> 
>  <2><47>: Abbrev Number: 5 (DW_TAG_subrange_type)
>     <48>   DW_AT_type        : <0x5a> 
>     <4c>   DW_AT_upper_bound : 31 
>  <1><4e>: Abbrev Number: 6 (DW_TAG_array_type)
>     <4f>   DW_AT_GNU_vector  : 1  
>     <4f>   DW_AT_type        : <0x61> 
>     <53>   DW_AT_sibling     : <0x5a> 
>  <2><57>: Abbrev Number: 7 (DW_TAG_subrange_type)
>     <58>   DW_AT_upper_bound : 3  
>  <1><5a>: Abbrev Number: 8 (DW_TAG_base_type)
>     <5b>   DW_AT_byte_size   : 8  
>     <5c>   DW_AT_encoding    : 7  (unsigned)
>     <5d>   DW_AT_name        : (indirect string, offset: 0x80): sizetype  
>  <1><61>: Abbrev Number: 9 (DW_TAG_base_type)
>     <62>   DW_AT_byte_size   : 4  
>     <63>   DW_AT_encoding    : 5  (signed)
>     <64>   DW_AT_name        : int

As you can see, the total size of gcc_vregs is 512 bytes.
Running the code in gdb and examining main memory prior to the return statement
verifies that the variable testData contains 128 values, each being a 4 byte
integer (see testData.txt in the appended tar for a hexdump of its memory
region).

The DW_AT_type of its member vr is 0x4e, which is an array (or, in fact, a
vector) containing four sizetype's of size 8 bytes each.
So in total a child of vr is 4*8 = 32 bytes large.
Using this information, the total size is <array element count> * 32 bytes.
Since there is just one subrange of size 32, the element count is 32 and thus
the total size should be 1024 bytes.

On the other hand, the 32 element subrange of vr has the type 0x5a.
This is the 'sizetype' of size 8 bytes. So each of the subrange elements should
be 8 bytes small, and the computed size of the array vr (ignoring its own
DW_AT_type) is 8 bytes * 32 = 256.

As you can see, both ways compute a different size.
While it is possible they differ, usually a small DW_TAG_array_types'
DW_AT_type is stored in a bigger DW_TAG_subrange_type's DW_AT_type.
I.e. a 'unsigned char[16]' could store each char (of size 1) in an unsigned int
(of size 4) due to alignment restrictions.

But the code generated here is completely off, since the size is definitely 512
bytes (32 Elements in the array, each element is vector of four 4 byte ints ->
32 * 4 * 4 Bytes = 512 Bytes; verified against binaries behaviour).

Expected:
* The DW_TAG_base_type at 0x5a should be unsigned int with a DW_AT_byte_size of
4.
* The DW_TAG_subrange_type at 0x47 should be of type 0x4e -> it's a subrange
containing 32 elements, which are themselfs vectors of four 4 byte integer
values.

I append a tarball containing
* minimal.c - my minimal example source code
* minimal.S - DWARF information
* testData.txt - a memory dump of the variable 'testData' prior to the return.

I don't know about the policy for binaries, so I didn't attach it. But I can
still do so, if that is required.

Reply via email to