Re: [Dwarf-Discuss] EXTERNAL: Corner-cases with bitfields

2022-05-06 Thread Todd Allen via Dwarf-Discuss
> 
> Dear all,
> 
> During our work on debugging support of compute workloads on AMDGPU[1],
> we (at AMD) have been seeing two cases regarding description of
> bitfields in DWARF for which we do not find definitive answers in the
> DWARF documentation.  For those cases, when experiencing with usual CPU
> targets we observe different behaviors on different toolchains.  As a
> consequence, we would like to discuss those points here to gather
> feedbacks.  If deemed necessary, we will submit a formal clarification
> issue to the dwarf committee.
> 
> Both of the cases we present below impact how arguments are passed
> during function calls in the ABI for at least our target (AMDGPU).
> However, the debug information available to the debugger does not give
> enough information to decide how to handle the type and the spec does
> not really say what debug information should be generated to properly
> describe those cases.  Also note that in both case, the DWARF
> information we have is sufficient to describe the memory layout of the
> types.
> 
> 1 - Bitfield member with a size matching its underlying type:
> 
> The first point we would like to discuss is the one of  bitfield members
> whose sizes match their underlying type.  Let's consider the following
> example:
> 
>  struct Foo
>  {
>char a :???8;
>char b : 8;
>  };
> 
> If we compile such example with GCC it will add the `DW_AT_bit_size` and
> `DW_AT_bit_offset` attributes to the `a` and `b` DIEs.
> 
> Clang on the other hand will not produce those attributes.
> 
> On the debugger side, GDB currently considers a struct member as being
> packed (i.e. part of a bitfield) if it has the `DW_AT_bit_size`
> attribute present and is non-0.  Therefore, GDB will "understand"
> what GCC produces, but not what Clang produces.
> 
> What Clang does seems to be a reasonable thing to do if one is only
> interested in the memory layout of the type.  This however is not
> sufficient in our case to decide how to handle such type when
> placing/inspecting arguments in registers in the context of function
> calls. In our ABI, bitfield members are passed packed together, while
> two chars in a struct would be placed in separate registers.
> 
> To clarify this situation, it would be helpful that a producer always
> includes the DW_AT_bit_size attribute for bit field, which the standard
> does not suggest nor require.
> 

It sounds like your ABI is basing its decision on a boolean: is the field a bit
field or not.  And you're trying to deduce this from DW_AT_bit_offset.  Perhaps
a better solution would be to make this explicit in the DWARF, some new
DW_AT_bitfield flag.  There's very little that the DWARF standard can do to
mandate such an attribute.  (Permissive standard yadda yadda.)  But if it's
necessary for debuggers to work correctly in a given ABI, compilers should be
well-motivated to produce it when generating code for that ABI.

> 2 - Unnamed zero sized bitfield
> 
> Another case we met is related to unnamed fields with a size of 0 bits.
> Such field is defined in the c++ standard as (in 9.6 Bit-Fields):
> 
>  > As a special case, an unnamed bit-field with a width of zero
>  > specifies alignment of the next bit-field at an allocation unit
>  > boundary
> 
> If we now consider an extended version of our previous example:
> 
>  struct Foo
>  {
>char a : 8;
>char : 0;
>char b :???8,
>  };
> 
> Neither GCC nor Clang give any information about the unnamed bitfield.
> As for the previous case, the presence of such field impacts how
> arguments are passed during function calls on our target, leaving the
> debugger unable to properly decide how to handle such cases.
> 
> As for the previous case, both compilers can properly describe Foo's
> memory layout using DW_AT_bit_offset.
> 
> It seems that such 0-sized field also has impact on ABI on other targets
> such as armv7hl and aarch64 as discussed in [2].  Should the DWARF
> specification give some guidance on how to handle such situation?
> 
> All thoughts on those cases are welcome.
> 

