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