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