I'm agreeing with Michael that describing the unnamed bitfield seems dubious.
If it does impact the ABI, I'm wondering if that impact is indirect: that is,
the presence of this 0-width bit field changes an attribute of the next field,
and that attribute is responsible for difference in the behavior.  If so, is
there any way other than a 0-width bit field to cause the same behavior?  This
might be another case where describing the attribute that's directly responsible
might be better.

-- 
Todd Allen
Concurrent Real-Time
___
Dwarf-Discuss mailing list
Dwarf-Discuss@lists.dwarfstd.org
http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org


Re: [Dwarf-Discuss] Corner-cases with bitfields

2022-05-06 Thread Michael Eager via Dwarf-Discuss

On 5/6/22 10:11, Lancelot SIX via Dwarf-Discuss wrote:

Dear all,

During our work on debugging support of compute workloads on AMDGPU[1],
we (at AMD) have been seeing two cases regarding description of
bitfields in DWARF for which we do not find definitive answers in the
DWARF documentation.  For those cases, when experiencing with usual CPU
targets we observe different behaviors on different toolchains.  As a
consequence, we would like to discuss those points here to gather
feedbacks.  If deemed necessary, we will submit a formal clarification
issue to the dwarf committee.

Both of the cases we present below impact how arguments are passed
during function calls in the ABI for at least our target (AMDGPU).
However, the debug information available to the debugger does not give
enough information to decide how to handle the type and the spec does
not really say what debug information should be generated to properly
describe those cases.  Also note that in both case, the DWARF
information we have is sufficient to describe the memory layout of the
types.

1 - Bitfield member with a size matching its underlying type:

The first point we would like to discuss is the one of  bitfield members
whose sizes match their underlying type.  Let's consider the following
example:

  struct Foo
  {
char a : 8;
char b : 8;
  };

If we compile such example with GCC it will add the `DW_AT_bit_size` and
`DW_AT_bit_offset` attributes to the `a` and `b` DIEs.

Clang on the other hand will not produce those attributes.


Since the specified bit size and the underlying type size are the same,
it would appear to me that specifying DW_AT_bit_size is redundant.

DW_AT_bit_offset was defined in DWARF Version 3 and 4, but has been
deprecated in DWARF Version 5.  See Section 5.7.6,
DW_AT_data_member_location and DW_AT_data_bit_offset.


On the debugger side, GDB currently considers a struct member as being
packed (i.e. part of a bitfield) if it has the `DW_AT_bit_size`
attribute present and is non-0.  Therefore, GDB will "understand"
what GCC produces, but not what Clang produces.


What is the difference in the layout for
  struct { char a; char b; } X;
and
  struct { char a:8; char b:8; } Y;

I would have to review the ISO C standard in detail, but I believe that
these are equivalent declarations.  In both structs, a is at byte offset
0 and b is at offset 1.

What is the difference in the DWARF description?


What Clang does seems to be a reasonable thing to do if one is only
interested in the memory layout of the type.  This however is not
sufficient in our case to decide how to handle such type when
placing/inspecting arguments in registers in the context of function
calls. In our ABI, bitfield members are passed packed together, while
two chars in a struct would be placed in separate registers.


It's not my position to critique an ABI, but this seems to require
additional packing and unpacking of char data.  Why not pack all struct
data into a minimum number of registers?  Or place all containing
entities in separate registers?


To clarify this situation, it would be helpful that a producer always
includes the DW_AT_bit_size attribute for bit field, which the standard
does not suggest nor require.


DWARF is a permissive standard, which means that at times there may be
different ways of describing the same source code.  DWARF is unlikely to
require that one description is prescribed and the other proscribed.



2 - Unnamed zero sized bitfield

Another case we met is related to unnamed fields with a size of 0 bits.
Such field is defined in the c++ standard as (in 9.6 Bit-Fields):

  > As a special case, an unnamed bit-field with a width of zero
  > specifies alignment of the next bit-field at an allocation unit
  > boundary

If we now consider an extended version of our previous example:

  struct Foo
  {
char a : 8;
char : 0;
char b : 8,
  };

