Skip to content

Commit cf53e62

Browse files
author
Alex B
committed
[DebugInfo] Add subprogram attr pointing to its line entries
1 parent 3864bfd commit cf53e62

File tree

7 files changed

+108
-9
lines changed

7 files changed

+108
-9
lines changed

llvm/include/llvm/BinaryFormat/Dwarf.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,8 @@ HANDLE_DW_AT(0x2904, GO_runtime_type, 0, GO)
578578

579579
HANDLE_DW_AT(0x3210, UPC_threads_scaled, 0, UPC)
580580

581+
HANDLE_DW_AT(0x3600, META_stmt_sequence, 0, META)
582+
581583
HANDLE_DW_AT(0x393e, IBM_wsa_addr, 0, IBM)
582584
HANDLE_DW_AT(0x393f, IBM_home_location, 0, IBM)
583585
HANDLE_DW_AT(0x3940, IBM_alt_srcview, 0, IBM)

llvm/include/llvm/BinaryFormat/Dwarf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum LLVMConstants : uint32_t {
8484
DWARF_VENDOR_PGI,
8585
DWARF_VENDOR_SUN,
8686
DWARF_VENDOR_UPC,
87+
DWARF_VENDOR_META,
8788
///\}
8889
};
8990

llvm/include/llvm/MC/MCDwarf.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ class MCDwarfLoc {
122122
private: // MCContext manages these
123123
friend class MCContext;
124124
friend class MCDwarfLineEntry;
125+
// DwarfDebug::endFunctionImpl needs to construct MCDwarfLoc(IsEndOfFunction)
126+
friend class DwarfDebug;
125127

126128
MCDwarfLoc(unsigned fileNum, unsigned line, unsigned column, unsigned flags,
127129
unsigned isa, unsigned discriminator)
@@ -194,14 +196,27 @@ class MCDwarfLineEntry : public MCDwarfLoc {
194196

195197
public:
196198
// Constructor to create an MCDwarfLineEntry given a symbol and the dwarf loc.
197-
MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc)
198-
: MCDwarfLoc(loc), Label(label) {}
199+
MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc,
200+
bool isEndOfFunction = false,
201+
MCSymbol *streamLabel = nullptr)
202+
: MCDwarfLoc(loc), Label(label), IsEndOfFunction(isEndOfFunction),
203+
StreamLabel(streamLabel) {}
199204

200205
MCSymbol *getLabel() const { return Label; }
201206

202207
// This indicates the line entry is synthesized for an end entry.
203208
bool IsEndEntry = false;
204209

