1 ; RUN: llc < %s -stack-symbol-ordering=0 -frame-pointer=all -mtriple=x86_64-pc-linux-gnu -mcpu=corei7 -o - | FileCheck %s
2 ; This test is fairly fragile. The goal is to ensure that "large" stack
3 ; objects are allocated closest to the stack protector (i.e., farthest away
4 ; from the Stack Pointer.) In standard SSP mode this means that large (>=
5 ; ssp-buffer-size) arrays and structures containing such arrays are
6 ; closet to the protector. With sspstrong and sspreq this means large
7 ; arrays/structures-with-arrays are closest, followed by small (< ssp-buffer-size)
8 ; arrays/structures-with-arrays, and then addr-taken variables.
10 ; Ideally, we only want verify that the objects appear in the correct groups
11 ; and that the groups have the correct relative stack offset. The ordering
12 ; within a group is not relevant to this test. Unfortunately, there is not
13 ; an elegant way to do this, so just match the offset for each object.
14 ; RUN: llc < %s -frame-pointer=all -mtriple=x86_64-unknown-unknown -O0 -mcpu=corei7 -o - \
15 ; RUN: | FileCheck --check-prefix=FAST-NON-LIN %s
16 ; FastISel was not setting the StackProtectorIndex when lowering
17 ; Intrinsic::stackprotector and as a result the stack re-arrangement code was
18 ; never applied. This problem only shows up on non-Linux platforms because on
19 ; Linux the stack protector cookie is loaded from a special address space which
20 ; always triggers standard ISel. Run a basic test to ensure that at -O0
21 ; on a non-linux target the data layout rules are triggered.
23 %struct.struct_large_char = type { [8 x i8] }
24 %struct.struct_small_char = type { [2 x i8] }
25 %struct.struct_large_nonchar = type { [8 x i32] }
26 %struct.struct_small_nonchar = type { [2 x i16] }
28 define void @layout_ssp() ssp {
30 ; Expected stack layout for ssp is
31 ; -16 large_char . Group 1, nested arrays, arrays >= ssp-buffer-size
32 ; -24 struct_large_char .
33 ; -28 scalar1 | Everything else
40 ; -88 struct_small_char
41 ; -120 struct_large_nonchar
42 ; -128 struct_small_nonchar
45 ; CHECK: call{{l|q}} get_scalar1
46 ; CHECK: movl %eax, -28(
47 ; CHECK: call{{l|q}} end_scalar1
49 ; CHECK: call{{l|q}} get_scalar2
50 ; CHECK: movl %eax, -32(
51 ; CHECK: call{{l|q}} end_scalar2
53 ; CHECK: call{{l|q}} get_scalar3
54 ; CHECK: movl %eax, -36(
55 ; CHECK: call{{l|q}} end_scalar3
57 ; CHECK: call{{l|q}} get_addrof
58 ; CHECK: movl %eax, -40(
59 ; CHECK: call{{l|q}} end_addrof
61 ; CHECK: get_small_nonchar
62 ; CHECK: movw %ax, -44(
63 ; CHECK: call{{l|q}} end_small_nonchar
65 ; CHECK: call{{l|q}} get_large_nonchar
66 ; CHECK: movl %eax, -80(
67 ; CHECK: call{{l|q}} end_large_nonchar
69 ; CHECK: call{{l|q}} get_small_char
70 ; CHECK: movb %al, -82(
71 ; CHECK: call{{l|q}} end_small_char
73 ; CHECK: call{{l|q}} get_large_char
74 ; CHECK: movb %al, -16(
75 ; CHECK: call{{l|q}} end_large_char
77 ; CHECK: call{{l|q}} get_struct_large_char
78 ; CHECK: movb %al, -24(
79 ; CHECK: call{{l|q}} end_struct_large_char
81 ; CHECK: call{{l|q}} get_struct_small_char
82 ; CHECK: movb %al, -88(
83 ; CHECK: call{{l|q}} end_struct_small_char
85 ; CHECK: call{{l|q}} get_struct_large_nonchar
86 ; CHECK: movl %eax, -120(
87 ; CHECK: call{{l|q}} end_struct_large_nonchar
89 ; CHECK: call{{l|q}} get_struct_small_nonchar
90 ; CHECK: movw %ax, -128(
91 ; CHECK: call{{l|q}} end_struct_small_nonchar
92 %x = alloca i32, align 4
93 %y = alloca i32, align 4
94 %z = alloca i32, align 4
95 %ptr = alloca i32, align 4
96 %small2 = alloca [2 x i16], align 4
97 %large2 = alloca [8 x i32], align 16
98 %small = alloca [2 x i8], align 2
99 %large = alloca [8 x i8], align 8
100 %a = alloca %struct.struct_large_char, align 8
101 %b = alloca %struct.struct_small_char, align 8
102 %c = alloca %struct.struct_large_nonchar, align 8
103 %d = alloca %struct.struct_small_nonchar, align 8
104 %call = call i32 @get_scalar1()
105 store i32 %call, ptr %x, align 4
106 call void @end_scalar1()
107 %call1 = call i32 @get_scalar2()
108 store i32 %call1, ptr %y, align 4
109 call void @end_scalar2()
110 %call2 = call i32 @get_scalar3()
111 store i32 %call2, ptr %z, align 4
112 call void @end_scalar3()
113 %call3 = call i32 @get_addrof()
114 store i32 %call3, ptr %ptr, align 4
115 call void @end_addrof()
116 %call4 = call signext i16 @get_small_nonchar()
117 store i16 %call4, ptr %small2, align 2
118 call void @end_small_nonchar()
119 %call5 = call i32 @get_large_nonchar()
120 store i32 %call5, ptr %large2, align 4
121 call void @end_large_nonchar()
122 %call7 = call signext i8 @get_small_char()
123 store i8 %call7, ptr %small, align 1
124 call void @end_small_char()
125 %call9 = call signext i8 @get_large_char()
126 store i8 %call9, ptr %large, align 1
127 call void @end_large_char()
128 %call11 = call signext i8 @get_struct_large_char()
129 store i8 %call11, ptr %a, align 1
130 call void @end_struct_large_char()
131 %call13 = call signext i8 @get_struct_small_char()
132 store i8 %call13, ptr %b, align 1
133 call void @end_struct_small_char()
134 %call16 = call i32 @get_struct_large_nonchar()
135 store i32 %call16, ptr %c, align 4
136 call void @end_struct_large_nonchar()
137 %call19 = call signext i16 @get_struct_small_nonchar()
138 store i16 %call19, ptr %d, align 2
139 call void @end_struct_small_nonchar()
140 %0 = load i32, ptr %x, align 4
141 %1 = load i32, ptr %y, align 4
142 %2 = load i32, ptr %z, align 4
143 %3 = load i64, ptr %a, align 1
144 %4 = load i16, ptr %b, align 1
145 %5 = load i32, ptr %d, align 1
146 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 8 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2)
150 define void @layout_sspstrong() nounwind uwtable sspstrong {
152 ; Expected stack layout for sspstrong is
153 ; -48 large_nonchar . Group 1, nested arrays,
154 ; -56 large_char . arrays >= ssp-buffer-size
155 ; -64 struct_large_char .
156 ; -96 struct_large_nonchar .
157 ; -100 small_non_char | Group 2, nested arrays,
158 ; -102 small_char | arrays < ssp-buffer-size
159 ; -104 struct_small_char |
160 ; -112 struct_small_nonchar |
161 ; -116 addrof * Group 3, addr-of local
162 ; -120 scalar + Group 4, everything else
166 ; CHECK: layout_sspstrong:
167 ; CHECK: call{{l|q}} get_scalar1
168 ; CHECK: movl %eax, -120(
169 ; CHECK: call{{l|q}} end_scalar1
171 ; CHECK: call{{l|q}} get_scalar2
172 ; CHECK: movl %eax, -124(
173 ; CHECK: call{{l|q}} end_scalar2
175 ; CHECK: call{{l|q}} get_scalar3
176 ; CHECK: movl %eax, -128(
177 ; CHECK: call{{l|q}} end_scalar3
179 ; CHECK: call{{l|q}} get_addrof
180 ; CHECK: movl %eax, -116(
181 ; CHECK: call{{l|q}} end_addrof
183 ; CHECK: get_small_nonchar
184 ; CHECK: movw %ax, -100(
185 ; CHECK: call{{l|q}} end_small_nonchar
187 ; CHECK: call{{l|q}} get_large_nonchar
188 ; CHECK: movl %eax, -48(
189 ; CHECK: call{{l|q}} end_large_nonchar
191 ; CHECK: call{{l|q}} get_small_char
192 ; CHECK: movb %al, -102(
193 ; CHECK: call{{l|q}} end_small_char
195 ; CHECK: call{{l|q}} get_large_char
196 ; CHECK: movb %al, -56(
197 ; CHECK: call{{l|q}} end_large_char
199 ; CHECK: call{{l|q}} get_struct_large_char
200 ; CHECK: movb %al, -64(
201 ; CHECK: call{{l|q}} end_struct_large_char
203 ; CHECK: call{{l|q}} get_struct_small_char
204 ; CHECK: movb %al, -104(
205 ; CHECK: call{{l|q}} end_struct_small_char
207 ; CHECK: call{{l|q}} get_struct_large_nonchar
208 ; CHECK: movl %eax, -96(
209 ; CHECK: call{{l|q}} end_struct_large_nonchar
211 ; CHECK: call{{l|q}} get_struct_small_nonchar
212 ; CHECK: movw %ax, -112(
213 ; CHECK: call{{l|q}} end_struct_small_nonchar
214 %x = alloca i32, align 4
215 %y = alloca i32, align 4
216 %z = alloca i32, align 4
217 %ptr = alloca i32, align 4
218 %small2 = alloca [2 x i16], align 2
219 %large2 = alloca [8 x i32], align 16
220 %small = alloca [2 x i8], align 2
221 %large = alloca [8 x i8], align 8
222 %a = alloca %struct.struct_large_char, align 8
223 %b = alloca %struct.struct_small_char, align 8
224 %c = alloca %struct.struct_large_nonchar, align 8
225 %d = alloca %struct.struct_small_nonchar, align 8
226 %call = call i32 @get_scalar1()
227 store i32 %call, ptr %x, align 4
228 call void @end_scalar1()
229 %call1 = call i32 @get_scalar2()
230 store i32 %call1, ptr %y, align 4
231 call void @end_scalar2()
232 %call2 = call i32 @get_scalar3()
233 store i32 %call2, ptr %z, align 4
234 call void @end_scalar3()
235 %call3 = call i32 @get_addrof()
236 store i32 %call3, ptr %ptr, align 4
237 call void @end_addrof()
238 %call4 = call signext i16 @get_small_nonchar()
239 store i16 %call4, ptr %small2, align 2
240 call void @end_small_nonchar()
241 %call5 = call i32 @get_large_nonchar()
242 store i32 %call5, ptr %large2, align 4
243 call void @end_large_nonchar()
244 %call7 = call signext i8 @get_small_char()
245 store i8 %call7, ptr %small, align 1
246 call void @end_small_char()
247 %call9 = call signext i8 @get_large_char()
248 store i8 %call9, ptr %large, align 1
249 call void @end_large_char()
250 %call11 = call signext i8 @get_struct_large_char()
251 store i8 %call11, ptr %a, align 1
252 call void @end_struct_large_char()
253 %call13 = call signext i8 @get_struct_small_char()
254 store i8 %call13, ptr %b, align 1
255 call void @end_struct_small_char()
256 %call16 = call i32 @get_struct_large_nonchar()
257 store i32 %call16, ptr %c, align 4
258 call void @end_struct_large_nonchar()
259 %call19 = call signext i16 @get_struct_small_nonchar()
260 store i16 %call19, ptr %d, align 2
261 call void @end_struct_small_nonchar()
262 %0 = load i32, ptr %x, align 4
263 %1 = load i32, ptr %y, align 4
264 %2 = load i32, ptr %z, align 4
265 %3 = load i64, ptr %a, align 1
266 %4 = load i16, ptr %b, align 1
267 %5 = load i32, ptr %d, align 1
268 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 8 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2)
272 define void @layout_sspreq() nounwind uwtable sspreq {
274 ; Expected stack layout for sspreq is the same as sspstrong
276 ; CHECK: layout_sspreq:
277 ; CHECK: call{{l|q}} get_scalar1
278 ; CHECK: movl %eax, -120(
279 ; CHECK: call{{l|q}} end_scalar1
281 ; CHECK: call{{l|q}} get_scalar2
282 ; CHECK: movl %eax, -124(
283 ; CHECK: call{{l|q}} end_scalar2
285 ; CHECK: call{{l|q}} get_scalar3
286 ; CHECK: movl %eax, -128(
287 ; CHECK: call{{l|q}} end_scalar3
289 ; CHECK: call{{l|q}} get_addrof
290 ; CHECK: movl %eax, -116(
291 ; CHECK: call{{l|q}} end_addrof
293 ; CHECK: get_small_nonchar
294 ; CHECK: movw %ax, -100(
295 ; CHECK: call{{l|q}} end_small_nonchar
297 ; CHECK: call{{l|q}} get_large_nonchar
298 ; CHECK: movl %eax, -48(
299 ; CHECK: call{{l|q}} end_large_nonchar
301 ; CHECK: call{{l|q}} get_small_char
302 ; CHECK: movb %al, -102(
303 ; CHECK: call{{l|q}} end_small_char
305 ; CHECK: call{{l|q}} get_large_char
306 ; CHECK: movb %al, -56(
307 ; CHECK: call{{l|q}} end_large_char
309 ; CHECK: call{{l|q}} get_struct_large_char
310 ; CHECK: movb %al, -64(
311 ; CHECK: call{{l|q}} end_struct_large_char
313 ; CHECK: call{{l|q}} get_struct_small_char
314 ; CHECK: movb %al, -104(
315 ; CHECK: call{{l|q}} end_struct_small_char
317 ; CHECK: call{{l|q}} get_struct_large_nonchar
318 ; CHECK: movl %eax, -96(
319 ; CHECK: call{{l|q}} end_struct_large_nonchar
321 ; CHECK: call{{l|q}} get_struct_small_nonchar
322 ; CHECK: movw %ax, -112(
323 ; CHECK: call{{l|q}} end_struct_small_nonchar
324 %x = alloca i32, align 4
325 %y = alloca i32, align 4
326 %z = alloca i32, align 4
327 %ptr = alloca i32, align 4
328 %small2 = alloca [2 x i16], align 4
329 %large2 = alloca [8 x i32], align 16
330 %small = alloca [2 x i8], align 2
331 %large = alloca [8 x i8], align 8
332 %a = alloca %struct.struct_large_char, align 8
333 %b = alloca %struct.struct_small_char, align 8
334 %c = alloca %struct.struct_large_nonchar, align 8
335 %d = alloca %struct.struct_small_nonchar, align 8
336 %call = call i32 @get_scalar1()
337 store i32 %call, ptr %x, align 4
338 call void @end_scalar1()
339 %call1 = call i32 @get_scalar2()
340 store i32 %call1, ptr %y, align 4
341 call void @end_scalar2()
342 %call2 = call i32 @get_scalar3()
343 store i32 %call2, ptr %z, align 4
344 call void @end_scalar3()
345 %call3 = call i32 @get_addrof()
346 store i32 %call3, ptr %ptr, align 4
347 call void @end_addrof()
348 %call4 = call signext i16 @get_small_nonchar()
349 store i16 %call4, ptr %small2, align 2
350 call void @end_small_nonchar()
351 %call5 = call i32 @get_large_nonchar()
352 store i32 %call5, ptr %large2, align 4
353 call void @end_large_nonchar()
354 %call7 = call signext i8 @get_small_char()
355 store i8 %call7, ptr %small, align 1
356 call void @end_small_char()
357 %call9 = call signext i8 @get_large_char()
358 store i8 %call9, ptr %large, align 1
359 call void @end_large_char()
360 %call11 = call signext i8 @get_struct_large_char()
361 store i8 %call11, ptr %a, align 1
362 call void @end_struct_large_char()
363 %call13 = call signext i8 @get_struct_small_char()
364 store i8 %call13, ptr %b, align 1
365 call void @end_struct_small_char()
366 %call16 = call i32 @get_struct_large_nonchar()
367 store i32 %call16, ptr %c, align 4
368 call void @end_struct_large_nonchar()
369 %call19 = call signext i16 @get_struct_small_nonchar()
370 store i16 %call19, ptr %d, align 2
371 call void @end_struct_small_nonchar()
372 %0 = load i32, ptr %x, align 4
373 %1 = load i32, ptr %y, align 4
374 %2 = load i32, ptr %z, align 4
375 %3 = load i64, ptr %a, align 1
376 %4 = load i16, ptr %b, align 1
377 %5 = load i32, ptr %d, align 1
378 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 8 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2)
382 define void @fast_non_linux() ssp {
384 ; FAST-NON-LIN: fast_non_linux:
385 ; FAST-NON-LIN: call{{l|q}} get_scalar1
386 ; FAST-NON-LIN: movl %eax, -20(
387 ; FAST-NON-LIN: call{{l|q}} end_scalar1
389 ; FAST-NON-LIN: call{{l|q}} get_large_char
390 ; FAST-NON-LIN: movb %al, -16(
391 ; FAST-NON-LIN: call{{l|q}} end_large_char
392 %x = alloca i32, align 4
393 %large = alloca [8 x i8], align 1
394 %call = call i32 @get_scalar1()
395 store i32 %call, ptr %x, align 4
396 call void @end_scalar1()
397 %call1 = call signext i8 @get_large_char()
398 store i8 %call1, ptr %large, align 1
399 call void @end_large_char()
400 %0 = load i32, ptr %x, align 4
401 call void @takes_two(i32 %0, ptr %large)
405 declare i32 @get_scalar1()
406 declare void @end_scalar1()
408 declare i32 @get_scalar2()
409 declare void @end_scalar2()
411 declare i32 @get_scalar3()
412 declare void @end_scalar3()
414 declare i32 @get_addrof()
415 declare void @end_addrof()
417 declare signext i16 @get_small_nonchar()
418 declare void @end_small_nonchar()
420 declare i32 @get_large_nonchar()
421 declare void @end_large_nonchar()
423 declare signext i8 @get_small_char()
424 declare void @end_small_char()
426 declare signext i8 @get_large_char()
427 declare void @end_large_char()
429 declare signext i8 @get_struct_large_char()
430 declare void @end_struct_large_char()
432 declare signext i8 @get_struct_small_char()
433 declare void @end_struct_small_char()
435 declare i32 @get_struct_large_nonchar()
436 declare void @end_struct_large_nonchar()
438 declare signext i16 @get_struct_small_nonchar()
439 declare void @end_struct_small_nonchar()
441 declare void @takes_all(i64, i16, ptr byval(%struct.struct_large_nonchar) align 8, i32, ptr, ptr, ptr, ptr, ptr, i32, i32, i32)
442 declare void @takes_two(i32, ptr)