1; Test hanlding of llvm.lifetime intrinsics.
2; RUN: opt < %s -asan -asan-module -asan-check-lifetime -asan-use-after-return=0 -S | FileCheck %s
3
4target 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"
5target triple = "x86_64-unknown-linux-gnu"
6
7declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind
8declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind
9
10define void @lifetime_no_size() sanitize_address {
11entry:
12  %i = alloca i32, align 4
13  %i.ptr = bitcast i32* %i to i8*
14  call void @llvm.lifetime.start(i64 -1, i8* %i.ptr)
15  store volatile i8 0, i8* %i.ptr
16  call void @llvm.lifetime.end(i64 -1, i8* %i.ptr)
17
18; Check that lifetime with no size are ignored.
19; CHECK-LABEL: define void @lifetime_no_size()
20; CHECK-NOT: @__asan_poison_stack_memory
21; CHECK-NOT: @__asan_unpoison_stack_memory
22; CHECK: ret void
23  ret void
24}
25
26; Generic case of lifetime analysis.
27define void @lifetime() sanitize_address {
28  ; CHECK-LABEL: define void @lifetime()
29
30  ; Regular variable lifetime intrinsics.
31  %i = alloca i32, align 4
32  %i.ptr = bitcast i32* %i to i8*
33  call void @llvm.lifetime.start(i64 3, i8* %i.ptr)
34  store volatile i8 0, i8* %i.ptr
35  ; Memory is unpoisoned at llvm.lifetime.start
36  ; CHECK: %[[VAR:[^ ]*]] = ptrtoint i32* %{{[^ ]+}} to i64
37  ; CHECK-NEXT: call void @__asan_unpoison_stack_memory(i64 %[[VAR]], i64 3)
38  call void @llvm.lifetime.end(i64 4, i8* %i.ptr)
39  call void @llvm.lifetime.end(i64 2, i8* %i.ptr)
40  ; Memory is poisoned at every call to llvm.lifetime.end
41  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 4)
42  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 2)
43
44  ; Lifetime intrinsics for array.
45  %arr = alloca [10 x i32], align 16
46  %arr.ptr = bitcast [10 x i32]* %arr to i8*
47  call void @llvm.lifetime.start(i64 40, i8* %arr.ptr)
48  store volatile i8 0, i8* %arr.ptr
49  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 40)
50  call void @llvm.lifetime.end(i64 40, i8* %arr.ptr)
51  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 40)
52
53  ; One more lifetime start/end for the same variable %i.
54  call void @llvm.lifetime.start(i64 4, i8* %i.ptr)
55  store volatile i8 0, i8* %i.ptr
56  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 4)
57  call void @llvm.lifetime.end(i64 4, i8* %i.ptr)
58  ; CHECK: call void @__asan_poison_stack_memory(i64 %{{[^ ]+}}, i64 4)
59
60  ; Memory is unpoisoned at function exit (only once).
61  ; CHECK: call void @__asan_unpoison_stack_memory(i64 %{{[^ ]+}}, i64 {{.*}})
62  ; CHECK-NOT: @__asan_unpoison_stack_memory
63  ; CHECK: ret void
64  ret void
65}
66
67; Check that arguments of lifetime may come from phi nodes.
68define void @phi_args(i1 %x) sanitize_address {
69  ; CHECK-LABEL: define void @phi_args(i1 %x)
70
71entry:
72  %i = alloca i64, align 4
73  %i.ptr = bitcast i64* %i to i8*
74  call void @llvm.lifetime.start(i64 8, i8* %i.ptr)
75  store volatile i8 0, i8* %i.ptr
76  ; CHECK: __asan_unpoison_stack_memory
77  br i1 %x, label %bb0, label %bb1
78
79bb0:
80  %i.ptr2 = bitcast i64* %i to i8*
81  br label %bb1
82
83bb1:
84  %i.phi = phi i8* [ %i.ptr, %entry ], [ %i.ptr2, %bb0 ]
85  call void @llvm.lifetime.end(i64 8, i8* %i.phi)
86  ; CHECK: __asan_poison_stack_memory
87  ; CHECK: ret void
88  ret void
89}
90