@@ -1013,7 +1013,6 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
10131013 // Add name if not anonymous or intermediate type.
10141014 StringRef Name = CTy->getName ();
10151015
1016- uint64_t Size = CTy->getSizeInBits () >> 3 ;
10171016 uint16_t Tag = Buffer.getTag ();
10181017
10191018 switch (Tag) {
@@ -1176,15 +1175,28 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
11761175 if (Tag == dwarf::DW_TAG_enumeration_type ||
11771176 Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type ||
11781177 Tag == dwarf::DW_TAG_union_type) {
1179- // Add size if non-zero (derived types might be zero-sized.)
1180- // Ignore the size if it's a non-enum forward decl.
1181- // TODO: Do we care about size for enum forward declarations?
1182- if (Size &&
1183- (!CTy->isForwardDecl () || Tag == dwarf::DW_TAG_enumeration_type))
1184- addUInt (Buffer, dwarf::DW_AT_byte_size, std::nullopt , Size);
1185- else if (!CTy->isForwardDecl ())
1186- // Add zero size if it is not a forward declaration.
1187- addUInt (Buffer, dwarf::DW_AT_byte_size, std::nullopt , 0 );
1178+ if (auto *Var = dyn_cast_or_null<DIVariable>(CTy->getRawSizeInBits ())) {
1179+ if (auto *VarDIE = getDIE (Var))
1180+ addDIEEntry (Buffer, dwarf::DW_AT_bit_size, *VarDIE);
1181+ } else if (auto *Exp =
1182+ dyn_cast_or_null<DIExpression>(CTy->getRawSizeInBits ())) {
1183+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
1184+ DIEDwarfExpression DwarfExpr (*Asm, getCU (), *Loc);
1185+ DwarfExpr.setMemoryLocationKind ();
1186+ DwarfExpr.addExpression (Exp);
1187+ addBlock (Buffer, dwarf::DW_AT_bit_size, DwarfExpr.finalize ());
1188+ } else {
1189+ uint64_t Size = CTy->getSizeInBits () >> 3 ;
1190+ // Add size if non-zero (derived types might be zero-sized.)
1191+ // Ignore the size if it's a non-enum forward decl.
1192+ // TODO: Do we care about size for enum forward declarations?
1193+ if (Size &&
1194+ (!CTy->isForwardDecl () || Tag == dwarf::DW_TAG_enumeration_type))
1195+ addUInt (Buffer, dwarf::DW_AT_byte_size, std::nullopt , Size);
1196+ else if (!CTy->isForwardDecl ())
1197+ // Add zero size if it is not a forward declaration.
1198+ addUInt (Buffer, dwarf::DW_AT_byte_size, std::nullopt , 0 );
1199+ }
11881200
11891201 // If we're a forward decl, say so.
11901202 if (CTy->isForwardDecl ())
@@ -1864,74 +1876,117 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
18641876
18651877 addBlock (MemberDie, dwarf::DW_AT_data_member_location, VBaseLocationDie);
18661878 } else {
1867- uint64_t Size = DT->getSizeInBits ();
1868- uint64_t FieldSize = DD->getBaseTypeSize (DT);
1869- uint32_t AlignInBytes = DT->getAlignInBytes ();
1870- uint64_t OffsetInBytes;
1879+ uint64_t Size = 0 ;
1880+ uint64_t FieldSize = 0 ;
18711881
18721882 bool IsBitfield = DT->isBitField ();
1873- if (IsBitfield) {
1874- // Handle bitfield, assume bytes are 8 bits.
1875- if (DD->useDWARF2Bitfields ())
1876- addUInt (MemberDie, dwarf::DW_AT_byte_size, std::nullopt , FieldSize / 8 );
1877- addUInt (MemberDie, dwarf::DW_AT_bit_size, std::nullopt , Size);
1878-
1879- assert (DT->getOffsetInBits () <=
1880- (uint64_t )std::numeric_limits<int64_t >::max ());
1881- int64_t Offset = DT->getOffsetInBits ();
1882- // We can't use DT->getAlignInBits() here: AlignInBits for member type
1883- // is non-zero if and only if alignment was forced (e.g. _Alignas()),
1884- // which can't be done with bitfields. Thus we use FieldSize here.
1885- uint32_t AlignInBits = FieldSize;
1886- uint32_t AlignMask = ~(AlignInBits - 1 );
1887- // The bits from the start of the storage unit to the start of the field.
1888- uint64_t StartBitOffset = Offset - (Offset & AlignMask);
1889- // The byte offset of the field's aligned storage unit inside the struct.
1890- OffsetInBytes = (Offset - StartBitOffset) / 8 ;
1891-
1892- if (DD->useDWARF2Bitfields ()) {
1893- uint64_t HiMark = (Offset + FieldSize) & AlignMask;
1894- uint64_t FieldOffset = (HiMark - FieldSize);
1895- Offset -= FieldOffset;
1896-
1897- // Maybe we need to work from the other end.
1898- if (Asm->getDataLayout ().isLittleEndian ())
1899- Offset = FieldSize - (Offset + Size);
1900-
1901- if (Offset < 0 )
1902- addSInt (MemberDie, dwarf::DW_AT_bit_offset, dwarf::DW_FORM_sdata,
1883+
1884+ // Handle the size.
1885+ if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawSizeInBits ())) {
1886+ if (auto *VarDIE = getDIE (Var))
1887+ addDIEEntry (MemberDie, dwarf::DW_AT_bit_size, *VarDIE);
1888+ } else if (auto *Exp =
1889+ dyn_cast_or_null<DIExpression>(DT->getRawSizeInBits ())) {
1890+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
1891+ DIEDwarfExpression DwarfExpr (*Asm, getCU (), *Loc);
1892+ DwarfExpr.setMemoryLocationKind ();
1893+ DwarfExpr.addExpression (Exp);
1894+ addBlock (MemberDie, dwarf::DW_AT_bit_size, DwarfExpr.finalize ());
1895+ } else {
1896+ Size = DT->getSizeInBits ();
1897+ FieldSize = DD->getBaseTypeSize (DT);
1898+ if (IsBitfield) {
1899+ // Handle bitfield, assume bytes are 8 bits.
1900+ if (DD->useDWARF2Bitfields ())
1901+ addUInt (MemberDie, dwarf::DW_AT_byte_size, std::nullopt ,
1902+ FieldSize / 8 );
1903+ addUInt (MemberDie, dwarf::DW_AT_bit_size, std::nullopt , Size);
1904+ }
1905+ }
1906+
1907+ // Handle the location. DW_AT_data_bit_offset won't allow an
1908+ // expression until DWARF 6, but it can be used as an extension.
1909+ // See https://dwarfstd.org/issues/250501.1.html
1910+ if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawOffsetInBits ())) {
1911+ if (!Asm->TM .Options .DebugStrictDwarf || DD->getDwarfVersion () >= 6 ) {
1912+ if (auto *VarDIE = getDIE (Var))
1913+ addDIEEntry (MemberDie, dwarf::DW_AT_data_bit_offset, *VarDIE);
1914+ }
1915+ } else if (auto *Expr =
1916+ dyn_cast_or_null<DIExpression>(DT->getRawOffsetInBits ())) {
1917+ if (!Asm->TM .Options .DebugStrictDwarf || DD->getDwarfVersion () >= 6 ) {
1918+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
1919+ DIEDwarfExpression DwarfExpr (*Asm, getCU (), *Loc);
1920+ DwarfExpr.setMemoryLocationKind ();
1921+ DwarfExpr.addExpression (Expr);
1922+ addBlock (MemberDie, dwarf::DW_AT_data_bit_offset, DwarfExpr.finalize ());
1923+ }
1924+ } else {
1925+ uint32_t AlignInBytes = DT->getAlignInBytes ();
1926+ uint64_t OffsetInBytes;
1927+
1928+ if (IsBitfield) {
1929+ assert (DT->getOffsetInBits () <=
1930+ (uint64_t )std::numeric_limits<int64_t >::max ());
1931+ int64_t Offset = DT->getOffsetInBits ();
1932+ // We can't use DT->getAlignInBits() here: AlignInBits for member type
1933+ // is non-zero if and only if alignment was forced (e.g. _Alignas()),
1934+ // which can't be done with bitfields. Thus we use FieldSize here.
1935+ uint32_t AlignInBits = FieldSize;
1936+ uint32_t AlignMask = ~(AlignInBits - 1 );
1937+ // The bits from the start of the storage unit to the start of the
1938+ // field.
1939+ uint64_t StartBitOffset = Offset - (Offset & AlignMask);
1940+ // The byte offset of the field's aligned storage unit inside the
1941+ // struct.
1942+ OffsetInBytes = (Offset - StartBitOffset) / 8 ;
1943+
1944+ if (DD->useDWARF2Bitfields ()) {
1945+ uint64_t HiMark = (Offset + FieldSize) & AlignMask;
1946+ uint64_t FieldOffset = (HiMark - FieldSize);
1947+ Offset -= FieldOffset;
1948+
1949+ // Maybe we need to work from the other end.
1950+ if (Asm->getDataLayout ().isLittleEndian ())
1951+ Offset = FieldSize - (Offset + Size);
1952+
1953+ if (Offset < 0 )
1954+ addSInt (MemberDie, dwarf::DW_AT_bit_offset, dwarf::DW_FORM_sdata,
1955+ Offset);
1956+ else
1957+ addUInt (MemberDie, dwarf::DW_AT_bit_offset, std::nullopt ,
1958+ (uint64_t )Offset);
1959+ OffsetInBytes = FieldOffset >> 3 ;
1960+ } else {
1961+ addUInt (MemberDie, dwarf::DW_AT_data_bit_offset, std::nullopt ,
19031962 Offset);
1904- else
1905- addUInt (MemberDie, dwarf::DW_AT_bit_offset, std::nullopt ,
1906- (uint64_t )Offset);
1907- OffsetInBytes = FieldOffset >> 3 ;
1963+ }
19081964 } else {
1909- addUInt (MemberDie, dwarf::DW_AT_data_bit_offset, std::nullopt , Offset);
1965+ // This is not a bitfield.
1966+ OffsetInBytes = DT->getOffsetInBits () / 8 ;
1967+ if (AlignInBytes)
1968+ addUInt (MemberDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
1969+ AlignInBytes);
19101970 }
1911- } else {
1912- // This is not a bitfield.
1913- OffsetInBytes = DT->getOffsetInBits () / 8 ;
1914- if (AlignInBytes)
1915- addUInt (MemberDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
1916- AlignInBytes);
1917- }
19181971
1919- if (DD->getDwarfVersion () <= 2 ) {
1920- DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc;
1921- addUInt (*MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
1922- addUInt (*MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
1923- addBlock (MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
1924- } else if (!IsBitfield || DD->useDWARF2Bitfields ()) {
1925- // In DWARF v3, DW_FORM_data4/8 in DW_AT_data_member_location are
1926- // interpreted as location-list pointers. Interpreting constants as
1927- // pointers is not expected, so we use DW_FORM_udata to encode the
1928- // constants here.
1929- if (DD->getDwarfVersion () == 3 )
1930- addUInt (MemberDie, dwarf::DW_AT_data_member_location,
1931- dwarf::DW_FORM_udata, OffsetInBytes);
1932- else
1933- addUInt (MemberDie, dwarf::DW_AT_data_member_location, std::nullopt ,
1934- OffsetInBytes);
1972+ if (DD->getDwarfVersion () <= 2 ) {
1973+ DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc;
1974+ addUInt (*MemLocationDie, dwarf::DW_FORM_data1,
1975+ dwarf::DW_OP_plus_uconst);
1976+ addUInt (*MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
1977+ addBlock (MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
1978+ } else if (!IsBitfield || DD->useDWARF2Bitfields ()) {
1979+ // In DWARF v3, DW_FORM_data4/8 in DW_AT_data_member_location are
1980+ // interpreted as location-list pointers. Interpreting constants as
1981+ // pointers is not expected, so we use DW_FORM_udata to encode the
1982+ // constants here.
1983+ if (DD->getDwarfVersion () == 3 )
1984+ addUInt (MemberDie, dwarf::DW_AT_data_member_location,
1985+ dwarf::DW_FORM_udata, OffsetInBytes);
1986+ else
1987+ addUInt (MemberDie, dwarf::DW_AT_data_member_location, std::nullopt ,
1988+ OffsetInBytes);
1989+ }
19351990 }
19361991 }
19371992
0 commit comments