Skip to content

Commit f2f36c9

Browse files
committed
Emit line numbers in CodeView for trailing (after ret) blocks from inlined functions
Issue Details: When building up line information for CodeView debug info, LLVM attempts to gather the "range" of instructions within a function as these are printed together in a single record. If there is an inlined function, then those lines are attributed to the original function to enable generating `S_INLINESITE` records. However, this thus requires there to be instructions from the inlining function after the inlined function otherwise the instruction range would not include the inlined function. Fix Details: Include any inlined functions when finding the extent of a function in `getFunctionLineEntries` Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D159226
1 parent c39edd7 commit f2f36c9

File tree

4 files changed

+380
-39
lines changed

4 files changed

+380
-39
lines changed

lld/test/COFF/symbolizer-line-numbers.s

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,16 @@
6262
# CHECK: f1
6363
# CHECK-NEXT: t.cpp:2:0
6464
# CHECK-NEXT: f2(int)
65-
# CHECK-NEXT: t.cpp:6:3
65+
# CHECK-NEXT: t.cpp:6:10
6666
.cv_inline_site_id 2 within 1 inlined_at 1 6 10
6767
.cv_loc 2 1 2 13 # t.cpp:2:13
6868
# kill: def $ecx killed $ecx def $rcx
6969
leal 1(%rcx), %eax
7070
.Ltmp1:
71-
.cv_loc 1 1 6 3 # t.cpp:6:3
72-
retq
7371
# CHECK: f2(int)
7472
# CHECK-NEXT: t.cpp:6:3
73+
.cv_loc 1 1 6 3 # t.cpp:6:3
74+
retq
7575
.Ltmp2:
7676
.Lfunc_end1:
7777
# -- End function

