<div dir="ltr">If I'm following correctly, Alexandre - you're suggesting a situation where an instance of a type, when it appears within a packed struct, may become smaller than it would otherwise be? (usually in C that's not the case - packing only changes the alignment of instances of the type - which may change the size of the containing object, but not the size of the underlying member that was packed.<br><br>If you have a language where "packing" a member might cause it to become smaller, not just cause the leading/trailing padding to be omitted - perhaps that'd be better modelled, not with a new/distinct type, but with the same mechanism as is used for bitfields in C? ie: using bit_size and data_bit_offset? as in: <a href="https://godbolt.org/z/nG89EPboM">https://godbolt.org/z/nG89EPboM</a></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Jul 26, 2024 at 10:20 PM Alexandre Oliva 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">On Jun 15, 2024, Ron Brender <<a href="mailto:ron.brender@gmail.com" target="_blank">ron.brender@gmail.com</a>> wrote:<br>
<br>
>> Because of the different sizes, this requires two distinct types to be<br>
>> defined in debug info.<br>
<br>
> There is no basis for this claim AFAIK.<br>
<br>
DW_TAG_subrange_type may have a DW_AT_(byte|bit)_size attribute "if the<br>
amount of storage allocated to hold each element of an object of the<br>
given subrange type is different from the amount of storage that is<br>
normally allocated to hold an individual object of the indicated element<br>
type."  As long as the packed field's size is different from the<br>
unpacked subrange type, each would require a different size attribute.<br>
<br>
Defining a single subrange with a single size would make the size wrong<br>
for at least one of the following scenarios:<br>
<br>
- larger unpacked size for packed field: consumers would regard extra<br>
  bits as part of the field<br>
<br>
- smaller packed size for unpacked field: consumers would miss a<br>
  significant part of the field, depending on endianness<br>
<br>
It seems to follow that we need two distinct types, one with the correct<br>
size for unpacked fields, another with the correct size for packed<br>
fields, unless we set a size in the type that is not correct for all<br>
entities, and override the sizes in objects and fields for which the<br>
type size doesn't apply.<br>
<br>
<br>
>> Despite sharing the same bounds, however, it seems that the bounds have<br>
>> to be explicitly mentioned in both types.<br>
<br>
> Equally unfounded. The type char in C has a range of -128..127 even if<br>
> no bounds are explicitly given.<br>
<br>
That counter-example is not relevant, char is not a subrange type.<br>
<br>
I'm talking specifically about subrange types, for which there's a rule<br>
for DW_AT_lower_bound when it's not explicitly specified.<br>
<br>
According to the rules set forth in DWARF5, a DW_TAG_subrange_type that<br>
uses e.g. C's signed char as its base type but that doesn't specify<br>
DW_AT_lower_bound would have the lower bound implicitly set to 0<br>
(assuming the language of the translation unit is set to C).<br>
<br>
Even if that subrange type had its DW_AT_lower_bound explicitly set to<br>
e.g. -100, another subrange that names it as the base type wouldn't<br>
inherit its lower bound, it would get the language's default lower<br>
bound, namely 0, AFAICT even if that is not in range for the base type<br>
(say, because it has an upper bound of -10).<br>
<br>
This seems suboptimal.<br>
<br>
<br>
Your full response below, for context, since it's been so long since the<br>
initial interaction:<br>
<br>
>> Consider a type that is a subrange of an integral base type, with an<br>
>> explicitly specified bit size smaller than the bit width of a storage<br>
>> unit.<br>
>> <br>
>> When used for a standalone variable, its byte size is the same as that<br>
>> of the base type, i.e., the type is padded to a whole unit.<br>
<br>
> The variable's size has to be at least that of the base type. But it could<br>
> be<br>
> larger. Especially likely if it is in a register. Actually it could be<br>
> smaller if the<br>
> compiler can prove the possible range of actual values is smaller than<br>
> allowed by the base type.<br>
<br>
>> However, when used for a packed record type, however, it takes on the<br>
>> requested bit size, without any padding whatsoever.<br>
<br>
> That is the purpose and meaning of packed, yes.<br>
<br>
>> Because of the different sizes, this requires two distinct types to be<br>
>> defined in debug info.<br>
<br>
> There is no basis for this claim AFAIK.<br>
<br>
>> Despite sharing the same bounds, however, it seems that the bounds have<br>
>> to be explicitly mentioned in both types.<br>
<br>
> Equally unfounded. The type char in C has a range of -128..127 even if<br>
> no bounds are explicitly given.<br>
<br>
>> That's because, AFAICT, when DW_AT_lower_bound is omitted in a<br>
>> DW_TAG_subrange_type, it is implied as either 0 or 1, depending on the<br>
>> source language, while DW_AT_upper bound is unknown.<br>
<br>
> Yes.<br>
<br>
>> There doesn't seem to be any provision for the bounds to be inherited<br>
>> from the base type.<br>
<br>
> The bounds of the subrange type do have to be within the bounds<br>
> of the basis type  (even if unknown).<br>
<br>
>> So now we have to resort to something like:<br>
<br>
>> (x) DW_TAG_base_type<br>
>> DW_AT_byte_size 1<br>
>> [...]<br>
>> (y) DW_TAG_subrange_type<br>
>> DW_AT_name ...<br>
>> DW_AT_type x<br>
>> DW_AT_lower_bound L<br>
>> DW_AT_upper_bound U<br>
>> [...]<br>
>> (z) DW_TAG_subrange_type<br>
>> DW_AT_type x (could it be y?)<br>
>> DW_AT_bit_size N<br>
>> DW_AT_lower_bound L<br>
>> DW_AT_lower_bound U<br>
<br>
> Not so as stated above.<br>
<br>
>> but if we had the possibility of inheriting bounds from the base type,<br>
>> it could be:<br>
<br>
>> (x) DW_TAG_base_type<br>
>> DW_AT_byte_size 1<br>
>> [...]<br>
>> (y) DW_TAG_subrange_type<br>
>> DW_AT_name ...<br>
>> DW_AT_type x<br>
>> DW_AT_lower_bound L<br>
>> DW_AT_upper_bound U<br>
>> [...]<br>
>> (z) DW_TAG_subrange_type<br>
>> DW_AT_type y<br>
>> DW_AT_bit_size N<br>
>> [bounds are inherited from y]<br>
<br>
> Subrange y seems unnecessary which will result in the range -4..3. If you<br>
> want some other range then you can add DW_AT_lower_bound/upper bound (that<br>
> specifies a range with at most 2**N possible values).<br>
<br>
>> I realize that this could bring complications in case the inheritance is<br>
>> not immediate.  Say, the base type could be a DW_TAG_const_type variant<br>
>> of a subrange type.  So, if we were to allow this sort of inheritance of<br>
>> bounds, it should probably also cover multiple levels.<br>
<br>
<br>
>> A simpler alternative could be to have another tag, say<br>
>> DW_TAG_[un]padded_type, for a different-sized variant of a type.  As<br>
>> usual for such tags, other properties would be inherited, including the<br>
>> bounds.<br>
<br>
> Because two base types are not needed in the first place, no additional tag<br>
> is needed.<br>
<br>
> On Fri, Jun 14, 2024 at 3:00 AM Alexandre Oliva via Dwarf-discuss <<br>
> <a href="mailto:dwarf-discuss@lists.dwarfstd.org" target="_blank">dwarf-discuss@lists.dwarfstd.org</a>> wrote:<br>
<br>
>> <br>
>> Consider a type that is a subrange of an integral base type, with an<br>
>> explicitly specified bit size smaller than the bit width of a storage<br>
>> unit.<br>
>> <br>
>> When used for a standalone variable, its byte size is the same as that<br>
>> of the base type, i.e., the type is padded to a whole unit.<br>
>> <br>
>> However, when used for a packed record type, however, it takes on the<br>
>> requested bit size, without any padding whatsoever.<br>
>> <br>
>> Because of the different sizes, this requires two distinct types to be<br>
>> defined in debug info.<br>
>> <br>
>> Despite sharing the same bounds, however, it seems that the bounds have<br>
>> to be explicitly mentioned in both types.<br>
>> <br>
>> That's because, AFAICT, when DW_AT_lower_bound is omitted in a<br>
>> DW_TAG_subrange_type, it is implied as either 0 or 1, depending on the<br>
>> source language, while DW_AT_upper bound is unknown.<br>
>> <br>
>> There doesn't seem to be any provision for the bounds to be inherited<br>
>> from the base type.<br>
>> <br>
>> So now we have to resort to something like:<br>
>> <br>
>> (x) DW_TAG_base_type<br>
>> DW_AT_byte_size 1<br>
>> [...]<br>
>> (y) DW_TAG_subrange_type<br>
>> DW_AT_name ...<br>
>> DW_AT_type x<br>
>> DW_AT_lower_bound L<br>
>> DW_AT_upper_bound U<br>
>> [...]<br>
>> (z) DW_TAG_subrange_type<br>
>> DW_AT_type x (could it be y?)<br>
>> DW_AT_bit_size N<br>
>> DW_AT_lower_bound L<br>
>> DW_AT_lower_bound U<br>
>> <br>
>> but if we had the possibility of inheriting bounds from the base type,<br>
>> it could be:<br>
>> <br>
>> (x) DW_TAG_base_type<br>
>> DW_AT_byte_size 1<br>
>> [...]<br>
>> (y) DW_TAG_subrange_type<br>
>> DW_AT_name ...<br>
>> DW_AT_type x<br>
>> DW_AT_lower_bound L<br>
>> DW_AT_upper_bound U<br>
>> [...]<br>
>> (z) DW_TAG_subrange_type<br>
>> DW_AT_type y<br>
>> DW_AT_bit_size N<br>
>> [bounds are inherited from y]<br>
>> <br>
>> I realize that this could bring complications in case the inheritance is<br>
>> not immediate.  Say, the base type could be a DW_TAG_const_type variant<br>
>> of a subrange type.  So, if we were to allow this sort of inheritance of<br>
>> bounds, it should probably also cover multiple levels.<br>
>> <br>
>> <br>
>> A simpler alternative could be to have another tag, say<br>
>> DW_TAG_[un]padded_type, for a different-sized variant of a type.  As<br>
>> usual for such tags, other properties would be inherited, including the<br>
>> bounds.<br>
>> <br>
>> This feels like a waste of a tag, though; DW_TAG_subrange_type seems<br>
>> like it could be enough.<br>
<br>
-- <br>
Alexandre Oliva, happy hacker                    <a href="https://FSFLA.org/blogs/lxo/" rel="noreferrer" target="_blank">https://FSFLA.org/blogs/lxo/</a><br>
   Free Software Activist                           GNU Toolchain Engineer<br>
Disinformation flourishes because many people care deeply about injustice but<br>
very few check the facts.  Think Assange & Stallman.  The empires strike back<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="https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss" rel="noreferrer" target="_blank">https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss</a><br>
</blockquote></div>