1 ; RUN: opt -S -analyze -stack-safety-local < %s | FileCheck %s
2 ; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s
3 ; RUN: opt -S -analyze -stack-safety < %s | FileCheck %s
4 ; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s
6 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7 target triple = "x86_64-unknown-linux-gnu"
9 declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile)
10 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
11 declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile)
13 define void @MemsetInBounds() {
14 ; CHECK-LABEL: MemsetInBounds dso_preemptable{{$}}
15 ; CHECK-NEXT: args uses:
16 ; CHECK-NEXT: allocas uses:
17 ; CHECK-NEXT: x[4]: [0,4){{$}}
20 %x = alloca i32, align 4
21 %x1 = bitcast i32* %x to i8*
22 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 4, i1 false)
26 ; Volatile does not matter for access bounds.
27 define void @VolatileMemsetInBounds() {
28 ; CHECK-LABEL: VolatileMemsetInBounds dso_preemptable{{$}}
29 ; CHECK-NEXT: args uses:
30 ; CHECK-NEXT: allocas uses:
31 ; CHECK-NEXT: x[4]: [0,4){{$}}
34 %x = alloca i32, align 4
35 %x1 = bitcast i32* %x to i8*
36 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 4, i1 true)
40 define void @MemsetOutOfBounds() {
41 ; CHECK-LABEL: MemsetOutOfBounds dso_preemptable{{$}}
42 ; CHECK-NEXT: args uses:
43 ; CHECK-NEXT: allocas uses:
44 ; CHECK-NEXT: x[4]: [0,5){{$}}
47 %x = alloca i32, align 4
48 %x1 = bitcast i32* %x to i8*
49 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 5, i1 false)
53 define void @MemsetNonConst(i32 %size) {
54 ; CHECK-LABEL: MemsetNonConst dso_preemptable{{$}}
55 ; CHECK-NEXT: args uses:
56 ; CHECK-NEXT: size[]: [0,1){{$}}
57 ; CHECK-NEXT: allocas uses:
58 ; CHECK-NEXT: x[4]: full-set{{$}}
61 %x = alloca i32, align 4
62 %x1 = bitcast i32* %x to i8*
63 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %size, i1 false)
67 ; FIXME: memintrinsics should look at size range when possible
68 ; Right now we refuse any non-constant size.
69 define void @MemsetNonConstInBounds(i1 zeroext %z) {
70 ; CHECK-LABEL: MemsetNonConstInBounds dso_preemptable{{$}}
71 ; CHECK-NEXT: args uses:
72 ; CHECK-NEXT: z[]: [0,1){{$}}
73 ; CHECK-NEXT: allocas uses:
74 ; CHECK-NEXT: x[4]: full-set{{$}}
77 %x = alloca i32, align 4
78 %x1 = bitcast i32* %x to i8*
79 %size = select i1 %z, i32 3, i32 4
80 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %size, i1 false)
84 define void @MemcpyInBounds() {
85 ; CHECK-LABEL: MemcpyInBounds dso_preemptable{{$}}
86 ; CHECK-NEXT: args uses:
87 ; CHECK-NEXT: allocas uses:
88 ; CHECK-NEXT: x[4]: [0,4){{$}}
89 ; CHECK-NEXT: y[4]: [0,4){{$}}
92 %x = alloca i32, align 4
93 %y = alloca i32, align 4
94 %x1 = bitcast i32* %x to i8*
95 %y1 = bitcast i32* %y to i8*
96 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 4, i1 false)
100 define void @MemcpySrcOutOfBounds() {
101 ; CHECK-LABEL: MemcpySrcOutOfBounds dso_preemptable{{$}}
102 ; CHECK-NEXT: args uses:
103 ; CHECK-NEXT: allocas uses:
104 ; CHECK-NEXT: x[8]: [0,5){{$}}
105 ; CHECK-NEXT: y[4]: [0,5){{$}}
108 %x = alloca i64, align 4
109 %y = alloca i32, align 4
110 %x1 = bitcast i64* %x to i8*
111 %y1 = bitcast i32* %y to i8*
112 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 5, i1 false)
116 define void @MemcpyDstOutOfBounds() {
117 ; CHECK-LABEL: MemcpyDstOutOfBounds dso_preemptable{{$}}
118 ; CHECK-NEXT: args uses:
119 ; CHECK-NEXT: allocas uses:
120 ; CHECK-NEXT: x[4]: [0,5){{$}}
121 ; CHECK-NEXT: y[8]: [0,5){{$}}
124 %x = alloca i32, align 4
125 %y = alloca i64, align 4
126 %x1 = bitcast i32* %x to i8*
127 %y1 = bitcast i64* %y to i8*
128 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 5, i1 false)
132 define void @MemcpyBothOutOfBounds() {
133 ; CHECK-LABEL: MemcpyBothOutOfBounds dso_preemptable{{$}}
134 ; CHECK-NEXT: args uses:
135 ; CHECK-NEXT: allocas uses:
136 ; CHECK-NEXT: x[4]: [0,9){{$}}
137 ; CHECK-NEXT: y[8]: [0,9){{$}}
140 %x = alloca i32, align 4
141 %y = alloca i64, align 4
142 %x1 = bitcast i32* %x to i8*
143 %y1 = bitcast i64* %y to i8*
144 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 9, i1 false)
148 define void @MemcpySelfInBounds() {
149 ; CHECK-LABEL: MemcpySelfInBounds dso_preemptable{{$}}
150 ; CHECK-NEXT: args uses:
151 ; CHECK-NEXT: allocas uses:
152 ; CHECK-NEXT: x[8]: [0,8){{$}}
155 %x = alloca i64, align 4
156 %x1 = bitcast i64* %x to i8*
157 %x2 = getelementptr i8, i8* %x1, i64 5
158 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 3, i1 false)
162 define void @MemcpySelfSrcOutOfBounds() {
163 ; CHECK-LABEL: MemcpySelfSrcOutOfBounds dso_preemptable{{$}}
164 ; CHECK-NEXT: args uses:
165 ; CHECK-NEXT: allocas uses:
166 ; CHECK-NEXT: x[8]: [0,9){{$}}
169 %x = alloca i64, align 4
170 %x1 = bitcast i64* %x to i8*
171 %x2 = getelementptr i8, i8* %x1, i64 5
172 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 4, i1 false)
176 define void @MemcpySelfDstOutOfBounds() {
177 ; CHECK-LABEL: MemcpySelfDstOutOfBounds dso_preemptable{{$}}
178 ; CHECK-NEXT: args uses:
179 ; CHECK-NEXT: allocas uses:
180 ; CHECK-NEXT: x[8]: [0,9){{$}}
183 %x = alloca i64, align 4
184 %x1 = bitcast i64* %x to i8*
185 %x2 = getelementptr i8, i8* %x1, i64 5
186 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x2, i8* %x1, i32 4, i1 false)
190 define void @MemmoveSelfBothOutOfBounds() {
191 ; CHECK-LABEL: MemmoveSelfBothOutOfBounds dso_preemptable{{$}}
192 ; CHECK-NEXT: args uses:
193 ; CHECK-NEXT: allocas uses:
194 ; CHECK-NEXT: x[8]: [0,14){{$}}
197 %x = alloca i64, align 4
198 %x1 = bitcast i64* %x to i8*
199 %x2 = getelementptr i8, i8* %x1, i64 5
200 call void @llvm.memmove.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 9, i1 false)