xref: /llvm-project/llvm/test/CodeGen/PowerPC/stack-guard-oob.ll (revision e018cbf7208b3d34f18997ddee84c66cee32fb1b)
1; RUN: llc -mtriple=powerpc64le -O0 < %s | FileCheck %s
2; RUN: llc -mtriple=powerpc64-ibm-aix-xcoff -O0 < %s | FileCheck %s --check-prefix=AIX
3; RUN: llc -mtriple=powerpc-ibm-aix-xcoff -O0 < %s | FileCheck %s --check-prefix=AIX
4
5; CHECK-LABEL: in_bounds:
6; CHECK-NOT: __stack_chk_guard
7; AIX-NOT: __ssp_canary_word
8define i32 @in_bounds() #0 {
9  %var = alloca i32, align 4
10  store i32 0, ptr %var, align 4
11  %ret = load i32, ptr %var, align 4
12  ret i32 %ret
13}
14
15; CHECK-LABEL: constant_out_of_bounds:
16; CHECK: __stack_chk_guard
17; AIX: __ssp_canary_word
18define i32 @constant_out_of_bounds() #0 {
19  %var = alloca i32, align 4
20  store i32 0, ptr %var, align 4
21  %gep = getelementptr inbounds i32, ptr %var, i32 1
22  %ret = load i32, ptr %gep, align 4
23  ret i32 %ret
24}
25
26; CHECK-LABEL: nonconstant_out_of_bounds:
27; CHECK: __stack_chk_guard
28; AIX: __ssp_canary_word
29define i32 @nonconstant_out_of_bounds(i32 %n) #0 {
30  %var = alloca i32, align 4
31  store i32 0, ptr %var, align 4
32  %gep = getelementptr inbounds i32, ptr %var, i32 %n
33  %ret = load i32, ptr %gep, align 4
34  ret i32 %ret
35}
36
37; CHECK-LABEL: phi_before_gep_in_bounds:
38; CHECK-NOT: __stack_chk_guard
39; AIX-NOT: __ssp_canary_word
40define i32 @phi_before_gep_in_bounds(i32 %k) #0 {
41entry:
42  %var1 = alloca i32, align 4
43  %var2 = alloca i32, align 4
44  store i32 0, ptr %var1, align 4
45  store i32 0, ptr %var2, align 4
46  %cmp = icmp ne i32 %k, 0
47  br i1 %cmp, label %if, label %then
48
49if:
50  br label %then
51
52then:
53  %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
54  %ret = load i32, ptr %ptr, align 4
55  ret i32 %ret
56}
57
58; CHECK-LABEL: phi_before_gep_constant_out_of_bounds:
59; CHECK: __stack_chk_guard
60; AIX: __ssp_canary_word
61define i32 @phi_before_gep_constant_out_of_bounds(i32 %k) #0 {
62entry:
63  %var1 = alloca i32, align 4
64  %var2 = alloca i32, align 4
65  store i32 0, ptr %var1, align 4
66  store i32 0, ptr %var2, align 4
67  %cmp = icmp ne i32 %k, 0
68  br i1 %cmp, label %if, label %then
69
70if:
71  br label %then
72
73then:
74  %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
75  %gep = getelementptr inbounds i32, ptr %ptr, i32 1
76  %ret = load i32, ptr %gep, align 4
77  ret i32 %ret
78}
79
80; CHECK-LABEL: phi_before_gep_nonconstant_out_of_bounds:
81; CHECK: __stack_chk_guard
82; AIX: __ssp_canary_word
83define i32 @phi_before_gep_nonconstant_out_of_bounds(i32 %k, i32 %n) #0 {
84entry:
85  %var1 = alloca i32, align 4
86  %var2 = alloca i32, align 4
87  store i32 0, ptr %var1, align 4
88  store i32 0, ptr %var2, align 4
89  %cmp = icmp ne i32 %k, 0
90  br i1 %cmp, label %if, label %then
91
92if:
93  br label %then
94
95then:
96  %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
97  %gep = getelementptr inbounds i32, ptr %ptr, i32 %n
98  %ret = load i32, ptr %gep, align 4
99  ret i32 %ret
100}
101
102; CHECK-LABEL: phi_after_gep_in_bounds:
103; CHECK-NOT: __stack_chk_guard
104; AIX-NOT: __ssp_canary_word
105define i32 @phi_after_gep_in_bounds(i32 %k) #0 {
106entry:
107  %var1 = alloca i32, align 4
108  %var2 = alloca i32, align 4
109  store i32 0, ptr %var1, align 4
110  store i32 0, ptr %var2, align 4
111  %cmp = icmp ne i32 %k, 0
112  br i1 %cmp, label %if, label %else
113
114if:
115  br label %then
116
117else:
118  br label %then
119
120then:
121  %ptr = phi ptr [ %var1, %if ], [ %var2, %else ]
122  %ret = load i32, ptr %ptr, align 4
123  ret i32 %ret
124}
125
126; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_a:
127; CHECK: __stack_chk_guard
128; AIX: __ssp_canary_word
129define i32 @phi_after_gep_constant_out_of_bounds_a(i32 %k) #0 {
130entry:
131  %var1 = alloca i32, align 4
132  %var2 = alloca i32, align 4
133  store i32 0, ptr %var1, align 4
134  store i32 0, ptr %var2, align 4
135  %cmp = icmp ne i32 %k, 0
136  br i1 %cmp, label %if, label %else
137
138if:
139  br label %then
140
141else:
142  %gep2 = getelementptr inbounds i32, ptr %var2, i32 1
143  br label %then
144
145then:
146  %ptr = phi ptr [ %var1, %if ], [ %gep2, %else ]
147  %ret = load i32, ptr %ptr, align 4
148  ret i32 %ret
149}
150
151; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_b:
152; CHECK: __stack_chk_guard
153; AIX: __ssp_canary_word
154define i32 @phi_after_gep_constant_out_of_bounds_b(i32 %k) #0 {
155entry:
156  %var1 = alloca i32, align 4
157  %var2 = alloca i32, align 4
158  store i32 0, ptr %var1, align 4
159  store i32 0, ptr %var2, align 4
160  %cmp = icmp ne i32 %k, 0
161  br i1 %cmp, label %if, label %else
162
163if:
164  %gep1 = getelementptr inbounds i32, ptr %var1, i32 1
165  br label %then
166
167else:
168  br label %then
169
170then:
171  %ptr = phi ptr [ %gep1, %if ], [ %var2, %else ]
172  %ret = load i32, ptr %ptr, align 4
173  ret i32 %ret
174}
175
176; CHECK-LABEL: phi_different_types_a:
177; CHECK: __stack_chk_guard
178; AIX: __ssp_canary_word
179define i64 @phi_different_types_a(i32 %k) #0 {
180entry:
181  %var1 = alloca i64, align 4
182  %var2 = alloca i32, align 4
183  store i64 0, ptr %var1, align 4
184  store i32 0, ptr %var2, align 4
185  %cmp = icmp ne i32 %k, 0
186  br i1 %cmp, label %if, label %then
187
188if:
189  br label %then
190
191then:
192  %ptr = phi ptr [ %var1, %entry ], [ %var2, %if ]
193  %ret = load i64, ptr %ptr, align 4
194  ret i64 %ret
195}
196
197; CHECK-LABEL: phi_different_types_b:
198; CHECK: __stack_chk_guard
199; AIX: __ssp_canary_word
200define i64 @phi_different_types_b(i32 %k) #0 {
201entry:
202  %var1 = alloca i32, align 4
203  %var2 = alloca i64, align 4
204  store i32 0, ptr %var1, align 4
205  store i64 0, ptr %var2, align 4
206  %cmp = icmp ne i32 %k, 0
207  br i1 %cmp, label %if, label %then
208
209if:
210  br label %then
211
212then:
213  %ptr = phi ptr [ %var2, %entry ], [ %var1, %if ]
214  %ret = load i64, ptr %ptr, align 4
215  ret i64 %ret
216}
217
218; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_a:
219; CHECK: __stack_chk_guard
220; AIX: __ssp_canary_word
221define i32 @phi_after_gep_nonconstant_out_of_bounds_a(i32 %k, i32 %n) #0 {
222entry:
223  %var1 = alloca i32, align 4
224  %var2 = alloca i32, align 4
225  store i32 0, ptr %var1, align 4
226  store i32 0, ptr %var2, align 4
227  %cmp = icmp ne i32 %k, 0
228  br i1 %cmp, label %if, label %else
229
230if:
231  br label %then
232
233else:
234  %gep2 = getelementptr inbounds i32, ptr %var2, i32 %n
235  br label %then
236
237then:
238  %ptr = phi ptr [ %var1, %if ], [ %gep2, %else ]
239  %ret = load i32, ptr %ptr, align 4
240  ret i32 %ret
241}
242
243; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_b:
244; CHECK: __stack_chk_guard
245; AIX: __ssp_canary_word
246define i32 @phi_after_gep_nonconstant_out_of_bounds_b(i32 %k, i32 %n) #0 {
247entry:
248  %var1 = alloca i32, align 4
249  %var2 = alloca i32, align 4
250  store i32 0, ptr %var1, align 4
251  store i32 0, ptr %var2, align 4
252  %cmp = icmp ne i32 %k, 0
253  br i1 %cmp, label %if, label %else
254
255if:
256  %gep1 = getelementptr inbounds i32, ptr %var1, i32 %n
257  br label %then
258
259else:
260  br label %then
261
262then:
263  %ptr = phi ptr [ %gep1, %if ], [ %var2, %else ]
264  %ret = load i32, ptr %ptr, align 4
265  ret i32 %ret
266}
267
268%struct.outer = type { %struct.inner, %struct.inner }
269%struct.inner = type { i32, i32 }
270
271; CHECK-LABEL: struct_in_bounds:
272; CHECK-NOT: __stack_chk_guard
273; AIX-NOT: __ssp_canary_word
274define void @struct_in_bounds() #0 {
275  %var = alloca %struct.outer, align 4
276  %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 0, i32 1
277  %innergep = getelementptr inbounds %struct.inner, ptr %outergep, i32 0, i32 1
278  store i32 0, ptr %innergep, align 4
279  ret void
280}
281
282; CHECK-LABEL: struct_constant_out_of_bounds_a:
283; CHECK: __stack_chk_guard
284; AIX: __ssp_canary_word
285define void @struct_constant_out_of_bounds_a() #0 {
286  %var = alloca %struct.outer, align 4
287  %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 1, i32 0
288  store i32 0, ptr %outergep, align 4
289  ret void
290}
291
292; CHECK-LABEL: struct_constant_out_of_bounds_b:
293; Here the offset is out-of-bounds of the addressed struct.inner member, but
294; still within bounds of the outer struct so no stack guard is needed.
295; CHECK-NOT: __stack_chk_guard
296; AIX-NOT: __ssp_canary_word
297define void @struct_constant_out_of_bounds_b() #0 {
298  %var = alloca %struct.outer, align 4
299  %innergep = getelementptr inbounds %struct.inner, ptr %var, i32 1, i32 0
300  store i32 0, ptr %innergep, align 4
301  ret void
302}
303
304; CHECK-LABEL: struct_constant_out_of_bounds_c:
305; Here we are out-of-bounds of both the inner and outer struct.
306; CHECK: __stack_chk_guard
307; AIX: __ssp_canary_word
308define void @struct_constant_out_of_bounds_c() #0 {
309  %var = alloca %struct.outer, align 4
310  %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 0, i32 1
311  %innergep = getelementptr inbounds %struct.inner, ptr %outergep, i32 1, i32 0
312  store i32 0, ptr %innergep, align 4
313  ret void
314}
315
316; CHECK-LABEL: struct_nonconstant_out_of_bounds_a:
317; CHECK: __stack_chk_guard
318; AIX: __ssp_canary_word
319define void @struct_nonconstant_out_of_bounds_a(i32 %n) #0 {
320  %var = alloca %struct.outer, align 4
321  %outergep = getelementptr inbounds %struct.outer, ptr %var, i32 %n, i32 0
322  store i32 0, ptr %outergep, align 4
323  ret void
324}
325
326; CHECK-LABEL: struct_nonconstant_out_of_bounds_b:
327; CHECK: __stack_chk_guard
328; AIX: __ssp_canary_word
329define void @struct_nonconstant_out_of_bounds_b(i32 %n) #0 {
330  %var = alloca %struct.outer, align 4
331  %innergep = getelementptr inbounds %struct.inner, ptr %var, i32 %n, i32 0
332  store i32 0, ptr %innergep, align 4
333  ret void
334}
335
336; CHECK-LABEL: bitcast_smaller_load
337; CHECK-NOT: __stack_chk_guard
338; AIX-NOT: __ssp_canary_word
339define i32 @bitcast_smaller_load() #0 {
340  %var = alloca i64, align 4
341  store i64 0, ptr %var, align 4
342  %ret = load i32, ptr %var, align 4
343  ret i32 %ret
344}
345
346; CHECK-LABEL: bitcast_same_size_load
347; CHECK-NOT: __stack_chk_guard
348; AIX-NOT: __ssp_canary_word
349define i32 @bitcast_same_size_load() #0 {
350  %var = alloca i64, align 4
351  store i64 0, ptr %var, align 4
352  %gep = getelementptr inbounds %struct.inner, ptr %var, i32 0, i32 1
353  %ret = load i32, ptr %gep, align 4
354  ret i32 %ret
355}
356
357; CHECK-LABEL: bitcast_larger_load
358; CHECK: __stack_chk_guard
359; AIX: __ssp_canary_word
360define i64 @bitcast_larger_load() #0 {
361  %var = alloca i32, align 4
362  store i32 0, ptr %var, align 4
363  %ret = load i64, ptr %var, align 4
364  ret i64 %ret
365}
366
367; CHECK-LABEL: bitcast_larger_store
368; CHECK: __stack_chk_guard
369; AIX: __ssp_canary_word
370define i32 @bitcast_larger_store() #0 {
371  %var = alloca i32, align 4
372  store i64 0, ptr %var, align 4
373  %ret = load i32, ptr %var, align 4
374  ret i32 %ret
375}
376
377; CHECK-LABEL: bitcast_larger_cmpxchg
378; CHECK: __stack_chk_guard
379; AIX: __ssp_canary_word
380define i64 @bitcast_larger_cmpxchg(i64 %desired, i64 %new) #0 {
381  %var = alloca i32, align 4
382  %pair = cmpxchg ptr %var, i64 %desired, i64 %new seq_cst monotonic
383  %ret = extractvalue { i64, i1 } %pair, 0
384  ret i64 %ret
385}
386
387; CHECK-LABEL: bitcast_larger_atomic_rmw
388; CHECK: __stack_chk_guard
389; AIX: __ssp_canary_word
390define i64 @bitcast_larger_atomic_rmw() #0 {
391  %var = alloca i32, align 4
392  %ret = atomicrmw add ptr %var, i64 1 monotonic
393  ret i64 %ret
394}
395
396%struct.packed = type <{ i16, i32 }>
397
398; CHECK-LABEL: bitcast_overlap
399; CHECK: __stack_chk_guard
400; AIX: __ssp_canary_word
401define i32 @bitcast_overlap() #0 {
402  %var = alloca i32, align 4
403  %gep = getelementptr inbounds %struct.packed, ptr %var, i32 0, i32 1
404  %ret = load i32, ptr %gep, align 2
405  ret i32 %ret
406}
407
408%struct.multi_dimensional = type { [10 x [10 x i32]], i32 }
409
410; CHECK-LABEL: multi_dimensional_array
411; CHECK: __stack_chk_guard
412; AIX: __ssp_canary_word
413define i32 @multi_dimensional_array() #0 {
414  %var = alloca %struct.multi_dimensional, align 4
415  %gep2 = getelementptr inbounds [10 x [10 x i32]], ptr %var, i32 0, i32 10
416  %gep3 = getelementptr inbounds [10 x i32], ptr %gep2, i32 0, i32 5
417  %ret = load i32, ptr %gep3, align 4
418  ret i32 %ret
419}
420
421attributes #0 = { sspstrong }
422
423!llvm.module.flags = !{!0}
424!0 = !{i32 7, !"direct-access-external-data", i32 1}
425