210+
// This indicates that the current line entry denotes the end of a function,
211+
// it is used to emit a DW_LNE_end_sequnece to reset the state machine
212+
// registers.
213+
bool IsEndOfFunction;
214+
215+
// Optional symbol to be emitted just before the line is written into the
216+
// output stream. It can be used to reference the position of the start of
217+
// this line's data in the output stream.
218+
MCSymbol *StreamLabel;
219+
205220
// Override the label with the given EndLabel.
206221
void setEndLabel(MCSymbol *EndLabel) {
207222
Label = EndLabel;
@@ -227,7 +242,7 @@ class MCLineSection {
227242

228243
// Add an end entry by cloning the last entry, if exists, for the section
229244
// the given EndLabel belongs to. The label is replaced by the given EndLabel.
230-
void addEndEntry(MCSymbol *EndLabel);
245+
void addEndEntry(MCSymbol *EndLabel, bool generatingFuncLineTableOffsets);
231246

232247
using MCDwarfLineEntryCollection = std::vector<MCDwarfLineEntry>;
233248
using iterator = MCDwarfLineEntryCollection::iterator;

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,15 @@ class MCStreamer {
254254
/// discussion for future inclusion.
255255
bool AllowAutoPadding = false;
256256

257+
// Flag specyfing weather functions will have an offset into the line table
258+
// where the line data for that function starts
259+
bool GenerateFuncLineTableOffsets = false;
260+
261+
// Symbol that tracks the stream symbol for first line of the current function
262+
// being generated. This symbol can be used to reference where the line
263+
// entries for the function start in the generated line table.
264+
MCSymbol *CurrentFuncFirstLineStreamSym;
265+
257266
protected:
258267
MCStreamer(MCContext &Ctx);
259268

@@ -310,6 +319,24 @@ class MCStreamer {
310319
void setAllowAutoPadding(bool v) { AllowAutoPadding = v; }
311320
bool getAllowAutoPadding() const { return AllowAutoPadding; }
312321

322+
void setGenerateFuncLineTableOffsets(bool v) {
323+
GenerateFuncLineTableOffsets = v;
324+
}
325+
bool getGenerateFuncLineTableOffsets() const {
326+
return GenerateFuncLineTableOffsets;
327+
}
328+
329+
// Use the below functions to track the symbol that points to the current
330+
// function's line info in the output stream.
331+
void beginFunction() { CurrentFuncFirstLineStreamSym = nullptr; }
332+
void emittedLineStreamSym(MCSymbol *StreamSym) {
333+
if (!CurrentFuncFirstLineStreamSym)
334+
CurrentFuncFirstLineStreamSym = StreamSym;
335+
}
336+
MCSymbol *getCurrentFuncFirstLineStreamSym() {
337+
return CurrentFuncFirstLineStreamSym;
338+
}
339+
313340
/// When emitting an object file, create and emit a real label. When emitting
314341
/// textual assembly, this should do nothing to avoid polluting our output.
315342
virtual MCSymbol *emitCFILabel();

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,14 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
526526
*DD->getCurrentFunction()))
527527
addFlag(*SPDie, dwarf::DW_AT_APPLE_omit_frame_ptr);
528528

529+
if (Asm->OutStreamer->getGenerateFuncLineTableOffsets() &&
530+
Asm->OutStreamer->getCurrentFuncFirstLineStreamSym()) {
531+
addSectionLabel(
532+
*SPDie, dwarf::DW_AT_META_stmt_sequence,
533+
Asm->OutStreamer->getCurrentFuncFirstLineStreamSym(),
534+
Asm->getObjFileLowering().getDwarfLineSection()->getBeginSymbol());
535+
}
536+
529537
// Only include DW_AT_frame_base in full debug info
530538
if (!includeMinimalInlineScopes()) {
531539
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();

llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ static cl::opt<DwarfDebug::MinimizeAddrInV5> MinimizeAddrInV5Option(
170170
"Stuff")),
171171
cl::init(DwarfDebug::MinimizeAddrInV5::Default));
172172

173+
static cl::opt<bool> EmitFuncLineTableOffsetsOption(
174+
"emit-func-debug-line-table-offsets", cl::Hidden,
175+
cl::desc("Include line table offset in function's debug info and emit end "
176+
"sequence after each function's line data."),
177+
cl::init(false));
178+
173179
static constexpr unsigned ULEB128PadSize = 4;
174180

175181
void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) {
@@ -440,6 +446,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A)
440446
Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
441447
Asm->OutStreamer->getContext().setDwarfFormat(Dwarf64 ? dwarf::DWARF64
442448
: dwarf::DWARF32);
449+
Asm->OutStreamer->setGenerateFuncLineTableOffsets(
450+
EmitFuncLineTableOffsetsOption);
443451
}
444452

445453
// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h.
@@ -2222,6 +2230,10 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) {
22222230
if (SP->getUnit()->getEmissionKind() == DICompileUnit::NoDebug)
22232231
return;
22242232

2233+
// Notify the streamer that we are beginning a function - this will reset the
2234+
// label pointing to the currently generated function's first line entry
2235+
Asm->OutStreamer->beginFunction();
2236+
22252237
DwarfCompileUnit &CU = getOrCreateDwarfCompileUnit(SP->getUnit());
22262238

22272239
Asm->OutStreamer->getContext().setDwarfCompileUnitID(
@@ -2250,7 +2262,8 @@ void DwarfDebug::terminateLineTable(const DwarfCompileUnit *CU) {
22502262
getDwarfCompileUnitIDForLineTable(*CU));
22512263
// Add the last range label for the given CU.
22522264
LineTable.getMCLineSections().addEndEntry(
2253-
const_cast<MCSymbol *>(CURanges.back().End));
2265+
const_cast<MCSymbol *>(CURanges.back().End),
2266+
EmitFuncLineTableOffsetsOption);
22542267
}
22552268

