[Dwarf-discuss] ISSUE: CPU vector types.

Ben Woodard woodard@redhat.com
Tue Mar 28 18:13:09 GMT 2023

On 3/27/23 23:51, Cary Coutant wrote:
>> Vector registers
>> It has been the long standing existing practice to treat hardware
>> vector registers as arrays of a fundamental base type. To deliniate
>> these hardware register arrays from arrays in the language source they
>> have been given the DW_AT_GNU_vector attribute. This proposal simply
>> standardizes the existing behavior.
>> In Section 2.2 Attribute Types, DW_AT_vector and
>> DW_AT_variable_vector_width shall be added to Table 2.2
>>      --------------------------------------------------------------------
>>      DW_AT_vector                | A hardware vector register
>>      DW_AT_variable_vector_width | Array bound for hardware
>>                                  | implementation defined vector register
>>                                  | width
>>      --------------------------------------------------------------------
> I don't understand what tags this DW_AT_vector attribute would apply
> to. Vector registers aren't *types*, they're *locations*, so it
> doesn't really make sense to me to put this attribute on a
> DW_TAG_array_type.

Maybe I should have said.

     DW_AT_vector                | A hardware vector register type

because what I'm talking about are types not locations. Consider a 
simple program like:

#include <x86intrin.h>

__m128 *f( __m128 a, float *b){
   __m128 *c=new __m128;
   return c;

Which when compiled by GCC generates DWARF like this:

  [    7c]    base_type            abbrev: 3
              byte_size            (data1) 4
              encoding             (data1) float (4)
              name                 (strp) "float"
[   7c5]    typedef              abbrev: 8
              name                 (strp) "__m128"
              decl_file            (data1) xmmintrin.h (2)
              decl_line            (data1) 69
              decl_column          (data1) 15
              type                 (ref4) [   7d1]
  [   7d1]    array_type           abbrev: 30
              GNU_vector           (flag_present) yes
              type                 (ref4) [    7c]
              sibling              (ref4) [   7dd]
  [   7da]      subrange_type        abbrev: 31
                upper_bound          (data1) 3
  [   7dd]    base_type            abbrev: 3
              byte_size            (data1) 2
              encoding             (data1) float (4)
              name                 (strp) "_Float16"
  [   7e4]    subprogram           abbrev: 32
              external             (flag_present) yes
              name                 (string) "f"
              decl_file            (data1) vecreg.C (1)
              decl_line            (data1) 3
              decl_column          (data1) 9
              linkage_name         (strp) "_Z1fDv4_fPf"
              type                 (ref4) [   881]
              low_pc               (addr) .text+000000000000000000 
              high_pc              (data8) 38 (.bss+000000000000000000)
              frame_base           (exprloc)
               [ 0] call_frame_cfa
              call_all_calls       (flag_present) yes
              sibling              (ref4) [   881]
  [   808]      formal_parameter     abbrev: 15
                name                 (string) "a"
                decl_file            (implicit_const) vecreg.C (1)
                decl_line            (implicit_const) 3
                decl_column          (data1) 19
                type                 (ref4) [   7c5]
                location             (sec_offset) location list [    10]
                GNU_locviews         (sec_offset) location list [     c]
  [   818]      formal_parameter     abbrev: 15
                name                 (string) "b"
                decl_file            (implicit_const) vecreg.C (1)
                decl_line            (implicit_const) 3
                decl_column          (data1) 29
                type                 (ref4) [   886]
                location             (sec_offset) location list [    22]
                GNU_locviews         (sec_offset) location list [    1c]
  [   828]      variable             abbrev: 33
                name                 (string) "c"
                decl_file            (data1) vecreg.C (1)
                decl_line            (data1) 4
                decl_column          (data1) 11
                type                 (ref4) [   881]
                location             (sec_offset) location list [    37]
                GNU_locviews         (sec_offset) location list [    35]
  [   881]    pointer_type         abbrev: 5
              byte_size            (implicit_const) 8
              type                 (ref4) [   7c5]
  [   886]    pointer_type         abbrev: 5
              byte_size            (implicit_const) 8
              type                 (ref4) [    7c]


   Offset: 10, Index: 4
     offset_pair 0, 15
       .text+000000000000000000 <_Z1fDv4_fPf>..
       .text+0x0000000000000014 <_Z1fDv4_fPf+0x14>
         [ 0] reg17
     offset_pair 15, 26
       .text+0x0000000000000015 <_Z1fDv4_fPf+0x15>..
       .text+0x0000000000000025 <_Z1fDv4_fPf+0x25>
         [ 0] fbreg -32

   Offset: 1c, Index: 10
     view pair 0, 0
     view pair 0, 0
     view pair 0, 0

   Offset: 22, Index: 16
     offset_pair 0, 9
       .text+000000000000000000 <_Z1fDv4_fPf>..
       .text+0x0000000000000008 <_Z1fDv4_fPf+0x8>
         [ 0] reg5
     offset_pair 9, 25
       .text+0x0000000000000009 <_Z1fDv4_fPf+0x9>..
       .text+0x0000000000000024 <_Z1fDv4_fPf+0x24>
         [ 0] reg3
     offset_pair 25, 26
       .text+0x0000000000000025 <_Z1fDv4_fPf+0x25>..
       .text+0x0000000000000025 <_Z1fDv4_fPf+0x25>
         [ 0] entry_value:
              [ 0] reg5
         [ 3] stack_value

The things that I wanted to point out with this example are:

  * that a vector is a type, in this case __mm128
  * As a location it is different than a packed array with the same type
    that it contains.
  * This vector type can have a location that exists in memory, but also
    can exist in a register. In this case it exists both in reg17 and on
    fbreg-32 (on the stack)

Also it should be noted that clang (thankfully) copies gcc's behavior in 
this respect at least on linux. For example:

DWARF section [ 6] '.debug_info' at offset 0x27b:
  Compilation unit at offset 0:
  Version: 4, Abbreviation section offset: 0, Address size: 8, Offset 
size: 4
  [     b]  compile_unit         abbrev: 1
            producer             (strp) "clang version 15.0.7 (Fedora 
            language             (data2) C_plus_plus_14 (33)
            name                 (strp) "vecreg.C"
            stmt_list            (sec_offset) 0
            comp_dir             (strp) "/home/ben/Shared/test"
            low_pc               (addr) .text+000000000000000000 
            high_pc              (data4) 38 (.text+0x0000000000000026)
  [    2a]    pointer_type         abbrev: 2
              type                 (ref4) [    2f]
  [    2f]    const_type           abbrev: 3
              type                 (ref4) [    34]
  [    34]    typedef              abbrev: 4
              type                 (ref4) [    3f]
              name                 (strp) "__m128"
              decl_file            (data1) xmmintrin.h (1)
              decl_line            (data1) 21
  [    3f]    array_type           abbrev: 5
              GNU_vector           (flag_present) yes
              type                 (ref4) [    4b]
  [    44]      subrange_type        abbrev: 6
                type                 (ref4) [    52]
                count                (data1) 4
  [    4b]    base_type            abbrev: 7
              name                 (strp) "float"
              encoding             (data1) float (4)
              byte_size            (data1) 4
  [    52]    base_type            abbrev: 8
              name                 (strp) "__ARRAY_SIZE_TYPE__"
              byte_size            (data1) 8
              encoding             (data1) unsigned (7)

> We don't have DW_TAGs that describe registers; the
> ABI defines the registers and DWARF producers and consumers should
> understand and agree on the sizes and shapes of the various registers.

Right and they do as you can see from the fragment above reg17 is the 
vector register.

The one tricky complication is ARM SVE and RISC-V RVV where the vector 
width is not an architectural feature but a particular hardware 
implementation feature. To be able to know the actual vector length you 
have to read a machine specific register that tells you the length of 
the vector registers in that machine. Never the less SVE types can be 
passed as parameters between functions and the ABI for the architecture 
explains how. This creates some interesting DWARF expressions.

> In Tony's proposal, the new attribute modifies a base type, thus
> introducing a vector type, which might get placed in a vector
> register. But there, I don't see how the vector base type is
> fundamentally different from an array type. It seems it's just a dodge
> to make it a base type so that we can put whole vectors on the stack.

 From a type system point of view they are the same and therefore I can 
see the appeal of just making them base types for a particular 
architecture. The thing that I worry about is the combinatorial 
expansion of the base types.

In code that is different than what posted above, the indexability of 
the type is important making it behave more like an array.

> Maybe what we're looking for is a DW_TAG_vector_type, whose DW_AT_type
> attribute gives the base type for each element of the vector. This
> seems to be more DWARF-like, and if we decide there's a reason to
> allow stack entries with vector types, we can do that.
In what ways would DW_TAG_vector_type be different than DW_TAG_array?


> -cary
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.dwarfstd.org/pipermail/dwarf-discuss/attachments/20230328/2bb13703/attachment-0001.htm>

More information about the Dwarf-discuss mailing list