[ARM] Cortex-M4 schedule additions
[llvm-complete.git] / test / CodeGen / ARM / ssp-data-layout.ll
blobfeb0189be9ed27920903f78e2a52e82dd409a9a1
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 ;  176 large_char          . Group 1, nested arrays, arrays >= ssp-buffer-size
25 ;  168 struct_large_char   .
26 ;  164 scalar1             | Everything else
27 ;  160 scalar2
28 ;  156 scalar3
29 ;  152 addr-of
30 ;  148 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, #164]
41 ; CHECK: bl end_scalar1
43 ; CHECK: bl get_scalar2
44 ; CHECK: str r0, [sp, #160]
45 ; CHECK: bl end_scalar2
47 ; CHECK: bl get_scalar3
48 ; CHECK: str r0, [sp, #156]
49 ; CHECK: bl end_scalar3
51 ; CHECK: bl get_addrof
52 ; CHECK: str r0, [sp, #152]
53 ; CHECK: bl end_addrof
55 ; CHECK: get_small_nonchar
56 ; CHECK: strh r0, [sp, #148]
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, #176]
69 ; CHECK: bl end_large_char
71 ; CHECK: bl get_struct_large_char
72 ; CHECK: strb r0, [sp, #168]
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, i32* %x, align 4
100   call void @end_scalar1()
101   %call1 = call i32 @get_scalar2()
102   store i32 %call1, i32* %y, align 4
103   call void @end_scalar2()
104   %call2 = call i32 @get_scalar3()
105   store i32 %call2, i32* %z, align 4
106   call void @end_scalar3()
107   %call3 = call i32 @get_addrof()
108   store i32 %call3, i32* %ptr, align 4
109   call void @end_addrof()
110   %call4 = call signext i16 @get_small_nonchar()
111   %arrayidx = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i64 0
112   store i16 %call4, i16* %arrayidx, align 2
113   call void @end_small_nonchar()
114   %call5 = call i32 @get_large_nonchar()
115   %arrayidx6 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i64 0
116   store i32 %call5, i32* %arrayidx6, align 4
117   call void @end_large_nonchar()
118   %call7 = call signext i8 @get_small_char()
119   %arrayidx8 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i64 0
120   store i8 %call7, i8* %arrayidx8, align 1
121   call void @end_small_char()
122   %call9 = call signext i8 @get_large_char()
123   %arrayidx10 = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i64 0
124   store i8 %call9, i8* %arrayidx10, align 1
125   call void @end_large_char()
126   %call11 = call signext i8 @get_struct_large_char()
127   %foo = getelementptr inbounds %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
128   %arrayidx12 = getelementptr inbounds [8 x i8], [8 x i8]* %foo, i32 0, i64 0
129   store i8 %call11, i8* %arrayidx12, align 1
130   call void @end_struct_large_char()
131   %call13 = call signext i8 @get_struct_small_char()
132   %foo14 = getelementptr inbounds %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
133   %arrayidx15 = getelementptr inbounds [2 x i8], [2 x i8]* %foo14, i32 0, i64 0
134   store i8 %call13, i8* %arrayidx15, align 1
135   call void @end_struct_small_char()
136   %call16 = call i32 @get_struct_large_nonchar()
137   %foo17 = getelementptr inbounds %struct.struct_large_nonchar, %struct.struct_large_nonchar* %c, i32 0, i32 0
138   %arrayidx18 = getelementptr inbounds [8 x i32], [8 x i32]* %foo17, i32 0, i64 0
139   store i32 %call16, i32* %arrayidx18, align 4
140   call void @end_struct_large_nonchar()
141   %call19 = call signext i16 @get_struct_small_nonchar()
142   %foo20 = getelementptr inbounds %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
143   %arrayidx21 = getelementptr inbounds [2 x i16], [2 x i16]* %foo20, i32 0, i64 0
144   store i16 %call19, i16* %arrayidx21, align 2
145   call void @end_struct_small_nonchar()
146   %arraydecay = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i32 0
147   %arraydecay22 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i32 0
148   %arraydecay23 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i32 0
149   %arraydecay24 = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i32 0
150   %0 = load i32, i32* %x, align 4
151   %1 = load i32, i32* %y, align 4
152   %2 = load i32, i32* %z, align 4
153   %coerce.dive = getelementptr %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
154   %3 = bitcast [8 x i8]* %coerce.dive to i64*
155   %4 = load i64, i64* %3, align 1
156   %coerce.dive25 = getelementptr %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
157   %5 = bitcast [2 x i8]* %coerce.dive25 to i16*
158   %6 = load i16, i16* %5, align 1
159   %coerce.dive26 = getelementptr %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
160   %7 = bitcast [2 x i16]* %coerce.dive26 to i32*
161   %8 = load i32, i32* %7, align 1
162   call void @takes_all(i64 %4, i16 %6, %struct.struct_large_nonchar* byval align 4 %c, i32 %8, i8* %arraydecay, i8* %arraydecay22, i32* %arraydecay23, i16* %arraydecay24, i32* %ptr, i32 %0, i32 %1, i32 %2)
163   ret void
166 define void @layout_sspstrong() sspstrong {
167 entry:
168 ; Expected stack layout for sspstrong is
169 ; 144  large_nonchar          . Group 1, nested arrays,
170 ; 136  large_char             .  arrays >= ssp-buffer-size
171 ; 128  struct_large_char      .
172 ; 96   struct_large_nonchar   .
173 ; 84+8 small_non_char         | Group 2, nested arrays, 
174 ; 90   small_char             |  arrays < ssp-buffer-size
175 ; 88   struct_small_char      |
176 ; 84   struct_small_nonchar   |
177 ; 80   addrof                 * Group 3, addr-of local
178 ; 76   scalar1                + Group 4, everything else
179 ; 72   scalar2                +
180 ; 68   scalar3                +
181 ;   
182 ; CHECK: layout_sspstrong:
184 ; CHECK: bl get_scalar1
185 ; CHECK: str r0, [sp, #76]
186 ; CHECK: bl end_scalar1
188 ; CHECK: bl get_scalar2
189 ; CHECK: str r0, [sp, #72]
190 ; CHECK: bl end_scalar2
192 ; CHECK: bl get_scalar3
193 ; CHECK: str r0, [sp, #68]
194 ; CHECK: bl end_scalar3
196 ; CHECK: bl get_addrof
197 ; CHECK: str r0, [sp, #80]
198 ; CHECK: bl end_addrof
200 ; CHECK: get_small_nonchar
201 ; CHECK: strh r0, [sp, #92]
202 ; CHECK: bl end_small_nonchar
204 ; CHECK: bl get_large_nonchar
205 ; CHECK: str r0, [sp, #144]
206 ; CHECK: bl end_large_nonchar
208 ; CHECK: bl get_small_char
209 ; CHECK: strb r0, [sp, #90]
210 ; CHECK: bl end_small_char
212 ; CHECK: bl get_large_char
213 ; CHECK: strb r0, [sp, #136]
214 ; CHECK: bl end_large_char
216 ; CHECK: bl get_struct_large_char
217 ; CHECK: strb r0, [sp, #128]
218 ; CHECK: bl end_struct_large_char
220 ; CHECK: bl get_struct_small_char
221 ; CHECK: strb r0, [sp, #88]
222 ; CHECK: bl end_struct_small_char
224 ; CHECK: bl get_struct_large_nonchar
225 ; CHECK: str r0, [sp, #96]
226 ; CHECK: bl end_struct_large_nonchar
228 ; CHECK: bl get_struct_small_nonchar
229 ; CHECK: strh r0, [sp, #84]
230 ; CHECK: bl end_struct_small_nonchar
231   %x = alloca i32, align 4
232   %y = alloca i32, align 4
233   %z = alloca i32, align 4
234   %ptr = alloca i32, align 4
235   %small2 = alloca [2 x i16], align 2
236   %large2 = alloca [8 x i32], align 16
237   %small = alloca [2 x i8], align 1
238   %large = alloca [8 x i8], align 1
239   %a = alloca %struct.struct_large_char, align 1
240   %b = alloca %struct.struct_small_char, align 1
241   %c = alloca %struct.struct_large_nonchar, align 8
242   %d = alloca %struct.struct_small_nonchar, align 2
243   %call = call i32 @get_scalar1()
244   store i32 %call, i32* %x, align 4
245   call void @end_scalar1()
246   %call1 = call i32 @get_scalar2()
247   store i32 %call1, i32* %y, align 4
248   call void @end_scalar2()
249   %call2 = call i32 @get_scalar3()
250   store i32 %call2, i32* %z, align 4
251   call void @end_scalar3()
252   %call3 = call i32 @get_addrof()
253   store i32 %call3, i32* %ptr, align 4
254   call void @end_addrof()
255   %call4 = call signext i16 @get_small_nonchar()
256   %arrayidx = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i64 0
257   store i16 %call4, i16* %arrayidx, align 2
258   call void @end_small_nonchar()
259   %call5 = call i32 @get_large_nonchar()
260   %arrayidx6 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i64 0
261   store i32 %call5, i32* %arrayidx6, align 4
262   call void @end_large_nonchar()
263   %call7 = call signext i8 @get_small_char()
264   %arrayidx8 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i64 0
265   store i8 %call7, i8* %arrayidx8, align 1
266   call void @end_small_char()
267   %call9 = call signext i8 @get_large_char()
268   %arrayidx10 = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i64 0
269   store i8 %call9, i8* %arrayidx10, align 1
270   call void @end_large_char()
271   %call11 = call signext i8 @get_struct_large_char()
272   %foo = getelementptr inbounds %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
273   %arrayidx12 = getelementptr inbounds [8 x i8], [8 x i8]* %foo, i32 0, i64 0
274   store i8 %call11, i8* %arrayidx12, align 1
275   call void @end_struct_large_char()
276   %call13 = call signext i8 @get_struct_small_char()
277   %foo14 = getelementptr inbounds %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
278   %arrayidx15 = getelementptr inbounds [2 x i8], [2 x i8]* %foo14, i32 0, i64 0
279   store i8 %call13, i8* %arrayidx15, align 1
280   call void @end_struct_small_char()
281   %call16 = call i32 @get_struct_large_nonchar()
282   %foo17 = getelementptr inbounds %struct.struct_large_nonchar, %struct.struct_large_nonchar* %c, i32 0, i32 0
283   %arrayidx18 = getelementptr inbounds [8 x i32], [8 x i32]* %foo17, i32 0, i64 0
284   store i32 %call16, i32* %arrayidx18, align 4
285   call void @end_struct_large_nonchar()
286   %call19 = call signext i16 @get_struct_small_nonchar()
287   %foo20 = getelementptr inbounds %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
288   %arrayidx21 = getelementptr inbounds [2 x i16], [2 x i16]* %foo20, i32 0, i64 0
289   store i16 %call19, i16* %arrayidx21, align 2
290   call void @end_struct_small_nonchar()
291   %arraydecay = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i32 0
292   %arraydecay22 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i32 0
293   %arraydecay23 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i32 0
294   %arraydecay24 = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i32 0
295   %0 = load i32, i32* %x, align 4
296   %1 = load i32, i32* %y, align 4
297   %2 = load i32, i32* %z, align 4
298   %coerce.dive = getelementptr %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
299   %3 = bitcast [8 x i8]* %coerce.dive to i64*
300   %4 = load i64, i64* %3, align 1
301   %coerce.dive25 = getelementptr %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
302   %5 = bitcast [2 x i8]* %coerce.dive25 to i16*
303   %6 = load i16, i16* %5, align 1
304   %coerce.dive26 = getelementptr %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
305   %7 = bitcast [2 x i16]* %coerce.dive26 to i32*
306   %8 = load i32, i32* %7, align 1
307   call void @takes_all(i64 %4, i16 %6, %struct.struct_large_nonchar* byval align 4 %c, i32 %8, i8* %arraydecay, i8* %arraydecay22, i32* %arraydecay23, i16* %arraydecay24, i32* %ptr, i32 %0, i32 %1, i32 %2)
308   ret void
311 define void @layout_sspreq() sspreq {
312 entry:
313 ; Expected stack layout for sspreq is the same as sspstrong
314 ;   
315 ; CHECK: layout_sspreq:
317 ; CHECK: bl get_scalar1
318 ; CHECK: str r0, [sp, #76]
319 ; CHECK: bl end_scalar1
321 ; CHECK: bl get_scalar2
322 ; CHECK: str r0, [sp, #72]
323 ; CHECK: bl end_scalar2
325 ; CHECK: bl get_scalar3
326 ; CHECK: str r0, [sp, #68]
327 ; CHECK: bl end_scalar3
329 ; CHECK: bl get_addrof
330 ; CHECK: str r0, [sp, #80]
331 ; CHECK: bl end_addrof
333 ; CHECK: get_small_nonchar
334 ; CHECK: strh r0, [sp, #92]
335 ; CHECK: bl end_small_nonchar
337 ; CHECK: bl get_large_nonchar
338 ; CHECK: str r0, [sp, #144]
339 ; CHECK: bl end_large_nonchar
341 ; CHECK: bl get_small_char
342 ; CHECK: strb r0, [sp, #90]
343 ; CHECK: bl end_small_char
345 ; CHECK: bl get_large_char
346 ; CHECK: strb r0, [sp, #136]
347 ; CHECK: bl end_large_char
349 ; CHECK: bl get_struct_large_char
350 ; CHECK: strb r0, [sp, #128]
351 ; CHECK: bl end_struct_large_char
353 ; CHECK: bl get_struct_small_char
354 ; CHECK: strb r0, [sp, #88]
355 ; CHECK: bl end_struct_small_char
357 ; CHECK: bl get_struct_large_nonchar
358 ; CHECK: str r0, [sp, #96]
359 ; CHECK: bl end_struct_large_nonchar
361 ; CHECK: bl get_struct_small_nonchar
362 ; CHECK: strh r0, [sp, #84]
363 ; CHECK: bl end_struct_small_nonchar
364   %x = alloca i32, align 4
365   %y = alloca i32, align 4
366   %z = alloca i32, align 4
367   %ptr = alloca i32, align 4
368   %small2 = alloca [2 x i16], align 2
369   %large2 = alloca [8 x i32], align 16
370   %small = alloca [2 x i8], align 1
371   %large = alloca [8 x i8], align 1
372   %a = alloca %struct.struct_large_char, align 1
373   %b = alloca %struct.struct_small_char, align 1
374   %c = alloca %struct.struct_large_nonchar, align 8
375   %d = alloca %struct.struct_small_nonchar, align 2
376   %call = call i32 @get_scalar1()
377   store i32 %call, i32* %x, align 4
378   call void @end_scalar1()
379   %call1 = call i32 @get_scalar2()
380   store i32 %call1, i32* %y, align 4
381   call void @end_scalar2()
382   %call2 = call i32 @get_scalar3()
383   store i32 %call2, i32* %z, align 4
384   call void @end_scalar3()
385   %call3 = call i32 @get_addrof()
386   store i32 %call3, i32* %ptr, align 4
387   call void @end_addrof()
388   %call4 = call signext i16 @get_small_nonchar()
389   %arrayidx = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i64 0
390   store i16 %call4, i16* %arrayidx, align 2
391   call void @end_small_nonchar()
392   %call5 = call i32 @get_large_nonchar()
393   %arrayidx6 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i64 0
394   store i32 %call5, i32* %arrayidx6, align 4
395   call void @end_large_nonchar()
396   %call7 = call signext i8 @get_small_char()
397   %arrayidx8 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i64 0
398   store i8 %call7, i8* %arrayidx8, align 1
399   call void @end_small_char()
400   %call9 = call signext i8 @get_large_char()
401   %arrayidx10 = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i64 0
402   store i8 %call9, i8* %arrayidx10, align 1
403   call void @end_large_char()
404   %call11 = call signext i8 @get_struct_large_char()
405   %foo = getelementptr inbounds %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
406   %arrayidx12 = getelementptr inbounds [8 x i8], [8 x i8]* %foo, i32 0, i64 0
407   store i8 %call11, i8* %arrayidx12, align 1
408   call void @end_struct_large_char()
409   %call13 = call signext i8 @get_struct_small_char()
410   %foo14 = getelementptr inbounds %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
411   %arrayidx15 = getelementptr inbounds [2 x i8], [2 x i8]* %foo14, i32 0, i64 0
412   store i8 %call13, i8* %arrayidx15, align 1
413   call void @end_struct_small_char()
414   %call16 = call i32 @get_struct_large_nonchar()
415   %foo17 = getelementptr inbounds %struct.struct_large_nonchar, %struct.struct_large_nonchar* %c, i32 0, i32 0
416   %arrayidx18 = getelementptr inbounds [8 x i32], [8 x i32]* %foo17, i32 0, i64 0
417   store i32 %call16, i32* %arrayidx18, align 4
418   call void @end_struct_large_nonchar()
419   %call19 = call signext i16 @get_struct_small_nonchar()
420   %foo20 = getelementptr inbounds %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
421   %arrayidx21 = getelementptr inbounds [2 x i16], [2 x i16]* %foo20, i32 0, i64 0
422   store i16 %call19, i16* %arrayidx21, align 2
423   call void @end_struct_small_nonchar()
424   %arraydecay = getelementptr inbounds [8 x i8], [8 x i8]* %large, i32 0, i32 0
425   %arraydecay22 = getelementptr inbounds [2 x i8], [2 x i8]* %small, i32 0, i32 0
426   %arraydecay23 = getelementptr inbounds [8 x i32], [8 x i32]* %large2, i32 0, i32 0
427   %arraydecay24 = getelementptr inbounds [2 x i16], [2 x i16]* %small2, i32 0, i32 0
428   %0 = load i32, i32* %x, align 4
429   %1 = load i32, i32* %y, align 4
430   %2 = load i32, i32* %z, align 4
431   %coerce.dive = getelementptr %struct.struct_large_char, %struct.struct_large_char* %a, i32 0, i32 0
432   %3 = bitcast [8 x i8]* %coerce.dive to i64*
433   %4 = load i64, i64* %3, align 1
434   %coerce.dive25 = getelementptr %struct.struct_small_char, %struct.struct_small_char* %b, i32 0, i32 0
435   %5 = bitcast [2 x i8]* %coerce.dive25 to i16*
436   %6 = load i16, i16* %5, align 1
437   %coerce.dive26 = getelementptr %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d, i32 0, i32 0
438   %7 = bitcast [2 x i16]* %coerce.dive26 to i32*
439   %8 = load i32, i32* %7, align 1
440   call void @takes_all(i64 %4, i16 %6, %struct.struct_large_nonchar* byval align 4 %c, i32 %8, i8* %arraydecay, i8* %arraydecay22, i32* %arraydecay23, i16* %arraydecay24, i32* %ptr, i32 %0, i32 %1, i32 %2)
441   ret void
444 define void @struct_with_protectable_arrays() sspstrong {
445 entry:
446 ; Check to ensure that a structure which contains a small array followed by a
447 ; large array is assigned to the stack properly as a large object.
448 ; CHECK: struct_with_protectable_arrays:
449 ; CHECK: bl get_struct_small_char
450 ; CHECK: strb r0, [sp, #68]
451 ; CHECK: bl end_struct_small_char
452 ; CHECK: bl get_struct_large_char2
453 ; CHECK: strb r0, [sp, #106]
454 ; CHECK: bl end_struct_large_char2
455   %a = alloca %struct.struct_small_char, align 1
456   %b = alloca %struct.struct_large_char2, align 1
457   %d1 = alloca %struct.struct_large_nonchar, align 8
458   %d2 = alloca %struct.struct_small_nonchar, align 2
459   %call = call signext i8 @get_struct_small_char()
460   %foo = getelementptr inbounds %struct.struct_small_char, %struct.struct_small_char* %a, i32 0, i32 0
461   %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %foo, i32 0, i64 0
462   store i8 %call, i8* %arrayidx, align 1
463   call void @end_struct_small_char()
464   %call1 = call signext i8 @get_struct_large_char2()
465   %foo2 = getelementptr inbounds %struct.struct_large_char2, %struct.struct_large_char2* %b, i32 0, i32 1
466   %arrayidx3 = getelementptr inbounds [8 x i8], [8 x i8]* %foo2, i32 0, i64 0
467   store i8 %call1, i8* %arrayidx3, align 1
468   call void @end_struct_large_char2()
469   %0 = bitcast %struct.struct_large_char2* %b to %struct.struct_large_char*
470   %coerce.dive = getelementptr %struct.struct_large_char, %struct.struct_large_char* %0, i32 0, i32 0
471   %1 = bitcast [8 x i8]* %coerce.dive to i64*
472   %2 = load i64, i64* %1, align 1
473   %coerce.dive4 = getelementptr %struct.struct_small_char, %struct.struct_small_char* %a, i32 0, i32 0
474   %3 = bitcast [2 x i8]* %coerce.dive4 to i16*
475   %4 = load i16, i16* %3, align 1
476   %coerce.dive5 = getelementptr %struct.struct_small_nonchar, %struct.struct_small_nonchar* %d2, i32 0, i32 0
477   %5 = bitcast [2 x i16]* %coerce.dive5 to i32*
478   %6 = load i32, i32* %5, align 1
479   call void @takes_all(i64 %2, i16 %4, %struct.struct_large_nonchar* byval align 4 %d1, i32 %6, i8* null, i8* null, i32* null, i16* null, i32* null, i32 0, i32 0, i32 0)
480   ret void
483 declare i32 @get_scalar1()
484 declare void @end_scalar1()
486 declare i32 @get_scalar2()
487 declare void @end_scalar2()
489 declare i32 @get_scalar3()
490 declare void @end_scalar3()
492 declare i32 @get_addrof()
493 declare void @end_addrof()
495 declare signext i16 @get_small_nonchar()
496 declare void @end_small_nonchar()
498 declare i32 @get_large_nonchar()
499 declare void @end_large_nonchar()
501 declare signext i8 @get_small_char()
502 declare void @end_small_char()
504 declare signext i8 @get_large_char()
505 declare void @end_large_char()
507 declare signext i8 @get_struct_large_char()
508 declare void @end_struct_large_char()
510 declare signext i8 @get_struct_large_char2()
511 declare void @end_struct_large_char2()
513 declare signext i8 @get_struct_small_char()
514 declare void @end_struct_small_char()
516 declare i32 @get_struct_large_nonchar()
517 declare void @end_struct_large_nonchar()
519 declare signext i16 @get_struct_small_nonchar()
520 declare void @end_struct_small_nonchar()
522 declare void @takes_all(i64, i16, %struct.struct_large_nonchar* byval align 8, i32, i8*, i8*, i32*, i16*, i32*, i32, i32, i32)