aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCCodeView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCCodeView.cpp')
-rw-r--r--llvm/lib/MC/MCCodeView.cpp152
1 files changed, 106 insertions, 46 deletions
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp
index b955511..acea1ec 100644
--- a/llvm/lib/MC/MCCodeView.cpp
+++ b/llvm/lib/MC/MCCodeView.cpp
@@ -65,6 +65,50 @@ bool CodeViewContext::addFile(unsigned FileNumber, StringRef Filename) {
return true;
}
+bool CodeViewContext::recordFunctionId(unsigned FuncId) {
+ if (FuncId >= Functions.size())
+ Functions.resize(FuncId + 1);
+
+ // Return false if this function info was already allocated.
+ if (!Functions[FuncId].isUnallocatedFunctionInfo())
+ return false;
+
+ // Mark this as an allocated normal function, and leave the rest alone.
+ Functions[FuncId].ParentFuncIdPlusOne = MCCVFunctionInfo::FunctionSentinel;
+ return true;
+}
+
+bool CodeViewContext::recordInlinedCallSiteId(unsigned FuncId, unsigned IAFunc,
+ unsigned IAFile, unsigned IALine,
+ unsigned IACol) {
+ if (FuncId >= Functions.size())
+ Functions.resize(FuncId + 1);
+
+ // Return false if this function info was already allocated.
+ if (!Functions[FuncId].isUnallocatedFunctionInfo())
+ return false;
+
+ MCCVFunctionInfo::LineInfo InlinedAt;
+ InlinedAt.File = IAFile;
+ InlinedAt.Line = IALine;
+ InlinedAt.Col = IACol;
+
+ // Mark this as an inlined call site and record call site line info.
+ MCCVFunctionInfo *Info = &Functions[FuncId];
+ Info->ParentFuncIdPlusOne = IAFunc + 1;
+ Info->InlinedAt = InlinedAt;
+
+ // Walk up the call chain adding this function id to the InlinedAtMap of all
+ // transitive callers until we hit a real function.
+ while (Info->isInlinedCallSite()) {
+ InlinedAt = Info->InlinedAt;
+ Info = getCVFunctionInfo(Info->getParentFuncId());
+ Info->InlinedAtMap[FuncId] = InlinedAt;
+ }
+
+ return true;
+}
+
MCDataFragment *CodeViewContext::getStringTableFragment() {
if (!StrTabFragment) {
StrTabFragment = new MCDataFragment();
@@ -237,15 +281,17 @@ static uint32_t encodeSignedNumber(uint32_t Data) {
return Data << 1;
}
-void CodeViewContext::emitInlineLineTableForFunction(
- MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
- unsigned SourceLineNum, const MCSymbol *FnStartSym,
- const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds) {
+void CodeViewContext::emitInlineLineTableForFunction(MCObjectStreamer &OS,
+ unsigned PrimaryFunctionId,
+ unsigned SourceFileId,
+ unsigned SourceLineNum,
+ const MCSymbol *FnStartSym,
+ const MCSymbol *FnEndSym) {
// Create and insert a fragment into the current section that will be encoded
// later.
- new MCCVInlineLineTableFragment(
- PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
- SecondaryFunctionIds, OS.getCurrentSectionOnly());
+ new MCCVInlineLineTableFragment(PrimaryFunctionId, SourceFileId,
+ SourceLineNum, FnStartSym, FnEndSym,
+ OS.getCurrentSectionOnly());
}
void CodeViewContext::emitDefRange(
@@ -280,69 +326,83 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
size_t LocBegin;
size_t LocEnd;
std::tie(LocBegin, LocEnd) = getLineExtent(Frag.SiteFuncId);
- for (unsigned SecondaryId : Frag.SecondaryFuncs) {
- auto Extent = getLineExtent(SecondaryId);
+
+ // Include all child inline call sites in our .cv_loc extent.
+ MCCVFunctionInfo *SiteInfo = getCVFunctionInfo(Frag.SiteFuncId);
+ for (auto &KV : SiteInfo->InlinedAtMap) {
+ unsigned ChildId = KV.first;
+ auto Extent = getLineExtent(ChildId);
LocBegin = std::min(LocBegin, Extent.first);
LocEnd = std::max(LocEnd, Extent.second);
}
+
if (LocBegin >= LocEnd)
return;
ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
if (Locs.empty())
return;
- SmallSet<unsigned, 8> InlinedFuncIds;
- InlinedFuncIds.insert(Frag.SiteFuncId);
- InlinedFuncIds.insert(Frag.SecondaryFuncs.begin(), Frag.SecondaryFuncs.end());
-
// Make an artificial start location using the function start and the inlinee
// lines start location information. All deltas start relative to this
// location.
MCCVLineEntry StartLoc(Frag.getFnStartSym(), MCCVLoc(Locs.front()));
StartLoc.setFileNum(Frag.StartFileId);
StartLoc.setLine(Frag.StartLineNum);
- const MCCVLineEntry *LastLoc = &StartLoc;
bool HaveOpenRange = false;
+ const MCSymbol *LastLabel = Frag.getFnStartSym();
+ MCCVFunctionInfo::LineInfo LastSourceLoc, CurSourceLoc;
+ LastSourceLoc.File = Frag.StartFileId;
+ LastSourceLoc.Line = Frag.StartLineNum;
+
SmallVectorImpl<char> &Buffer = Frag.getContents();
Buffer.clear(); // Clear old contents if we went through relaxation.
for (const MCCVLineEntry &Loc : Locs) {
- if (!InlinedFuncIds.count(Loc.getFunctionId())) {
- // We've hit a cv_loc not attributed to this inline call site. Use this
- // label to end the PC range.
- if (HaveOpenRange) {
- unsigned Length =
- computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
- compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
- compressAnnotation(Length, Buffer);
+ if (Loc.getFunctionId() == Frag.SiteFuncId) {
+ CurSourceLoc.File = Loc.getFileNum();
+ CurSourceLoc.Line = Loc.getLine();
+ } else {
+ auto I = SiteInfo->InlinedAtMap.find(Loc.getFunctionId());
+ if (I != SiteInfo->InlinedAtMap.end()) {
+ // This .cv_loc is from a child inline call site. Use the source
+ // location of the inlined call site instead of the .cv_loc directive
+ // source location.
+ CurSourceLoc = I->second;
+ } else {
+ // We've hit a cv_loc not attributed to this inline call site. Use this
+ // label to end the PC range.
+ if (HaveOpenRange) {
+ unsigned Length = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
+ compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);
+ compressAnnotation(Length, Buffer);
+ LastLabel = Loc.getLabel();
+ }
+ HaveOpenRange = false;
+ continue;
}
- HaveOpenRange = false;
- continue;
}
- // If we've already opened the function and we're at an indirectly inlined
- // location, continue until the next directly inlined location.
- bool DirectlyInlined = Loc.getFunctionId() == Frag.SiteFuncId;
- if (!DirectlyInlined && HaveOpenRange)
+ // Skip this .cv_loc if we have an open range and this isn't a meaningful
+ // source location update. The current table format does not support column
+ // info, so we can skip updates for those.
+ if (HaveOpenRange && CurSourceLoc.File == LastSourceLoc.File &&
+ CurSourceLoc.Line == LastSourceLoc.Line)
continue;
+
HaveOpenRange = true;
- if (Loc.getFileNum() != LastLoc->getFileNum()) {
+ if (CurSourceLoc.File != LastSourceLoc.File) {
// File ids are 1 based, and each file checksum table entry is 8 bytes
// long. See emitFileChecksums above.
- unsigned FileOffset = 8 * (Loc.getFileNum() - 1);
+ unsigned FileOffset = 8 * (CurSourceLoc.File - 1);
compressAnnotation(BinaryAnnotationsOpCode::ChangeFile, Buffer);
compressAnnotation(FileOffset, Buffer);
}
- int LineDelta = Loc.getLine() - LastLoc->getLine();
- if (LineDelta == 0)
- continue;
-
+ int LineDelta = CurSourceLoc.Line - LastSourceLoc.Line;
unsigned EncodedLineDelta = encodeSignedNumber(LineDelta);
- unsigned CodeDelta =
- computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
- if (CodeDelta == 0) {
+ unsigned CodeDelta = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
+ if (CodeDelta == 0 && LineDelta != 0) {
compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
compressAnnotation(EncodedLineDelta, Buffer);
} else if (EncodedLineDelta < 0x8 && CodeDelta <= 0xf) {
@@ -355,29 +415,29 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
compressAnnotation(Operand, Buffer);
} else {
// Otherwise use the separate line and code deltas.
- compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
- compressAnnotation(EncodedLineDelta, Buffer);
+ if (LineDelta != 0) {
+ compressAnnotation(BinaryAnnotationsOpCode::ChangeLineOffset, Buffer);
+ compressAnnotation(EncodedLineDelta, Buffer);
+ }
compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeOffset, Buffer);
compressAnnotation(CodeDelta, Buffer);
}
- LastLoc = &Loc;
+ LastLabel = Loc.getLabel();
+ LastSourceLoc = CurSourceLoc;
}
assert(HaveOpenRange);
unsigned EndSymLength =
- computeLabelDiff(Layout, LastLoc->getLabel(), Frag.getFnEndSym());
+ computeLabelDiff(Layout, LastLabel, Frag.getFnEndSym());
unsigned LocAfterLength = ~0U;
ArrayRef<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
if (!LocAfter.empty()) {
// Only try to compute this difference if we're in the same section.
const MCCVLineEntry &Loc = LocAfter[0];
- if (&Loc.getLabel()->getSection(false) ==
- &LastLoc->getLabel()->getSection(false)) {
- LocAfterLength =
- computeLabelDiff(Layout, LastLoc->getLabel(), Loc.getLabel());
- }
+ if (&Loc.getLabel()->getSection(false) == &LastLabel->getSection(false))
+ LocAfterLength = computeLabelDiff(Layout, LastLabel, Loc.getLabel());
}
compressAnnotation(BinaryAnnotationsOpCode::ChangeCodeLength, Buffer);