1; Test basic address sanitizer instrumentation.
2;
3; RUN: opt < %s -asan -asan-module -S -enable-new-pm=0 | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
4; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S -enable-new-pm=0 | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
5
6; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
7; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
8
9target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
10target triple = "x86_64-unknown-linux-gnu"
11; CHECK: @llvm.global_ctors = {{.*}}@asan.module_ctor
12
13define i32 @test_load(i32* %a) sanitize_address {
14; CHECK-LABEL: @test_load
15; CHECK-NOT: load
16; CHECK:   %[[LOAD_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
17; CHECK-S3:   lshr i64 %[[LOAD_ADDR]], 3
18; CHECK-S5:   lshr i64 %[[LOAD_ADDR]], 5
19; CHECK:   {{or|add}}
20; CHECK:   %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
21; CHECK:   %[[LOAD_SHADOW:[^ ]*]] = load i8, i8* %[[LOAD_SHADOW_PTR]]
22; CHECK:   icmp ne i8
23; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}!prof ![[PROF:[0-9]+]]
24;
25; First instrumentation block refines the shadow test.
26; CHECK-S3:   and i64 %[[LOAD_ADDR]], 7
27; CHECK-S5:   and i64 %[[LOAD_ADDR]], 31
28; CHECK:   add i64 %{{.*}}, 3
29; CHECK:   trunc i64 %{{.*}} to i8
30; CHECK:   icmp sge i8 %{{.*}}, %[[LOAD_SHADOW]]
31; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
32;
33; The crash block reports the error.
34; CHECK:   call void @__asan_report_load4(i64 %[[LOAD_ADDR]])
35; CHECK:   unreachable
36;
37; The actual load.
38; CHECK:   %tmp1 = load i32, i32* %a
39; CHECK:   ret i32 %tmp1
40
41
42
43entry:
44  %tmp1 = load i32, i32* %a, align 4
45  ret i32 %tmp1
46}
47
48define void @test_store(i32* %a) sanitize_address {
49; CHECK-LABEL: @test_store
50; CHECK-NOT: store
51; CHECK:   %[[STORE_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
52; CHECK-S3:   lshr i64 %[[STORE_ADDR]], 3
53; CHECK-S5:   lshr i64 %[[STORE_ADDR]], 5
54; CHECK:   {{or|add}}
55; CHECK:   %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
56; CHECK:   %[[STORE_SHADOW:[^ ]*]] = load i8, i8* %[[STORE_SHADOW_PTR]]
57; CHECK:   icmp ne i8
58; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
59;
60; First instrumentation block refines the shadow test.
61; CHECK-S3:   and i64 %[[STORE_ADDR]], 7
62; CHECK-S5:   and i64 %[[STORE_ADDR]], 31
63; CHECK:   add i64 %{{.*}}, 3
64; CHECK:   trunc i64 %{{.*}} to i8
65; CHECK:   icmp sge i8 %{{.*}}, %[[STORE_SHADOW]]
66; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
67;
68; The crash block reports the error.
69; CHECK:   call void @__asan_report_store4(i64 %[[STORE_ADDR]])
70; CHECK:   unreachable
71;
72; The actual load.
73; CHECK:   store i32 42, i32* %a
74; CHECK:   ret void
75;
76
77entry:
78  store i32 42, i32* %a, align 4
79  ret void
80}
81
82; Check that asan leaves just one alloca.
83
84declare void @alloca_test_use([10 x i8]*)
85define void @alloca_test() sanitize_address {
86entry:
87  %x = alloca [10 x i8], align 1
88  %y = alloca [10 x i8], align 1
89  %z = alloca [10 x i8], align 1
90  call void @alloca_test_use([10 x i8]* %x)
91  call void @alloca_test_use([10 x i8]* %y)
92  call void @alloca_test_use([10 x i8]* %z)
93  ret void
94}
95
96; CHECK-LABEL: define void @alloca_test()
97; CHECK: %asan_local_stack_base = alloca
98; CHECK: = alloca
99; CHECK-NOT: = alloca
100; CHECK: ret void
101
102define void @LongDoubleTest(x86_fp80* nocapture %a) nounwind uwtable sanitize_address {
103entry:
104    store x86_fp80 0xK3FFF8000000000000000, x86_fp80* %a, align 16
105    ret void
106}
107
108; CHECK-LABEL: LongDoubleTest
109; CHECK: __asan_report_store_n
110; CHECK: __asan_report_store_n
111; CHECK: ret void
112
113
114define void @i40test(i40* %a, i40* %b) nounwind uwtable sanitize_address {
115  entry:
116  %t = load i40, i40* %a
117  store i40 %t, i40* %b, align 8
118  ret void
119}
120
121; CHECK-LABEL: i40test
122; CHECK: __asan_report_load_n{{.*}}, i64 5)
123; CHECK: __asan_report_load_n{{.*}}, i64 5)
124; CHECK: __asan_report_store_n{{.*}}, i64 5)
125; CHECK: __asan_report_store_n{{.*}}, i64 5)
126; CHECK: ret void
127
128define void @i64test_align1(i64* %b) nounwind uwtable sanitize_address {
129  entry:
130  store i64 0, i64* %b, align 1
131  ret void
132}
133
134; CHECK-LABEL: i64test_align1
135; CHECK: __asan_report_store_n{{.*}}, i64 8)
136; CHECK: __asan_report_store_n{{.*}}, i64 8)
137; CHECK: ret void
138
139
140define void @i80test(i80* %a, i80* %b) nounwind uwtable sanitize_address {
141  entry:
142  %t = load i80, i80* %a
143  store i80 %t, i80* %b, align 8
144  ret void
145}
146
147; CHECK-LABEL: i80test
148; CHECK: __asan_report_load_n{{.*}}, i64 10)
149; CHECK: __asan_report_load_n{{.*}}, i64 10)
150; CHECK: __asan_report_store_n{{.*}}, i64 10)
151; CHECK: __asan_report_store_n{{.*}}, i64 10)
152; CHECK: ret void
153
154; asan should not instrument functions with available_externally linkage.
155define available_externally i32 @f_available_externally(i32* %a) sanitize_address  {
156entry:
157  %tmp1 = load i32, i32* %a
158  ret i32 %tmp1
159}
160; CHECK-LABEL: @f_available_externally
161; CHECK-NOT: __asan_report
162; CHECK: ret i32
163
164declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
165declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind
166declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind
167
168define void @memintr_test(i8* %a, i8* %b) nounwind uwtable sanitize_address {
169  entry:
170  tail call void @llvm.memset.p0i8.i64(i8* %a, i8 0, i64 100, i1 false)
171  tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false)
172  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false)
173  ret void
174}
175
176; CHECK-LABEL: memintr_test
177; CHECK: __asan_memset
178; CHECK: __asan_memmove
179; CHECK: __asan_memcpy
180; CHECK: ret void
181
182declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture writeonly, i8, i64, i32) nounwind
183declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind
184declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind
185
186define void @memintr_element_atomic_test(i8* %a, i8* %b) nounwind uwtable sanitize_address {
187  ; This is a canary test to make sure that these don't get lowered into calls that don't
188  ; have the element-atomic property. Eventually, asan will have to be enhanced to lower
189  ; these properly.
190  ; CHECK-LABEL: memintr_element_atomic_test
191  ; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1)
192  ; CHECK-NEXT: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
193  ; CHECK-NEXT: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
194  ; CHECK-NEXT: ret void
195  tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1)
196  tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
197  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
198  ret void
199}
200
201
202; CHECK-LABEL: @test_swifterror
203; CHECK-NOT: __asan_report_load
204; CHECK: ret void
205define void @test_swifterror(i8** swifterror) sanitize_address {
206  %swifterror_ptr_value = load i8*, i8** %0
207  ret void
208}
209
210; CHECK-LABEL: @test_swifterror_2
211; CHECK-NOT: __asan_report_store
212; CHECK: ret void
213define void @test_swifterror_2(i8** swifterror) sanitize_address {
214  store i8* null, i8** %0
215  ret void
216}
217
218; CHECK-LABEL: @test_swifterror_3
219; CHECK-NOT: __asan_report_store
220; CHECK: ret void
221define void @test_swifterror_3() sanitize_address {
222  %swifterror_addr = alloca swifterror i8*
223  store i8* null, i8** %swifterror_addr
224  call void @test_swifterror_2(i8** swifterror %swifterror_addr)
225  ret void
226}
227
228;; ctor/dtor have the nounwind attribute. See uwtable.ll, they additionally have
229;; the uwtable attribute with the module flag "uwtable".
230; CHECK: define internal void @asan.module_ctor() #[[#ATTR:]] {{(comdat )?}}{
231; CHECK: call void @__asan_init()
232
233; CHECK: attributes #[[#ATTR]] = { nounwind }
234
235; PROF
236; CHECK: ![[PROF]] = !{!"branch_weights", i32 1, i32 100000}
237