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