Skip to content

Commit 728a6c9

Browse files
tromeyslinder1
authored andcommitted
Introduce DwarfUnit::addBlock helper method (llvm#168446)
This patch is just a small cleanup that unifies the various spots that add a DWARF expression to the output.
1 parent 09e5dc6 commit 728a6c9

File tree

1 file changed

+116
-72
lines changed

1 file changed

+116
-72
lines changed

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 116 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,6 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
10591059
// Add name if not anonymous or intermediate type.
10601060
StringRef Name = CTy->getName();
10611061

1062-
uint64_t Size = CTy->getSizeInBits() >> 3;
10631062
uint16_t Tag = Buffer.getTag();
10641063

10651064
switch (Tag) {
@@ -1222,15 +1221,24 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
12221221
if (Tag == dwarf::DW_TAG_enumeration_type ||
12231222
Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type ||
12241223
Tag == dwarf::DW_TAG_union_type) {
1225-
// Add size if non-zero (derived types might be zero-sized.)
1226-
// Ignore the size if it's a non-enum forward decl.
1227-
// TODO: Do we care about size for enum forward declarations?
1228-
if (Size &&
1229-
(!CTy->isForwardDecl() || Tag == dwarf::DW_TAG_enumeration_type))
1230-
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size);
1231-
else if (!CTy->isForwardDecl())
1232-
// Add zero size if it is not a forward declaration.
1233-
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, 0);
1224+
if (auto *Var = dyn_cast_or_null<DIVariable>(CTy->getRawSizeInBits())) {
1225+
if (auto *VarDIE = getDIE(Var))
1226+
addDIEEntry(Buffer, dwarf::DW_AT_bit_size, *VarDIE);
1227+
} else if (auto *Exp =
1228+
dyn_cast_or_null<DIExpression>(CTy->getRawSizeInBits())) {
1229+
addBlock(Buffer, dwarf::DW_AT_bit_size, Exp);
1230+
} else {
1231+
uint64_t Size = CTy->getSizeInBits() >> 3;
1232+
// Add size if non-zero (derived types might be zero-sized.)
1233+
// Ignore the size if it's a non-enum forward decl.
1234+
// TODO: Do we care about size for enum forward declarations?
1235+
if (Size &&
1236+
(!CTy->isForwardDecl() || Tag == dwarf::DW_TAG_enumeration_type))
1237+
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size);
1238+
else if (!CTy->isForwardDecl())
1239+
// Add zero size if it is not a forward declaration.
1240+
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, 0);
1241+
}
12341242

12351243
// If we're a forward decl, say so.
12361244
if (CTy->isForwardDecl())
@@ -1884,74 +1892,110 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
18841892