llvm/include/llvm/MC/MCCodeView.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ class CodeViewContext {
182182
std::vector<MCCVLoc> getFunctionLineEntries(unsigned FuncId);
183183

184184
std::pair<size_t, size_t> getLineExtent(unsigned FuncId);
185+
std::pair<size_t, size_t> getLineExtentIncludingInlinees(unsigned FuncId);
185186

186187
ArrayRef<MCCVLoc> getLinesForExtent(size_t L, size_t R);
187188

llvm/lib/MC/MCCodeView.cpp

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -275,32 +275,35 @@ void CodeViewContext::addLineEntry(const MCCVLoc &LineEntry) {
275275
std::vector<MCCVLoc>
276276
CodeViewContext::getFunctionLineEntries(unsigned FuncId) {
277277
std::vector<MCCVLoc> FilteredLines;
278-
auto I = MCCVLineStartStop.find(FuncId);
279-
if (I != MCCVLineStartStop.end()) {
280-
MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(FuncId);
281-
for (size_t Idx = I->second.first, End = I->second.second; Idx != End;
282-
++Idx) {
283-
unsigned LocationFuncId = MCCVLines[Idx].getFunctionId();
284-
if (LocationFuncId == FuncId) {
285-
// This was a .cv_loc directly for FuncId, so record it.
286-
FilteredLines.push_back(MCCVLines[Idx]);
287-
} else {
288-
// Check if the current location is inlined in this function. If it is,
289-
// synthesize a statement .cv_loc at the original inlined call site.
290-
auto I = SiteInfo->InlinedAtMap.find(LocationFuncId);
291-
if (I != SiteInfo->InlinedAtMap.end()) {
292-
MCCVFunctionInfo::LineInfo &IA = I->second;
293-
// Only add the location if it differs from the previous location.
294-
// Large inlined calls will have many .cv_loc entries and we only need
295-
// one line table entry in the parent function.
296-
if (FilteredLines.empty() ||
297-
FilteredLines.back().getFileNum() != IA.File ||
298-
FilteredLines.back().getLine() != IA.Line ||
299-
FilteredLines.back().getColumn() != IA.Col) {
300-
FilteredLines.push_back(MCCVLoc(
301-
MCCVLines[Idx].getLabel(),
302-
FuncId, IA.File, IA.Line, IA.Col, false, false));
303-
}
278+
size_t LocBegin;
279+
size_t LocEnd;
280+
std::tie(LocBegin, LocEnd) = getLineExtentIncludingInlinees(FuncId);
281+
if (LocBegin >= LocEnd) {
282+
return FilteredLines;
283+
}
284+
285+
MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(FuncId);
286+
for (size_t Idx = LocBegin; Idx != LocEnd; ++Idx) {
287+
unsigned LocationFuncId = MCCVLines[Idx].getFunctionId();
288+
if (LocationFuncId == FuncId) {
289+
// This was a .cv_loc directly for FuncId, so record it.
290+
FilteredLines.push_back(MCCVLines[Idx]);
291+
} else {
292+
// Check if the current location is inlined in this function. If it is,
293+
// synthesize a statement .cv_loc at the original inlined call site.
294+
auto I = SiteInfo->InlinedAtMap.find(LocationFuncId);
295+
if (I != SiteInfo->InlinedAtMap.end()) {
296+
MCCVFunctionInfo::LineInfo &IA = I->second;
297+
// Only add the location if it differs from the previous location.
298+
// Large inlined calls will have many .cv_loc entries and we only need
299+
// one line table entry in the parent function.
300+
if (FilteredLines.empty() ||
301+
FilteredLines.back().getFileNum() != IA.File ||
302+
FilteredLines.back().getLine() != IA.Line ||
303+
FilteredLines.back().getColumn() != IA.Col) {
304+
FilteredLines.push_back(MCCVLoc(MCCVLines[Idx].getLabel(), FuncId,
305+
IA.File, IA.Line, IA.Col, false,
306+
false));
304307
}
305308
}
306309
}
@@ -316,6 +319,26 @@ std::pair<size_t, size_t> CodeViewContext::getLineExtent(unsigned FuncId) {
316319
return I->second;
317320
}
318321

322+
std::pair<size_t, size_t>
323+
CodeViewContext::getLineExtentIncludingInlinees(unsigned FuncId) {
324+
size_t LocBegin;
325+
size_t LocEnd;
326+
std::tie(LocBegin, LocEnd) = getLineExtent(FuncId);
327+
328+
// Include all child inline call sites in our extent.
329+
MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(FuncId);
330+
if (SiteInfo) {
331+
for (auto &KV : SiteInfo->InlinedAtMap) {
332+
unsigned ChildId = KV.first;
333+
auto Extent = getLineExtent(ChildId);
334+
LocBegin = std::min(LocBegin, Extent.first);
335+
LocEnd = std::max(LocEnd, Extent.second);
336+
}
337+
}
338+
339+
return {LocBegin, LocEnd};
340+
}
341+
319342
ArrayRef<MCCVLoc> CodeViewContext::getLinesForExtent(size_t L, size_t R) {
320343
if (R <= L)
321344
return std::nullopt;
@@ -463,16 +486,7 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
463486
MCCVInlineLineTableFragment &Frag) {
464487
size_t LocBegin;
465488
size_t LocEnd;
466-
std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId);
467-
468-
// Include all child inline call sites in our .cv_loc extent.
469-
MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId);
470-
for (auto &KV : SiteInfo->InlinedAtMap) {
471-
unsigned ChildId = KV.first;
472-
auto Extent = getLineExtent(ChildId);
473-
LocBegin = std::min(LocBegin, Extent.first);
474-
LocEnd = std::max(LocEnd, Extent.second);
475-
}
489+
std::tie(LocBegin, LocEnd) = getLineExtentIncludingInlinees(Frag.SiteFuncId);
476490

477491
if (LocBegin >= LocEnd)
478492
return;
@@ -507,6 +521,8 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
507521
LastSourceLoc.File = Frag.StartFileId;
508522
LastSourceLoc.Line = Frag.StartLineNum;
509523

524+
MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId);
525+
510526
SmallVectorImpl<char> &Buffer = Frag.getContents();
511527
Buffer.clear(); // Clear old contents if we went through relaxation.
512528
for (const MCCVLoc &Loc : Locs) {

0 commit comments

Comments
 (0)