[codeview] Correctly handle inlining functions post-dominated by unreachable

CodeView requires us to accurately describe the extent of the inlined
code.  We did this by grabbing the next debug location in source order
and using *that* to denote where we stopped inlining.  However, this is
not sufficient or correct in instances where there is no next debug
location or the next debug location belongs to the start of another
function.

To get this correct, use the end symbol of the function to denote the
last possible place the inlining could have stopped at.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@259548 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Majnemer 2016-02-02 19:22:34 +00:00
parent d01172110e
commit b20745dd5e
13 changed files with 154 additions and 28 deletions

View File

@ -145,8 +145,11 @@ public:
}
ArrayRef<MCCVLineEntry> getLinesForExtent(size_t L, size_t R) {
size_t S = std::min(R, MCCVLines.size()) - L;
return makeArrayRef(&MCCVLines[L], S);
if (R <= L)
return None;
if (L >= MCCVLines.size())
return None;
return makeArrayRef(&MCCVLines[L], R - L);
}
/// Emits a line table substream.
@ -154,12 +157,10 @@ public:
const MCSymbol *FuncBegin,
const MCSymbol *FuncEnd);
void emitInlineLineTableForFunction(MCObjectStreamer &OS,
unsigned PrimaryFunctionId,
unsigned SourceFileId,
unsigned SourceLineNum,
const MCSymbol *FnStartSym,
ArrayRef<unsigned> SecondaryFunctionIds);
void emitInlineLineTableForFunction(
MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
unsigned SourceLineNum, const MCSymbol *FnStartSym,
const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds);
/// Encodes the binary annotations once we have a layout.
void encodeInlineLineTable(MCAsmLayout &Layout,

View File

@ -492,6 +492,7 @@ class MCCVInlineLineTableFragment : public MCFragment {
unsigned StartFileId;
unsigned StartLineNum;
const MCSymbol *FnStartSym;
const MCSymbol *FnEndSym;
SmallVector<unsigned, 3> SecondaryFuncs;
SmallString<8> Contents;
@ -502,11 +503,12 @@ class MCCVInlineLineTableFragment : public MCFragment {
public:
MCCVInlineLineTableFragment(unsigned SiteFuncId, unsigned StartFileId,
unsigned StartLineNum, const MCSymbol *FnStartSym,
const MCSymbol *FnEndSym,
ArrayRef<unsigned> SecondaryFuncs,
MCSection *Sec = nullptr)
: MCFragment(FT_CVInlineLines, false, 0, Sec), SiteFuncId(SiteFuncId),
StartFileId(StartFileId), StartLineNum(StartLineNum),
FnStartSym(FnStartSym),
FnStartSym(FnStartSym), FnEndSym(FnEndSym),
SecondaryFuncs(SecondaryFuncs.begin(), SecondaryFuncs.end()) {
Contents.push_back(0);
}
@ -515,6 +517,7 @@ public:
/// @{
const MCSymbol *getFnStartSym() const { return FnStartSym; }
const MCSymbol *getFnEndSym() const { return FnEndSym; }
SmallString<8> &getContents() { return Contents; }
const SmallString<8> &getContents() const { return Contents; }

View File

@ -129,7 +129,7 @@ public:
const MCSymbol *End) override;
void EmitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
const MCSymbol *FnStartSym,
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
ArrayRef<unsigned> SecondaryFunctionIds) override;
void EmitCVStringTableDirective() override;
void EmitCVFileChecksumsDirective() override;

View File

@ -659,7 +659,8 @@ public:
/// directive.
virtual void EmitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
const MCSymbol *FnStartSym, ArrayRef<unsigned> SecondaryFunctionIds);
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
ArrayRef<unsigned> SecondaryFunctionIds);
/// \brief This implements the CodeView '.cv_stringtable' assembler directive.
virtual void EmitCVStringTableDirective() {}

View File

@ -345,7 +345,7 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
collectInlineSiteChildren(SecondaryFuncIds, FI, Site);
OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
FI.Begin, SecondaryFuncIds);
FI.Begin, FI.End, SecondaryFuncIds);
OS.EmitLabel(InlineEnd);

View File

