| # RUN: llvm-mc -triple=x86_64-windows -filetype=obj < %s | llvm-readobj -codeview | FileCheck %s |
| |
| # C source to generate the assembly: |
| # volatile int unlikely_cond = 0; |
| # extern void __declspec(noreturn) abort(); |
| # __forceinline void f() { |
| # if (unlikely_cond) |
| # abort(); |
| # } |
| # void g() { |
| # unlikely_cond = 0; |
| # f(); |
| # unlikely_cond = 0; |
| # } |
| |
| # This test is interesting because the inlined instructions are discontiguous. |
| # LLVM's block layout algorithms will put the 'abort' call last, as it is |
| # considered highly unlikely to execute. This is similar to what it does for |
| # calls to __asan_report*, for which it is very important to have an accurate |
| # stack trace. |
| |
| # CHECK: GlobalProcIdSym { |
| # CHECK: FunctionType: g (0x1003) |
| # CHECK: CodeOffset: g+0x0 |
| # CHECK: DisplayName: g |
| # CHECK: LinkageName: g |
| # CHECK: } |
| # CHECK: InlineSiteSym { |
| # CHECK: Inlinee: f (0x1002) |
| # CHECK: BinaryAnnotations [ |
| # CHECK-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xE, LineOffset: 1} |
| # CHECK-NEXT: ChangeCodeLength: 0x9 |
| # CHECK-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xF, LineOffset: 1} |
| # CHECK-NEXT: ChangeCodeLength: 0x7 |
| # CHECK-NEXT: ] |
| |
| .text |
| .globl g |
| g: # @g |
| .Lfunc_begin0: |
| .cv_func_id 0 |
| .cv_file 1 "C:\\src\\llvm\\build\\t.cpp" |
| .cv_loc 0 1 7 0 is_stmt 0 # t.cpp:7:0 |
| .seh_proc g |
| subq $40, %rsp |
| .seh_stackalloc 40 |
| .seh_endprologue |
| .cv_loc 0 1 8 17 # t.cpp:8:17 |
| movl $0, unlikely_cond(%rip) |
| .cv_inline_site_id 1 within 0 inlined_at 1 9 3 |
| .cv_loc 1 1 4 7 # t.cpp:4:7 |
| cmpl $0, unlikely_cond(%rip) |
| jne .LBB0_1 |
| .cv_loc 0 1 10 17 # t.cpp:10:17 |
| movl $0, unlikely_cond(%rip) |
| .cv_loc 0 1 11 1 # t.cpp:11:1 |
| addq $40, %rsp |
| retq |
| |
| .LBB0_1: # %if.then.i |
| .cv_loc 1 1 5 5 # t.cpp:5:5 |
| callq abort |
| ud2 |
| .Lfunc_end0: |
| .seh_handlerdata |
| .text |
| .seh_endproc |
| |
| .bss |
| .globl unlikely_cond # @unlikely_cond |
| .p2align 2 |
| unlikely_cond: |
| .long 0 # 0x0 |
| |
| .section .debug$S,"dr" |
| .p2align 2 |
| .long 4 # Debug section magic |
| .long 246 # Inlinee lines subsection |
| .long .Ltmp9-.Ltmp8 # Subsection size |
| .Ltmp8: |
| .long 0 # Inlinee lines signature |
| |
| # Inlined function f starts at t.cpp:3 |
| .long 4098 # Type index of inlined function |
| .long 0 # Offset into filechecksum table |
| .long 3 # Starting line number |
| .Ltmp9: |
| .p2align 2 |
| .long 241 # Symbol subsection for g |
| .long .Ltmp11-.Ltmp10 # Subsection size |
| .Ltmp10: |
| .short .Ltmp13-.Ltmp12 # Record length |
| .Ltmp12: |
| .short 4423 # Record kind: S_GPROC32_ID |
| .long 0 # PtrParent |
| .long 0 # PtrEnd |
| .long 0 # PtrNext |
| .long .Lfunc_end0-g # Code size |
| .long 0 # Offset after prologue |
| .long 0 # Offset before epilogue |
| .long 4099 # Function type index |
| .secrel32 g # Function section relative address |
| .secidx g # Function section index |
| .byte 0 # Flags |
| .asciz "g" # Function name |
| .Ltmp13: |
| .short .Ltmp15-.Ltmp14 # Record length |
| .Ltmp14: |
| .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 |
| .Ltmp15: |
| .short 2 # Record length |
| .short 4430 # Record kind: S_INLINESITE_END |
| .short 2 # Record length |
| .short 4431 # Record kind: S_PROC_ID_END |
| .Ltmp11: |
| .p2align 2 |
| .cv_linetable 0, g, .Lfunc_end0 |
| .long 241 # Symbol subsection for globals |
| .long .Ltmp17-.Ltmp16 # Subsection size |
| .Ltmp16: |
| .short .Ltmp19-.Ltmp18 # Record length |
| .Ltmp18: |
| .short 4365 # Record kind: S_GDATA32 |
| .long 4100 # Type |
| .secrel32 unlikely_cond # DataOffset |
| .secidx unlikely_cond # Segment |
| .asciz "unlikely_cond" # Name |
| .Ltmp19: |
| .Ltmp17: |
| .p2align 2 |
| .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: f |
| # } |
| .byte 0x0e, 0x00, 0x01, 0x16 |
| .byte 0x00, 0x00, 0x00, 0x00 |
| .byte 0x01, 0x10, 0x00, 0x00 |
| .byte 0x66, 0x00, 0xf2, 0xf1 |
| # FuncId (0x1003) { |
| # TypeLeafKind: LF_FUNC_ID (0x1601) |
| # ParentScope: 0x0 |
| # FunctionType: void () (0x1001) |
| # Name: g |
| # } |
| .byte 0x0e, 0x00, 0x01, 0x16 |
| .byte 0x00, 0x00, 0x00, 0x00 |
| .byte 0x01, 0x10, 0x00, 0x00 |
| .byte 0x67, 0x00, 0xf2, 0xf1 |
| # Modifier (0x1004) { |
| # TypeLeafKind: LF_MODIFIER (0x1001) |
| # ModifiedType: int (0x74) |
| # Modifiers [ (0x2) |
| # Volatile (0x2) |
| # ] |
| # } |
| .byte 0x0a, 0x00, 0x01, 0x10 |
| .byte 0x74, 0x00, 0x00, 0x00 |
| .byte 0x02, 0x00, 0xf2, 0xf1 |
| |