This was reported to me by someone trying to debug SVE and SME code that switched streaming modes, using qemu-user. When in streaming mode they could not read the Z registers but they could in non-streaming mode. Qemu was returning valid data each time but lldb refused to display it in streaming mode.
The cause is a difference in how lldb-server and qemu describe the type of these registers. lldb-server describes them as:
<reg name="z31" bitsize="256" regnum="193" encoding="vector" format="vector-uint8" group="Scalable Vector Extension Registers" ehframe_regnum="127" dwarf_regnum="127" />
And this gets converted to eEncodingVector. We can see that lldb-server sets that in the source:
// Defines a Z vector register with 16-byte default size
#define DEFINE_ZREG(reg) \
{ \
#reg, nullptr, 16, 0, lldb::eEncodingVector, lldb::eFormatVectorOfUInt8, \
SVE_REG_KIND(reg), nullptr, nullptr, nullptr, \
}
This format lets us handle any amount of elements in the vector. So if you increase the vector length, no problem.
qemu on the other hand uses <vector> and <union> (see https://sourceware.org/gdb/current/onlinedocs/gdb.html/Target-Description-Format.html):
<vector id="svevqu" type="uint128" count="16"/>
<...>
</union><union id="svev">
<field name="q" type="svevnq"/>
<field name="d" type="svevnd"/>
<field name="s" type="svevns"/>
<field name="h" type="svevnh"/>
<field name="b" type="svevnb"/>
</union>
<reg name="z0" bitsize="2048" regnum="34" type="svev"/>
lldb doesn't recognise the type svev and so defaults to unsigned int. That goes through
which only supports up to 128 bit numbers. So you can read the Z registers if the vector length is less than 128 bits (vg = 2) but as soon as it goes beyond that, lldb rejects the data.
The example I was given used streaming mode and set qemu's SVE/SME default vector lengths like:
-cpu max,sve-default-vector-length=16,sme-default-vector-length=64
But you can also reproduce by writing vg from within lldb register write vg 4.
We could add some arbitrary sized integer support (Scalar already stores the value using APSInt and APFloat). This would be the quick fix.
Long term we should support <vector> and <union> as they do have some advantages. <union> causes the debugger to display the vector in multiple ways, which can be useful for SVE where you don't know what type is in the register at a given point.
This was reported to me by someone trying to debug SVE and SME code that switched streaming modes, using qemu-user. When in streaming mode they could not read the Z registers but they could in non-streaming mode. Qemu was returning valid data each time but lldb refused to display it in streaming mode.
The cause is a difference in how lldb-server and qemu describe the type of these registers. lldb-server describes them as:
And this gets converted to
eEncodingVector. We can see that lldb-server sets that in the source:This format lets us handle any amount of elements in the vector. So if you increase the vector length, no problem.
qemu on the other hand uses
<vector>and<union>(see https://sourceware.org/gdb/current/onlinedocs/gdb.html/Target-Description-Format.html):lldb doesn't recognise the type
svevand so defaults to unsigned int. That goes throughllvm-project/lldb/source/Utility/RegisterValue.cpp
Line 189 in e05c1b4
The example I was given used streaming mode and set qemu's SVE/SME default vector lengths like:
But you can also reproduce by writing vg from within lldb
register write vg 4.We could add some arbitrary sized integer support (
Scalaralready stores the value usingAPSIntandAPFloat). This would be the quick fix.Long term we should support
<vector>and<union>as they do have some advantages.<union>causes the debugger to display the vector in multiple ways, which can be useful for SVE where you don't know what type is in the register at a given point.