summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp23
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp109
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h3
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfFile.h8
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp9
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h5
6 files changed, 138 insertions, 19 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 04c206ffea2..cf941a920c5 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -399,21 +399,30 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
SmallVector<RangeSpan, 2> Range) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
- // Emit offset in .debug_range as a relocatable label. emitDIE will handle
- // emitting it appropriately.
+ // Emit the offset into .debug_ranges or .debug_rnglists as a relocatable
+ // label. emitDIE() will handle emitting it appropriately.
const MCSymbol *RangeSectionSym =
- TLOF.getDwarfRangesSection()->getBeginSymbol();
+ DD->getDwarfVersion() >= 5
+ ? TLOF.getDwarfRnglistsSection()->getBeginSymbol()
+ : TLOF.getDwarfRangesSection()->getBeginSymbol();
RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range));
// Under fission, ranges are specified by constant offsets relative to the
// CU's DW_AT_GNU_ranges_base.
- if (isDwoUnit())
- addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
- RangeSectionSym);
- else
+ // FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under
+ // fission until we support the forms using the .debug_addr section
+ // (DW_RLE_startx_endx etc.).
+ if (isDwoUnit()) {
+ if (DD->getDwarfVersion() < 5)
+ addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
+ RangeSectionSym);
+ } else {
addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
RangeSectionSym);
+ if (DD->getDwarfVersion() >= 5)
+ addRnglistsBase();
+ }
// Add the range list to the set of ranges to be emitted.
(Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List));
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index c9e7a917daf..e12c866def1 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -645,6 +645,12 @@ void DwarfDebug::beginModule() {
(useSplitDwarf() ? SkeletonHolder : InfoHolder)
.setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base"));
+ // Create the symbol that designates the start of the DWARF v5 range list
+ // table. It is located past the header and before the offsets table.
+ if (getDwarfVersion() >= 5)
+ (useSplitDwarf() ? SkeletonHolder : InfoHolder)
+ .setRnglistsTableBaseSym(Asm->createTempSymbol("rnglists_table_base"));
+
for (DICompileUnit *CUNode : M->debug_compile_units()) {
// FIXME: Move local imported entities into a list attached to the
// subprogram, then this search won't be needed and a
@@ -765,7 +771,7 @@ void DwarfDebug::finalizeModuleInfo() {
SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base,
Sym, Sym);
}
- if (!SkCU->getRangeLists().empty()) {
+ if (getDwarfVersion() < 5 && !SkCU->getRangeLists().empty()) {
const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol();
SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,
Sym, Sym);
@@ -1970,9 +1976,11 @@ void DwarfDebug::emitDebugARanges() {
}
}
-/// Emit a single range list.
+/// Emit a single range list. We handle both DWARF v5 and earlier.
static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
const RangeSpanList &List) {
+
+ auto DwarfVersion = CU->getDwarfVersion();
// Emit our symbol so we can find the beginning of the range.
Asm->OutStreamer->EmitLabel(List.getSym());
// Gather all the ranges that apply to the same section so they can share
@@ -1992,18 +2000,24 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
// usually consist of single regions from each of many sections
// (-ffunction-sections, or just C++ inline functions) except under LTO
// or optnone where there may be holes in a single CU's section
- // contrubutions.
+ // contributions.
auto *Base = CUBase;
if (!Base && P.second.size() > 1 && UseDwarfRangesBaseAddressSpecifier) {
BaseIsSet = true;
// FIXME/use care: This may not be a useful base address if it's not
// the lowest address/range in this object.
Base = P.second.front()->getStart();
- Asm->OutStreamer->EmitIntValue(-1, Size);
+ if (DwarfVersion >= 5)
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1);
+ else
+ Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->EmitSymbolValue(Base, Size);
} else if (BaseIsSet) {
BaseIsSet = false;
- Asm->OutStreamer->EmitIntValue(-1, Size);
+ if (DwarfVersion >= 5)
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1);
+ else
+ Asm->OutStreamer->EmitIntValue(-1, Size);
Asm->OutStreamer->EmitIntValue(0, Size);
}
@@ -2013,21 +2027,87 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
assert(Begin && "Range without a begin symbol?");
assert(End && "Range without an end symbol?");
if (Base) {
- Asm->EmitLabelDifference(Begin, Base, Size);
- Asm->EmitLabelDifference(End, Base, Size);
+ if (DwarfVersion >= 5) {
+ // Emit DW_RLE_offset_pair when we have a base.
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_offset_pair, 1);
+ Asm->EmitLabelDifferenceAsULEB128(Begin, Base);
+ Asm->EmitLabelDifferenceAsULEB128(End, Base);
+ } else {
+ Asm->EmitLabelDifference(Begin, Base, Size);
+ Asm->EmitLabelDifference(End, Base, Size);
+ }
+ } else if (DwarfVersion >= 5) {
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1);
+ Asm->OutStreamer->EmitSymbolValue(Begin, Size);
+ Asm->EmitLabelDifferenceAsULEB128(End, Begin);
} else {
Asm->OutStreamer->EmitSymbolValue(Begin, Size);
Asm->OutStreamer->EmitSymbolValue(End, Size);
}
}
}
+ if (DwarfVersion >= 5)
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_end_of_list, 1);
+ else {
+ // Terminate the list with two 0 values.
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ }
+}
+
+void DwarfDebug::emitDebugRnglists() {
- // And terminate the list with two 0 values.
- Asm->OutStreamer->EmitIntValue(0, Size);
- Asm->OutStreamer->EmitIntValue(0, Size);
+ // Don't emit a rangelist table if there are no ranges.
+ if (llvm::all_of(CUMap,
+ [](const decltype(CUMap)::const_iterator::value_type &Pair) {
+ DwarfCompileUnit *TheCU = Pair.second;
+ if (auto *Skel = TheCU->getSkeleton())
+ TheCU = Skel;
+ return TheCU->getRangeLists().empty();
+ }))
+ return;
+
+ assert(getDwarfVersion() >= 5 && "Dwarf version must be 5 or greater");
+ // FIXME: As long as we don't support DW_RLE_base_addrx, we cannot generate
+ // any tables in the .debug_rnglists.dwo section.
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfRnglistsSection());
+ // The length is described by a starting label right after the length field
+ // and an end label.
+ MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start");
+ MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end");
+ // Build the range table header, which starts with the length field.
+ Asm->EmitLabelDifference(TableEnd, TableStart, 4);
+ Asm->OutStreamer->EmitLabel(TableStart);
+ // Version number (DWARF v5 and later).
+ Asm->emitInt16(getDwarfVersion());
+ // Address size.
+ Asm->emitInt8(Asm->MAI->getCodePointerSize());
+ // Segment selector size.
+ Asm->emitInt8(0);
+
+ MCSymbol *RnglistTableBaseSym =
+ (useSplitDwarf() ? SkeletonHolder : InfoHolder).getRnglistsTableBaseSym();
+
+ // FIXME: Generate the offsets table and use DW_FORM_rnglistx with the
+ // DW_AT_ranges attribute. Until then set the number of offsets to 0.
+ Asm->emitInt32(0);
+ Asm->OutStreamer->EmitLabel(RnglistTableBaseSym);
+
+ // Emit the individual range lists.
+ for (const auto &I : CUMap) {
+ DwarfCompileUnit *TheCU = I.second;
+ if (auto *Skel = TheCU->getSkeleton())
+ TheCU = Skel;
+ for (const RangeSpanList &List : TheCU->getRangeLists())
+ emitRangeList(Asm, TheCU, List);
+ }
+
+ Asm->OutStreamer->EmitLabel(TableEnd);
}
-/// Emit address ranges into a debug ranges section.
+/// Emit address ranges into the .debug_ranges section or DWARF v5 rangelists
+/// into the .debug_rnglists section.
void DwarfDebug::emitDebugRanges() {
if (CUMap.empty())
return;
@@ -2042,6 +2122,11 @@ void DwarfDebug::emitDebugRanges() {
return;
}
+ if (getDwarfVersion() >= 5) {
+ emitDebugRnglists();
+ return;
+ }
+
// Start the dwarf ranges section.
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
@@ -2134,7 +2219,7 @@ void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
-// DW_AT_addr_base, DW_AT_ranges_base.
+// DW_AT_addr_base, DW_AT_ranges_base or DW_AT_rnglists_base.
DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>(
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 54f0e5b6a79..528f83d2e4b 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -405,6 +405,9 @@ class DwarfDebug : public DebugHandlerBase {
/// Emit address ranges into a debug ranges section.
void emitDebugRanges();
+ /// Emit range lists into a DWARF v5 debug rnglists section.
+ void emitDebugRnglists();
+
/// Emit macros into a debug macinfo section.
void emitDebugMacinfo();
void emitMacro(DIMacro &M);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
index 442b4fc14b5..272a26851b7 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -48,6 +48,10 @@ class DwarfFile {
/// the string offsets table. The contribution is shared by all units.
MCSymbol *StringOffsetsStartSym = nullptr;
+ /// DWARF v5: The symbol that designates the base of the range list table.
+ /// The table is shared by all units.
+ MCSymbol *RnglistsTableBaseSym = nullptr;
+
/// The variables of a lexical scope.
struct ScopeVars {
/// We need to sort Args by ArgNo and check for duplicates. This could also
@@ -114,6 +118,10 @@ public:
void setStringOffsetsStartSym(MCSymbol *Sym) { StringOffsetsStartSym = Sym; }
+ MCSymbol *getRnglistsTableBaseSym() const { return RnglistsTableBaseSym; }
+
+ void setRnglistsTableBaseSym(MCSymbol *Sym) { RnglistsTableBaseSym = Sym; }
+
/// \returns false if the variable was merged with a previous one.
bool addScopeVariable(LexicalScope *LS, DbgVariable *Var);
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 77861ad45be..9af555464d4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1757,3 +1757,12 @@ void DwarfUnit::addStringOffsetsStart() {
DU->getStringOffsetsStartSym(),
TLOF.getDwarfStrOffSection()->getBeginSymbol());
}
+
+void DwarfUnit::addRnglistsBase() {
+ assert(DD->getDwarfVersion() >= 5 &&
+ "DW_AT_rnglists_base requires DWARF version 5 or later");
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ addSectionLabel(getUnitDie(), dwarf::DW_AT_rnglists_base,
+ DU->getRnglistsTableBaseSym(),
+ TLOF.getDwarfRnglistsSection()->getBeginSymbol());
+}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index c1d46173567..08c6f455d76 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -112,6 +112,8 @@ public:
uint16_t getLanguage() const { return CUNode->getSourceLanguage(); }
const DICompileUnit *getCUNode() const { return CUNode; }
+ uint16_t getDwarfVersion() const { return DD->getDwarfVersion(); }
+
/// Return true if this compile unit has something to write out.
bool hasContent() const { return getUnitDie().hasChildren(); }
@@ -293,6 +295,9 @@ public:
/// Add the DW_AT_str_offsets_base attribute to the unit DIE.
void addStringOffsetsStart();
+ /// Add the DW_AT_rnglists_base attribute to the unit DIE.
+ void addRnglistsBase();
+
virtual DwarfCompileUnit &getCU() = 0;
void constructTypeDIE(DIE &Buffer, const DICompositeType *CTy);
OpenPOWER on IntegriCloud