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