<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>