<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 3/28/23 13:17, David Blaikie wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CAENS6EsXHZZ4bDD=ag77YnTj3orGsOTXS65BufJFsx9croN6rA@mail.gmail.com">
      <blockquote type="cite">
        <pre class="moz-quote-pre" wrap="">DW_AT[_GNU]_vector is best understood not as "a hardware vector register" but rather as a marker that "this type is eligible to be passed in hardware vector registers at function boundaries according to the platform ABI".
</pre>
      </blockquote>
      <pre class="moz-quote-pre" wrap="">
My 2c would not be to describe these in terms of
hardware/implementations (that gets confusing/blurs the line between
variable/types and locations - as you say, these things can be stored
in memory, so they aren't uniquely in registers - you might have a
member of this type in a struct passed in memory and need to know the
ABI/struct layout for that, etc), but at the source level - which the
ABI is defined in those same terms. Overloading, for instance, still
applies if these are different types - so other debugger features need
to work based on this type information.

So it seems like a simpler question is:

How should DWARF producers/consumers expect to encode the source
example Ben provided (well, simplified a bit):

#include <x86intrin.h>

void f( __m128 a){
}

What DWARF should be used to describe the type of 'a'? And how does
this encoding scale to all the other similar intrinsic types?

</pre>
    </blockquote>
    <p>As a person who has spent a crazy amount of time doing ABI work
      and static analysis this is what I would like: (I'm kind of
      assembling this by cutting and pasting and editing so please
      excuse minor errors like sizes and ignoring siblings. It is hand
      written hand-wavy DWARF)</p>
    <p><font face="monospace"><font face="monospace"><b>Factored out
            preamble to all of them:</b><br>
          [0] base_type            abbrev: 3<br>
                 byte_size            (data1) 4<br>
                 encoding             (data1) float (4)<br>
                 name                 (strp) "float"</font><br>
      </font><font face="monospace"><font face="monospace">[5]  </font><font
          face="monospace"><font face="monospace"><font face="monospace">
              base_type            abbrev: 3<br>
                     byte_size            (data1) 4<br>
                     encoding             (data1) unsigned (4)<br>
                     name                 (strp) "unsigned int"</font></font></font></font><br>
      <font face="monospace"><font face="monospace"><font
            face="monospace">[8]  </font><font face="monospace"><font
              face="monospace"><font face="monospace">
                base_type            abbrev: 3<br>
                       byte_size            (data1) 4<br>
                       encoding             (data1) signed (4)<br>
                       name                 (strp) "int"</font></font></font></font></font><br>
      <font face="monospace"><font face="monospace"><font
            face="monospace"><font face="monospace"><font
                face="monospace"><font face="monospace"><font
                    face="monospace">[10] base_type            abbrev: 3<br>
                           byte_size            (data1) 8<br>
                           encoding             (data1) double (4)<br>
                           name                 (strp) "double float"<br>
                  </font></font>
              </font></font></font></font>[15] subprogram          
        abbrev: 32<br>
           external             (flag_present) yes<br>
           name                 (string) "f"<br>
        [20]      formal_parameter     abbrev: 15<br>
                 name                 (string) "a"<br>
                 type                 (ref4) [30]</font></p>
    <p><font face="monospace"><b>void f( float *a){}</b><b><br>
        </b>[30] pointer_type         abbrev: 5<br>
               byte_size            (implicit_const) 8<br>
               type                 (ref4) [0]<br>
      </font></p>
    <p><font face="monospace"><b>void f( float a[]){}</b></font><br>
      <font face="monospace"><font face="monospace">[30] array_type
                  abbrev: 5<br>
                 type                 (ref4) [0]</font></font></p>
    <p><font face="monospace"><b>void f( float a[4]){}<br>
        </b></font><font face="monospace"><font face="monospace"><font
            face="monospace">[30] array_type         abbrev: 5<br>
                   type                 (ref4) [0]</font></font><br>
        [40] subrange_type        abbrev: 31<br>
               upper_bound          (data1) 3<b><br>
        </b></font></p>
    <p><b><font face="monospace">void f( float a[s], </font></b><font
        face="monospace"><b><font face="monospace">unsigned s</font></b><b>){}
          // C only</b></font><font face="monospace"><br>
      </font><font face="monospace"><font face="monospace"><font
            face="monospace">[30] array_type         abbrev: 5<br>
                   type                 (ref4) [0]</font></font><br>
        [40] subrange_type        abbrev: 31<br>
               upper_bound          (data1) DW_OP_reg reg4<br>
        [50]</font><font face="monospace"> formal_parameter     abbrev:
        15<br>
                 name                 (string) "s"<br>
                 type                 (ref4) [5]</font></p>
    <p><font face="monospace"><b>void f( __m128 a){} // floats implied</b><br>
      </font><font face="monospace"><font face="monospace"><font
            face="monospace">[30] typedef              abbrev: 8<br>
                    name                 (strp) "__m128"<br>
                         decl_file            (data1) xmmintrin.h (2)<br>
                         decl_line            (data1) 69<br>
                         decl_column          (data1) 15<br>
                         type                 (ref4) [40]<br>
            [40] array_type         abbrev: 5<br>
          </font></font></font><font face="monospace"><font
          face="monospace"><font face="monospace">      
            vector           (flag_present) yes<br>
                   type                 (ref4) [0]</font></font><br>
        [50] subrange_type        abbrev: 31<br>
               upper_bound          (data1) 3<b><br>
        </b></font><font face="monospace"></font></p>
    <p><b><font face="monospace">void f( __m128i a){} // integer</font></b><br>
      <font face="monospace"><font face="monospace"><font
            face="monospace"><font face="monospace">[30]
              typedef              abbrev: 8<br>
                      name                 (strp) "__m128i"<br>
                           decl_file            (data1) xmmintrin.h (2)<br>
                           decl_line            (data1) 69<br>
                           decl_column          (data1) 15<br>
                           type                 (ref4) [40]<br>
              [40] array_type         abbrev: 5<br>
            </font></font></font><font face="monospace"><font
            face="monospace"><font face="monospace">      
              vector           (flag_present) yes<br>
                     type                 (ref4) [8]</font></font><br>
          [50] subrange_type        abbrev: 31<br>
                 upper_bound          (data1) 3</font></font></p>
    <p><font face="monospace"><b>void f( __m128d a){}</b><br>
      </font><font face="monospace"><font face="monospace"><font
            face="monospace">[30] typedef              abbrev: 8<br>
                    name                 (strp) "__m128d"<br>
                         decl_file            (data1) xmmintrin.h (2)<br>
                         decl_line            (data1) 69<br>
                         decl_column          (data1) 15<br>
                         type                 (ref4) [40]<br>
            [40] array_type         abbrev: 5<br>
          </font></font></font><font face="monospace"><font
          face="monospace"><font face="monospace">      
            vector           (flag_present) yes<br>
                   type                 (ref4) [10]</font></font><br>
        [50] subrange_type        abbrev: 31<br>
               upper_bound          (data1) 2</font></p>
    <p><b><font face="monospace">void f( __m128u a){} // unsigned</font></b><br>
      <font face="monospace"><font face="monospace"><font
            face="monospace"><font face="monospace">[30]
              typedef              abbrev: 8<br>
                      name                 (strp) "__m128u"<br>
                           decl_file            (data1) xmmintrin.h (2)<br>
                           decl_line            (data1) 69<br>
                           decl_column          (data1) 15<br>
                           type                 (ref4) [40]<br>
              [40] array_type         abbrev: 5<br>
            </font></font></font><font face="monospace"><font
            face="monospace"><font face="monospace">      
              vector           (flag_present) yes<br>
                     type                 (ref4) [5]</font></font><br>
          [50] subrange_type        abbrev: 31<br>
                 upper_bound          (data1) 3</font></font></p>
    <p>Then I would continue on with all various encodings and base
      types that can be in a the various kinds of vectors. Because the
      instructions that load the base types into the vector register do
      not care about encodings, they are just moving bytes, the Intel
      vector intrinsics type names kind of merge encoding and length in
      a way that I'm not fond of as someone who cares about ABI. For
      example I invented __m128u above to go along with the __m128i
      already defined in intel's intrinsics manual.<br>
    </p>
    <p>I would also expand that the larger vector sizes. For example:</p>
    <p><font face="monospace"><b>void f( __mm256 a){} // floats implied</b><br>
      </font><font face="monospace"><font face="monospace"><font
            face="monospace">[30] typedef              abbrev: 8<br>
                    name                 (strp) "__mm256"<br>
                         decl_file            (data1) xmmintrin.h (2)<br>
                         decl_line            (data1) 69<br>
                         decl_column          (data1) 15<br>
                         type                 (ref4) [40]<br>
            [40] array_type         abbrev: 5<br>
          </font></font></font><font face="monospace"><font
          face="monospace"><font face="monospace">      
            vector           (flag_present) yes<br>
                   type                 (ref4) [0]</font></font><br>
        [50] subrange_type        abbrev: 31<br>
               upper_bound          (data1) 7</font></p>
    <p>As you can see, much of what I really would like is to:</p>
    <ol>
      <li>Not have arrays degenerate into pointers when the source code
        is explicit about this. Consider a linked lists vs an arrays,
        both could have the same ABI fingerprint. - I believe that this
        should be written into the standard as a best practice example.I
        will write this up and file it.<br>
      </li>
      <li>When it is an array and the bound is specified, this also
        should be included in the ABI fingerprint. - I believe that this
        to should be written into the standard as a best practice
        example.I will write this up and file it.</li>
      <li>In my ABI work I need a way to disambiguate "typedef float[4]
        __m128" from "__m128" as it is now defined in xmmintrin.h. The
        difference is important because in libabigail we do not look at
        the location of the parameters, we just assume that the platform
        ABI as implemented by the compiler takes care of that. Thus if
        arrays didn't degenerate into pointers (introducing the
        ambiguity between the head of a linked list and an array), then:</li>
    </ol>
    <p><font face="monospace">typedef float[4] __m128;<br>
        void f( __m128 a){}</font></p>
    <p>Would stick a pointer to a in general purpose register. While:</p>
    <p><font face="monospace">#include "xmmintin.h"<br>
        void f( __m128 a){}</font></p>
    <p>Would stick a in a vector register because calling convention is
      different and libabigail wouldn't be able to tell the difference.<br>
    </p>
    <p>We don't process the formal parameter's location at least in part
      because it is hard. We would have to add code in libabigail to
      process the location list but also because the quality of location
      information from different compilers has been inconsistent. And
      the purpose of libabigail the tool was not to check how well the
      compilers implemented the platform ABI but to test libraries for
      ABI compatibility.<br>
    </p>
    <p>I spent a notable portion of yesterday writing various bits of
      arguments against Cary's DW_TAG_vector and then throwing them away
      because they really were not at all convincing even to myself. The
      only argument that I found convincing to even myself was
      parsimony. We currently have DW_TAG_array and I couldn't come up
      with how it would be different in any way from DW_TAG_array +
      DW_AT_vector. So based on that rather weak argument, I'll say that
      I really don't care if it is:</p>
    <p>DW_TAG_vector</p>
    <p>or <br>
    </p>
    <p>DW_TAG_array<br>
        DW_AT_vector</p>
    <p>Tony let me know he's become convinced that they do not need a
      vector type for their GPU work and are planning to drop their
      vectors as base type proposal. That leaves my needs around ABI as
      the only pending concern and that may be handled by Kyle's
      proposal to make the location of the return value something
      encoded in the DWARF rather than having to infer it from the
      platform ABI.</p>
    <p>If we didn't get something like DW_TAG_vector or DW_TAG_array +
      DW_AT_vector, and instead only went with just Kyle's proposal
      specifying the location of the return value, then libabigail would
      then need to be taught to process location information.</p>
    <p>-ben<br>
    </p>
    <p><br>
    </p>
    <p><font face="monospace"><b> </b></font></p>
    <p><font face="monospace"></font></p>
  </body>
</html>