Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / CodeGen / ARM / ssp-data-layout.ll
blobc5f13a66c11ca224e76191b6cfbe2a9fd962f170
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 {
22 entry:
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
27 ;  164 scalar2
28 ;  160 scalar3
29 ;  156 addr-of
30 ;  152 small_nonchar
31 ;  112 large_nonchar
32 ;  110 small_char
33 ;  108 struct_small_char
34 ;   72 struct_large_nonchar
35 ;   68 struct_small_nonchar
37 ; CHECK: layout_ssp:
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)
141   ret void
144 define void @layout_sspstrong() sspstrong {
145 entry:
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
157 ; 72   scalar2                +
158 ; 68   scalar3                +
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)
264   ret void
267 define void @layout_sspreq() sspreq {
268 entry:
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)
375   ret void
378 define void @struct_with_protectable_arrays() sspstrong {
379 entry:
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)
404   ret void
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)