1 // Check that backend stack layout diagnostics are working correctly with and
2 // without debug information, and when optimizations are enabled
4 // REQUIRES: x86-registered-target
8 // RUN: %clang_cc1 %s -emit-codegen-only -triple x86_64-unknown-linux-gnu -target-cpu corei7 -Rpass-analysis=stack-frame-layout -o /dev/null -O0 2>&1 | FileCheck %s --check-prefix=O0-NODEBUG
9 // RUN: %clang_cc1 %s -emit-codegen-only -triple x86_64-unknown-linux-gnu -target-cpu corei7 -Rpass-analysis=stack-frame-layout -o /dev/null -O0 -debug-info-kind=constructor -dwarf-version=5 -debugger-tuning=gdb 2>&1 | FileCheck %s --check-prefix=O0-DEBUG
10 // RUN: %clang_cc1 %s -emit-codegen-only -triple x86_64-unknown-linux-gnu -target-cpu corei7 -funwind-tables=2 -O3 -Rpass-analysis=stack-frame-layout -debug-info-kind=constructor -dwarf-version=5 -debugger-tuning=gdb -opt-record-file %t/stack-layout-remark.c.yml -opt-record-passes stack-frame-layout 2>&1 | FileCheck %s --check-prefix=O3-DEBUG
11 // RUN: cat %t/stack-layout-remark.c.yml | FileCheck %s --check-prefix=YAML
15 extern void* allocate(unsigned size
);
16 extern void deallocate(void* ptr
);
17 extern int work(char *ary
, int size
);
18 extern int rand(void);
21 // YAML: --- !Analysis
22 // YAML: Pass: stack-frame-layout
23 // YAML: Name: StackLayout
24 // YAML: DebugLoc: { File: '{{.*}}stack-layout-remark.c',{{[[:space:]]*}}Line: [[# @LINE + 24]],
25 // YAML: Function: foo
27 // YAML: - Offset: '-40'
28 // YAML: - Type: Variable
29 // YAML: - Align: '16'
31 // YAML: - DataLoc: 'a @ {{.*}}stack-layout-remark.c:[[# @LINE + 19]]'
32 // YAML: - DataLoc: 'f @ {{.*}}stack-layout-remark.c:[[# @LINE + 21]]'
34 // O0-NODEBUG: Function: foo
35 // O0-NODEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 32
36 // O0-NODEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 32
38 // O0-DEBUG: Function: foo
39 // O0-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 32
40 // O0-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]
41 // O0-DEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 32
42 // O0-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 11]]
44 // O3-DEBUG: Function: foo
45 // O3-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 32
46 // O3-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 4]]
47 // O3-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 6]]
56 // O0-NODEBUG: Function: bar
57 // O0-NODEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 32
58 // O0-NODEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 32
60 // O0-DEBUG: Function: bar
61 // O0-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 32
62 // O0-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]
63 // O0-DEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 32
64 // O0-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]
66 // O3-DEBUG: Function: bar
67 // O3-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 16, Size: 32
68 // O3-DEBUG-NEXT: f @ {{.*}}stack-layout-remark.c:[[# @LINE + 4]]
69 // O3-DEBUG-NEXT: Offset: [SP-72], Type: Variable, Align: 16, Size: 32
70 // O3-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 4]]
90 // O0-NODEBUG: Function: cleanup_array
91 // O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8
93 // O0-DEBUG: Function: cleanup_array
94 // O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8
95 // O0-DEBUG-NEXT: a @ {{.*}}stack-layout-remark.c:[[# @LINE + 5]]
97 // O3-DEBUG: Function: cleanup_array
98 // O3-DEBUG: Function: cleanup_result
99 // O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8
100 void cleanup_array(struct Array
*a
) {
108 // O0-NODEBUG: Function: cleanup_result
109 // O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8
111 // O0-DEBUG: Function: cleanup_result
112 // O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8
113 // O0-DEBUG-NEXT: res @ {{.*}}stack-layout-remark.c:[[# @LINE + 1]]
114 void cleanup_result(struct Result
*res
) {
119 cleanup_array(res
->data
);
120 deallocate(res
->data
);
123 extern void use_dot_vector(struct Array
*data
);
125 // O0-NODEBUG: Function: do_work
126 // O0-NODEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4
127 // O0-NODEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8
128 // O0-NODEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8
129 // O0-NODEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8
130 // O0-NODEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4
131 // O0-NODEBUG-NEXT: Offset: [SP-48], Type: Variable, Align: 8, Size: 8
132 // O0-NODEBUG-NEXT: Offset: [SP-52], Type: Variable, Align: 4, Size: 4
133 // O0-NODEBUG-NEXT: Offset: [SP-56], Type: Variable, Align: 4, Size: 4
135 // O0-DEBUG: Function: do_work
136 // O0-DEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4
137 // O0-DEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8
138 // O0-DEBUG-NEXT: A @ {{.*}}stack-layout-remark.c:[[# @LINE + 20]]
139 // O0-DEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8
140 // O0-DEBUG-NEXT: B @ {{.*}}stack-layout-remark.c:[[# @LINE + 18]]
141 // O0-DEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8
142 // O0-DEBUG-NEXT: out @ {{.*}}stack-layout-remark.c:[[# @LINE + 16]]
143 // O0-DEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4
144 // O0-DEBUG-NEXT: len @ {{.*}}stack-layout-remark.c:[[# @LINE + 19]]
145 // O0-DEBUG-NEXT: Offset: [SP-48], Type: Variable, Align: 8, Size: 8
146 // O0-DEBUG-NEXT: AB @ {{.*}}stack-layout-remark.c:[[# @LINE + 18]]
147 // O0-DEBUG-NEXT: Offset: [SP-52], Type: Variable, Align: 4, Size: 4
148 // O0-DEBUG-NEXT: sum @ {{.*}}stack-layout-remark.c:[[# @LINE + 32]]
149 // O0-DEBUG-NEXT: Offset: [SP-56], Type: Variable, Align: 4, Size: 4
150 // O0-DEBUG-NEXT: i @ {{.*}}stack-layout-remark.c:[[# @LINE + 31]]
152 // O3-DEBUG: Function: do_work
153 // O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8
154 // O3-DEBUG-NEXT: Offset: [SP-16], Type: Spill, Align: 8, Size: 8
155 // O3-DEBUG-NEXT: Offset: [SP-24], Type: Spill, Align: 16, Size: 8
156 // O3-DEBUG-NEXT: Offset: [SP-32], Type: Spill, Align: 8, Size: 8
157 // O3-DEBUG-NEXT: Offset: [SP-40], Type: Spill, Align: 16, Size: 8
158 int do_work(struct Array
*A
, struct Array
*B
, struct Result
*out
) {
161 if (A
->size
!= B
->size
)
163 const int len
= A
->size
;
165 if (out
->data
== NULL
) {
166 AB
= (struct Array
*)allocate(sizeof(struct Array
));
175 deallocate(AB
->data
);
177 AB
->data
= (int *)allocate(len
* sizeof(int));
181 for (int i
= 0; i
< len
; ++i
) {
182 AB
->data
[i
] = A
->data
[i
] * B
->data
[i
];
188 // O0-NODEBUG: Function: gen_array
189 // O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8
190 // O0-NODEBUG-NEXT: Offset: [SP-12], Type: Variable, Align: 4, Size: 4
191 // O0-NODEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8
192 // O0-NODEBUG-NEXT: Offset: [SP-28], Type: Variable, Align: 4, Size: 4
194 // O0-DEBUG: Function: gen_array
195 // O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 8, Size: 8
196 // O0-DEBUG-NEXT: Offset: [SP-12], Type: Variable, Align: 4, Size: 4
197 // O0-DEBUG-NEXT: size @ {{.*}}stack-layout-remark.c:[[# @LINE + 10]]
198 // O0-DEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8
199 // O0-DEBUG-NEXT: res @ {{.*}}stack-layout-remark.c:[[# @LINE + 11]]
200 // O0-DEBUG-NEXT: Offset: [SP-28], Type: Variable, Align: 4, Size: 4
201 // O0-DEBUG-NEXT: i @ {{.*}}stack-layout-remark.c:[[# @LINE + 13]]
203 // O3-DEBUG: Function: gen_array
204 // O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8
205 // O3-DEBUG-NEXT: Offset: [SP-16], Type: Spill, Align: 8, Size: 8
206 // O3-DEBUG-NEXT: Offset: [SP-24], Type: Spill, Align: 16, Size: 8
207 struct Array
*gen_array(int size
) {
210 struct Array
*res
= (struct Array
*)allocate(sizeof(struct Array
));
212 res
->data
= (int *)allocate(size
* sizeof(int));
214 for (int i
= 0; i
< size
; ++i
) {
215 res
->data
[i
] = rand();
221 // YAML: --- !Analysis
222 // YAML: Pass: stack-frame-layout
223 // YAML: Name: StackLayout
224 // YAML: DebugLoc: { File: '{{.*}}stack-layout-remark.c',{{[[:space:]]*}}Line: [[# @LINE + 59]],
225 // YAML: Function: caller
227 // YAML: - Offset: '-8'
228 // YAML: - Type: Spill
229 // YAML: - Align: '16'
231 // YAML: - Offset: '-16'
232 // YAML: - Type: Spill
233 // YAML: - Align: '8'
235 // YAML: - Offset: '-24'
236 // YAML: - Type: Spill
237 // YAML: - Align: '16'
239 // YAML: - Offset: '-32'
240 // YAML: - Type: Spill
241 // YAML: - Align: '8'
243 // YAML: - Offset: '-40'
244 // YAML: - Type: Spill
245 // YAML: - Align: '16'
247 // YAML: - Offset: '-48'
248 // YAML: - Type: Spill
249 // YAML: - Align: '8'
252 // O0-NODEBUG: Function: caller
253 // O0-NODEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4
254 // O0-NODEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 4, Size: 4
255 // O0-NODEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8
256 // O0-NODEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8
257 // O0-NODEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8
258 // O0-NODEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4
259 // O0-NODEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 4, Size: 4
261 // O0-DEBUG: Function: caller
262 // O0-DEBUG-NEXT: Offset: [SP-4], Type: Variable, Align: 4, Size: 4
263 // O0-DEBUG-NEXT: Offset: [SP-8], Type: Variable, Align: 4, Size: 4
264 // O0-DEBUG-NEXT: size @ {{.*}}stack-layout-remark.c:[[# @LINE + 20]]
265 // O0-DEBUG-NEXT: Offset: [SP-16], Type: Variable, Align: 8, Size: 8
266 // O0-DEBUG-NEXT: A @ {{.*}}stack-layout-remark.c:[[# @LINE + 19]]
267 // O0-DEBUG-NEXT: Offset: [SP-24], Type: Variable, Align: 8, Size: 8
268 // O0-DEBUG-NEXT: B @ {{.*}}stack-layout-remark.c:[[# @LINE + 18]]
269 // O0-DEBUG-NEXT: Offset: [SP-32], Type: Variable, Align: 8, Size: 8
270 // O0-DEBUG-NEXT: res @ {{.*}}stack-layout-remark.c:[[# @LINE + 17]]
271 // O0-DEBUG-NEXT: Offset: [SP-36], Type: Variable, Align: 4, Size: 4
272 // O0-DEBUG-NEXT: ret @ {{.*}}stack-layout-remark.c:[[# @LINE + 16]]
273 // O0-DEBUG-NEXT: Offset: [SP-40], Type: Variable, Align: 4, Size: 4
274 // O0-DEBUG-NEXT: err @ {{.*}}stack-layout-remark.c:[[# @LINE + 16]]
276 // O3-DEBUG: Function: caller
277 // O3-DEBUG-NEXT: Offset: [SP-8], Type: Spill, Align: 16, Size: 8
278 // O3-DEBUG-NEXT: Offset: [SP-16], Type: Spill, Align: 8, Size: 8
279 // O3-DEBUG-NEXT: Offset: [SP-24], Type: Spill, Align: 16, Size: 8
280 // O3-DEBUG-NEXT: Offset: [SP-32], Type: Spill, Align: 8, Size: 8
281 // O3-DEBUG-NEXT: Offset: [SP-40], Type: Spill, Align: 16, Size: 8
282 // O3-DEBUG-NEXT: Offset: [SP-48], Type: Spill, Align: 8, Size: 8
284 const int size
= 100;
285 struct Array
*A
= gen_array(size
);
286 struct Array
*B
= gen_array(size
);
287 struct Result
*res
= (struct Result
*)allocate(sizeof(struct Result
));
290 int err
= do_work(A
, B
, res
);
299 use_dot_vector(res
->data
);