Skip to content

Commit b667783

Browse files
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (llvm#77457)
This implements the ideas discussed in [1]. To summarize, this commit changes AsmPrinter so that it outputs DW_IDX_parent information for debug_name entries. It will enable debuggers to speed up queries for fully qualified types (based on a DWARFDeclContext) significantly, as debuggers will no longer need to parse the entire CU in order to inspect the parent chain of a DIE. Instead, a debugger can simply take the parent DIE offset from the accelerator table and peek at its name in the debug_info/debug_str sections. The implementation uses two types of DW_FORM for the DW_IDX_parent attribute: 1. DW_FORM_ref4, which points to the accelerator table entry for the parent. 2. DW_FORM_flag_present, when the entry has a parent that is not in the table (that is, the parent doesn't have a name, or isn't allowed to be in the table as per the DWARF spec). This is space-efficient, since it takes 0 bytes. The implementation works by: 1. Changing how abbreviations are encoded (so that they encode which form, if any, was used to encode IDX_Parent) 2. Creating an MCLabel per accelerator table entry, so that they may be referred by IDX_parent references. When all patches related to this are merged, we are able to show that evaluating an expression such as: ``` lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \ clang++ -c -g test.cpp -o /dev/null ``` is far faster: from ~5000 ms to ~1500ms. Building llvm-project + clang with and without this patch, and looking at its impact on object file size: ``` ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}' 11,507,327,592 -la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}' 11,436,446,616 ``` That is, an increase of 0.62% in total object file size. Looking only at debug_names: ``` $stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}' 440,772,348 $stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}' 369,867,920 ``` That is an increase of 19%. DWARF Linkers need to be changed in order to support this. This commit already brings support to "base" linker, but it does not attempt to modify the parallel linker. Accelerator entries refer to the corresponding DIE offset, and this patch also requires the parent DIE offset -- it's not clear how the parallel linker can access this. It may be obvious to someone familiar with it, but it would be nice to get help from its authors. [1]: https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
1 parent c80d68a commit b667783

File tree

12 files changed

+356
-58
lines changed

12 files changed

+356
-58
lines changed

llvm/include/llvm/CodeGen/AccelTable.h

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,20 @@ class AppleAccelTableData : public AccelTableData {
255255
static uint32_t hash(StringRef Buffer) { return djbHash(Buffer); }
256256
};
257257

258+
/// Helper class to identify an entry in DWARF5AccelTable based on their DIE
259+
/// offset and UnitID.
260+
struct OffsetAndUnitID : std::pair<uint64_t, uint32_t> {
261+
using Base = std::pair<uint64_t, uint32_t>;
262+
OffsetAndUnitID(Base B) : Base(B) {}
263+
264+
OffsetAndUnitID(uint64_t Offset, uint32_t UnitID) : Base(Offset, UnitID) {}
265+
uint64_t offset() const { return first; };
266+
uint32_t unitID() const { return second; };
267+
};
268+
269+
template <>
270+
struct DenseMapInfo<OffsetAndUnitID> : DenseMapInfo<OffsetAndUnitID::Base> {};
271+
258272
/// The Data class implementation for DWARF v5 accelerator table. Unlike the
259273
/// Apple Data classes, this class is just a DIE wrapper, and does not know to
260274
/// serialize itself. The complete serialization logic is in the
@@ -270,9 +284,12 @@ class DWARF5AccelTableData : public AccelTableData {
270284

271285
DWARF5AccelTableData(const DIE &Die, const uint32_t UnitID,
272286
const bool IsTU = false);
273-
DWARF5AccelTableData(const uint64_t DieOffset, const unsigned DieTag,
274-
const unsigned UnitID, const bool IsTU = false)
275-
: OffsetVal(DieOffset), DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {}
287+
DWARF5AccelTableData(const uint64_t DieOffset,
288+
const std::optional<uint64_t> DefiningParentOffset,
289+
const unsigned DieTag, const unsigned UnitID,
290+
const bool IsTU = false)
291+
: OffsetVal(DieOffset), ParentOffset(DefiningParentOffset),
292+
DieTag(DieTag), UnitID(UnitID), IsTU(IsTU) {}
276293

277294
#ifndef NDEBUG
278295
void print(raw_ostream &OS) const override;
@@ -282,19 +299,44 @@ class DWARF5AccelTableData : public AccelTableData {
282299
assert(isNormalized() && "Accessing DIE Offset before normalizing.");
283300
return std::get<uint64_t>(OffsetVal);
284301
}
302+
303+
OffsetAndUnitID getDieOffsetAndUnitID() const {
304+
return {getDieOffset(), UnitID};
305+
}
306+
285307
unsigned getDieTag() const { return DieTag; }
286308
unsigned getUnitID() const { return UnitID; }
287309
bool isTU() const { return IsTU; }
288310
void normalizeDIEToOffset() {
289311
assert(!isNormalized() && "Accessing offset after normalizing.");
290-
OffsetVal = std::get<const DIE *>(OffsetVal)->getOffset();
312+
const DIE *Entry = std::get<const DIE *>(OffsetVal);
313+
ParentOffset = getDefiningParentDieOffset(*Entry);
314+
OffsetVal = Entry->getOffset();
291315
}
292316
bool isNormalized() const {
293317
return std::holds_alternative<uint64_t>(OffsetVal);
294318
}
295319

320+
std::optional<uint64_t> getParentDieOffset() const {
321+
if (auto OffsetAndId = getParentDieOffsetAndUnitID())
322+
return OffsetAndId->offset();
323+
return {};
324+
}
325+
326+
std::optional<OffsetAndUnitID> getParentDieOffsetAndUnitID() const {
327+
assert(isNormalized() && "Accessing DIE Offset before normalizing.");
328+
if (!ParentOffset)
329+
return std::nullopt;
330+
return OffsetAndUnitID(*ParentOffset, getUnitID());
331+
}
332+
333+
/// If `Die` has a non-null parent and the parent is not a declaration,
334+
/// return its offset.
335+
static std::optional<uint64_t> getDefiningParentDieOffset(const DIE &Die);
336+
296337
protected:
297338
std::variant<const DIE *, uint64_t> OffsetVal;
339+
std::optional<uint64_t> ParentOffset;
298340
uint32_t DieTag : 16;
299341
uint32_t UnitID : 15;
300342
uint32_t IsTU : 1;
@@ -341,7 +383,8 @@ class DWARF5AccelTable : public AccelTable<DWARF5AccelTableData> {
341383
void addTypeEntries(DWARF5AccelTable &Table) {
342384
for (auto &Entry : Table.getEntries()) {
343385
for (auto *Data : Entry.second.getValues<DWARF5AccelTableData *>()) {
344-
addName(Entry.second.Name, Data->getDieOffset(), Data->getDieTag(),
386+
addName(Entry.second.Name, Data->getDieOffset(),
387+
Data->getParentDieOffset(), Data->getDieTag(),
345388
Data->getUnitID(), true);
346389
}
347390
}

llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp

Lines changed: 113 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/CodeGen/AccelTable.h"
1414
#include "DwarfCompileUnit.h"
1515
#include "DwarfUnit.h"
16+
#include "llvm/ADT/DenseSet.h"
1617
#include "llvm/ADT/STLExtras.h"
1718
#include "llvm/ADT/Twine.h"
1819
#include "llvm/BinaryFormat/Dwarf.h"
@@ -207,7 +208,7 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
207208
};
208209

209210
Header Header;
210-
DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 2>>
211+
DenseMap<uint32_t, SmallVector<DWARF5AccelTableData::AttributeEncoding, 3>>
211212
Abbreviations;
212213
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
213214
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
@@ -220,6 +221,8 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
220221
MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
221222
// Indicates if this module is built with Split Dwarf enabled.
222223
bool IsSplitDwarf = false;
224+
/// Stores the DIE offsets which are indexed by this table.
225+
DenseSet<OffsetAndUnitID> IndexedOffsets;
223226

224227
void populateAbbrevsMap();
225228

@@ -228,8 +231,11 @@ class Dwarf5AccelTableWriter : public AccelTableWriter {
228231
void emitBuckets() const;
229232
void emitStringOffsets() const;
230233
void emitAbbrevs() const;
231-
void emitEntry(const DWARF5AccelTableData &Entry) const;
232-
void emitData() const;
234+
void emitEntry(
235+
const DWARF5AccelTableData &Entry,
236+
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
237+
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols) const;
238+
void emitData();
233239

234240
public:
235241
Dwarf5AccelTableWriter(
@@ -395,36 +401,90 @@ void Dwarf5AccelTableWriter::Header::emit(Dwarf5AccelTableWriter &Ctx) {
395401
Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize});
396402
}
397403

398-
static uint32_t constexpr LowerBitSize = dwarf::DW_IDX_type_hash;
404+
std::optional<uint64_t>
405+
DWARF5AccelTableData::getDefiningParentDieOffset(const DIE &Die) {
406+
if (auto *Parent = Die.getParent();
407+
Parent && !Parent->findAttribute(dwarf::Attribute::DW_AT_declaration))
408+
return Parent->getOffset();
409+
return {};
410+
}
411+
412+
enum IdxParentEncoding : uint8_t {
413+
NoIndexedParent = 0, /// Parent information present but parent isn't indexed.
414+
Ref4 = 1, /// Parent information present and parent is indexed.
415+
NoParent = 2, /// Parent information missing.
416+
};
417+
418+
static uint32_t constexpr NumBitsIdxParent = 2;
419+
420+
uint8_t encodeIdxParent(const std::optional<dwarf::Form> MaybeParentForm) {
421+
if (!MaybeParentForm)
422+
return NoParent;
423+
switch (*MaybeParentForm) {
424+
case dwarf::Form::DW_FORM_flag_present:
425+
return NoIndexedParent;
426+
case dwarf::Form::DW_FORM_ref4:
427+
return Ref4;
428+
default:
429+
// This is not crashing on bad input: we should only reach this if the
430+
// internal compiler logic is faulty; see getFormForIdxParent.
431+
llvm_unreachable("Bad form for IDX_parent");
432+
}
433+
}
434+
435+
static uint32_t constexpr ParentBitOffset = dwarf::DW_IDX_type_hash;
436+
static uint32_t constexpr TagBitOffset = ParentBitOffset + NumBitsIdxParent;
399437
static uint32_t getTagFromAbbreviationTag(const uint32_t AbbrvTag) {
400-
return AbbrvTag >> LowerBitSize;
438+
return AbbrvTag >> TagBitOffset;
401439
}
402440

403441
/// Constructs a unique AbbrevTag that captures what a DIE accesses.
404442
/// Using this tag we can emit a unique abbreviation for each DIE.
405443
static uint32_t constructAbbreviationTag(
406444
const unsigned Tag,
407-
const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> &EntryRet) {
445+
const std::optional<DWARF5AccelTable::UnitIndexAndEncoding> &EntryRet,
446+
std::optional<dwarf::Form> MaybeParentForm) {
408447
uint32_t AbbrvTag = 0;
409448
if (EntryRet)
410449
AbbrvTag |= 1 << EntryRet->Encoding.Index;
411450
AbbrvTag |= 1 << dwarf::DW_IDX_die_offset;
412-
AbbrvTag |= Tag << LowerBitSize;
451+
AbbrvTag |= 1 << dwarf::DW_IDX_parent;
452+
AbbrvTag |= encodeIdxParent(MaybeParentForm) << ParentBitOffset;
453+
AbbrvTag |= Tag << TagBitOffset;
413454
return AbbrvTag;
414455
}
456+
457+
static std::optional<dwarf::Form>
458+
getFormForIdxParent(const DenseSet<OffsetAndUnitID> &IndexedOffsets,
459+
std::optional<OffsetAndUnitID> ParentOffset) {
460+
// No parent information
461+
if (!ParentOffset)
462+
return std::nullopt;
463+
// Parent is indexed by this table.
464+
if (IndexedOffsets.contains(*ParentOffset))
465+
return dwarf::Form::DW_FORM_ref4;
466+
// Parent is not indexed by this table.
467+
return dwarf::Form::DW_FORM_flag_present;
468+
}
469+
415470
void Dwarf5AccelTableWriter::populateAbbrevsMap() {
416471
for (auto &Bucket : Contents.getBuckets()) {
417472
for (auto *Hash : Bucket) {
418473
for (auto *Value : Hash->getValues<DWARF5AccelTableData *>()) {
419474
std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
420475
getIndexForEntry(*Value);
421476
unsigned Tag = Value->getDieTag();
422-
uint32_t AbbrvTag = constructAbbreviationTag(Tag, EntryRet);
477+
std::optional<dwarf::Form> MaybeParentForm = getFormForIdxParent(
478+
IndexedOffsets, Value->getParentDieOffsetAndUnitID());
479+
uint32_t AbbrvTag =
480+
constructAbbreviationTag(Tag, EntryRet, MaybeParentForm);
423481
if (Abbreviations.count(AbbrvTag) == 0) {
424-
SmallVector<DWARF5AccelTableData::AttributeEncoding, 2> UA;
482+
SmallVector<DWARF5AccelTableData::AttributeEncoding, 3> UA;
425483
if (EntryRet)
426484
UA.push_back(EntryRet->Encoding);
427485
UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
486+
if (MaybeParentForm)
487+
UA.push_back({dwarf::DW_IDX_parent, *MaybeParentForm});
428488
Abbreviations.try_emplace(AbbrvTag, UA);
429489
}
430490
}
@@ -496,15 +556,34 @@ void Dwarf5AccelTableWriter::emitAbbrevs() const {
496556
}
497557

498558
void Dwarf5AccelTableWriter::emitEntry(
499-
const DWARF5AccelTableData &Entry) const {
559+
const DWARF5AccelTableData &Entry,
560+
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
561+
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols) const {
500562
std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
501563
getIndexForEntry(Entry);
502-
uint32_t AbbrvTag = constructAbbreviationTag(Entry.getDieTag(), EntryRet);
564+
std::optional<OffsetAndUnitID> MaybeParentOffset =
565+
Entry.getParentDieOffsetAndUnitID();
566+
std::optional<dwarf::Form> MaybeParentForm =
567+
getFormForIdxParent(IndexedOffsets, MaybeParentOffset);
568+
uint32_t AbbrvTag =
569+
constructAbbreviationTag(Entry.getDieTag(), EntryRet, MaybeParentForm);
503570
auto AbbrevIt = Abbreviations.find(AbbrvTag);
504571
assert(AbbrevIt != Abbreviations.end() &&
505572
"Why wasn't this abbrev generated?");
506573
assert(getTagFromAbbreviationTag(AbbrevIt->first) == Entry.getDieTag() &&
507574
"Invalid Tag");
575+
576+
auto EntrySymbolIt =
577+
DIEOffsetToAccelEntryLabel.find(Entry.getDieOffsetAndUnitID());
578+
assert(EntrySymbolIt != DIEOffsetToAccelEntryLabel.end());
579+
MCSymbol *EntrySymbol = EntrySymbolIt->getSecond();
580+
581+
// Emit the label for this Entry, so that IDX_parents may refer to it.
582+
// Note: a DIE may have multiple accelerator Entries; this check avoids
583+
// creating/emitting multiple labels for the same DIE.
584+
if (EmittedAccelEntrySymbols.insert(EntrySymbol).second)
585+
Asm->OutStreamer->emitLabel(EntrySymbol);
586+
508587
Asm->emitULEB128(AbbrevIt->first, "Abbreviation code");
509588

510589
for (const auto &AttrEnc : AbbrevIt->second) {
@@ -520,20 +599,34 @@ void Dwarf5AccelTableWriter::emitEntry(
520599
assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
521600
Asm->emitInt32(Entry.getDieOffset());
522601
break;
602+
case dwarf::DW_IDX_parent: {
603+
if (AttrEnc.Form == dwarf::Form::DW_FORM_flag_present)
604+
break;
605+
auto ParentSymbolIt = DIEOffsetToAccelEntryLabel.find(*MaybeParentOffset);
606+
assert(ParentSymbolIt != DIEOffsetToAccelEntryLabel.end());
607+
Asm->emitLabelDifference(ParentSymbolIt->getSecond(), EntryPool, 4);
608+
break;
609+
}
523610
default:
524611
llvm_unreachable("Unexpected index attribute!");
525612
}
526613
}
527614
}
528615

529-
void Dwarf5AccelTableWriter::emitData() const {
616+
void Dwarf5AccelTableWriter::emitData() {
617+
DenseMap<OffsetAndUnitID, MCSymbol *> DIEOffsetToAccelEntryLabel;
618+
619+
for (OffsetAndUnitID Offset : IndexedOffsets)
620+
DIEOffsetToAccelEntryLabel.insert({Offset, Asm->createTempSymbol("")});
621+
530622
Asm->OutStreamer->emitLabel(EntryPool);
623+
DenseSet<MCSymbol *> EmittedAccelEntrySymbols;
531624
for (auto &Bucket : Contents.getBuckets()) {
532625
for (auto *Hash : Bucket) {
533626
// Remember to emit the label for our offset.
534627
Asm->OutStreamer->emitLabel(Hash->Sym);
535-
for (const auto *Value : Hash->Values)
536-
emitEntry(*static_cast<const DWARF5AccelTableData *>(Value));
628+
for (const auto *Value : Hash->getValues<DWARF5AccelTableData *>())
629+
emitEntry(*Value, DIEOffsetToAccelEntryLabel, EmittedAccelEntrySymbols);
537630
Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
538631
Asm->emitInt8(0);
539632
}
@@ -555,6 +648,12 @@ Dwarf5AccelTableWriter::Dwarf5AccelTableWriter(
555648
CompUnits(CompUnits), TypeUnits(TypeUnits),
556649
getIndexForEntry(std::move(getIndexForEntry)),
557650
IsSplitDwarf(IsSplitDwarf) {
651+
652+
for (auto &Bucket : Contents.getBuckets())
653+
for (auto *Hash : Bucket)
654+
for (auto *Value : Hash->getValues<DWARF5AccelTableData *>())
655+
IndexedOffsets.insert(Value->getDieOffsetAndUnitID());
656+
558657
populateAbbrevsMap();
559658
}
560659

llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2240,14 +2240,20 @@ void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) {
22402240
} break;
22412241
case AccelTableKind::DebugNames: {
22422242
for (const auto &Namespace : Unit.getNamespaces())
2243-
DebugNames.addName(Namespace.Name, Namespace.Die->getOffset(),
2244-
Namespace.Die->getTag(), Unit.getUniqueID());
2243+
DebugNames.addName(
2244+
Namespace.Name, Namespace.Die->getOffset(),
2245+
DWARF5AccelTableData::getDefiningParentDieOffset(*Namespace.Die),
2246+
Namespace.Die->getTag(), Unit.getUniqueID());
22452247
for (const auto &Pubname : Unit.getPubnames())
2246-
DebugNames.addName(Pubname.Name, Pubname.Die->getOffset(),
2247-
Pubname.Die->getTag(), Unit.getUniqueID());
2248+
DebugNames.addName(
2249+
Pubname.Name, Pubname.Die->getOffset(),
2250+
DWARF5AccelTableData::getDefiningParentDieOffset(*Pubname.Die),
2251+
Pubname.Die->getTag(), Unit.getUniqueID());
22482252
for (const auto &Pubtype : Unit.getPubtypes())
2249-
DebugNames.addName(Pubtype.Name, Pubtype.Die->getOffset(),
2250-
Pubtype.Die->getTag(), Unit.getUniqueID());
2253+
DebugNames.addName(
2254+
Pubtype.Name, Pubtype.Die->getOffset(),
2255+
DWARF5AccelTableData::getDefiningParentDieOffset(*Pubtype.Die),
2256+
Pubtype.Die->getTag(), Unit.getUniqueID());
22512257
} break;
22522258
}
22532259
}

llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,8 @@ void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
13581358
case DwarfUnit::AccelType::Namespace:
13591359
case DwarfUnit::AccelType::Type: {
13601360
DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1361-
Info.OutOffset, Info.Tag, CU->getUniqueID());
1361+
Info.OutOffset, std::nullopt /*ParentDIEOffset*/,
1362+
Info.Tag, CU->getUniqueID());
13621363
} break;
13631364

13641365
default:

llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88
#include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
99
#include "llvm/ADT/IntervalMap.h"
10+
#include "llvm/ADT/STLExtras.h"
1011
#include "llvm/ADT/SmallSet.h"
1112
#include "llvm/BinaryFormat/Dwarf.h"
1213
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
@@ -1272,6 +1273,20 @@ unsigned DWARFVerifier::verifyNameIndexAttribute(
12721273
NI.getUnitOffset(), Abbr.Code, AttrEnc.Form, dwarf::DW_FORM_data8);
12731274
return 1;
12741275
}
1276+
return 0;
1277+
}
1278+
1279+
if (AttrEnc.Index == dwarf::DW_IDX_parent) {
1280+
constexpr static auto AllowedForms = {dwarf::Form::DW_FORM_flag_present,
1281+
dwarf::Form::DW_FORM_ref4};
1282+
if (!is_contained(AllowedForms, AttrEnc.Form)) {
1283+
error() << formatv("NameIndex @ {0:x}: Abbreviation {1:x}: DW_IDX_parent "
1284+
"uses an unexpected form {2} (should be "
1285+
"DW_FORM_ref4 or DW_FORM_flag_present).\n",
1286+
NI.getUnitOffset(), Abbr.Code, AttrEnc.Form);
1287+
return 1;
1288+
}
1289+
return 0;
12751290
}
12761291

12771292
// A list of known index attributes and their expected form classes.
@@ -1286,7 +1301,6 @@ unsigned DWARFVerifier::verifyNameIndexAttribute(
12861301
{dwarf::DW_IDX_compile_unit, DWARFFormValue::FC_Constant, {"constant"}},
12871302
{dwarf::DW_IDX_type_unit, DWARFFormValue::FC_Constant, {"constant"}},
12881303
{dwarf::DW_IDX_die_offset, DWARFFormValue::FC_Reference, {"reference"}},
1289-
{dwarf::DW_IDX_parent, DWARFFormValue::FC_Constant, {"constant"}},
12901304
};
12911305

12921306
ArrayRef<FormClassTable> TableRef(Table);

0 commit comments

Comments
 (0)