18851893
addBlock(MemberDie, dwarf::DW_AT_data_member_location, VBaseLocationDie);
18861894
} else {
1887-
uint64_t Size = DT->getSizeInBits();
1888-
uint64_t FieldSize = DD->getBaseTypeSize(DT);
1889-
uint32_t AlignInBytes = DT->getAlignInBytes();
1890-
uint64_t OffsetInBytes;
1895+
uint64_t Size = 0;
1896+
uint64_t FieldSize = 0;
18911897

18921898
bool IsBitfield = DT->isBitField();
1893-
if (IsBitfield) {
1894-
// Handle bitfield, assume bytes are 8 bits.
1895-
if (DD->useDWARF2Bitfields())
1896-
addUInt(MemberDie, dwarf::DW_AT_byte_size, std::nullopt, FieldSize / 8);
1897-
addUInt(MemberDie, dwarf::DW_AT_bit_size, std::nullopt, Size);
1898-
1899-
assert(DT->getOffsetInBits() <=
1900-
(uint64_t)std::numeric_limits<int64_t>::max());
1901-
int64_t Offset = DT->getOffsetInBits();
1902-
// We can't use DT->getAlignInBits() here: AlignInBits for member type
1903-
// is non-zero if and only if alignment was forced (e.g. _Alignas()),
1904-
// which can't be done with bitfields. Thus we use FieldSize here.
1905-
uint32_t AlignInBits = FieldSize;
1906-
uint32_t AlignMask = ~(AlignInBits - 1);
1907-
// The bits from the start of the storage unit to the start of the field.
1908-
uint64_t StartBitOffset = Offset - (Offset & AlignMask);
1909-
// The byte offset of the field's aligned storage unit inside the struct.
1910-
OffsetInBytes = (Offset - StartBitOffset) / 8;
1911-
1912-
if (DD->useDWARF2Bitfields()) {
1913-
uint64_t HiMark = (Offset + FieldSize) & AlignMask;
1914-
uint64_t FieldOffset = (HiMark - FieldSize);
1915-
Offset -= FieldOffset;
1916-
1917-
// Maybe we need to work from the other end.
1918-
if (Asm->getDataLayout().isLittleEndian())
1919-
Offset = FieldSize - (Offset + Size);
1920-
1921-
if (Offset < 0)
1922-
addSInt(MemberDie, dwarf::DW_AT_bit_offset, dwarf::DW_FORM_sdata,
1899+
1900+
// Handle the size.
1901+
if (DT->getRawSizeInBits() == nullptr) {
1902+
// No size, just ignore.
1903+
} else if (auto *Var = dyn_cast<DIVariable>(DT->getRawSizeInBits())) {
1904+
if (auto *VarDIE = getDIE(Var))
1905+
addDIEEntry(MemberDie, dwarf::DW_AT_bit_size, *VarDIE);
1906+
} else if (auto *Exp = dyn_cast<DIExpression>(DT->getRawSizeInBits())) {
1907+
addBlock(MemberDie, dwarf::DW_AT_bit_size, Exp);
1908+
} else {
1909+
Size = DT->getSizeInBits();
1910+
FieldSize = DD->getBaseTypeSize(DT);
1911+
if (IsBitfield) {
1912+
// Handle bitfield, assume bytes are 8 bits.
1913+
if (DD->useDWARF2Bitfields())
1914+
addUInt(MemberDie, dwarf::DW_AT_byte_size, std::nullopt,
1915+
FieldSize / 8);
1916+
addUInt(MemberDie, dwarf::DW_AT_bit_size, std::nullopt, Size);
1917+
}
1918+
}
1919+
1920+
// Handle the location. DW_AT_data_bit_offset won't allow an
1921+
// expression until DWARF 6, but it can be used as an extension.
1922+
// See https://dwarfstd.org/issues/250501.1.html
1923+
if (auto *Var = dyn_cast_or_null<DIVariable>(DT->getRawOffsetInBits())) {
1924+
if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 6) {
1925+
if (auto *VarDIE = getDIE(Var))
1926+
addDIEEntry(MemberDie, dwarf::DW_AT_data_bit_offset, *VarDIE);
1927+
}
1928+
} else if (auto *Expr =
1929+
dyn_cast_or_null<DIExpression>(DT->getRawOffsetInBits())) {
1930+
if (!Asm->TM.Options.DebugStrictDwarf || DD->getDwarfVersion() >= 6) {
1931+
addBlock(MemberDie, dwarf::DW_AT_data_bit_offset, Expr);
1932+
}
1933+
} else {
1934+
uint32_t AlignInBytes = DT->getAlignInBytes();
1935+
uint64_t OffsetInBytes;
1936+
1937+
if (IsBitfield) {
1938+
assert(DT->getOffsetInBits() <=
1939+
(uint64_t)std::numeric_limits<int64_t>::max());
1940+
int64_t Offset = DT->getOffsetInBits();
1941+
// We can't use DT->getAlignInBits() here: AlignInBits for member type
1942+
// is non-zero if and only if alignment was forced (e.g. _Alignas()),
1943+
// which can't be done with bitfields. Thus we use FieldSize here.
1944+
uint32_t AlignInBits = FieldSize;
1945+
uint32_t AlignMask = ~(AlignInBits - 1);
1946+
// The bits from the start of the storage unit to the start of the
1947+
// field.
1948+
uint64_t StartBitOffset = Offset - (Offset & AlignMask);
1949+
// The byte offset of the field's aligned storage unit inside the
1950+
// struct.
1951+
OffsetInBytes = (Offset - StartBitOffset) / 8;
1952+
1953+
if (DD->useDWARF2Bitfields()) {
1954+
uint64_t HiMark = (Offset + FieldSize) & AlignMask;
1955+
uint64_t FieldOffset = (HiMark - FieldSize);
1956+
Offset -= FieldOffset;
1957+
1958+
// Maybe we need to work from the other end.
1959+
if (Asm->getDataLayout().isLittleEndian())
1960+
Offset = FieldSize - (Offset + Size);
1961+
1962+
if (Offset < 0)
1963+
addSInt(MemberDie, dwarf::DW_AT_bit_offset, dwarf::DW_FORM_sdata,
1964+
Offset);
1965+
else
1966+
addUInt(MemberDie, dwarf::DW_AT_bit_offset, std::nullopt,
1967+
(uint64_t)Offset);
1968+
OffsetInBytes = FieldOffset >> 3;
1969+
} else {
1970+
addUInt(MemberDie, dwarf::DW_AT_data_bit_offset, std::nullopt,
19231971
Offset);
1924-
else
1925-
addUInt(MemberDie, dwarf::DW_AT_bit_offset, std::nullopt,
1926-
(uint64_t)Offset);
1927-
OffsetInBytes = FieldOffset >> 3;
1972+
}
19281973
} else {
1929-
addUInt(MemberDie, dwarf::DW_AT_data_bit_offset, std::nullopt, Offset);
1974+
// This is not a bitfield.
1975+
OffsetInBytes = DT->getOffsetInBits() / 8;
1976+
if (AlignInBytes)
1977+
addUInt(MemberDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
1978+
AlignInBytes);
19301979
}
1931-
} else {
1932-
// This is not a bitfield.
1933-
OffsetInBytes = DT->getOffsetInBits() / 8;
1934-
if (AlignInBytes)
1935-
addUInt(MemberDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
1936-
AlignInBytes);
1937-
}
19381980

1939-
if (DD->getDwarfVersion() <= 2) {
1940-
DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc;
1941-
addUInt(*MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
1942-
addUInt(*MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
1943-
addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
1944-
} else if (!IsBitfield || DD->useDWARF2Bitfields()) {
1945-
// In DWARF v3, DW_FORM_data4/8 in DW_AT_data_member_location are
1946-
// interpreted as location-list pointers. Interpreting constants as
1947-
// pointers is not expected, so we use DW_FORM_udata to encode the
1948-
// constants here.
1949-
if (DD->getDwarfVersion() == 3)
1950-
addUInt(MemberDie, dwarf::DW_AT_data_member_location,
1951-
dwarf::DW_FORM_udata, OffsetInBytes);
1952-
else
1953-
addUInt(MemberDie, dwarf::DW_AT_data_member_location, std::nullopt,
1954-
OffsetInBytes);
1981+
if (DD->getDwarfVersion() <= 2) {
1982+
DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc;
1983+
addUInt(*MemLocationDie, dwarf::DW_FORM_data1,
1984+
dwarf::DW_OP_plus_uconst);
1985+
addUInt(*MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
1986+
addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
1987+
} else if (!IsBitfield || DD->useDWARF2Bitfields()) {
1988+
// In DWARF v3, DW_FORM_data4/8 in DW_AT_data_member_location are
1989+
// interpreted as location-list pointers. Interpreting constants as
1990+
// pointers is not expected, so we use DW_FORM_udata to encode the
1991+
// constants here.
1992+
if (DD->getDwarfVersion() == 3)
1993+
addUInt(MemberDie, dwarf::DW_AT_data_member_location,
1994+
dwarf::DW_FORM_udata, OffsetInBytes);
1995+
else
1996+
addUInt(MemberDie, dwarf::DW_AT_data_member_location, std::nullopt,
1997+
OffsetInBytes);
1998+
}
19551999
}
19562000
}
19572001

0 commit comments

Comments
 (0)