From: David Majnemer Date: Tue, 2 Feb 2016 19:22:34 +0000 (+0000) Subject: [codeview] Correctly handle inlining functions post-dominated by unreachable X-Git-Tag: llvmorg-3.9.0-rc1~15313 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9911f28e5a8060a439aa475e0a95793b1b1e970;p=platform%2Fupstream%2Fllvm.git [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. llvm-svn: 259548 --- diff --git a/llvm/include/llvm/MC/MCCodeView.h b/llvm/include/llvm/MC/MCCodeView.h index 71096bc..22cf94f 100644 --- a/llvm/include/llvm/MC/MCCodeView.h +++ b/llvm/include/llvm/MC/MCCodeView.h @@ -145,8 +145,11 @@ public: } ArrayRef 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 SecondaryFunctionIds); + void emitInlineLineTableForFunction( + MCObjectStreamer &OS, unsigned PrimaryFunctionId, unsigned SourceFileId, + unsigned SourceLineNum, const MCSymbol *FnStartSym, + const MCSymbol *FnEndSym, ArrayRef SecondaryFunctionIds); /// Encodes the binary annotations once we have a layout. void encodeInlineLineTable(MCAsmLayout &Layout, diff --git a/llvm/include/llvm/MC/MCFragment.h b/llvm/include/llvm/MC/MCFragment.h index 3d7d1b8..a7548be 100644 --- a/llvm/include/llvm/MC/MCFragment.h +++ b/llvm/include/llvm/MC/MCFragment.h @@ -492,6 +492,7 @@ class MCCVInlineLineTableFragment : public MCFragment { unsigned StartFileId; unsigned StartLineNum; const MCSymbol *FnStartSym; + const MCSymbol *FnEndSym; SmallVector 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 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; } diff --git a/llvm/include/llvm/MC/MCObjectStreamer.h b/llvm/include/llvm/MC/MCObjectStreamer.h index cf0ee5d..6a4ee8c 100644 --- a/llvm/include/llvm/MC/MCObjectStreamer.h +++ b/llvm/include/llvm/MC/MCObjectStreamer.h @@ -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 SecondaryFunctionIds) override; void EmitCVStringTableDirective() override; void EmitCVFileChecksumsDirective() override; diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h index 7fd4277..8c4d4ee 100644 --- a/llvm/include/llvm/MC/MCStreamer.h +++ b/llvm/include/llvm/MC/MCStreamer.h @@ -659,7 +659,8 @@ public: /// directive. virtual void EmitCVInlineLinetableDirective( unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, - const MCSymbol *FnStartSym, ArrayRef SecondaryFunctionIds); + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef SecondaryFunctionIds); /// \brief This implements the CodeView '.cv_stringtable' assembler directive. virtual void EmitCVStringTableDirective() {} diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index de12fc3..7bded31 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -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); diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 712b7a9..9fcfcf7 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -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 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 SecondaryFunctionIds) { + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef 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); } diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index ea226f7..81597f6 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -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 SecondaryFunctionIds) { + const MCSymbol *FnEndSym, ArrayRef 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 Locs = getLinesForExtent(LocBegin, LocEnd + 1); + ArrayRef 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 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); } // diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 4d84904..40c2e8d 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -386,12 +386,13 @@ void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId, void MCObjectStreamer::EmitCVInlineLinetableDirective( unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, - const MCSymbol *FnStartSym, ArrayRef SecondaryFunctionIds) { + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef 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); } diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 9f8027a..2db7504 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -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 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; } diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp index dcb01b4..8ee41261 100644 --- a/llvm/lib/MC/MCStreamer.cpp +++ b/llvm/lib/MC/MCStreamer.cpp @@ -198,7 +198,8 @@ void MCStreamer::EmitCVLinetableDirective(unsigned FunctionId, void MCStreamer::EmitCVInlineLinetableDirective( unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, - const MCSymbol *FnStartSym, ArrayRef SecondaryFunctionIds) {} + const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, + ArrayRef SecondaryFunctionIds) {} void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { diff --git a/llvm/test/DebugInfo/COFF/inlining.ll b/llvm/test/DebugInfo/COFF/inlining.ll index fafc224..6f5650a 100644 --- a/llvm/test/DebugInfo/COFF/inlining.ll +++ b/llvm/test/DebugInfo/COFF/inlining.ll @@ -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 diff --git a/llvm/test/MC/COFF/cv-inline-linetable-unreachable.s b/llvm/test/MC/COFF/cv-inline-linetable-unreachable.s new file mode 100644 index 0000000..eb89dd51 --- /dev/null +++ b/llvm/test/MC/COFF/cv-inline-linetable-unreachable.s @@ -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\\" + .cv_loc 0 1 7 0 is_stmt 0 # :7:0 +# BB#0: # %entry + pushl %ebp + movl %esp, %ebp + .cv_loc 1 1 4 3 # :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 :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 diff --git a/llvm/test/MC/COFF/cv-inline-linetable.s b/llvm/test/MC/COFF/cv-inline-linetable.s index 222a085..22aa48f 100644 --- a/llvm/test/MC/COFF/cv-inline-linetable.s +++ b/llvm/test/MC/COFF/cv-inline-linetable.s @@ -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