Skip to content

Commit 5f777b2

Browse files
authored
[dwarf] make dwarf fission compatible with RISCV relaxations 1/2 (#166597)
Currently, -gsplit-dwarf and -mrelax are incompatible options in Clang. The issue is that .dwo files should not contain any relocations, as they are not processed by the linker. However, relaxable code emits relocations in DWARF for debug ranges that reside in the .dwo file when DWARF fission is enabled. This patch makes DWARF fission compatible with RISC-V relaxations. It uses the StartxEndx DWARF forms in .debug_rnglists.dwo, which allow referencing addresses from .debug_addr instead of using absolute addresses. This approach eliminates relocations from .dwo files.
1 parent 4f39a4f commit 5f777b2

File tree

4 files changed

+249
-28
lines changed

4 files changed

+249
-28
lines changed

llvm/include/llvm/MC/MCSymbol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
383383
return OS;
384384
}
385385

386+
bool isRangeRelaxable(const MCSymbol *Begin, const MCSymbol *End);
387+
386388
} // end namespace llvm
387389

388390
#endif // LLVM_MC_MCSYMBOL_H

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3307,14 +3307,12 @@ static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm,
33073307
}
33083308

33093309
template <typename Ranges, typename PayloadEmitter>
3310-
static void emitRangeList(
3311-
DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym, const Ranges &R,
3312-
const DwarfCompileUnit &CU, unsigned BaseAddressx, unsigned OffsetPair,
3313-
unsigned StartxLength, unsigned EndOfList,
3314-
StringRef (*StringifyEnum)(unsigned),
3315-
bool ShouldUseBaseAddress,
3316-
PayloadEmitter EmitPayload) {
3317-
3310+
static void
3311+
emitRangeList(DwarfDebug &DD, AsmPrinter *Asm, MCSymbol *Sym, const Ranges &R,
3312+
const DwarfCompileUnit &CU, unsigned BaseAddressx,
3313+
unsigned OffsetPair, unsigned StartxLength, unsigned StartxEndx,
3314+
unsigned EndOfList, StringRef (*StringifyEnum)(unsigned),
3315+
bool ShouldUseBaseAddress, PayloadEmitter EmitPayload) {
33183316
auto Size = Asm->MAI->getCodePointerSize();
33193317
bool UseDwarf5 = DD.getDwarfVersion() >= 5;
33203318

@@ -3333,7 +3331,8 @@ static void emitRangeList(
33333331
bool BaseIsSet = false;
33343332
for (const auto &P : SectionRanges) {
33353333
auto *Base = CUBase;
3336-
if ((Asm->TM.getTargetTriple().isNVPTX() && DD.tuneForGDB())) {
3334+
if ((Asm->TM.getTargetTriple().isNVPTX() && DD.tuneForGDB()) ||
3335+
(DD.useSplitDwarf() && UseDwarf5 && P.first->isLinkerRelaxable())) {
33373336
// PTX does not support subtracting labels from the code section in the
33383337
// debug_loc section. To work around this, the NVPTX backend needs the
33393338
// compile unit to have no low_pc in order to have a zero base_address
@@ -3389,12 +3388,27 @@ static void emitRangeList(
33893388
Asm->emitLabelDifference(End, Base, Size);
33903389
}
33913390
} else if (UseDwarf5) {
3392-
Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));
3393-
Asm->emitInt8(StartxLength);
3394-
Asm->OutStreamer->AddComment(" start index");
3395-
Asm->emitULEB128(DD.getAddressPool().getIndex(Begin));
3396-
Asm->OutStreamer->AddComment(" length");
3397-
Asm->emitLabelDifferenceAsULEB128(End, Begin);
3391+
// NOTE: We can't use absoluteSymbolDiff here instead of
3392+
// isRangeRelaxable. While isRangeRelaxable only checks that the offset
3393+
// between labels won't change at link time (which is exactly what we
3394+
// need), absoluteSymbolDiff also requires that the offset remain
3395+
// unchanged at assembly time, imposing a much stricter condition.
3396+
// Consequently, this would lead to less optimal debug info emission.
3397+
if (DD.useSplitDwarf() && llvm::isRangeRelaxable(Begin, End)) {
3398+
Asm->OutStreamer->AddComment(StringifyEnum(StartxEndx));
3399+
Asm->emitInt8(StartxEndx);
3400+
Asm->OutStreamer->AddComment(" start index");
3401+
Asm->emitULEB128(DD.getAddressPool().getIndex(Begin));
3402+
Asm->OutStreamer->AddComment(" end index");
3403+
Asm->emitULEB128(DD.getAddressPool().getIndex(End));
3404+
} else {
3405+
Asm->OutStreamer->AddComment(StringifyEnum(StartxLength));
3406+
Asm->emitInt8(StartxLength);
3407+
Asm->OutStreamer->AddComment(" start index");
3408+
Asm->emitULEB128(DD.getAddressPool().getIndex(Begin));
3409+
Asm->OutStreamer->AddComment(" length");
3410+
Asm->emitLabelDifferenceAsULEB128(End, Begin);
3411+
}
33983412
} else {
33993413
Asm->OutStreamer->emitSymbolValue(Begin, Size);
34003414
Asm->OutStreamer->emitSymbolValue(End, Size);
@@ -3415,14 +3429,14 @@ static void emitRangeList(
34153429

34163430
// Handles emission of both debug_loclist / debug_loclist.dwo
34173431
static void emitLocList(DwarfDebug &DD, AsmPrinter *Asm, const DebugLocStream::List &List) {
3418-
emitRangeList(DD, Asm, List.Label, DD.getDebugLocs().getEntries(List),
3419-
*List.CU, dwarf::DW_LLE_base_addressx,
3420-
dwarf::DW_LLE_offset_pair, dwarf::DW_LLE_startx_length,
3421-
dwarf::DW_LLE_end_of_list, llvm::dwarf::LocListEncodingString,
3422-
/* ShouldUseBaseAddress */ true,
3423-
[&](const DebugLocStream::Entry &E) {
3424-
DD.emitDebugLocEntryLocation(E, List.CU);
3425-
});
3432+
emitRangeList(
3433+
DD, Asm, List.Label, DD.getDebugLocs().getEntries(List), *List.CU,
3434+
dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair,
3435+
dwarf::DW_LLE_startx_length, dwarf::DW_LLE_startx_endx,
3436+
dwarf::DW_LLE_end_of_list, llvm::dwarf::LocListEncodingString,
3437+
/* ShouldUseBaseAddress */ true, [&](const DebugLocStream::Entry &E) {
3438+
DD.emitDebugLocEntryLocation(E, List.CU);
3439+
});
34263440
}
34273441

34283442
void DwarfDebug::emitDebugLocImpl(MCSection *Sec) {
@@ -3644,8 +3658,8 @@ static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm,
36443658
const RangeSpanList &List) {
36453659
emitRangeList(DD, Asm, List.Label, List.Ranges, *List.CU,
36463660
dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,
3647-
dwarf::DW_RLE_startx_length, dwarf::DW_RLE_end_of_list,
3648-
llvm::dwarf::RangeListEncodingString,
3661+
dwarf::DW_RLE_startx_length, dwarf::DW_RLE_startx_endx,
3662+
dwarf::DW_RLE_end_of_list, llvm::dwarf::RangeListEncodingString,
36493663
List.CU->getCUNode()->getRangesBaseAddress() ||
36503664
DD.getDwarfVersion() >= 5,
36513665
[](auto) {});

llvm/lib/MC/MCSymbol.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,21 @@ void MCSymbol::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
8484
}
8585

8686
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
87-
LLVM_DUMP_METHOD void MCSymbol::dump() const {
88-
dbgs() << *this;
89-
}
87+
LLVM_DUMP_METHOD void MCSymbol::dump() const { dbgs() << *this; }
9088
#endif
89+
90+
// Determine whether the offset between two labels can change at link time.
91+
// Currently, this function is used only in DWARF info emission logic, where it
92+
// helps generate more optimal debug info when the offset between labels is
93+
// constant at link time.
94+
bool llvm::isRangeRelaxable(const MCSymbol *Begin, const MCSymbol *End) {
95+
assert(Begin && "Range without a begin symbol?");
96+
assert(End && "Range without an end symbol?");
97+
for (const auto *Fragment = Begin->getFragment();
98+
Fragment != End->getFragment(); Fragment = Fragment->getNext()) {
99+
assert(Fragment);
100+
if (Fragment->isLinkerRelaxable())
101+
return true;
102+
}
103+
return false;
104+
}

0 commit comments

Comments
 (0)