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.

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: https://godbolt.org/z/nG89EPboM

On Fri, Jul 26, 2024 at 10:20 PM Alexandre Oliva via Dwarf-discuss <
dwarf-discuss@lists.dwarfstd.org> wrote:

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

Reply via email to