diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 109 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h | 3 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfFile.h | 8 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h | 5 |
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); |