@ -207,7 +207,7 @@ public:
const MCSymbol *FnEnd) override;
void EmitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
const MCSymbol *FnStartSym,
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
ArrayRef<unsigned> SecondaryFunctionIds) override;
void EmitCVStringTableDirective() override;
void EmitCVFileChecksumsDirective() override;
@ -1020,10 +1020,13 @@ void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
void MCAsmStreamer::EmitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
const MCSymbol *FnStartSym, ArrayRef<unsigned> SecondaryFunctionIds) {
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
ArrayRef<unsigned> SecondaryFunctionIds) {
OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
<< ' ' << SourceLineNum << ' ';
FnStartSym->print(OS, MAI);
OS << ' ';
FnEndSym->print(OS, MAI);
if (!SecondaryFunctionIds.empty()) {
OS << " contains";
for (unsigned SecondaryFunctionId : SecondaryFunctionIds)
@ -1031,7 +1034,7 @@ void MCAsmStreamer::EmitCVInlineLinetableDirective(
}
EmitEOL();
this->MCStreamer::EmitCVInlineLinetableDirective(
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
SecondaryFunctionIds);
}

View File

@ -228,11 +228,11 @@ static uint32_t encodeSignedNumber(uint32_t Data) {
void CodeViewContext::emitInlineLineTableForFunction(
MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId,
unsigned SourceLineNum, const MCSymbol *FnStartSym,
ArrayRef<unsigned> SecondaryFunctionIds) {
const MCSymbol *FnEndSym, ArrayRef<unsigned> SecondaryFunctionIds) {
// Create and insert a fragment into the current section that will be encoded
// later.
new MCCVInlineLineTableFragment(
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
SecondaryFunctionIds, OS.getCurrentSectionOnly());
}
@ -265,7 +265,7 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
}
if (LocBegin >= LocEnd)
return;
ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd + 1);
ArrayRef<MCCVLineEntry> Locs = getLinesForExtent(LocBegin, LocEnd);
if (Locs.empty())
return;
@ -331,6 +331,19 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout,
LastLoc = &Loc;
}
assert(WithinFunction);
unsigned EndSymLength =
computeLabelDiff(Layout, LastLoc->getLabel(), Frag.getFnEndSym());
unsigned LocAfterLength = ~0U;
ArrayRef<MCCVLineEntry> LocAfter = getLinesForExtent(LocEnd, LocEnd + 1);
if (!LocAfter.empty())
LocAfterLength =
computeLabelDiff(Layout, LastLoc->getLabel(), LocAfter[0].getLabel());
compressAnnotation(ChangeCodeLength, Buffer);
compressAnnotation(std::min(EndSymLength, LocAfterLength), Buffer);
}
//

View File

@ -386,12 +386,13 @@ void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
void MCObjectStreamer::EmitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
const MCSymbol *FnStartSym, ArrayRef<unsigned> SecondaryFunctionIds) {
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
ArrayRef<unsigned> SecondaryFunctionIds) {
getContext().getCVContext().emitInlineLineTableForFunction(
*this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
SecondaryFunctionIds);
FnEndSym, SecondaryFunctionIds);
this->MCStreamer::EmitCVInlineLinetableDirective(
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym,
SecondaryFunctionIds);
}

View File

