1; RUN: opt < %s -aarch64-stack-tagging -S -o - | FileCheck %s --check-prefixes=CHECK,SSI 2; RUN: opt < %s -aarch64-stack-tagging -stack-tagging-use-stack-safety=0 -S -o - | FileCheck %s --check-prefixes=CHECK 3 4target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 5target triple = "aarch64--linux-android" 6 7declare void @use8(ptr) 8declare void @use32(ptr) 9declare void @llvm.lifetime.start.p0(i64, ptr nocapture) 10declare void @llvm.lifetime.end.p0(i64, ptr nocapture) 11 12define dso_local void @noUse32(ptr) sanitize_memtag { 13entry: 14 ret void 15} 16 17define void @OneVar() sanitize_memtag { 18entry: 19 %x = alloca i32, align 4 20 call void @use32(ptr %x) 21 ret void 22} 23 24; CHECK-LABEL: define void @OneVar( 25; CHECK: [[BASE:%.*]] = call ptr @llvm.aarch64.irg.sp(i64 0) 26; CHECK: [[X:%.*]] = alloca { i32, [12 x i8] }, align 16 27; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp.{{.*}}(ptr [[X]], ptr [[BASE]], i64 0) 28; CHECK: call void @llvm.aarch64.settag(ptr [[TX]], i64 16) 29; CHECK: call void @use32(ptr [[TX]]) 30; CHECK: call void @llvm.aarch64.settag(ptr [[X]], i64 16) 31; CHECK: ret void 32 33 34define void @ManyVars() sanitize_memtag { 35entry: 36 %x1 = alloca i32, align 4 37 %x2 = alloca i8, align 4 38 %x3 = alloca i32, i32 11, align 4 39 %x4 = alloca i32, align 4 40 call void @use32(ptr %x1) 41 call void @use8(ptr %x2) 42 call void @use32(ptr %x3) 43 ret void 44} 45 46; CHECK-LABEL: define void @ManyVars( 47; CHECK: alloca { i32, [12 x i8] }, align 16 48; CHECK: call ptr @llvm.aarch64.tagp.{{.*}}(ptr {{.*}}, i64 0) 49; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) 50; CHECK: alloca { i8, [15 x i8] }, align 16 51; CHECK: call ptr @llvm.aarch64.tagp.{{.*}}(ptr {{.*}}, i64 1) 52; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) 53; CHECK: alloca { [11 x i32], [4 x i8] }, align 16 54; CHECK: call ptr @llvm.aarch64.tagp.{{.*}}(ptr {{.*}}, i64 2) 55; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 48) 56; CHECK: alloca i32, align 4 57; SSI-NOT: @llvm.aarch64.tagp 58; SSI-NOT: @llvm.aarch64.settag 59 60; CHECK: call void @use32( 61; CHECK: call void @use8( 62; CHECK: call void @use32( 63 64; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) 65; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) 66; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 48) 67; CHECK-NEXT: ret void 68 69 70define void @Scope(i32 %b) sanitize_memtag { 71entry: 72 %x = alloca i32, align 4 73 %tobool = icmp eq i32 %b, 0 74 br i1 %tobool, label %if.end, label %if.then 75 76if.then: 77 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %x) 78 call void @use8(ptr %x) #3 79 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %x) 80 br label %if.end 81 82if.end: 83 ret void 84} 85 86; CHECK-LABEL: define void @Scope( 87; CHECK: br i1 88; CHECK: call void @llvm.lifetime.start.p0( 89; CHECK: call void @llvm.aarch64.settag( 90; CHECK: call void @use8( 91; CHECK: call void @llvm.aarch64.settag( 92; CHECK: call void @llvm.lifetime.end.p0( 93; CHECK: br label 94; CHECK: ret void 95 96 97; Spooked by the multiple lifetime ranges, StackTagging remove all of them and sets tags on entry and exit. 98define void @BadScope(i32 %b) sanitize_memtag { 99entry: 100 %x = alloca i32, align 4 101 %tobool = icmp eq i32 %b, 0 102 br i1 %tobool, label %if.end, label %if.then 103 104if.then: 105 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %x) 106 call void @use8(ptr %x) #3 107 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %x) 108 109 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %x) 110 call void @use8(ptr %x) #3 111 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %x) 112 br label %if.end 113 114if.end: 115 ret void 116} 117 118; CHECK-LABEL: define void @BadScope( 119; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) 120; CHECK: br i1 121; CHECK: call void @use8(ptr 122; CHECK-NEXT: call void @use8(ptr 123; CHECK: br label 124; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16) 125; CHECK-NEXT: ret void 126 127define void @DynamicAllocas(i32 %cnt) sanitize_memtag { 128entry: 129 %x = alloca i32, i32 %cnt, align 4 130 br label %l 131l: 132 %y = alloca i32, align 4 133 call void @use32(ptr %x) 134 call void @use32(ptr %y) 135 ret void 136} 137 138; CHECK-LABEL: define void @DynamicAllocas( 139; CHECK-NOT: @llvm.aarch64.irg.sp 140; CHECK: %x = alloca i32, i32 %cnt, align 4 141; CHECK-NOT: @llvm.aarch64.irg.sp 142; CHECK: alloca i32, align 4 143; CHECK-NOT: @llvm.aarch64.irg.sp 144; CHECK: ret void 145 146; If we can't trace one of the lifetime markers to a single alloca, fall back 147; to poisoning all allocas at the beginning of the function. 148; Each alloca must be poisoned only once. 149define void @UnrecognizedLifetime(i8 %v) sanitize_memtag { 150entry: 151 %x = alloca i32, align 4 152 %y = alloca i32, align 4 153 %z = alloca i32, align 4 154 %tobool = icmp eq i8 %v, 0 155 %xy = select i1 %tobool, ptr %x, ptr %y 156 %cxcy = select i1 %tobool, ptr %x, ptr %y 157 br label %another_bb 158 159another_bb: 160 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %z) 161 store i32 7, ptr %z 162 call void @noUse32(ptr %z) 163 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %z) 164 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %z) 165 store i32 7, ptr %z 166 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %z) 167 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %cxcy) 168 store i32 8, ptr %xy 169 call void @noUse32(ptr %x) 170 call void @noUse32(ptr %y) 171 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %cxcy) 172 ret void 173} 174 175; CHECK-LABEL: define void @UnrecognizedLifetime( 176; CHECK: call ptr @llvm.aarch64.irg.sp(i64 0) 177; CHECK: alloca { i32, [12 x i8] }, align 16 178; CHECK: call ptr @llvm.aarch64.tagp 179; CHECK: call void @llvm.aarch64.settag( 180; CHECK: alloca { i32, [12 x i8] }, align 16 181; CHECK: call ptr @llvm.aarch64.tagp 182; CHECK: call void @llvm.aarch64.settag( 183; CHECK: alloca { i32, [12 x i8] }, align 16 184; CHECK: call ptr @llvm.aarch64.tagp 185; CHECK: call void @llvm.aarch64.settag( 186; CHECK: store i32 187; CHECK: call void @noUse32(ptr 188; CHECK: store i32 189; CHECK: store i32 190; CHECK: call void @noUse32(ptr 191; CHECK: call void @llvm.aarch64.settag( 192; CHECK: call void @llvm.aarch64.settag( 193; CHECK: call void @llvm.aarch64.settag( 194; CHECK: ret void 195 196!0 = !{} 197