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 5 6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 7target triple = "x86_64-unknown-linux-gnu" 8 9declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile) 10declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 11declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 12 13define 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){{$}} 18; CHECK-NOT: ]: 19entry: 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) 23 ret void 24} 25 26; Volatile does not matter for access bounds. 27define 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){{$}} 32; CHECK-NOT: ]: 33entry: 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) 37 ret void 38} 39 40define 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){{$}} 45; CHECK-NOT: ]: 46entry: 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) 50 ret void 51} 52 53define 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{{$}} 59; CHECK-NOT: ]: 60entry: 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) 64 ret void 65} 66 67; FIXME: memintrinsics should look at size range when possible 68; Right now we refuse any non-constant size. 69define 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{{$}} 75; CHECK-NOT: ]: 76entry: 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) 81 ret void 82} 83 84define 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){{$}} 90; CHECK-NOT: ]: 91entry: 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) 97 ret void 98} 99 100define 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){{$}} 106; CHECK-NOT: ]: 107entry: 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) 113 ret void 114} 115 116define 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){{$}} 122; CHECK-NOT: ]: 123entry: 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) 129 ret void 130} 131 132define 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){{$}} 138; CHECK-NOT: ]: 139entry: 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) 145 ret void 146} 147 148define 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){{$}} 153; CHECK-NOT: ]: 154entry: 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) 159 ret void 160} 161 162define 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){{$}} 167; CHECK-NOT: ]: 168entry: 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) 173 ret void 174} 175 176define 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){{$}} 181; CHECK-NOT: ]: 182entry: 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) 187 ret void 188} 189 190define 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){{$}} 195; CHECK-NOT: ]: 196entry: 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) 201 ret void 202} 203