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
4 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
5 target triple = "aarch64--linux-android"
7 declare void @use8(ptr)
8 declare void @use32(ptr)
9 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
10 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
12 define dso_local void @noUse32(ptr) sanitize_memtag {
17 define void @OneVar() sanitize_memtag {
19 %x = alloca i32, align 4
20 call void @use32(ptr %x)
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)
34 define void @ManyVars() sanitize_memtag {
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)
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
60 ; CHECK: call void @use32(
61 ; CHECK: call void @use8(
62 ; CHECK: call void @use32(
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
70 define void @Scope(i32 %b) sanitize_memtag {
72 %x = alloca i32, align 4
73 %tobool = icmp eq i32 %b, 0
74 br i1 %tobool, label %if.end, label %if.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)
86 ; CHECK-LABEL: define void @Scope(
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(
97 ; Spooked by the multiple lifetime ranges, StackTagging remove all of them and sets tags on entry and exit.
98 define void @BadScope(i32 %b) sanitize_memtag {
100 %x = alloca i32, align 4
101 %tobool = icmp eq i32 %b, 0
102 br i1 %tobool, label %if.end, label %if.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)
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)
118 ; CHECK-LABEL: define void @BadScope(
119 ; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16)
121 ; CHECK: call void @use8(ptr
122 ; CHECK-NEXT: call void @use8(ptr
124 ; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 16)
125 ; CHECK-NEXT: ret void
127 define void @DynamicAllocas(i32 %cnt) sanitize_memtag {
129 %x = alloca i32, i32 %cnt, align 4
132 %y = alloca i32, align 4
133 call void @use32(ptr %x)
134 call void @use32(ptr %y)
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
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.
149 define void @UnrecognizedLifetime(i8 %v) sanitize_memtag {
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
160 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %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)
166 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %z)
167 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %cxcy)
169 call void @noUse32(ptr %x)
170 call void @noUse32(ptr %y)
171 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %cxcy)
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(
187 ; CHECK: call void @noUse32(ptr
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(