<div dir="ltr"><div>It seems to me that the problem here is not so much in the DWARF standard, as in the DWARF that is produced.</div><div><br></div><div>The DWARF representation generally serves to capture all the semantic information needed to properly represent</div><div>the source program. In the example discussed here it appears that GCC does that (by including the bit field information) and</div><div>CLANG does not (by erroneously omitting the bit field information).</div><div><br></div><div>It is probably the case that in most languages char a; and char a:8; are semantically equivalent IN ALL RESPECTS. <br></div><div>For such languages,the producer/compiler is probably justified (or at least can be forgiven) for omitting the bit field information <br></div><div>for char a:8. But evidently for 
"AMDGP-Lang" the two are not the same--while the storage layout may be the same, other</div><div>subtle but critical aspects of the language and its ABI are quite different in the two cases.</div><div><br></div><div>One might have a philosophical debate about whether this difference is appropriate or not. But as Lancelot says, the ABI is <br></div><div>what it is and any change is unlikely nearterm so such a debate is moot. The only issue is whether DWARF is able to</div><div>convey the needed information. I think DWARF is able, if only the producer/compiler would do it properly.</div><div><br></div><div>So my suggestion is to file a bug report with CLANG, requesting they correct their DWARF output to reflect all details needed</div><div>by your language.</div><div><br></div><div>Ron Brender<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, May 9, 2022 at 7:13 AM Lancelot SIX via Dwarf-Discuss <<a href="mailto:dwarf-discuss@lists.dwarfstd.org">dwarf-discuss@lists.dwarfstd.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi,<br>
<br>
Thanks for the feedback.<br>
<br>
> <br>
> It sounds like your ABI is basing its decision on a boolean: is the field a bit<br>
> field or not.  And you're trying to deduce this from DW_AT_bit_offset.  Perhaps<br>
> a better solution would be to make this explicit in the DWARF, some new<br>
> DW_AT_bitfield flag.  There's very little that the DWARF standard can do to<br>
> mandate such an attribute.  (Permissive standard yadda yadda.)  But if it's<br>
> necessary for debuggers to work correctly in a given ABI, compilers should be<br>
> well-motivated to produce it when generating code for that ABI.<br>
> <br>
> [...]<br>
> <br>
> I'm agreeing with Michael that describing the unnamed bitfield seems dubious.<br>
> If it does impact the ABI, I'm wondering if that impact is indirect: that is,<br>
> the presence of this 0-width bit field changes an attribute of the next field,<br>
> and that attribute is responsible for difference in the behavior.  If so, is<br>
> there any way other than a 0-width bit field to cause the same behavior?  This<br>
> might be another case where describing the attribute that's directly responsible<br>
> might be better.<br>
> <br>
> -- <br>
> Todd Allen<br>
> Concurrent Real-Time<br>
<br>
Indeed, two flags can conceptually provide sufficient information to the<br>
debugger.  I am not aware of a situation not involving the 0-wide<br>
unnamed bitfield which can trigger the same behavior.  The unnamed<br>
field is not really important in itself, only the effect it has on the<br>
following field is.<br>
<br>
To help the discussion, let me use a concrete example and how it is<br>
handled in our ABI as it is today.  Lets suppose you have a struct like:<br>
<br>
  struct Foo {<br>
      int fill[4];<br>
      char c1;<br>
      char c2 : 8;<br>
      char c3 : 8;<br>
      char : 0;<br>
      char c4 : 8;<br>
      char c5 : 8;<br>
  };<br>
<br>
If we have a function returning a value of such type by value, the<br>
return value would be passed in registers back to the caller (the<br>
situation would be similar when calling a function with a Foo<br>
parameter).  In our architecture, the registers used are 32 bit wide*<br>
and called Vx, x being the register number (*this is a simplified<br>
model sufficient for the current discussion).<br>
<br>
In this example, the `fill` member is not really important.  It is only<br>
there because a value under 64 bits  would otherwise be returned packed.<br>
<br>
So suppose that we stop a program just after returning from a function<br>
returning such value.  This is what a debugger such as GDB would do when<br>
using the `finish` command.  To figure out the value returned by the<br>
function, the debugger needs to inspect the debuggee's registers based<br>
on the function's return type.<br>
<br>
In this situation, the ABI conceptually decomposes the struct into its<br>
member and places each member in a register.  Bitfield members are<br>
considered as packed into one member.  The result is:<br>
<br>
+-------------------+-------------------+-------------------+-------------------+<br>
| V0                | V1                | V2                | V3                |<br>
|      fill[0]      |      fill[1]      |      fill[2]      |      fill[3]      |<br>
+-------------------+-------------------+-------------------+-------------------+<br>
+-------------------+-------------------+-------------------+<br>
| V4                | V5                | V6                |<br>
| xxxxxxxxxxxx | c1 | xxxxxxx | c3 | c2 | xxxxxxx | c5 | c4 |<br>
+-------------------+-------------------+-------------------+<br>
<br>
If we do not specify the `: 8`s, then each char is allocated its own<br>
register (so c1 in V4, c2 in V5, and so on until c5 in V8).<br>
<br>
If we remove the unnamed 0-sized field, then c2, c3, c4, c5 are all<br>
packed into V5.<br>
<br>
My main problem today is that the debugger needs to figure out how such<br>
type is passed as an argument or returned from a function, while basing<br>
its decision solely on the description of the Foo type in the debugging<br>
information.<br>
<br>
Unfortunately, as far I know, the debugging information does not allow<br>
me to differentiate the Foo type as written above to a type without the<br>
`: 8` or without the unnamed field.  As a consequence, the debugger will<br>
in some situations make wrong decisions.  Also note that such difference<br>
would not change how a value of type Foo is laid out in memory, only the<br>
decomposition into registers for function call purposes is impacted.<br>
<br>
I do not claim the ABI is flawless, good or bad in any way.  It is the<br>
way it is and for the time being it is going to remain stable.<br>
Nevertheless, if we want to provide good debugging experience for our<br>
target (which we do), we need to address those cases in a way or<br>
another (two flags are good candidates).<br>
<br>
I hope this example helps to illustrate the limitations we are<br>
currently facing.<br>
<br>
Best,<br>
Lancelot.<br>
_______________________________________________<br>
Dwarf-Discuss mailing list<br>
<a href="mailto:Dwarf-Discuss@lists.dwarfstd.org" target="_blank">Dwarf-Discuss@lists.dwarfstd.org</a><br>
<a href="http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org" rel="noreferrer" target="_blank">http://lists.dwarfstd.org/listinfo.cgi/dwarf-discuss-dwarfstd.org</a><br>
</blockquote></div>