Neither GCC nor Clang give any information about the unnamed bitfield.
As for the previous case, the presence of such field impacts how
arguments are passed during function calls on our target, leaving the
debugger unable to properly decide how to handle such cases.


The unnamed field is not accessible by any user code and, as the ISO C
standard describes, is only to insure that the following declarations
are aligned on a specific boundary which is associated with the type.

Other than forcing the alignment of following declarations, the :0
declaration has no other effect.


As for the previous case, both compilers can properly describe Foo's
memory layout using DW_AT_bit_offset.


Not that I agree with this contention, but DW_AT_bit_offset has been
deprecated.


It seems that such 0-sized field also has impact on ABI on other targets
such as armv7hl and aarch64 as discussed in [2].  Should the DWARF
specification give some guidance on how to handle such situation?


As mentioned in [2], in the x86-64 ABI "zero width bitfield

[Dwarf-Discuss] Corner-cases with bitfields

2022-05-06 Thread Lancelot SIX via Dwarf-Discuss
Dear all,

During our work on debugging support of compute workloads on AMDGPU[1],
we (at AMD) have been seeing two cases regarding description of
bitfields in DWARF for which we do not find definitive answers in the
DWARF documentation.  For those cases, when experiencing with usual CPU
targets we observe different behaviors on different toolchains.  As a
consequence, we would like to discuss those points here to gather
feedbacks.  If deemed necessary, we will submit a formal clarification
issue to the dwarf committee.

Both of the cases we present below impact how arguments are passed
during function calls in the ABI for at least our target (AMDGPU).
However, the debug information available to the debugger does not give
enough information to decide how to handle the type and the spec does
not really say what debug information should be generated to properly
describe those cases.  Also note that in both case, the DWARF
information we have is sufficient to describe the memory layout of the
types.

1 - Bitfield member with a size matching its underlying type:

The first point we would like to discuss is the one of  bitfield members
whose sizes match their underlying type.  Let's consider the following
example:

 struct Foo
 {
   char a : 8;
   char b : 8;
 };

If we compile such example with GCC it will add the `DW_AT_bit_size` and
`DW_AT_bit_offset` attributes to the `a` and `b` DIEs.

Clang on the other hand will not produce those attributes.

On the debugger side, GDB currently considers a struct member as being
packed (i.e. part of a bitfield) if it has the `DW_AT_bit_size`
attribute present and is non-0.  Therefore, GDB will "understand"
what GCC produces, but not what Clang produces.

What Clang does seems to be a reasonable thing to do if one is only
interested in the memory layout of the type.  This however is not
sufficient in our case to decide how to handle such type when
placing/inspecting arguments in registers in the context of function
calls. In our ABI, bitfield members are passed packed together, while
two chars in a struct would be placed in separate registers.

To clarify this situation, it would be helpful that a producer always
includes the DW_AT_bit_size attribute for bit field, which the standard
does not suggest nor require.

2 - Unnamed zero sized bitfield

Another case we met is related to unnamed fields with a size of 0 bits.
Such field is defined in the c++ standard as (in 9.6 Bit-Fields):

 > As a special case, an unnamed bit-field with a width of zero
 > specifies alignment of the next bit-field at an allocation unit
 > boundary

If we now consider an extended version of our previous example:

 struct Foo
 {
   char a : 8;
   char : 0;
   char b : 8,
 };

Neither GCC nor Clang give any information about the unnamed bitfield.
As for the previous case, the presence of such field impacts how
arguments are passed during function calls on our target, leaving the
debugger unable to properly decide how to handle such cases.

As for the previous case, both compilers can properly describe Foo's
memory layout using DW_AT_bit_offset.

It seems that such 0-sized field also has impact on ABI on other targets
such as armv7hl and aarch64 as discussed in [2].  Should the DWARF
specification give some guidance on how to handle such situation?

All thoughts on those cases are welcome.

Best,
Lancelot SIX.