@ -3229,7 +3229,7 @@ bool AsmParser::parseDirectiveCVLinetable() {
}
/// parseDirectiveCVInlineLinetable
/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart
/// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
/// ("contains" SecondaryFunctionId+)?
bool AsmParser::parseDirectiveCVInlineLinetable() {
int64_t PrimaryFunctionId = getTok().getIntVal();
@ -3256,6 +3256,12 @@ bool AsmParser::parseDirectiveCVInlineLinetable() {
return Error(Loc, "expected identifier in directive");
MCSymbol *FnStartSym = getContext().getOrCreateSymbol(FnStartName);
Loc = getLexer().getLoc();
StringRef FnEndName;
if (parseIdentifier(FnEndName))
return Error(Loc, "expected identifier in directive");
MCSymbol *FnEndSym = getContext().getOrCreateSymbol(FnEndName);
SmallVector<unsigned, 8> SecondaryFunctionIds;
if (getLexer().is(AsmToken::Identifier)) {
if (getTok().getIdentifier() != "contains")
@ -3276,7 +3282,7 @@ bool AsmParser::parseDirectiveCVInlineLinetable() {
getStreamer().EmitCVInlineLinetableDirective(PrimaryFunctionId, SourceFileId,
SourceLineNum, FnStartSym,
SecondaryFunctionIds);
FnEndSym, SecondaryFunctionIds);
return false;
}

View File

@ -198,7 +198,8 @@ void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId,
void MCStreamer::EmitCVInlineLinetableDirective(
unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
const MCSymbol *FnStartSym, ArrayRef<unsigned> SecondaryFunctionIds) {}
const MCSymbol *FnStartSym, const MCSymbol *FnEndSym,
ArrayRef<unsigned> SecondaryFunctionIds) {}
void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol,
MCSymbol *EHSymbol) {

View File

@ -56,10 +56,10 @@
; ASM: .long Ltmp3-Ltmp2
; ASM: .short 4429
; ASM: .asciz
; ASM: .cv_inline_linetable 1 1 8 Lfunc_begin0 contains 2
; ASM: .cv_inline_linetable 1 1 8 Lfunc_begin0 Lfunc_end0 contains 2
; ASM: .short 4429
; ASM: .asciz
; ASM: .cv_inline_linetable 2 1 2 Lfunc_begin0
; ASM: .cv_inline_linetable 2 1 2 Lfunc_begin0 Lfunc_end0
; ASM: .short 4430
; ASM: .short 4430

View File

@ -0,0 +1,97 @@
# RUN: llvm-mc -triple=i686-pc-win32 -filetype=obj < %s | llvm-readobj -codeview | FileCheck %s
.text
.def @feat.00;
.scl 3;
.type 0;
.endef
.globl @feat.00
@feat.00 = 1
.def _g;
.scl 2;
.type 32;
.endef
.globl _g
.p2align 4, 0x90
_g: # @g
Lfunc_begin0:
.cv_file 1 "\\usr\\local\\google\\home\\majnemer\\llvm\\src\\<stdin>"
.cv_loc 0 1 7 0 is_stmt 0 # <stdin>:7:0
# BB#0: # %entry
pushl %ebp
movl %esp, %ebp
.cv_loc 1 1 4 3 # <stdin>:4:3
movl _x, %eax
addl $1, %eax
movl %eax, _x
Lfunc_end0:
.comm _x,4,2 # @x
.section .debug$T,"dr"
.long 4
.short 6
.short 4609
.long 0
.short 14
.short 4104
.asciz "\003\000\000\000\000\000\000\000\000\020\000"
.short 12
.short 5633
.asciz "\000\000\000\000\001\020\000"
.byte 103
.byte 0
.short 12
.short 5633
.asciz "\000\000\000\000\001\020\000"
.byte 102
.byte 0
.section .debug$S,"dr"
.long 4
.long 246 # Inlinee lines subsection
.long Ltmp1-Ltmp0
Ltmp0:
.long 0
.long 4099 # Inlined function f starts at <stdin>:3
.long 0
.long 3
Ltmp1:
.long 241 # Symbol subsection for g
.long Ltmp3-Ltmp2
Ltmp2:
.short Ltmp5-Ltmp4
Ltmp4:
.short 4423
.zero 12
.long Lfunc_end0-_g
.zero 12
.secrel32 _g
.secidx _g
.byte 0
.byte 103
.byte 0
Ltmp5:
.short Ltmp7-Ltmp6
Ltmp6:
.short 4429
.asciz "\000\000\000\000\000\000\000\000\003\020\000"
.cv_inline_linetable 1 1 3 Lfunc_begin0 Lfunc_end0
# CHECK: InlineSite {
# CHECK: PtrParent: 0x0
# CHECK: PtrEnd: 0x0
# CHECK: Inlinee: f (0x1003)
# CHECK: BinaryAnnotations [
# CHECK: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x3, LineOffset: 1}
# CHECK: ChangeCodeLength: 0xD
# CHECK: ]
# CHECK: }
Ltmp7:
.short 2
.short 4430
# CHECK: InlineSiteEnd {
# CHECK: }
.short 2
.short 4431
Ltmp3:
.p2align 2
.cv_linetable 0, _g, Lfunc_end0
.cv_filechecksums # File index to string table offset subsection
.cv_stringtable # String table

View File

@ -84,7 +84,7 @@ Ltmp3:
Ltmp4:
.short 4429
.asciz "\000\000\000\000\000\000\000\000\003\020\000"
.cv_inline_linetable 1 1 9 Lfunc_begin0 contains 2
.cv_inline_linetable 1 1 9 Lfunc_begin0 Lfunc_end0 contains 2
# CHECK: InlineSite {
# CHECK: PtrParent: 0x0
# CHECK: PtrEnd: 0x0
@ -105,7 +105,7 @@ Ltmp5:
Ltmp6:
.short 4429
.asciz "\000\000\000\000\000\000\000\000\004\020\000"
.cv_inline_linetable 2 1 3 Lfunc_begin0
.cv_inline_linetable 2 1 3 Lfunc_begin0 Lfunc_end0
# CHECK: InlineSite {
# CHECK: PtrParent: 0x0
# CHECK: PtrEnd: 0x0