1# RUN: llvm-mc -triple=x86_64-windows -filetype=obj < %s -o %t.obj 2# RUN: llvm-objdump -d %t.obj | FileCheck %s --check-prefix=ASM 3# RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=CODEVIEW 4 5# C source to generate the assembly: 6# volatile int unlikely_cond = 0; 7# extern void __declspec(noreturn) abort(); 8# __forceinline void f() { 9# if (unlikely_cond) 10# abort(); 11# } 12# void g() { 13# unlikely_cond = 0; 14# f(); 15# unlikely_cond = 0; 16# } 17 18# This test is interesting because the inlined instructions are discontiguous. 19# LLVM's block layout algorithms will put the 'abort' call last, as it is 20# considered highly unlikely to execute. This is similar to what it does for 21# calls to __asan_report*, for which it is very important to have an accurate 22# stack trace. 23 24# ASM: 0000000000000000 <g>: 25# ASM-NEXT: 0: 48 83 ec 28 subq $40, %rsp 26# ASM-NEXT: 4: c7 05 fc ff ff ff 00 00 00 00 movl $0, -4(%rip) 27# Begin inline loc (matches cv_loc below) 28# ASM-NEXT: e: 83 3d ff ff ff ff 00 cmpl $0, -1(%rip) 29# ASM-NEXT: 15: 75 0f jne 0x26 <g+0x26> 30# End inline loc 31# ASM-NEXT: 17: c7 05 fc ff ff ff 00 00 00 00 movl $0, -4(%rip) 32# ASM-NEXT: 21: 48 83 c4 28 addq $40, %rsp 33# ASM-NEXT: 25: c3 retq 34# Begin inline loc (matches cv_loc below) 35# ASM-NEXT: 26: e8 00 00 00 00 callq 0x2b <g+0x2b> 36# ASM-NEXT: 2b: 0f 0b ud2 37# End inline loc 38 39# CODEVIEW: S_INLINESITE [size = 24] 40# CODEVIEW-NEXT: inlinee = 0x1002 (f), parent = 0, end = 0 41# CODEVIEW-NEXT: 0B2E code 0xE (+0xE) line 1 (+1) 42# CODEVIEW-NEXT: 0409 code end 0x17 (+0x9) 43# CODEVIEW-NEXT: 0B2F code 0x26 (+0xF) line 2 (+1) 44# CODEVIEW-NEXT: 0407 code end 0x2D (+0x7) 45 46 .text 47 .globl g 48g: # @g 49.Lfunc_begin0: 50 .cv_func_id 0 51 .cv_file 1 "C:\\src\\llvm\\build\\t.cpp" 52 .cv_loc 0 1 7 0 is_stmt 0 # t.cpp:7:0 53.seh_proc g 54 subq $40, %rsp 55 .seh_stackalloc 40 56 .seh_endprologue 57 .cv_loc 0 1 8 17 # t.cpp:8:17 58 movl $0, unlikely_cond(%rip) 59 .cv_inline_site_id 1 within 0 inlined_at 1 9 3 60 .cv_loc 1 1 4 7 # t.cpp:4:7 61 cmpl $0, unlikely_cond(%rip) 62 jne .LBB0_1 63 .cv_loc 0 1 10 17 # t.cpp:10:17 64 movl $0, unlikely_cond(%rip) 65 .cv_loc 0 1 11 1 # t.cpp:11:1 66 addq $40, %rsp 67 retq 68 69.LBB0_1: # %if.then.i 70 .cv_loc 1 1 5 5 # t.cpp:5:5 71 callq abort 72 ud2 73.Lfunc_end0: 74 .seh_handlerdata 75 .text 76 .seh_endproc 77 78 .bss 79 .globl unlikely_cond # @unlikely_cond 80 .p2align 2 81unlikely_cond: 82 .long 0 # 0x0 83 84 .section .debug$S,"dr" 85 .p2align 2 86 .long 4 # Debug section magic 87 .long 246 # Inlinee lines subsection 88 .long .Ltmp9-.Ltmp8 # Subsection size 89.Ltmp8: 90 .long 0 # Inlinee lines signature 91 92 # Inlined function f starts at t.cpp:3 93 .long 4098 # Type index of inlined function 94 .long 0 # Offset into filechecksum table 95 .long 3 # Starting line number 96.Ltmp9: 97 .p2align 2 98 .long 241 # Symbol subsection for g 99 .long .Ltmp11-.Ltmp10 # Subsection size 100.Ltmp10: 101 .short .Ltmp13-.Ltmp12 # Record length 102.Ltmp12: 103 .short 4423 # Record kind: S_GPROC32_ID 104 .long 0 # PtrParent 105 .long 0 # PtrEnd 106 .long 0 # PtrNext 107 .long .Lfunc_end0-g # Code size 108 .long 0 # Offset after prologue 109 .long 0 # Offset before epilogue 110 .long 4099 # Function type index 111 .secrel32 g # Function section relative address 112 .secidx g # Function section index 113 .byte 0 # Flags 114 .asciz "g" # Function name 115.Ltmp13: 116 .short .Ltmp15-.Ltmp14 # Record length 117.Ltmp14: 118 .short 4429 # Record kind: S_INLINESITE 119 .long 0 # PtrParent 120 .long 0 # PtrEnd 121 .long 4098 # Inlinee type index 122 .cv_inline_linetable 1 1 3 .Lfunc_begin0 .Lfunc_end0 123.Ltmp15: 124 .short 2 # Record length 125 .short 4430 # Record kind: S_INLINESITE_END 126 .short 2 # Record length 127 .short 4431 # Record kind: S_PROC_ID_END 128.Ltmp11: 129 .p2align 2 130 .cv_linetable 0, g, .Lfunc_end0 131 .long 241 # Symbol subsection for globals 132 .long .Ltmp17-.Ltmp16 # Subsection size 133.Ltmp16: 134 .short .Ltmp19-.Ltmp18 # Record length 135.Ltmp18: 136 .short 4365 # Record kind: S_GDATA32 137 .long 4100 # Type 138 .secrel32 unlikely_cond # DataOffset 139 .secidx unlikely_cond # Segment 140 .asciz "unlikely_cond" # Name 141.Ltmp19: 142.Ltmp17: 143 .p2align 2 144 .cv_filechecksums # File index to string table offset subsection 145 .cv_stringtable # String table 146 .section .debug$T,"dr" 147 .p2align 2 148 .long 4 # Debug section magic 149 # ArgList (0x1000) { 150 # TypeLeafKind: LF_ARGLIST (0x1201) 151 # NumArgs: 0 152 # Arguments [ 153 # ] 154 # } 155 .byte 0x06, 0x00, 0x01, 0x12 156 .byte 0x00, 0x00, 0x00, 0x00 157 # Procedure (0x1001) { 158 # TypeLeafKind: LF_PROCEDURE (0x1008) 159 # ReturnType: void (0x3) 160 # CallingConvention: NearC (0x0) 161 # FunctionOptions [ (0x0) 162 # ] 163 # NumParameters: 0 164 # ArgListType: () (0x1000) 165 # } 166 .byte 0x0e, 0x00, 0x08, 0x10 167 .byte 0x03, 0x00, 0x00, 0x00 168 .byte 0x00, 0x00, 0x00, 0x00 169 .byte 0x00, 0x10, 0x00, 0x00 170 # FuncId (0x1002) { 171 # TypeLeafKind: LF_FUNC_ID (0x1601) 172 # ParentScope: 0x0 173 # FunctionType: void () (0x1001) 174 # Name: f 175 # } 176 .byte 0x0e, 0x00, 0x01, 0x16 177 .byte 0x00, 0x00, 0x00, 0x00 178 .byte 0x01, 0x10, 0x00, 0x00 179 .byte 0x66, 0x00, 0xf2, 0xf1 180 # FuncId (0x1003) { 181 # TypeLeafKind: LF_FUNC_ID (0x1601) 182 # ParentScope: 0x0 183 # FunctionType: void () (0x1001) 184 # Name: g 185 # } 186 .byte 0x0e, 0x00, 0x01, 0x16 187 .byte 0x00, 0x00, 0x00, 0x00 188 .byte 0x01, 0x10, 0x00, 0x00 189 .byte 0x67, 0x00, 0xf2, 0xf1 190 # Modifier (0x1004) { 191 # TypeLeafKind: LF_MODIFIER (0x1001) 192 # ModifiedType: int (0x74) 193 # Modifiers [ (0x2) 194 # Volatile (0x2) 195 # ] 196 # } 197 .byte 0x0a, 0x00, 0x01, 0x10 198 .byte 0x74, 0x00, 0x00, 0x00 199 .byte 0x02, 0x00, 0xf2, 0xf1 200 201