1; RUN: opt -S -passes="print<stack-safety-local>" -disable-output < %s 2>&1 | FileCheck %s 2; RUN: opt -S -passes="print-stack-safety" -disable-output < %s 2>&1 | FileCheck %s 3 4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-unknown-linux-gnu" 6 7declare void @llvm.memset.p0i8.i64(i8* %dest, i8 %val, i64 %len, i1 %isvolatile) 8declare void @llvm.memset.p0i8.i32(i8* %dest, i8 %val, i32 %len, i1 %isvolatile) 9declare void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 10declare void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 %isvolatile) 11 12define void @MemsetInBounds() { 13; CHECK-LABEL: MemsetInBounds dso_preemptable{{$}} 14; CHECK-NEXT: args uses: 15; CHECK-NEXT: allocas uses: 16; CHECK-NEXT: x[4]: [0,4){{$}} 17; CHECK-EMPTY: 18entry: 19 %x = alloca i32, align 4 20 %x1 = bitcast i32* %x to i8* 21 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 4, i1 false) 22 ret void 23} 24 25; Volatile does not matter for access bounds. 26define void @VolatileMemsetInBounds() { 27; CHECK-LABEL: VolatileMemsetInBounds dso_preemptable{{$}} 28; CHECK-NEXT: args uses: 29; CHECK-NEXT: allocas uses: 30; CHECK-NEXT: x[4]: [0,4){{$}} 31; CHECK-EMPTY: 32entry: 33 %x = alloca i32, align 4 34 %x1 = bitcast i32* %x to i8* 35 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 4, i1 true) 36 ret void 37} 38 39define void @MemsetOutOfBounds() { 40; CHECK-LABEL: MemsetOutOfBounds dso_preemptable{{$}} 41; CHECK-NEXT: args uses: 42; CHECK-NEXT: allocas uses: 43; CHECK-NEXT: x[4]: [0,5){{$}} 44; CHECK-EMPTY: 45entry: 46 %x = alloca i32, align 4 47 %x1 = bitcast i32* %x to i8* 48 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 5, i1 false) 49 ret void 50} 51 52define void @MemsetNonConst(i32 %size) { 53; CHECK-LABEL: MemsetNonConst dso_preemptable{{$}} 54; CHECK-NEXT: args uses: 55; CHECK-NEXT: allocas uses: 56; CHECK-NEXT: x[4]: [0,4294967295){{$}} 57; CHECK-EMPTY: 58entry: 59 %x = alloca i32, align 4 60 %x1 = bitcast i32* %x to i8* 61 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %size, i1 false) 62 ret void 63} 64 65; FIXME: memintrinsics should look at size range when possible 66; Right now we refuse any non-constant size. 67define void @MemsetNonConstInBounds(i1 zeroext %z) { 68; CHECK-LABEL: MemsetNonConstInBounds dso_preemptable{{$}} 69; CHECK-NEXT: args uses: 70; CHECK-NEXT: allocas uses: 71; CHECK-NEXT: x[4]: [0,7){{$}} 72; CHECK-EMPTY: 73entry: 74 %x = alloca i32, align 4 75 %x1 = bitcast i32* %x to i8* 76 %size = select i1 %z, i32 3, i32 4 77 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %size, i1 false) 78 ret void 79} 80 81define void @MemsetNonConstSize() { 82; CHECK-LABEL: MemsetNonConstSize dso_preemptable{{$}} 83; CHECK-NEXT: args uses: 84; CHECK-NEXT: allocas uses: 85; CHECK-NEXT: x[4]: [0,4294967295){{$}} 86; CHECK-NEXT: y[4]: empty-set{{$}} 87; CHECK-EMPTY: 88entry: 89 %x = alloca i32, align 4 90 %y = alloca i32, align 4 91 %x1 = bitcast i32* %x to i8* 92 %xint = ptrtoint i32* %x to i32 93 %yint = ptrtoint i32* %y to i32 94 %d = sub i32 %xint, %yint 95 call void @llvm.memset.p0i8.i32(i8* %x1, i8 42, i32 %d, i1 false) 96 ret void 97} 98 99define void @MemcpyInBounds() { 100; CHECK-LABEL: MemcpyInBounds dso_preemptable{{$}} 101; CHECK-NEXT: args uses: 102; CHECK-NEXT: allocas uses: 103; CHECK-NEXT: x[4]: [0,4){{$}} 104; CHECK-NEXT: y[4]: [0,4){{$}} 105; CHECK-EMPTY: 106entry: 107 %x = alloca i32, align 4 108 %y = alloca i32, align 4 109 %x1 = bitcast i32* %x to i8* 110 %y1 = bitcast i32* %y to i8* 111 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 4, i1 false) 112 ret void 113} 114 115define void @MemcpySrcOutOfBounds() { 116; CHECK-LABEL: MemcpySrcOutOfBounds dso_preemptable{{$}} 117; CHECK-NEXT: args uses: 118; CHECK-NEXT: allocas uses: 119; CHECK-NEXT: x[8]: [0,5){{$}} 120; CHECK-NEXT: y[4]: [0,5){{$}} 121; CHECK-EMPTY: 122entry: 123 %x = alloca i64, align 4 124 %y = alloca i32, align 4 125 %x1 = bitcast i64* %x to i8* 126 %y1 = bitcast i32* %y to i8* 127 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 5, i1 false) 128 ret void 129} 130 131define void @MemcpyDstOutOfBounds() { 132; CHECK-LABEL: MemcpyDstOutOfBounds dso_preemptable{{$}} 133; CHECK-NEXT: args uses: 134; CHECK-NEXT: allocas uses: 135; CHECK-NEXT: x[4]: [0,5){{$}} 136; CHECK-NEXT: y[8]: [0,5){{$}} 137; CHECK-EMPTY: 138entry: 139 %x = alloca i32, align 4 140 %y = alloca i64, align 4 141 %x1 = bitcast i32* %x to i8* 142 %y1 = bitcast i64* %y to i8* 143 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 5, i1 false) 144 ret void 145} 146 147define void @MemcpyBothOutOfBounds() { 148; CHECK-LABEL: MemcpyBothOutOfBounds dso_preemptable{{$}} 149; CHECK-NEXT: args uses: 150; CHECK-NEXT: allocas uses: 151; CHECK-NEXT: x[4]: [0,9){{$}} 152; CHECK-NEXT: y[8]: [0,9){{$}} 153; CHECK-EMPTY: 154entry: 155 %x = alloca i32, align 4 156 %y = alloca i64, align 4 157 %x1 = bitcast i32* %x to i8* 158 %y1 = bitcast i64* %y to i8* 159 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %y1, i32 9, i1 false) 160 ret void 161} 162 163define void @MemcpySelfInBounds() { 164; CHECK-LABEL: MemcpySelfInBounds dso_preemptable{{$}} 165; CHECK-NEXT: args uses: 166; CHECK-NEXT: allocas uses: 167; CHECK-NEXT: x[8]: [0,8){{$}} 168; CHECK-EMPTY: 169entry: 170 %x = alloca i64, align 4 171 %x1 = bitcast i64* %x to i8* 172 %x2 = getelementptr i8, i8* %x1, i64 5 173 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 3, i1 false) 174 ret void 175} 176 177define void @MemcpySelfSrcOutOfBounds() { 178; CHECK-LABEL: MemcpySelfSrcOutOfBounds dso_preemptable{{$}} 179; CHECK-NEXT: args uses: 180; CHECK-NEXT: allocas uses: 181; CHECK-NEXT: x[8]: [0,9){{$}} 182; CHECK-EMPTY: 183entry: 184 %x = alloca i64, align 4 185 %x1 = bitcast i64* %x to i8* 186 %x2 = getelementptr i8, i8* %x1, i64 5 187 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 4, i1 false) 188 ret void 189} 190 191define void @MemcpySelfDstOutOfBounds() { 192; CHECK-LABEL: MemcpySelfDstOutOfBounds dso_preemptable{{$}} 193; CHECK-NEXT: args uses: 194; CHECK-NEXT: allocas uses: 195; CHECK-NEXT: x[8]: [0,9){{$}} 196; CHECK-EMPTY: 197entry: 198 %x = alloca i64, align 4 199 %x1 = bitcast i64* %x to i8* 200 %x2 = getelementptr i8, i8* %x1, i64 5 201 call void @llvm.memcpy.p0i8.p0i8.i32(i8* %x2, i8* %x1, i32 4, i1 false) 202 ret void 203} 204 205define void @MemmoveSelfBothOutOfBounds() { 206; CHECK-LABEL: MemmoveSelfBothOutOfBounds dso_preemptable{{$}} 207; CHECK-NEXT: args uses: 208; CHECK-NEXT: allocas uses: 209; CHECK-NEXT: x[8]: [0,14){{$}} 210; CHECK-EMPTY: 211entry: 212 %x = alloca i64, align 4 213 %x1 = bitcast i64* %x to i8* 214 %x2 = getelementptr i8, i8* %x1, i64 5 215 call void @llvm.memmove.p0i8.p0i8.i32(i8* %x1, i8* %x2, i32 9, i1 false) 216 ret void 217} 218