From b20745dd5e2029f8c5cc64f16c3d865c6771cecb Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Tue, 2 Feb 2016 19:22:34 +0000 Subject: [PATCH] [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 --- include/llvm/MC/MCCodeView.h | 17 ++-- include/llvm/MC/MCFragment.h | 5 +- include/llvm/MC/MCObjectStreamer.h | 2 +- include/llvm/MC/MCStreamer.h | 3 +- lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 2 +- lib/MC/MCAsmStreamer.cpp | 9 +- lib/MC/MCCodeView.cpp | 19 +++- lib/MC/MCObjectStreamer.cpp | 7 +- lib/MC/MCParser/AsmParser.cpp | 10 +- lib/MC/MCStreamer.cpp | 3 +- test/DebugInfo/COFF/inlining.ll | 4 +- .../MC/COFF/cv-inline-linetable-unreachable.s | 97 +++++++++++++++++++ test/MC/COFF/cv-inline-linetable.s | 4 +- 13 files changed, 154 insertions(+), 28 deletions(-) create mode 100644 test/MC/COFF/cv-inline-linetable-unreachable.s diff --git a/include/llvm/MC/MCCodeView.h b/include/llvm/MC/MCCodeView.h index 71096bc1a5c..22cf94f45c7 100644 --- a/include/llvm/MC/MCCodeView.h +++ b/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/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h index 3d7d1b84a00..a7548be6a97 100644 --- a/include/llvm/MC/MCFragment.h +++ b/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/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index cf0ee5d4a42..6a4ee8c363c 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/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/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 7fd4277f753..8c4d4eef506 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/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/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index de12fc38138..7bded31271a 100644 --- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/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/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 712b7a938be..9fcfcf76756 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/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/lib/MC/MCCodeView.cpp b/lib/MC/MCCodeView.cpp index ea226f7769e..81597f6c145 100644 --- a/lib/MC/MCCodeView.cpp +++ b/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/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 4d849049f60..40c2e8dab9f 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/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/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 9f8027a381e..2db7504b377 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/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/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index dcb01b4d119..8ee41261d59 100644 --- a/lib/MC/MCStreamer.cpp +++ b/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/test/DebugInfo/COFF/inlining.ll b/test/DebugInfo/COFF/inlining.ll index fafc224022e..6f5650a3ad4 100644 --- a/test/DebugInfo/COFF/inlining.ll +++ b/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/test/MC/COFF/cv-inline-linetable-unreachable.s b/test/MC/COFF/cv-inline-linetable-unreachable.s new file mode 100644 index 00000000000..eb89dd51927 --- /dev/null +++ b/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/test/MC/COFF/cv-inline-linetable.s b/test/MC/COFF/cv-inline-linetable.s index 222a0859db5..22aa48f8bc8 100644 --- a/test/MC/COFF/cv-inline-linetable.s +++ b/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