1 ; RUN: opt < %s -aarch64-stack-tagging -S -o - | FileCheck %s
3 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
4 target triple = "aarch64--linux-android"
7 declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
8 declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
9 declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
11 define void @OneVarNoInit() sanitize_memtag {
13 %x = alloca i32, align 4
14 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %x)
15 call void @use(ptr nonnull %x)
16 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %x)
20 ; CHECK-LABEL: define void @OneVarNoInit(
21 ; CHECK-DAG: [[X:%.*]] = alloca { i32, [12 x i8] }, align 16
22 ; CHECK-DAG: [[TX:%.*]] = call ptr @llvm.aarch64.tagp.{{.*}}(ptr [[X]], {{.*}}, i64 0)
23 ; CHECK-DAG: call void @llvm.lifetime.start.p0(i64 4, ptr nonnull [[TX]])
24 ; CHECK-DAG: call void @llvm.aarch64.settag(ptr [[TX]], i64 16)
25 ; CHECK-DAG: call void @use(ptr nonnull [[TX]])
26 ; CHECK-DAG: call void @llvm.lifetime.end.p0(i64 4, ptr nonnull [[TX]])
28 define void @OneVarInitConst() sanitize_memtag {
30 %x = alloca i32, align 4
31 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %x)
32 store i32 42, ptr %x, align 4
33 call void @use(ptr nonnull %x)
34 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %x)
38 ; CHECK-LABEL: define void @OneVarInitConst(
39 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp
40 ; CHECK-NOT: aarch64.settag
41 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 42, i64 0)
42 ; Untagging before lifetime.end:
43 ; CHECK: call void @llvm.aarch64.settag(
44 ; CHECK-NOT: aarch64.settag
47 define void @ArrayInitConst() sanitize_memtag {
49 %x = alloca i32, i32 16, align 4
50 call void @llvm.lifetime.start.p0(i64 64, ptr nonnull %x)
51 store i32 42, ptr %x, align 4
52 call void @use(ptr nonnull %x)
53 call void @llvm.lifetime.end.p0(i64 64, ptr nonnull %x)
57 ; CHECK-LABEL: define void @ArrayInitConst(
58 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp.
59 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 42, i64 0)
60 ; CHECK: [[TX8_16:%.*]] = getelementptr i8, ptr [[TX]], i32 16
61 ; CHECK: call void @llvm.aarch64.settag.zero(ptr [[TX8_16]], i64 48)
64 define void @ArrayInitConst2() sanitize_memtag {
66 %x = alloca i32, i32 16, align 4
67 call void @llvm.lifetime.start.p0(i64 64, ptr nonnull %x)
68 store i32 42, ptr %x, align 4
69 %0 = getelementptr i32, ptr %x, i32 1
70 store i32 43, ptr %0, align 4
71 %1 = getelementptr i32, ptr %x, i32 2
72 store i64 -1, ptr %1, align 4
73 call void @use(ptr nonnull %x)
74 call void @llvm.lifetime.end.p0(i64 64, ptr nonnull %x)
78 ; CHECK-LABEL: define void @ArrayInitConst2(
79 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp.
80 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 184683593770, i64 -1)
81 ; CHECK: [[TX8_16:%.*]] = getelementptr i8, ptr [[TX]], i32 16
82 ; CHECK: call void @llvm.aarch64.settag.zero(ptr [[TX8_16]], i64 48)
85 define void @ArrayInitConstSplit() sanitize_memtag {
87 %x = alloca i32, i32 16, align 4
88 call void @llvm.lifetime.start.p0(i64 64, ptr nonnull %x)
89 %0 = getelementptr i32, ptr %x, i32 1
90 store i64 -1, ptr %0, align 4
91 call void @use(ptr nonnull %x)
92 call void @llvm.lifetime.end.p0(i64 64, ptr nonnull %x)
96 ; CHECK-LABEL: define void @ArrayInitConstSplit(
97 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp.
98 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 -4294967296, i64 4294967295)
101 define void @ArrayInitConstWithHoles() sanitize_memtag {
103 %x = alloca i32, i32 32, align 4
104 call void @llvm.lifetime.start.p0(i64 128, ptr nonnull %x)
105 %0 = getelementptr i32, ptr %x, i32 5
106 store i32 42, ptr %0, align 4
107 %1 = getelementptr i32, ptr %x, i32 14
108 store i32 43, ptr %1, align 4
109 call void @use(ptr nonnull %x)
110 call void @llvm.lifetime.end.p0(i64 128, ptr nonnull %x)
114 ; CHECK-LABEL: define void @ArrayInitConstWithHoles(
115 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp.
116 ; CHECK: call void @llvm.aarch64.settag.zero(ptr [[TX]], i64 16)
117 ; CHECK: [[TX8_16:%.*]] = getelementptr i8, ptr %x.tag, i32 16
118 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX8_16]], i64 180388626432, i64 0)
119 ; CHECK: [[TX8_32:%.*]] = getelementptr i8, ptr %x.tag, i32 32
120 ; CHECK: call void @llvm.aarch64.settag.zero(ptr [[TX8_32]], i64 16)
121 ; CHECK: [[TX8_48:%.*]] = getelementptr i8, ptr %x.tag, i32 48
122 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX8_48]], i64 0, i64 43)
123 ; CHECK: [[TX8_64:%.*]] = getelementptr i8, ptr %x.tag, i32 64
124 ; CHECK: call void @llvm.aarch64.settag.zero(ptr [[TX8_64]], i64 64)
127 define void @InitNonConst(i32 %v) sanitize_memtag {
129 %x = alloca i32, align 4
130 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %x)
131 store i32 %v, ptr %x, align 4
132 call void @use(ptr nonnull %x)
133 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %x)
137 ; CHECK-LABEL: define void @InitNonConst(
138 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp
139 ; CHECK: [[V:%.*]] = zext i32 %v to i64
140 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 [[V]], i64 0)
143 define void @InitNonConst2(i32 %v, i32 %w) sanitize_memtag {
145 %x = alloca i32, i32 4, align 4
146 call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %x)
147 store i32 %v, ptr %x, align 4
148 %0 = getelementptr i32, ptr %x, i32 1
149 store i32 %w, ptr %0, align 4
150 call void @use(ptr nonnull %x)
151 call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %x)
155 ; CHECK-LABEL: define void @InitNonConst2(
156 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp
157 ; CHECK: [[V:%.*]] = zext i32 %v to i64
158 ; CHECK: [[W:%.*]] = zext i32 %w to i64
159 ; CHECK: [[WS:%.*]] = shl i64 [[W]], 32
160 ; CHECK: [[VW:%.*]] = or i64 [[V]], [[WS]]
161 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 [[VW]], i64 0)
164 define void @InitVector() sanitize_memtag {
166 %x = alloca i32, i32 4, align 4
167 call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %x)
168 store <2 x i32> <i32 1, i32 2>, ptr %x, align 4
169 call void @use(ptr nonnull %x)
170 call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %x)
174 ; CHECK-LABEL: define void @InitVector(
175 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp
176 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 bitcast (<2 x i32> <i32 1, i32 2> to i64), i64 0)
179 define void @InitVectorPtr(ptr %p) sanitize_memtag {
181 %s = alloca <4 x ptr>, align 8
182 %v0 = insertelement <4 x ptr> undef, ptr %p, i32 0
183 %v1 = shufflevector <4 x ptr> %v0, <4 x ptr> undef, <4 x i32> zeroinitializer
184 store <4 x ptr> %v1, ptr %s
185 call void @use(ptr nonnull %s)
189 ; CHECK-LABEL: define void @InitVectorPtr(
190 ; CHECK: call ptr @llvm.aarch64.tagp
191 ; CHECK: [[V1:%.*]] = shufflevector
192 ; CHECK: [[V2:%.*]] = ptrtoint <4 x ptr> [[V1]] to <4 x i64>
193 ; CHECK: [[V3:%.*]] = bitcast <4 x i64> [[V2]] to i256
194 ; CHECK: [[A1:%.*]] = trunc i256 [[V3]] to i64
195 ; CHECK: [[A2_:%.*]] = lshr i256 [[V3]], 64
196 ; CHECK: [[A2:%.*]] = trunc i256 [[A2_]] to i64
197 ; CHECK: [[A3_:%.*]] = lshr i256 [[V3]], 128
198 ; CHECK: [[A3:%.*]] = trunc i256 [[A3_]] to i64
199 ; CHECK: [[A4_:%.*]] = lshr i256 [[V3]], 192
200 ; CHECK: [[A4:%.*]] = trunc i256 [[A4_]] to i64
201 ; CHECK: call void @llvm.aarch64.stgp({{.*}}, i64 [[A1]], i64 [[A2]])
202 ; CHECK: call void @llvm.aarch64.stgp({{.*}}, i64 [[A3]], i64 [[A4]])
205 define void @InitVectorSplit() sanitize_memtag {
207 %x = alloca i32, i32 4, align 4
208 call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %x)
209 %0 = getelementptr i32, ptr %x, i32 1
210 store <2 x i32> <i32 1, i32 2>, ptr %0, align 4
211 call void @use(ptr nonnull %x)
212 call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %x)
216 ; CHECK-LABEL: define void @InitVectorSplit(
217 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp
218 ; CHECK: call void @llvm.aarch64.stgp(ptr [[TX]], i64 shl (i64 bitcast (<2 x i32> <i32 1, i32 2> to i64), i64 32), i64 lshr (i64 bitcast (<2 x i32> <i32 1, i32 2> to i64), i64 32))
221 define void @MemSetZero() sanitize_memtag {
223 %x = alloca i32, i32 8, align 16
224 call void @llvm.memset.p0.i64(ptr nonnull align 16 %x, i8 0, i64 32, i1 false)
225 call void @use(ptr nonnull %x)
229 ; CHECK-LABEL: define void @MemSetZero(
230 ; CHECK: [[TX:%.*]] = call ptr @llvm.aarch64.tagp
231 ; CHECK: call void @llvm.aarch64.settag.zero(ptr [[TX]], i64 32)
235 define void @MemSetNonZero() sanitize_memtag {
237 %x = alloca i32, i32 8, align 16
238 call void @llvm.memset.p0.i64(ptr nonnull align 16 %x, i8 42, i64 32, i1 false)
239 call void @use(ptr nonnull %x)
243 ; CHECK-LABEL: define void @MemSetNonZero(
244 ; CHECK: call void @llvm.aarch64.stgp(ptr {{.*}}, i64 3038287259199220266, i64 3038287259199220266)
245 ; CHECK: call void @llvm.aarch64.stgp(ptr {{.*}}, i64 3038287259199220266, i64 3038287259199220266)
249 define void @MemSetNonZero2() sanitize_memtag {
251 %x = alloca [32 x i8], align 16
252 %0 = getelementptr inbounds [32 x i8], ptr %x, i64 0, i64 2
253 call void @llvm.memset.p0.i64(ptr nonnull %0, i8 42, i64 28, i1 false)
254 call void @use(ptr nonnull %0)
258 ; CHECK-LABEL: define void @MemSetNonZero2(
259 ; CHECK: call void @llvm.aarch64.stgp(ptr {{.*}}, i64 3038287259199209472, i64 3038287259199220266)
260 ; CHECK: call void @llvm.aarch64.stgp(ptr {{.*}}, i64 3038287259199220266, i64 46360584399402)
263 define void @MemSetNonZero3() sanitize_memtag {
265 %x = alloca [32 x i8], align 16
266 %0 = getelementptr inbounds [32 x i8], ptr %x, i64 0, i64 2
267 call void @llvm.memset.p0.i64(ptr nonnull %0, i8 42, i64 4, i1 false)
268 %1 = getelementptr inbounds [32 x i8], ptr %x, i64 0, i64 24
269 call void @llvm.memset.p0.i64(ptr nonnull %1, i8 42, i64 8, i1 false)
270 call void @use(ptr nonnull %0)
274 ; CHECK-LABEL: define void @MemSetNonZero3(
275 ; CHECK: call void @llvm.aarch64.stgp(ptr {{.*}}, i64 46360584388608, i64 0)
276 ; CHECK: call void @llvm.aarch64.stgp(ptr {{.*}}, i64 0, i64 3038287259199220266)
279 define void @LargeAlloca() sanitize_memtag {
281 %x = alloca i32, i32 256, align 16
282 call void @llvm.memset.p0.i64(ptr nonnull align 16 %x, i8 42, i64 256, i1 false)
283 call void @use(ptr nonnull %x)
287 ; CHECK-LABEL: define void @LargeAlloca(
288 ; CHECK: call void @llvm.aarch64.settag(ptr {{.*}}, i64 1024)
289 ; CHECK: call void @llvm.memset.p0.i64(ptr {{.*}}, i8 42, i64 256,