[1] https://llvm.org/docs/AMDGPUUsage.html
[2] https://www.mail-archive.com/gcc@gcc.gnu.org/msg97797.html

___
Dwarf-Discuss mailing list
Dwarf-Discuss@lists.dwarfstd.org
http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org


Re: [Dwarf-Discuss] How to generate DWARF info for a template alias to a raw pointer

2022-05-06 Thread Robinson, Paul via Dwarf-Discuss
> Could someone help to point out what kind of DWARF info should
> be generated for below c++ source? Thanks
> 
> ```
> template
> using ptr = T*;
> 
> ptr  abc;
> ```
> 
> We declare a template alias here, so we may generate
> `DW_TAG_template_type_parameter` like:
> 
> ```
> 0x0057:   DW_TAG_base_type
>     DW_AT_name  ("int")
>     DW_AT_byte_size  (0x04)
>     DW_AT_encoding   (DW_ATE_signed)
> 
> 0x005e:   DW_TAG_pointer_type
>     DW_AT_type    (0x0057 "int")
> 
> 0x0064:   DW_TAG_template_alias
>     DW_AT_name  ("ptr")
>     DW_AT_type    (0x005e "int *")
> 
> 0x0076: DW_TAG_template_type_parameter
>   DW_AT_name   ("T")
>   DW_AT_type  (0x0057 "int")
> 
> 0x007e:   DW_TAG_variable
>     DW_AT_name  ("abc")
>     DW_AT_type    (0x0064 "ptr")
> ```

This all looks okay to me, with DW_TAG_template_type_parameter
being a child of DW_TAG_template_alias.  There's an alias
named `ptr`, its formal parameter is `T`, its actual parameter
is `int`, and so the alias is a typedef of `int *`.

> ` DW_TAG_template_type_parameter ` should be for a notation to
> create a template base on another template, but as you can see
> the referred type 0x005e is not a template. What kind of
> DWARF info should we generate here? We should use 
> ` DW_TAG_typedef` instead of ` DW_TAG_template_type_parameter`
> for this special case?

DW_TAG_template_type_parameter is correctly describing the
parameter to the template.

There's no need for a DW_TAG_typedef, because DW_TAG_template_alias
is implicitly a typedef.

--paulr

___
Dwarf-Discuss mailing list
Dwarf-Discuss@lists.dwarfstd.org
http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org


[Dwarf-Discuss] How to generate DWARF info for a template alias to a raw pointer

2022-05-06 Thread Zheng CZ Chen via Dwarf-Discuss

Hi all,

Could someone help to point out what kind of DWARF info should be generated for 
below c++ source? Thanks

```
template
using ptr = T*;

ptr  abc;
```

We declare a template alias here, so we may generate  
`DW_TAG_template_type_parameter` like:

```
0x0057:   DW_TAG_base_type
DW_AT_name  ("int")
DW_AT_byte_size  (0x04)
DW_AT_encoding   (DW_ATE_signed)

0x005e:   DW_TAG_pointer_type
DW_AT_type(0x0057 "int")

0x0064:   DW_TAG_template_alias
DW_AT_name  ("ptr")
DW_AT_type(0x005e "int *")

0x0076: DW_TAG_template_type_parameter
  DW_AT_name   ("T")
  DW_AT_type  (0x0057 "int")

0x007e:   DW_TAG_variable
DW_AT_name  ("abc")
DW_AT_type(0x0064 "ptr")
```

` DW_TAG_template_type_parameter ` should be for a notation to create a 
template base on another template, but as you can see the referred type 
0x005e is not a template. What kind of DWARF info should we generate here? 
We should use ` DW_TAG_typedef` instead of ` DW_TAG_template_type_parameter` 
for this special case?

--
Thanks.

BRS//
Chen Zheng
IBM PowerPC Compiler Backend Developer

___
Dwarf-Discuss mailing list
Dwarf-Discuss@lists.dwarfstd.org
http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org