diff options
author | Reid Kleckner <rnk@google.com> | 2018-04-25 23:34:15 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2018-04-25 23:34:15 +0000 |
commit | 2c6430fe3c2005a60680b72a52bfb4e81ca841ee (patch) | |
tree | 28e62f54a215254efc9790922a5cfed6861e7890 | |
parent | 947647d0c1fd9557f2dd8ddda3a15622da2c7f77 (diff) | |
download | bcm5719-llvm-2c6430fe3c2005a60680b72a52bfb4e81ca841ee.tar.gz bcm5719-llvm-2c6430fe3c2005a60680b72a52bfb4e81ca841ee.zip |
[codeview] Ignore .cv_loc directives at the end of a function
If no data or instructions are emitted after a location directive, we
should clear the cv_loc when we change sections, or it will be emitted
at the beginning of the next section. This violates our invariant that
all .cv_loc directives belong to the same section. Add clearer
assertions for this.
llvm-svn: 330884
-rw-r--r-- | llvm/include/llvm/MC/MCContext.h | 4 | ||||
-rw-r--r-- | llvm/lib/MC/MCCodeView.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/MC/MCContext.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 1 | ||||
-rw-r--r-- | llvm/test/MC/COFF/cv-loc-unreachable.s | 183 |
5 files changed, 206 insertions, 0 deletions
diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index c110ffd3a77..ca31f8aab2a 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -295,6 +295,10 @@ namespace llvm { CodeViewContext &getCVContext(); + /// Clear the current cv_loc, if there is one. Avoids lazily creating a + /// CodeViewContext if none is needed. + void clearCVLocSeen(); + void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; } diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp index 8247db1c622..7d79fc74c18 100644 --- a/llvm/lib/MC/MCCodeView.cpp +++ b/llvm/lib/MC/MCCodeView.cpp @@ -472,6 +472,19 @@ void CodeViewContext::encodeInlineLineTable(MCAsmLayout &Layout, if (Locs.empty()) return; + // Check that the locations are all in the same section. +#ifndef NDEBUG + const MCSection *FirstSec = &Locs.front().getLabel()->getSection(); + for (const MCCVLineEntry &Loc : Locs) { + if (&Loc.getLabel()->getSection() != FirstSec) { + errs() << ".cv_loc " << Loc.getFunctionId() << ' ' << Loc.getFileNum() + << ' ' << Loc.getLine() << ' ' << Loc.getColumn() + << " is in the wrong section\n"; + llvm_unreachable(".cv_loc crosses sections"); + } + } +#endif + // Make an artificial start location using the function start and the inlinee // lines start location information. All deltas start relative to this // location. diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 69c10f535e5..ac9259a4d24 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -570,6 +570,11 @@ CodeViewContext &MCContext::getCVContext() { return *CVContext.get(); } +void MCContext::clearCVLocSeen() { + if (CVContext) + CVContext->clearCVLocSeen(); +} + //===----------------------------------------------------------------------===// // Error Reporting //===----------------------------------------------------------------------===// diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index 0a684588110..316a3be8d89 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -247,6 +247,7 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); flushPendingLabels(nullptr); + getContext().clearCVLocSeen(); getContext().clearDwarfLocSeen(); bool Created = getAssembler().registerSection(*Section); diff --git a/llvm/test/MC/COFF/cv-loc-unreachable.s b/llvm/test/MC/COFF/cv-loc-unreachable.s new file mode 100644 index 00000000000..c91c4776074 --- /dev/null +++ b/llvm/test/MC/COFF/cv-loc-unreachable.s @@ -0,0 +1,183 @@ +# RUN: llvm-mc < %s -triple=i686-pc-win32 -filetype=obj | llvm-readobj - -codeview | FileCheck %s + +# Original source, slightly modified with an extra .cv_loc directive (at EXTRA +# below) that was causing assertions: +# +# void __declspec(noreturn) __declspec(dllimport) exit(int); +# int unlikely(); +# static inline void do_exit() { +# if (unlikely()) { +# exit(32); +# } +# } +# void callit() { +# do_exit(); +# } + +# We should *not* see t.cpp:6 in the inline line table because we change +# sections before the next instruction. We should only see t.cpp:5. + +# CHECK-LABEL: InlineeSourceLine { +# CHECK: Inlinee: do_exit (0x1002) +# CHECK: FileID: C:\src\llvm-project\build\t.cpp (0x0) +# CHECK: SourceLineNum: 3 +# CHECK: } + +# CHECK-LABEL: InlineSiteSym { +# CHECK: Kind: S_INLINESITE (0x114D) +# CHECK: Inlinee: do_exit (0x1002) +# CHECK: BinaryAnnotations [ +# CHECK-NEXT: ChangeLineOffset: 1 +# CHECK-NEXT: ChangeCodeLength: 0x9 +# CHECK-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x1, LineOffset: 1} +# CHECK-NEXT: ChangeCodeLength: 0x8 +# CHECK-NEXT: ] +# CHECK: } + + .text + .def _callit; .scl 2; .type 32; .endef + .globl _callit # -- Begin function callit +_callit: # @callit +Lfunc_begin0: + .cv_func_id 0 + .cv_fpo_proc _callit 0 +# %bb.0: # %entry + .cv_file 1 "C:\\src\\llvm-project\\build\\t.cpp" "0BC092F354CE14FDC2FA78F8EDE7426E" 1 + .cv_inline_site_id 1 within 0 inlined_at 1 9 0 + .cv_loc 1 1 4 0 is_stmt 0 # t.cpp:4:0 + calll _unlikely + testl %eax, %eax + jne LBB0_1 +Ltmp0: +# %bb.2: # %do_exit.exit + .cv_loc 0 1 10 0 # t.cpp:10:0 + retl +LBB0_1: # %if.then.i +Ltmp1: + .cv_loc 1 1 5 0 # t.cpp:5:0 + pushl $32 + calll *__imp__exit + # EXTRA + .cv_loc 1 1 6 0 # t.cpp:6:0 +Ltmp2: + .cv_fpo_endproc +Lfunc_end0: + # -- End function + + .section .debug$S,"dr" + .p2align 2 + .long 4 # Debug section magic + .long 241 + .long Ltmp4-Ltmp3 # Subsection size +Ltmp3: + .short Ltmp6-Ltmp5 # Record length +Ltmp5: + .short 4412 # Record kind: S_COMPILE3 + .long 0 # Flags and language + .short 7 # CPUType + .short 7 # Frontend version + .short 0 + .short 0 + .short 0 + .short 7000 # Backend version + .short 0 + .short 0 + .short 0 + .asciz "clang version 7.0.0 " # Null-terminated compiler version string +Ltmp6: +Ltmp4: + .p2align 2 + .long 246 # Inlinee lines subsection + .long Ltmp8-Ltmp7 # Subsection size +Ltmp7: + .long 0 # Inlinee lines signature + + # Inlined function do_exit starts at t.cpp:3 + .long 4098 # Type index of inlined function + .cv_filechecksumoffset 1 # Offset into filechecksum table + .long 3 # Starting line number +Ltmp8: + .p2align 2 + .cv_fpo_data _callit + .long 241 # Symbol subsection for callit + .long Ltmp10-Ltmp9 # Subsection size +Ltmp9: + .short Ltmp12-Ltmp11 # Record length +Ltmp11: + .short 4423 # Record kind: S_GPROC32_ID + .long 0 # PtrParent + .long 0 # PtrEnd + .long 0 # PtrNext + .long Lfunc_end0-_callit # Code size + .long 0 # Offset after prologue + .long 0 # Offset before epilogue + .long 4099 # Function type index + .secrel32 _callit # Function section relative address + .secidx _callit # Function section index + .byte 0 # Flags + .asciz "callit" # Function name +Ltmp12: + .short Ltmp14-Ltmp13 # Record length +Ltmp13: + .short 4429 # Record kind: S_INLINESITE + .long 0 # PtrParent + .long 0 # PtrEnd + .long 4098 # Inlinee type index + .cv_inline_linetable 1 1 3 Lfunc_begin0 Lfunc_end0 +Ltmp14: + .short 2 # Record length + .short 4430 # Record kind: S_INLINESITE_END + .short 2 # Record length + .short 4431 # Record kind: S_PROC_ID_END +Ltmp10: + .p2align 2 + .cv_linetable 0, _callit, Lfunc_end0 + .cv_filechecksums # File index to string table offset subsection + .cv_stringtable # String table + .section .debug$T,"dr" + .p2align 2 + .long 4 # Debug section magic + # ArgList (0x1000) { + # TypeLeafKind: LF_ARGLIST (0x1201) + # NumArgs: 0 + # Arguments [ + # ] + # } + .byte 0x06, 0x00, 0x01, 0x12 + .byte 0x00, 0x00, 0x00, 0x00 + # Procedure (0x1001) { + # TypeLeafKind: LF_PROCEDURE (0x1008) + # ReturnType: void (0x3) + # CallingConvention: NearC (0x0) + # FunctionOptions [ (0x0) + # ] + # NumParameters: 0 + # ArgListType: () (0x1000) + # } + .byte 0x0e, 0x00, 0x08, 0x10 + .byte 0x03, 0x00, 0x00, 0x00 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x00, 0x10, 0x00, 0x00 + # FuncId (0x1002) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: void () (0x1001) + # Name: do_exit + # } + .byte 0x12, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x01, 0x10, 0x00, 0x00 + .byte 0x64, 0x6f, 0x5f, 0x65 + .byte 0x78, 0x69, 0x74, 0x00 + # FuncId (0x1003) { + # TypeLeafKind: LF_FUNC_ID (0x1601) + # ParentScope: 0x0 + # FunctionType: void () (0x1001) + # Name: callit + # } + .byte 0x12, 0x00, 0x01, 0x16 + .byte 0x00, 0x00, 0x00, 0x00 + .byte 0x01, 0x10, 0x00, 0x00 + .byte 0x63, 0x61, 0x6c, 0x6c + .byte 0x69, 0x74, 0x00, 0xf1 + |