22562269
void DwarfDebug::skippedNonDebugFunction() {
@@ -2343,6 +2356,21 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
23432356
// Construct call site entries.
23442357
constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);
23452358

2359+
// If we're emitting line table offsets, we also need to emit an end label
2360+
// after all function's line entries
2361+
if (EmitFuncLineTableOffsetsOption) {
2362+
MCSymbol *LineSym = Asm->OutStreamer->getContext().createTempSymbol();
2363+
Asm->OutStreamer->emitLabel(LineSym);
2364+
MCDwarfLoc DwarfLoc(
2365+
1, 1, 0, DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0, 0, 0);
2366+
MCDwarfLineEntry LineEntry(LineSym, DwarfLoc, /*IsEndOfFunction*/ true);
2367+
Asm->OutStreamer->getContext()
2368+
.getMCDwarfLineTable(
2369+
Asm->OutStreamer->getContext().getDwarfCompileUnitID())
2370+
.getMCLineSections()
2371+
.addLineEntry(LineEntry, Asm->OutStreamer->getCurrentSectionOnly());
2372+
}
2373+
23462374
// Clear debug info
23472375
// Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the
23482376
// DbgVariables except those that are also in AbstractVariables (since they

llvm/lib/MC/MCDwarf.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,18 @@ void MCDwarfLineEntry::make(MCStreamer *MCOS, MCSection *Section) {
103103
// Get the current .loc info saved in the context.
104104
const MCDwarfLoc &DwarfLoc = MCOS->getContext().getCurrentDwarfLoc();
105105

106+
MCSymbol *StreamLabel = nullptr;
107+
// If functions need offsets into the generated line table, then we need to
108+
// create a label referencing where the line was generated in the output
109+
// stream
110+
if (MCOS->getGenerateFuncLineTableOffsets()) {
111+
StreamLabel = MCOS->getContext().createTempSymbol();
112+
MCOS->emittedLineStreamSym(StreamLabel);
113+
}
114+
106115
// Create a (local) line entry with the symbol and the current .loc info.
107-
MCDwarfLineEntry LineEntry(LineSym, DwarfLoc);
116+
MCDwarfLineEntry LineEntry(LineSym, DwarfLoc, /*isEndOfFunction=*/false,
117+
StreamLabel);
108118

109119
// clear DwarfLocSeen saying the current .loc info is now used.
110120
MCOS->getContext().clearDwarfLocSeen();
@@ -144,7 +154,8 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
144154
return Res;
145155
}
146156

147-
void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
157+
void MCLineSection::addEndEntry(MCSymbol *EndLabel,
158+
bool generatingFuncLineTableOffsets) {
148159
auto *Sec = &EndLabel->getSection();
149160
// The line table may be empty, which we should skip adding an end entry.
150161
// There are two cases:
@@ -157,8 +168,12 @@ void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
157168
if (I != MCLineDivisions.end()) {
158169
auto &Entries = I->second;
159170
auto EndEntry = Entries.back();
160-
EndEntry.setEndLabel(EndLabel);
161-
Entries.push_back(EndEntry);
171+
// If generatingFuncLineTableOffsets is set, then we already generated an
172+
// end label at the end of the last function, so skip generating another one
173+
if (!generatingFuncLineTableOffsets) {
174+
EndEntry.setEndLabel(EndLabel);
175+
Entries.push_back(EndEntry);
176+
}
162177
}
163178
}
164179

@@ -187,8 +202,11 @@ void MCDwarfLineTable::emitOne(
187202
bool EndEntryEmitted = false;
188203
for (const MCDwarfLineEntry &LineEntry : LineEntries) {
189204
MCSymbol *Label = LineEntry.getLabel();
205+
if (LineEntry.StreamLabel && MCOS->getGenerateFuncLineTableOffsets()) {
206+
MCOS->emitLabel(LineEntry.StreamLabel);
207+
}
190208
const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
191-
if (LineEntry.IsEndEntry) {
209+
if (LineEntry.IsEndEntry || LineEntry.IsEndOfFunction) {
192210
MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label,
193211
asmInfo->getCodePointerSize());
194212
init();

0 commit comments

Comments
 (0)