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;
  *c=_mm_load_ps(b);
  *c+=a;
  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"
<snip>
[   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 <_Z1fDv4_fPf>
             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]
<snip>
 [   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
    end_of_list

  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
    end_of_list

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:
 [Offset]
 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 15.0.7-2.fc37)"
           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 <_Z1fDv4_fPf>
           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?

-ben



-cary
-- 
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss

Reply via email to