1; Test basic address sanitizer instrumentation.
2;
3; RUN: opt < %s -asan -asan-module -S | FileCheck %s
4
5target 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"
6target triple = "x86_64-unknown-linux-gnu"
7; CHECK: @llvm.global_ctors = {{.*}}@asan.module_ctor
8
9define i32 @test_load(i32* %a) sanitize_address {
10; CHECK-LABEL: @test_load
11; CHECK-NOT: load
12; CHECK:   %[[LOAD_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
13; CHECK:   lshr i64 %[[LOAD_ADDR]], 3
14; CHECK:   {{or|add}}
15; CHECK:   %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
16; CHECK:   %[[LOAD_SHADOW:[^ ]*]] = load i8, i8* %[[LOAD_SHADOW_PTR]]
17; CHECK:   icmp ne i8
18; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}!prof ![[PROF:[0-9]+]]
19;
20; First instrumentation block refines the shadow test.
21; CHECK:   and i64 %[[LOAD_ADDR]], 7
22; CHECK:   add i64 %{{.*}}, 3
23; CHECK:   trunc i64 %{{.*}} to i8
24; CHECK:   icmp sge i8 %{{.*}}, %[[LOAD_SHADOW]]
25; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
26;
27; The crash block reports the error.
28; CHECK:   call void @__asan_report_load4(i64 %[[LOAD_ADDR]])
29; CHECK:   unreachable
30;
31; The actual load.
32; CHECK:   %tmp1 = load i32, i32* %a
33; CHECK:   ret i32 %tmp1
34
35
36
37entry:
38  %tmp1 = load i32, i32* %a, align 4
39  ret i32 %tmp1
40}
41
42define void @test_store(i32* %a) sanitize_address {
43; CHECK-LABEL: @test_store
44; CHECK-NOT: store
45; CHECK:   %[[STORE_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
46; CHECK:   lshr i64 %[[STORE_ADDR]], 3
47; CHECK:   {{or|add}}
48; CHECK:   %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
49; CHECK:   %[[STORE_SHADOW:[^ ]*]] = load i8, i8* %[[STORE_SHADOW_PTR]]
50; CHECK:   icmp ne i8
51; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
52;
53; First instrumentation block refines the shadow test.
54; CHECK:   and i64 %[[STORE_ADDR]], 7
55; CHECK:   add i64 %{{.*}}, 3
56; CHECK:   trunc i64 %{{.*}} to i8
57; CHECK:   icmp sge i8 %{{.*}}, %[[STORE_SHADOW]]
58; CHECK:   br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
59;
60; The crash block reports the error.
61; CHECK:   call void @__asan_report_store4(i64 %[[STORE_ADDR]])
62; CHECK:   unreachable
63;
64; The actual load.
65; CHECK:   store i32 42, i32* %a
66; CHECK:   ret void
67;
68
69entry:
70  store i32 42, i32* %a, align 4
71  ret void
72}
73
74; Check that asan leaves just one alloca.
75
76declare void @alloca_test_use([10 x i8]*)
77define void @alloca_test() sanitize_address {
78entry:
79  %x = alloca [10 x i8], align 1
80  %y = alloca [10 x i8], align 1
81  %z = alloca [10 x i8], align 1
82  call void @alloca_test_use([10 x i8]* %x)
83  call void @alloca_test_use([10 x i8]* %y)
84  call void @alloca_test_use([10 x i8]* %z)
85  ret void
86}
87
88; CHECK-LABEL: define void @alloca_test()
89; CHECK: = alloca
90; CHECK-NOT: = alloca
91; CHECK: ret void
92
93define void @LongDoubleTest(x86_fp80* nocapture %a) nounwind uwtable sanitize_address {
94entry:
95    store x86_fp80 0xK3FFF8000000000000000, x86_fp80* %a, align 16
96    ret void
97}
98
99; CHECK-LABEL: LongDoubleTest
100; CHECK: __asan_report_store_n
101; CHECK: __asan_report_store_n
102; CHECK: ret void
103
104
105define void @i40test(i40* %a, i40* %b) nounwind uwtable sanitize_address {
106  entry:
107  %t = load i40, i40* %a
108  store i40 %t, i40* %b, align 8
109  ret void
110}
111
112; CHECK-LABEL: i40test
113; CHECK: __asan_report_load_n{{.*}}, i64 5)
114; CHECK: __asan_report_load_n{{.*}}, i64 5)
115; CHECK: __asan_report_store_n{{.*}}, i64 5)
116; CHECK: __asan_report_store_n{{.*}}, i64 5)
117; CHECK: ret void
118
119define void @i64test_align1(i64* %b) nounwind uwtable sanitize_address {
120  entry:
121  store i64 0, i64* %b, align 1
122  ret void
123}
124
125; CHECK-LABEL: i64test_align1
126; CHECK: __asan_report_store_n{{.*}}, i64 8)
127; CHECK: __asan_report_store_n{{.*}}, i64 8)
128; CHECK: ret void
129
130
131define void @i80test(i80* %a, i80* %b) nounwind uwtable sanitize_address {
132  entry:
133  %t = load i80, i80* %a
134  store i80 %t, i80* %b, align 8
135  ret void
136}
137
138; CHECK-LABEL: i80test
139; CHECK: __asan_report_load_n{{.*}}, i64 10)
140; CHECK: __asan_report_load_n{{.*}}, i64 10)
141; CHECK: __asan_report_store_n{{.*}}, i64 10)
142; CHECK: __asan_report_store_n{{.*}}, i64 10)
143; CHECK: ret void
144
145; asan should not instrument functions with available_externally linkage.
146define available_externally i32 @f_available_externally(i32* %a) sanitize_address  {
147entry:
148  %tmp1 = load i32, i32* %a
149  ret i32 %tmp1
150}
151; CHECK-LABEL: @f_available_externally
152; CHECK-NOT: __asan_report
153; CHECK: ret i32
154
155declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind
156declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) nounwind
157declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) nounwind
158
159define void @memintr_test(i8* %a, i8* %b) nounwind uwtable sanitize_address {
160  entry:
161  tail call void @llvm.memset.p0i8.i64(i8* %a, i8 0, i64 100, i32 1, i1 false)
162  tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i32 1, i1 false)
163  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i32 1, i1 false)
164  ret void
165}
166
167; CHECK-LABEL: memintr_test
168; CHECK: __asan_memset
169; CHECK: __asan_memmove
170; CHECK: __asan_memcpy
171; CHECK: ret void
172
173; CHECK: define internal void @asan.module_ctor()
174; CHECK: call void @__asan_init()
175
176; PROF
177; CHECK: ![[PROF]] = !{!"branch_weights", i32 1, i32 100000}
178