1 ; RUN: llc < %s -frame-pointer=all -mcpu=cortex-a8 -mtriple arm-linux-gnu -target-abi=apcs -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.
15 %struct.struct_large_char = type { [8 x i8] }
16 %struct.struct_large_char2 = type { [2 x i8], [8 x i8] }
17 %struct.struct_small_char = type { [2 x i8] }
18 %struct.struct_large_nonchar = type { [8 x i32] }
19 %struct.struct_small_nonchar = type { [2 x i16] }
21 define void @layout_ssp() ssp {
23 ; Expected stack layout for ssp is
24 ; 180 large_char . Group 1, nested arrays, arrays >= ssp-buffer-size
25 ; 172 struct_large_char .
26 ; 168 scalar1 | Everything else
33 ; 108 struct_small_char
34 ; 72 struct_large_nonchar
35 ; 68 struct_small_nonchar
39 ; CHECK: bl get_scalar1
40 ; CHECK: str r0, [sp, #168]
41 ; CHECK: bl end_scalar1
43 ; CHECK: bl get_scalar2
44 ; CHECK: str r0, [sp, #164]
45 ; CHECK: bl end_scalar
47 ; CHECK: bl get_scalar3
48 ; CHECK: str r0, [sp, #160]
49 ; CHECK: bl end_scalar3
51 ; CHECK: bl get_addrof
52 ; CHECK: str r0, [sp, #156]
53 ; CHECK: bl end_addrof
55 ; CHECK: get_small_nonchar
56 ; CHECK: strh r0, [sp, #152]
57 ; CHECK: bl end_small_nonchar
59 ; CHECK: bl get_large_nonchar
60 ; CHECK: str r0, [sp, #112]
61 ; CHECK: bl end_large_nonchar
63 ; CHECK: bl get_small_char
64 ; CHECK: strb r0, [sp, #110]
65 ; CHECK: bl end_small_char
67 ; CHECK: bl get_large_char
68 ; CHECK: strb r0, [sp, #180]
69 ; CHECK: bl end_large_char
71 ; CHECK: bl get_struct_large_char
72 ; CHECK: strb r0, [sp, #172]
73 ; CHECK: bl end_struct_large_char
75 ; CHECK: bl get_struct_small_char
76 ; CHECK: strb r0, [sp, #108]
77 ; CHECK: bl end_struct_small_char
79 ; CHECK: bl get_struct_large_nonchar
80 ; CHECK:str r0, [sp, #72]
81 ; CHECK: bl end_struct_large_nonchar
83 ; CHECK: bl get_struct_small_nonchar
84 ; CHECK: strh r0, [sp, #68]
85 ; CHECK: bl end_struct_small_nonchar
86 %x = alloca i32, align 4
87 %y = alloca i32, align 4
88 %z = alloca i32, align 4
89 %ptr = alloca i32, align 4
90 %small2 = alloca [2 x i16], align 2
91 %large2 = alloca [8 x i32], align 16
92 %small = alloca [2 x i8], align 1
93 %large = alloca [8 x i8], align 1
94 %a = alloca %struct.struct_large_char, align 1
95 %b = alloca %struct.struct_small_char, align 1
96 %c = alloca %struct.struct_large_nonchar, align 8
97 %d = alloca %struct.struct_small_nonchar, align 2
98 %call = call i32 @get_scalar1()
99 store i32 %call, ptr %x, align 4
100 call void @end_scalar1()
101 %call1 = call i32 @get_scalar2()
102 store i32 %call1, ptr %y, align 4
103 call void @end_scalar2()
104 %call2 = call i32 @get_scalar3()
105 store i32 %call2, ptr %z, align 4
106 call void @end_scalar3()
107 %call3 = call i32 @get_addrof()
108 store i32 %call3, ptr %ptr, align 4
109 call void @end_addrof()
110 %call4 = call signext i16 @get_small_nonchar()
111 store i16 %call4, ptr %small2, align 2
112 call void @end_small_nonchar()
113 %call5 = call i32 @get_large_nonchar()
114 store i32 %call5, ptr %large2, align 4
115 call void @end_large_nonchar()
116 %call7 = call signext i8 @get_small_char()
117 store i8 %call7, ptr %small, align 1
118 call void @end_small_char()
119 %call9 = call signext i8 @get_large_char()
120 store i8 %call9, ptr %large, align 1
121 call void @end_large_char()
122 %call11 = call signext i8 @get_struct_large_char()
123 store i8 %call11, ptr %a, align 1
124 call void @end_struct_large_char()
125 %call13 = call signext i8 @get_struct_small_char()
126 store i8 %call13, ptr %b, align 1
127 call void @end_struct_small_char()
128 %call16 = call i32 @get_struct_large_nonchar()
129 store i32 %call16, ptr %c, align 4
130 call void @end_struct_large_nonchar()
131 %call19 = call signext i16 @get_struct_small_nonchar()
132 store i16 %call19, ptr %d, align 2
133 call void @end_struct_small_nonchar()
134 %0 = load i32, ptr %x, align 4
135 %1 = load i32, ptr %y, align 4
136 %2 = load i32, ptr %z, align 4
137 %3 = load i64, ptr %a, align 1
138 %4 = load i16, ptr %b, align 1
139 %5 = load i32, ptr %d, align 1
140 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 4 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2)
144 define void @layout_sspstrong() sspstrong {
146 ; Expected stack layout for sspstrong is
147 ; 144 large_nonchar . Group 1, nested arrays,
148 ; 136 large_char . arrays >= ssp-buffer-size
149 ; 128 struct_large_char .
150 ; 96 struct_large_nonchar .
151 ; 84+8 small_non_char | Group 2, nested arrays,
152 ; 90 small_char | arrays < ssp-buffer-size
153 ; 88 struct_small_char |
154 ; 84 struct_small_nonchar |
155 ; 80 addrof * Group 3, addr-of local
156 ; 76 scalar1 + Group 4, everything else
160 ; CHECK: layout_sspstrong:
162 ; CHECK: bl get_scalar1
163 ; CHECK: str r0, [sp, #76]
164 ; CHECK: bl end_scalar1
166 ; CHECK: bl get_scalar2
167 ; CHECK: str r0, [sp, #72]
168 ; CHECK: bl end_scalar2
170 ; CHECK: bl get_scalar3
171 ; CHECK: str r0, [sp, #68]
172 ; CHECK: bl end_scalar3
174 ; CHECK: bl get_addrof
175 ; CHECK: str r0, [sp, #80]
176 ; CHECK: bl end_addrof
178 ; CHECK: get_small_nonchar
179 ; CHECK: strh r0, [sp, #92]
180 ; CHECK: bl end_small_nonchar
182 ; CHECK: bl get_large_nonchar
183 ; CHECK: str r0, [sp, #144]
184 ; CHECK: bl end_large_nonchar
186 ; CHECK: bl get_small_char
187 ; CHECK: strb r0, [sp, #90]
188 ; CHECK: bl end_small_char
190 ; CHECK: bl get_large_char
191 ; CHECK: strb r0, [sp, #136]
192 ; CHECK: bl end_large_char
194 ; CHECK: bl get_struct_large_char
195 ; CHECK: strb r0, [sp, #128]
196 ; CHECK: bl end_struct_large_char
198 ; CHECK: bl get_struct_small_char
199 ; CHECK: strb r0, [sp, #88]
200 ; CHECK: bl end_struct_small_char
202 ; CHECK: bl get_struct_large_nonchar
203 ; CHECK: str r0, [sp, #96]
204 ; CHECK: bl end_struct_large_nonchar
206 ; CHECK: bl get_struct_small_nonchar
207 ; CHECK: strh r0, [sp, #84]
208 ; CHECK: bl end_struct_small_nonchar
209 %x = alloca i32, align 4
210 %y = alloca i32, align 4
211 %z = alloca i32, align 4
212 %ptr = alloca i32, align 4
213 %small2 = alloca [2 x i16], align 2
214 %large2 = alloca [8 x i32], align 16
215 %small = alloca [2 x i8], align 1
216 %large = alloca [8 x i8], align 1
217 %a = alloca %struct.struct_large_char, align 1
218 %b = alloca %struct.struct_small_char, align 1
219 %c = alloca %struct.struct_large_nonchar, align 8
220 %d = alloca %struct.struct_small_nonchar, align 2
221 %call = call i32 @get_scalar1()
222 store i32 %call, ptr %x, align 4
223 call void @end_scalar1()
224 %call1 = call i32 @get_scalar2()
225 store i32 %call1, ptr %y, align 4
226 call void @end_scalar2()
227 %call2 = call i32 @get_scalar3()
228 store i32 %call2, ptr %z, align 4
229 call void @end_scalar3()
230 %call3 = call i32 @get_addrof()
231 store i32 %call3, ptr %ptr, align 4
232 call void @end_addrof()
233 %call4 = call signext i16 @get_small_nonchar()
234 store i16 %call4, ptr %small2, align 2
235 call void @end_small_nonchar()
236 %call5 = call i32 @get_large_nonchar()
237 store i32 %call5, ptr %large2, align 4
238 call void @end_large_nonchar()
239 %call7 = call signext i8 @get_small_char()
240 store i8 %call7, ptr %small, align 1
241 call void @end_small_char()
242 %call9 = call signext i8 @get_large_char()
243 store i8 %call9, ptr %large, align 1
244 call void @end_large_char()
245 %call11 = call signext i8 @get_struct_large_char()
246 store i8 %call11, ptr %a, align 1
247 call void @end_struct_large_char()
248 %call13 = call signext i8 @get_struct_small_char()
249 store i8 %call13, ptr %b, align 1
250 call void @end_struct_small_char()
251 %call16 = call i32 @get_struct_large_nonchar()
252 store i32 %call16, ptr %c, align 4
253 call void @end_struct_large_nonchar()
254 %call19 = call signext i16 @get_struct_small_nonchar()
255 store i16 %call19, ptr %d, align 2
256 call void @end_struct_small_nonchar()
257 %0 = load i32, ptr %x, align 4
258 %1 = load i32, ptr %y, align 4
259 %2 = load i32, ptr %z, align 4
260 %3 = load i64, ptr %a, align 1
261 %4 = load i16, ptr %b, align 1
262 %5 = load i32, ptr %d, align 1
263 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 4 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2)
267 define void @layout_sspreq() sspreq {
269 ; Expected stack layout for sspreq is the same as sspstrong
271 ; CHECK: layout_sspreq:
273 ; CHECK: bl get_scalar1
274 ; CHECK: str r0, [sp, #76]
275 ; CHECK: bl end_scalar1
277 ; CHECK: bl get_scalar2
278 ; CHECK: str r0, [sp, #72]
279 ; CHECK: bl end_scalar2
281 ; CHECK: bl get_scalar3
282 ; CHECK: str r0, [sp, #68]
283 ; CHECK: bl end_scalar3
285 ; CHECK: bl get_addrof
286 ; CHECK: str r0, [sp, #80]
287 ; CHECK: bl end_addrof
289 ; CHECK: get_small_nonchar
290 ; CHECK: strh r0, [sp, #92]
291 ; CHECK: bl end_small_nonchar
293 ; CHECK: bl get_large_nonchar
294 ; CHECK: str r0, [sp, #144]
295 ; CHECK: bl end_large_nonchar
297 ; CHECK: bl get_small_char
298 ; CHECK: strb r0, [sp, #90]
299 ; CHECK: bl end_small_char
301 ; CHECK: bl get_large_char
302 ; CHECK: strb r0, [sp, #136]
303 ; CHECK: bl end_large_char
305 ; CHECK: bl get_struct_large_char
306 ; CHECK: strb r0, [sp, #128]
307 ; CHECK: bl end_struct_large_char
309 ; CHECK: bl get_struct_small_char
310 ; CHECK: strb r0, [sp, #88]
311 ; CHECK: bl end_struct_small_char
313 ; CHECK: bl get_struct_large_nonchar
314 ; CHECK: str r0, [sp, #96]
315 ; CHECK: bl end_struct_large_nonchar
317 ; CHECK: bl get_struct_small_nonchar
318 ; CHECK: strh r0, [sp, #84]
319 ; CHECK: bl end_struct_small_nonchar
320 %x = alloca i32, align 4
321 %y = alloca i32, align 4
322 %z = alloca i32, align 4
323 %ptr = alloca i32, align 4
324 %small2 = alloca [2 x i16], align 2
325 %large2 = alloca [8 x i32], align 16
326 %small = alloca [2 x i8], align 1
327 %large = alloca [8 x i8], align 1
328 %a = alloca %struct.struct_large_char, align 1
329 %b = alloca %struct.struct_small_char, align 1
330 %c = alloca %struct.struct_large_nonchar, align 8
331 %d = alloca %struct.struct_small_nonchar, align 2
332 %call = call i32 @get_scalar1()
333 store i32 %call, ptr %x, align 4
334 call void @end_scalar1()
335 %call1 = call i32 @get_scalar2()
336 store i32 %call1, ptr %y, align 4
337 call void @end_scalar2()
338 %call2 = call i32 @get_scalar3()
339 store i32 %call2, ptr %z, align 4
340 call void @end_scalar3()
341 %call3 = call i32 @get_addrof()
342 store i32 %call3, ptr %ptr, align 4
343 call void @end_addrof()
344 %call4 = call signext i16 @get_small_nonchar()
345 store i16 %call4, ptr %small2, align 2
346 call void @end_small_nonchar()
347 %call5 = call i32 @get_large_nonchar()
348 store i32 %call5, ptr %large2, align 4
349 call void @end_large_nonchar()
350 %call7 = call signext i8 @get_small_char()
351 store i8 %call7, ptr %small, align 1
352 call void @end_small_char()
353 %call9 = call signext i8 @get_large_char()
354 store i8 %call9, ptr %large, align 1
355 call void @end_large_char()
356 %call11 = call signext i8 @get_struct_large_char()
357 store i8 %call11, ptr %a, align 1
358 call void @end_struct_large_char()
359 %call13 = call signext i8 @get_struct_small_char()
360 store i8 %call13, ptr %b, align 1
361 call void @end_struct_small_char()
362 %call16 = call i32 @get_struct_large_nonchar()
363 store i32 %call16, ptr %c, align 4
364 call void @end_struct_large_nonchar()
365 %call19 = call signext i16 @get_struct_small_nonchar()
366 store i16 %call19, ptr %d, align 2
367 call void @end_struct_small_nonchar()
368 %0 = load i32, ptr %x, align 4
369 %1 = load i32, ptr %y, align 4
370 %2 = load i32, ptr %z, align 4
371 %3 = load i64, ptr %a, align 1
372 %4 = load i16, ptr %b, align 1
373 %5 = load i32, ptr %d, align 1
374 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 4 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2)
378 define void @struct_with_protectable_arrays() sspstrong {
380 ; Check to ensure that a structure which contains a small array followed by a
381 ; large array is assigned to the stack properly as a large object.
382 ; CHECK: struct_with_protectable_arrays:
383 ; CHECK: bl get_struct_small_char
384 ; CHECK: strb r0, [sp, #68]
385 ; CHECK: bl end_struct_small_char
386 ; CHECK: bl get_struct_large_char2
387 ; CHECK: strb r0, [sp, #106]
388 ; CHECK: bl end_struct_large_char2
389 %a = alloca %struct.struct_small_char, align 4
390 %b = alloca %struct.struct_large_char2, align 4
391 %d1 = alloca %struct.struct_large_nonchar, align 8
392 %d2 = alloca %struct.struct_small_nonchar, align 2
393 %call = call signext i8 @get_struct_small_char()
394 store i8 %call, ptr %a, align 1
395 call void @end_struct_small_char()
396 %call1 = call signext i8 @get_struct_large_char2()
397 %foo2 = getelementptr inbounds %struct.struct_large_char2, ptr %b, i32 0, i32 1
398 store i8 %call1, ptr %foo2, align 1
399 call void @end_struct_large_char2()
400 %0 = load i64, ptr %b, align 1
401 %1 = load i16, ptr %a, align 1
402 %2 = load i32, ptr %d2, align 1
403 call void @takes_all(i64 %0, i16 %1, ptr byval(%struct.struct_large_nonchar) align 4 %d1, i32 %2, ptr null, ptr null, ptr null, ptr null, ptr null, i32 0, i32 0, i32 0)
407 declare i32 @get_scalar1()
408 declare void @end_scalar1()
410 declare i32 @get_scalar2()
411 declare void @end_scalar2()
413 declare i32 @get_scalar3()
414 declare void @end_scalar3()
416 declare i32 @get_addrof()
417 declare void @end_addrof()
419 declare signext i16 @get_small_nonchar()
420 declare void @end_small_nonchar()
422 declare i32 @get_large_nonchar()
423 declare void @end_large_nonchar()
425 declare signext i8 @get_small_char()
426 declare void @end_small_char()
428 declare signext i8 @get_large_char()
429 declare void @end_large_char()
431 declare signext i8 @get_struct_large_char()
432 declare void @end_struct_large_char()
434 declare signext i8 @get_struct_large_char2()
435 declare void @end_struct_large_char2()
437 declare signext i8 @get_struct_small_char()
438 declare void @end_struct_small_char()
440 declare i32 @get_struct_large_nonchar()
441 declare void @end_struct_large_nonchar()
443 declare signext i16 @get_struct_small_nonchar()
444 declare void @end_struct_small_nonchar()
446 declare void @takes_all(i64, i16, ptr byval(%struct.struct_large_nonchar) align 8, i32, ptr, ptr, ptr, ptr, ptr, i32, i32, i32)