1; Test basic address sanitizer instrumentation.
2;
3; RUN: opt < %s -memprof -memprof-module -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
4; RUN: opt < %s -memprof -memprof-module -memprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
5
6; We need the requires since both memprof and memprof-module require reading module level metadata which is done once by the memprof-globals-md analysis
7; RUN: opt < %s -passes='function(memprof),module(memprof-module)' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s
8; RUN: opt < %s -passes='function(memprof),module(memprof-module)' -memprof-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s
9
10target 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"
11target triple = "x86_64-unknown-linux-gnu"
12
13; CHECK: @llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @memprof.module_ctor to i8*)]
14; CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @memprof.module_ctor, i8* null }]
15
16define i32 @test_load(i32* %a) {
17entry:
18  %tmp1 = load i32, i32* %a, align 4
19  ret i32 %tmp1
20}
21; CHECK-LABEL: @test_load
22; CHECK:         %[[SHADOW_OFFSET:[^ ]*]] = load i64, i64* @__memprof_shadow_memory_dynamic_address
23; CHECK-NEXT:    %[[LOAD_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
24; CHECK-NEXT:    %[[MASKED_ADDR:[^ ]*]] = and i64 %[[LOAD_ADDR]], -64
25; CHECK-S3-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 3
26; CHECK-S5-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 5
27; CHECK-NEXT:    add i64 %[[SHIFTED_ADDR]], %[[SHADOW_OFFSET]]
28; CHECK-NEXT:    %[[LOAD_SHADOW_PTR:[^ ]*]] = inttoptr
29; CHECK-NEXT:    %[[LOAD_SHADOW:[^ ]*]] = load i64, i64* %[[LOAD_SHADOW_PTR]]
30; CHECK-NEXT:    %[[NEW_SHADOW:[^ ]*]] = add i64 %[[LOAD_SHADOW]], 1
31; CHECK-NEXT:    store i64 %[[NEW_SHADOW]], i64* %[[LOAD_SHADOW_PTR]]
32; The actual load.
33; CHECK-NEXT:    %tmp1 = load i32, i32* %a
34; CHECK-NEXT:    ret i32 %tmp1
35
36define void @test_store(i32* %a) {
37entry:
38  store i32 42, i32* %a, align 4
39  ret void
40}
41; CHECK-LABEL: @test_store
42; CHECK:         %[[SHADOW_OFFSET:[^ ]*]] = load i64, i64* @__memprof_shadow_memory_dynamic_address
43; CHECK-NEXT:    %[[STORE_ADDR:[^ ]*]] = ptrtoint i32* %a to i64
44; CHECK-NEXT:    %[[MASKED_ADDR:[^ ]*]] = and i64 %[[STORE_ADDR]], -64
45; CHECK-S3-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 3
46; CHECK-S5-NEXT: %[[SHIFTED_ADDR:[^ ]*]] = lshr i64 %[[MASKED_ADDR]], 5
47; CHECK-NEXT:    add i64 %[[SHIFTED_ADDR]], %[[SHADOW_OFFSET]]
48; CHECK-NEXT:    %[[STORE_SHADOW_PTR:[^ ]*]] = inttoptr
49; CHECK-NEXT:    %[[STORE_SHADOW:[^ ]*]] = load i64, i64* %[[STORE_SHADOW_PTR]]
50; CHECK-NEXT:    %[[NEW_SHADOW:[^ ]*]] = add i64 %[[STORE_SHADOW]], 1
51; CHECK-NEXT:    store i64 %[[NEW_SHADOW]], i64* %[[STORE_SHADOW_PTR]]
52; The actual store.
53; CHECK-NEXT:    store i32 42, i32* %a
54; CHECK-NEXT:    ret void
55
56define void @FP80Test(x86_fp80* nocapture %a) nounwind uwtable {
57entry:
58    store x86_fp80 0xK3FFF8000000000000000, x86_fp80* %a, align 16
59    ret void
60}
61; CHECK-LABEL: @FP80Test
62; Exactly one shadow update for store access.
63; CHECK-NOT:  store i64
64; CHECK:      %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
65; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
66; CHECK-NOT:  store i64
67; The actual store.
68; CHECK:      store x86_fp80 0xK3FFF8000000000000000, x86_fp80* %a
69; CHECK:      ret void
70
71define void @i40test(i40* %a, i40* %b) nounwind uwtable {
72entry:
73  %t = load i40, i40* %a
74  store i40 %t, i40* %b, align 8
75  ret void
76}
77; CHECK-LABEL: @i40test
78; Exactly one shadow update for load access.
79; CHECK-NOT:  store i64
80; CHECK:      %[[NEW_LD_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
81; CHECK-NEXT: store i64 %[[NEW_LD_SHADOW]]
82; CHECK-NOT:  store i64
83; The actual load.
84; CHECK:      %t = load i40, i40* %a
85; Exactly one shadow update for store access.
86; CHECK-NOT:  store i64
87; CHECK:      %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
88; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
89; CHECK-NOT:  store i64
90; The actual store.
91; CHECK:      store i40 %t, i40* %b
92; CHECK:      ret void
93
94define void @i64test_align1(i64* %b) nounwind uwtable {
95  entry:
96  store i64 0, i64* %b, align 1
97  ret void
98}
99; CHECK-LABEL: @i64test
100; Exactly one shadow update for store access.
101; CHECK-NOT:  store i64
102; CHECK: %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
103; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
104; CHECK-NOT:  store i64
105; The actual store.
106; CHECK:      store i64 0, i64* %b
107; CHECK:      ret void
108
109define void @i80test(i80* %a, i80* %b) nounwind uwtable {
110  entry:
111  %t = load i80, i80* %a
112  store i80 %t, i80* %b, align 8
113  ret void
114}
115; CHECK-LABEL: i80test
116; Exactly one shadow update for load access.
117; CHECK-NOT:  store i64
118; CHECK:      %[[NEW_LD_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
119; CHECK-NEXT: store i64 %[[NEW_LD_SHADOW]]
120; CHECK-NOT:  store i64
121; The actual load.
122; CHECK:      %t = load i80, i80* %a
123; Exactly one shadow update for store access.
124; CHECK-NOT:  store i64
125; CHECK:      %[[NEW_ST_SHADOW:[^ ]*]] = add i64 %{{.*}}, 1
126; CHECK-NEXT: store i64 %[[NEW_ST_SHADOW]]
127; CHECK-NOT:  store i64
128; The actual store.
129; CHECK:      store i80 %t, i80* %b
130; CHECK:      ret void
131
132; memprof should not instrument functions with available_externally linkage.
133define available_externally i32 @f_available_externally(i32* %a)  {
134entry:
135  %tmp1 = load i32, i32* %a
136  ret i32 %tmp1
137}
138; CHECK-LABEL: @f_available_externally
139; CHECK-NOT: __memprof_shadow_memory_dynamic_address
140; CHECK: ret i32
141
142declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
143declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind
144declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1) nounwind
145
146define void @memintr_test(i8* %a, i8* %b) nounwind uwtable {
147  entry:
148  tail call void @llvm.memset.p0i8.i64(i8* %a, i8 0, i64 100, i1 false)
149  tail call void @llvm.memmove.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false)
150  tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 100, i1 false)
151  ret void
152}
153
154; CHECK-LABEL: memintr_test
155; CHECK: __memprof_memset
156; CHECK: __memprof_memmove
157; CHECK: __memprof_memcpy
158; CHECK: ret void
159
160declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture writeonly, i8, i64, i32) nounwind
161declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind
162declare void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32) nounwind
163
164define void @memintr_element_atomic_test(i8* %a, i8* %b) nounwind uwtable {
165  ; This is a canary test to make sure that these don't get lowered into calls that don't
166  ; have the element-atomic property. Eventually, memprof will have to be enhanced to lower
167  ; these properly.
168  ; CHECK-LABEL: memintr_element_atomic_test
169  ; CHECK: tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1)
170  ; CHECK: tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
171  ; CHECK: tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
172  ; CHECK: ret void
173  tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 1 %a, i8 0, i64 100, i32 1)
174  tail call void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
175  tail call void @llvm.memcpy.element.unordered.atomic.p0i8.p0i8.i64(i8* align 1 %a, i8* align 1 %b, i64 100, i32 1)
176  ret void
177}
178
179
180; CHECK: define internal void @memprof.module_ctor()
181; CHECK: call void @__memprof_init()
182