xref: /llvm-project/llvm/test/CodeGen/AArch64/stack-tagging.ll (revision 5ddce70ef0e5a641d7fea95e31fc5e2439cb98cb)
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