1; Test handling of llvm.lifetime intrinsics.
2; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT
3; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -asan-instrument-dynamic-allocas=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DYNAMIC
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-S128"
6target triple = "x86_64-unknown-linux-gnu"
7
8declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
9declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind
10
11define void @lifetime_no_size() sanitize_address {
12  ; CHECK-LABEL: define void @lifetime_no_size()
13entry:
14  %i = alloca i32, align 4
15  %i.ptr = bitcast i32* %i to i8*
16
17  ; Poison memory in prologue: F1F1F1F104F3F3F3
18  ; CHECK: store i64 -868083100587789839, i64* %{{[0-9]+}}
19
20  call void @llvm.lifetime.start.p0i8(i64 -1, i8* %i.ptr)
21  ; Check that lifetime with no size are ignored.
22  ; CHECK-NOT: store
23  ; CHECK: call void @llvm.lifetime.start
24
25  store volatile i8 0, i8* %i.ptr
26  ; CHECK: store volatile
27
28  call void @llvm.lifetime.end.p0i8(i64 -1, i8* %i.ptr)
29  ; Check that lifetime with no size are ignored.
30  ; CHECK-NOT: store
31  ; CHECK: call void @llvm.lifetime.end
32
33  ; Unpoison stack frame on exit.
34  ; CHECK: store i64 0, i64* %{{[0-9]+}}
35  ; CHECK: ret void
36  ret void
37}
38
39; Generic case of lifetime analysis.
40define void @lifetime() sanitize_address {
41  ; CHECK-LABEL: define void @lifetime()
42
43  ; Regular variable lifetime intrinsics.
44  %i = alloca i32, align 4
45  %i.ptr = bitcast i32* %i to i8*
46
47  ; Poison memory in prologue: F1F1F1F1F8F3F3F3
48  ; CHECK: store i64 -868082052615769615, i64* %{{[0-9]+}}
49
50  ; Memory is unpoisoned at llvm.lifetime.start
51  call void @llvm.lifetime.start.p0i8(i64 3, i8* %i.ptr)
52  ; CHECK: store i8 4, i8* %{{[0-9]+}}
53  ; CHECK-NEXT: llvm.lifetime.start
54
55  store volatile i8 0, i8* %i.ptr
56  ; CHECK: store volatile
57
58  call void @llvm.lifetime.end.p0i8(i64 4, i8* %i.ptr)
59  ; CHECK: store i8 -8, i8* %{{[0-9]+}}
60  ; CHECK-NEXT: call void @llvm.lifetime.end
61
62  ; Memory is poisoned at every call to llvm.lifetime.end
63  call void @llvm.lifetime.end.p0i8(i64 2, i8* %i.ptr)
64  ; CHECK: store i8 -8, i8* %{{[0-9]+}}
65  ; CHECK-NEXT: call void @llvm.lifetime.end
66
67  ; Lifetime intrinsics for array.
68  %arr = alloca [10 x i32], align 16
69  %arr.ptr = bitcast [10 x i32]* %arr to i8*
70
71  call void @llvm.lifetime.start.p0i8(i64 40, i8* %arr.ptr)
72  ; CHECK-DEFAULT: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 40)
73  ; CHECK-NO-DYNAMIC-NOT: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 40)
74
75  store volatile i8 0, i8* %arr.ptr
76  ; CHECK: store volatile
77
78  call void @llvm.lifetime.end.p0i8(i64 40, i8* %arr.ptr)
79  ; CHECK-DEFAULT: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 40)
80  ; CHECK-NO-DYNAMIC-NOT: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 40)
81
82  ; One more lifetime start/end for the same variable %i.
83  call void @llvm.lifetime.start.p0i8(i64 2, i8* %i.ptr)
84  ; CHECK: store i8 4, i8* %{{[0-9]+}}
85  ; CHECK-NEXT: llvm.lifetime.start
86
87  store volatile i8 0, i8* %i.ptr
88  ; CHECK: store volatile
89
90  call void @llvm.lifetime.end.p0i8(i64 4, i8* %i.ptr)
91  ; CHECK: store i8 -8, i8* %{{[0-9]+}}
92  ; CHECK-NEXT: llvm.lifetime.end
93
94  ; Memory is unpoisoned at function exit (only once).
95  ; CHECK: store i64 0, i64* %{{[0-9]+}}
96  ; CHECK-NEXT: ret void
97  ret void
98}
99
100; Check that arguments of lifetime may come from phi nodes.
101define void @phi_args(i1 %x) sanitize_address {
102  ; CHECK-LABEL: define void @phi_args(i1 %x)
103
104entry:
105  %i = alloca i64, align 4
106  %i.ptr = bitcast i64* %i to i8*
107
108  ; Poison memory in prologue: F1F1F1F1F8F3F3F3
109  ; CHECK: store i64 -868082052615769615, i64* %{{[0-9]+}}
110
111  call void @llvm.lifetime.start.p0i8(i64 8, i8* %i.ptr)
112  ; CHECK: store i8 0, i8* %{{[0-9]+}}
113  ; CHECK-NEXT: llvm.lifetime.start
114
115  store volatile i8 0, i8* %i.ptr
116  ; CHECK: store volatile
117
118  br i1 %x, label %bb0, label %bb1
119
120bb0:
121  %i.ptr2 = bitcast i64* %i to i8*
122  br label %bb1
123
124bb1:
125  %i.phi = phi i8* [ %i.ptr, %entry ], [ %i.ptr2, %bb0 ]
126  call void @llvm.lifetime.end.p0i8(i64 8, i8* %i.phi)
127  ; CHECK: store i8 -8, i8* %{{[0-9]+}}
128  ; CHECK-NEXT: llvm.lifetime.end
129
130  ret void
131  ; CHECK: store i64 0, i64* %{{[0-9]+}}
132  ; CHECK-NEXT: ret void
133}
134
135; Check that arguments of lifetime may come from getelementptr nodes.
136define void @getelementptr_args() sanitize_address{
137  ; CHECK-LABEL: define void @getelementptr_args
138entry:
139  %x = alloca [1024 x i8], align 16
140  %d = alloca i8*, align 8
141
142  ; F1F1F1F1
143  ; CHECK: store i32 -235802127, i32* %{{[0-9]+}}
144  ; F3F3F3F3F3F3F3F3
145  ; CHECK: store i64 -868082074056920077, i64* %{{[0-9]+}}
146  ; F3F3F3F3F3F3F3F3
147  ; CHECK: store i64 -868082074056920077, i64* %{{[0-9]+}}
148
149  %0 = getelementptr inbounds [1024 x i8], [1024 x i8]* %x, i64 0, i64 0
150  call void @llvm.lifetime.start.p0i8(i64 1024, i8* %0)
151  ; CHECK: call void @__asan_set_shadow_00(i64 %{{[0-9]+}}, i64 128)
152  ; CHECK-NEXT: call void @llvm.lifetime.start
153
154  store i8* %0, i8** %d, align 8
155  ; CHECK: store i8
156
157  call void @llvm.lifetime.end.p0i8(i64 1024, i8* %0)
158  ; CHECK: call void @__asan_set_shadow_f8(i64 %{{[0-9]+}}, i64 128)
159  ; CHECK-NEXT: call void @llvm.lifetime.end
160
161  ret void
162  ; CHECK: call void @__asan_set_shadow_00(i64 %{{[0-9]+}}, i64 148)
163  ; CHECK-NEXT: ret void
164}
165
166define void @zero_sized(i64 %a) #0 {
167; CHECK-LABEL: define void @zero_sized(i64 %a)
168
169entry:
170  %a.addr = alloca i64, align 8
171  %b = alloca [0 x i8], align 1
172  store i64 %a, i64* %a.addr, align 8
173
174  %0 = bitcast [0 x i8]* %b to i8*
175  call void @llvm.lifetime.start.p0i8(i64 0, i8* %0) #2
176  ; CHECK: %{{[0-9]+}} = bitcast
177  ; CHECK-NEXT: call void @llvm.lifetime.start
178
179  %1 = bitcast [0 x i8]* %b to i8*
180  call void @llvm.lifetime.end.p0i8(i64 0, i8* %1) #2
181  ; CHECK-NEXT: %{{[0-9]+}} = bitcast
182  ; CHECK-NEXT: call void @llvm.lifetime.end
183
184  ret void
185  ; CHECK-NEXT: ret void
186}
187