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