[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / CodeGen / X86 / stack-guard-oob.ll
blob74eb69328e6ddafbf4a49d21d0bd681db8786379
1 ; RUN: llc -mtriple=i686 -O0 < %s | FileCheck %s
2 ; RUN: llc -mtriple=x86_64 -O0 < %s | FileCheck %s
4 ; CHECK-LABEL: in_bounds:
5 ; CHECK-NOT: __stack_chk_guard
6 define i32 @in_bounds() #0 {
7   %var = alloca i32, align 4
8   store i32 0, i32* %var, align 4
9   %gep = getelementptr inbounds i32, i32* %var, i32 0
10   %ret = load i32, i32* %gep, align 4
11   ret i32 %ret
14 ; CHECK-LABEL: constant_out_of_bounds:
15 ; CHECK: __stack_chk_guard
16 define i32 @constant_out_of_bounds() #0 {
17   %var = alloca i32, align 4
18   store i32 0, i32* %var, align 4
19   %gep = getelementptr inbounds i32, i32* %var, i32 1
20   %ret = load i32, i32* %gep, align 4
21   ret i32 %ret
24 ; CHECK-LABEL: nonconstant_out_of_bounds:
25 ; CHECK: __stack_chk_guard
26 define i32 @nonconstant_out_of_bounds(i32 %n) #0 {
27   %var = alloca i32, align 4
28   store i32 0, i32* %var, align 4
29   %gep = getelementptr inbounds i32, i32* %var, i32 %n
30   %ret = load i32, i32* %gep, align 4
31   ret i32 %ret
34 ; CHECK-LABEL: phi_before_gep_in_bounds:
35 ; CHECK-NOT: __stack_chk_guard
36 define i32 @phi_before_gep_in_bounds(i32 %k) #0 {
37 entry:
38   %var1 = alloca i32, align 4
39   %var2 = alloca i32, align 4
40   store i32 0, i32* %var1, align 4
41   store i32 0, i32* %var2, align 4
42   %cmp = icmp ne i32 %k, 0
43   br i1 %cmp, label %if, label %then
45 if:
46   br label %then
48 then:
49   %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
50   %gep = getelementptr inbounds i32, i32* %ptr, i32 0
51   %ret = load i32, i32* %gep, align 4
52   ret i32 %ret
55 ; CHECK-LABEL: phi_before_gep_constant_out_of_bounds:
56 ; CHECK: __stack_chk_guard
57 define i32 @phi_before_gep_constant_out_of_bounds(i32 %k) #0 {
58 entry:
59   %var1 = alloca i32, align 4
60   %var2 = alloca i32, align 4
61   store i32 0, i32* %var1, align 4
62   store i32 0, i32* %var2, align 4
63   %cmp = icmp ne i32 %k, 0
64   br i1 %cmp, label %if, label %then
66 if:
67   br label %then
69 then:
70   %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
71   %gep = getelementptr inbounds i32, i32* %ptr, i32 1
72   %ret = load i32, i32* %gep, align 4
73   ret i32 %ret
76 ; CHECK-LABEL: phi_before_gep_nonconstant_out_of_bounds:
77 ; CHECK: __stack_chk_guard
78 define i32 @phi_before_gep_nonconstant_out_of_bounds(i32 %k, i32 %n) #0 {
79 entry:
80   %var1 = alloca i32, align 4
81   %var2 = alloca i32, align 4
82   store i32 0, i32* %var1, align 4
83   store i32 0, i32* %var2, align 4
84   %cmp = icmp ne i32 %k, 0
85   br i1 %cmp, label %if, label %then
87 if:
88   br label %then
90 then:
91   %ptr = phi i32* [ %var1, %entry ], [ %var2, %if ]
92   %gep = getelementptr inbounds i32, i32* %ptr, i32 %n
93   %ret = load i32, i32* %gep, align 4
94   ret i32 %ret
97 ; CHECK-LABEL: phi_after_gep_in_bounds:
98 ; CHECK-NOT: __stack_chk_guard
99 define i32 @phi_after_gep_in_bounds(i32 %k) #0 {
100 entry:
101   %var1 = alloca i32, align 4
102   %var2 = alloca i32, align 4
103   store i32 0, i32* %var1, align 4
104   store i32 0, i32* %var2, align 4
105   %cmp = icmp ne i32 %k, 0
106   br i1 %cmp, label %if, label %else
109   %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
110   br label %then
112 else:
113   %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
114   br label %then
116 then:
117   %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
118   %ret = load i32, i32* %ptr, align 4
119   ret i32 %ret
122 ; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_a:
123 ; CHECK: __stack_chk_guard
124 define i32 @phi_after_gep_constant_out_of_bounds_a(i32 %k) #0 {
125 entry:
126   %var1 = alloca i32, align 4
127   %var2 = alloca i32, align 4
128   store i32 0, i32* %var1, align 4
129   store i32 0, i32* %var2, align 4
130   %cmp = icmp ne i32 %k, 0
131   br i1 %cmp, label %if, label %else
134   %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
135   br label %then
137 else:
138   %gep2 = getelementptr inbounds i32, i32* %var2, i32 1
139   br label %then
141 then:
142   %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
143   %ret = load i32, i32* %ptr, align 4
144   ret i32 %ret
147 ; CHECK-LABEL: phi_after_gep_constant_out_of_bounds_b:
148 ; CHECK: __stack_chk_guard
149 define i32 @phi_after_gep_constant_out_of_bounds_b(i32 %k) #0 {
150 entry:
151   %var1 = alloca i32, align 4
152   %var2 = alloca i32, align 4
153   store i32 0, i32* %var1, align 4
154   store i32 0, i32* %var2, align 4
155   %cmp = icmp ne i32 %k, 0
156   br i1 %cmp, label %if, label %else
159   %gep1 = getelementptr inbounds i32, i32* %var1, i32 1
160   br label %then
162 else:
163   %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
164   br label %then
166 then:
167   %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
168   %ret = load i32, i32* %ptr, align 4
169   ret i32 %ret
172 ; CHECK-LABEL: phi_different_types_a:
173 ; CHECK: __stack_chk_guard
174 define i64 @phi_different_types_a(i32 %k) #0 {
175 entry:
176   %var1 = alloca i64, align 4
177   %var2 = alloca i32, align 4
178   store i64 0, i64* %var1, align 4
179   store i32 0, i32* %var2, align 4
180   %cmp = icmp ne i32 %k, 0
181   br i1 %cmp, label %if, label %then
184   %bitcast = bitcast i32* %var2 to i64*
185   br label %then
187 then:
188   %ptr = phi i64* [ %var1, %entry ], [ %bitcast, %if ]
189   %ret = load i64, i64* %ptr, align 4
190   ret i64 %ret
193 ; CHECK-LABEL: phi_different_types_b:
194 ; CHECK: __stack_chk_guard
195 define i64 @phi_different_types_b(i32 %k) #0 {
196 entry:
197   %var1 = alloca i32, align 4
198   %var2 = alloca i64, align 4
199   store i32 0, i32* %var1, align 4
200   store i64 0, i64* %var2, align 4
201   %cmp = icmp ne i32 %k, 0
202   br i1 %cmp, label %if, label %then
205   %bitcast = bitcast i32* %var1 to i64*
206   br label %then
208 then:
209   %ptr = phi i64* [ %var2, %entry ], [ %bitcast, %if ]
210   %ret = load i64, i64* %ptr, align 4
211   ret i64 %ret
214 ; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_a:
215 ; CHECK: __stack_chk_guard
216 define i32 @phi_after_gep_nonconstant_out_of_bounds_a(i32 %k, i32 %n) #0 {
217 entry:
218   %var1 = alloca i32, align 4
219   %var2 = alloca i32, align 4
220   store i32 0, i32* %var1, align 4
221   store i32 0, i32* %var2, align 4
222   %cmp = icmp ne i32 %k, 0
223   br i1 %cmp, label %if, label %else
226   %gep1 = getelementptr inbounds i32, i32* %var1, i32 0
227   br label %then
229 else:
230   %gep2 = getelementptr inbounds i32, i32* %var2, i32 %n
231   br label %then
233 then:
234   %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
235   %ret = load i32, i32* %ptr, align 4
236   ret i32 %ret
239 ; CHECK-LABEL: phi_after_gep_nonconstant_out_of_bounds_b:
240 ; CHECK: __stack_chk_guard
241 define i32 @phi_after_gep_nonconstant_out_of_bounds_b(i32 %k, i32 %n) #0 {
242 entry:
243   %var1 = alloca i32, align 4
244   %var2 = alloca i32, align 4
245   store i32 0, i32* %var1, align 4
246   store i32 0, i32* %var2, align 4
247   %cmp = icmp ne i32 %k, 0
248   br i1 %cmp, label %if, label %else
251   %gep1 = getelementptr inbounds i32, i32* %var1, i32 %n
252   br label %then
254 else:
255   %gep2 = getelementptr inbounds i32, i32* %var2, i32 0
256   br label %then
258 then:
259   %ptr = phi i32* [ %gep1, %if ], [ %gep2, %else ]
260   %ret = load i32, i32* %ptr, align 4
261   ret i32 %ret
264 %struct.outer = type { %struct.inner, %struct.inner }
265 %struct.inner = type { i32, i32 }
267 ; CHECK-LABEL: struct_in_bounds:
268 ; CHECK-NOT: __stack_chk_guard
269 define void @struct_in_bounds() #0 {
270   %var = alloca %struct.outer, align 4
271   %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1
272   %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 1
273   store i32 0, i32* %innergep, align 4
274   ret void
277 ; CHECK-LABEL: struct_constant_out_of_bounds_a:
278 ; CHECK: __stack_chk_guard
279 define void @struct_constant_out_of_bounds_a() #0 {
280   %var = alloca %struct.outer, align 4
281   %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 1, i32 0
282   %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0
283   store i32 0, i32* %innergep, align 4
284   ret void
287 ; CHECK-LABEL: struct_constant_out_of_bounds_b:
288 ; Here the offset is out-of-bounds of the addressed struct.inner member, but
289 ; still within bounds of the outer struct so no stack guard is needed.
290 ; CHECK-NOT: __stack_chk_guard
291 define void @struct_constant_out_of_bounds_b() #0 {
292   %var = alloca %struct.outer, align 4
293   %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0
294   %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0
295   store i32 0, i32* %innergep, align 4
296   ret void
299 ; CHECK-LABEL: struct_constant_out_of_bounds_c:
300 ; Here we are out-of-bounds of both the inner and outer struct.
301 ; CHECK: __stack_chk_guard
302 define void @struct_constant_out_of_bounds_c() #0 {
303   %var = alloca %struct.outer, align 4
304   %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 1
305   %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 1, i32 0
306   store i32 0, i32* %innergep, align 4
307   ret void
310 ; CHECK-LABEL: struct_nonconstant_out_of_bounds_a:
311 ; CHECK: __stack_chk_guard
312 define void @struct_nonconstant_out_of_bounds_a(i32 %n) #0 {
313   %var = alloca %struct.outer, align 4
314   %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 %n, i32 0
315   %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 0, i32 0
316   store i32 0, i32* %innergep, align 4
317   ret void
320 ; CHECK-LABEL: struct_nonconstant_out_of_bounds_b:
321 ; CHECK: __stack_chk_guard
322 define void @struct_nonconstant_out_of_bounds_b(i32 %n) #0 {
323   %var = alloca %struct.outer, align 4
324   %outergep = getelementptr inbounds %struct.outer, %struct.outer* %var, i32 0, i32 0
325   %innergep = getelementptr inbounds %struct.inner, %struct.inner* %outergep, i32 %n, i32 0
326   store i32 0, i32* %innergep, align 4
327   ret void
330 ; CHECK-LABEL: bitcast_smaller_load
331 ; CHECK-NOT: __stack_chk_guard
332 define i32 @bitcast_smaller_load() #0 {
333   %var = alloca i64, align 4
334   store i64 0, i64* %var, align 4
335   %bitcast = bitcast i64* %var to i32*
336   %ret = load i32, i32* %bitcast, align 4
337   ret i32 %ret
340 ; CHECK-LABEL: bitcast_same_size_load
341 ; CHECK-NOT: __stack_chk_guard
342 define i32 @bitcast_same_size_load() #0 {
343   %var = alloca i64, align 4
344   store i64 0, i64* %var, align 4
345   %bitcast = bitcast i64* %var to %struct.inner*
346   %gep = getelementptr inbounds %struct.inner, %struct.inner* %bitcast, i32 0, i32 1
347   %ret = load i32, i32* %gep, align 4
348   ret i32 %ret
351 ; CHECK-LABEL: bitcast_larger_load
352 ; CHECK: __stack_chk_guard
353 define i64 @bitcast_larger_load() #0 {
354   %var = alloca i32, align 4
355   store i32 0, i32* %var, align 4
356   %bitcast = bitcast i32* %var to i64*
357   %ret = load i64, i64* %bitcast, align 4
358   ret i64 %ret
361 ; CHECK-LABEL: bitcast_larger_store
362 ; CHECK: __stack_chk_guard
363 define i32 @bitcast_larger_store() #0 {
364   %var = alloca i32, align 4
365   %bitcast = bitcast i32* %var to i64*
366   store i64 0, i64* %bitcast, align 4
367   %ret = load i32, i32* %var, align 4
368   ret i32 %ret
371 ; CHECK-LABEL: bitcast_larger_cmpxchg
372 ; CHECK: __stack_chk_guard
373 define i64 @bitcast_larger_cmpxchg(i64 %desired, i64 %new) #0 {
374   %var = alloca i32, align 4
375   %bitcast = bitcast i32* %var to i64*
376   %pair = cmpxchg i64* %bitcast, i64 %desired, i64 %new seq_cst monotonic
377   %ret = extractvalue { i64, i1 } %pair, 0
378   ret i64 %ret
381 ; CHECK-LABEL: bitcast_larger_atomic_rmw
382 ; CHECK: __stack_chk_guard
383 define i64 @bitcast_larger_atomic_rmw() #0 {
384   %var = alloca i32, align 4
385   %bitcast = bitcast i32* %var to i64*
386   %ret = atomicrmw add i64* %bitcast, i64 1 monotonic
387   ret i64 %ret
390 %struct.packed = type <{ i16, i32 }>
392 ; CHECK-LABEL: bitcast_overlap
393 ; CHECK: __stack_chk_guard
394 define i32 @bitcast_overlap() #0 {
395   %var = alloca i32, align 4
396   %bitcast = bitcast i32* %var to %struct.packed*
397   %gep = getelementptr inbounds %struct.packed, %struct.packed* %bitcast, i32 0, i32 1
398   %ret = load i32, i32* %gep, align 2
399   ret i32 %ret
402 %struct.multi_dimensional = type { [10 x [10 x i32]], i32 }
404 ; CHECK-LABEL: multi_dimensional_array
405 ; CHECK: __stack_chk_guard
406 define i32 @multi_dimensional_array() #0 {
407   %var = alloca %struct.multi_dimensional, align 4
408   %gep1 = getelementptr inbounds %struct.multi_dimensional, %struct.multi_dimensional* %var, i32 0, i32 0
409   %gep2 = getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* %gep1, i32 0, i32 10
410   %gep3 = getelementptr inbounds [10 x i32], [10 x i32]* %gep2, i32 0, i32 5
411   %ret = load i32, i32* %gep3, align 4
412   ret i32 %ret
415 attributes #0 = { sspstrong }