159 lines · plain
1; RUN: opt < %s -passes=asan -asan-use-after-scope -asan-use-stack-safety=1 -S | FileCheck %s2 3; Source (-O0 -fsanitize=address -fsanitize-address-use-after-scope):4;; struct S { int x, y; };5;; void swap(S *a, S *b, bool doit) {6;; if (!doit)7;; return;8;; auto tmp = *a;9;; *a = *b;10;; *b = tmp;11;; }12 13target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"14target triple = "x86_64-apple-macosx10.14.0"15 16%struct.S = type { i32, i32 }17 18; CHECK-LABEL: define {{.*}} @_Z4swapP1SS0_b(19 20; First come the argument allocas.21; CHECK: %a.addr = alloca ptr, align 822; CHECK-NEXT: %b.addr = alloca ptr, align 823; CHECK-NEXT: %doit.addr = alloca i8, align 124 25; Next, the stores into the argument allocas.26; CHECK-NEXT: store ptr {{.*}}, ptr %a.addr27; CHECK-NEXT: store ptr {{.*}}, ptr %b.addr28; CHECK-NEXT: [[frombool:%.*]] = zext i1 {{.*}} to i829; CHECK-NEXT: store i8 %frombool, ptr %doit.addr, align 130; CHECK-NEXT: [[stack_base:%.*]] = alloca i64, align 831 32define void @_Z4swapP1SS0_b(ptr %a, ptr %b, i1 zeroext %doit) sanitize_address {33entry:34 %a.addr = alloca ptr, align 835 %b.addr = alloca ptr, align 836 %doit.addr = alloca i8, align 137 %tmp = alloca %struct.S, align 438 store ptr %a, ptr %a.addr, align 839 store ptr %b, ptr %b.addr, align 840 %frombool = zext i1 %doit to i841 store i8 %frombool, ptr %doit.addr, align 142 %0 = load i8, ptr %doit.addr, align 143 %tobool = trunc i8 %0 to i144 br i1 %tobool, label %if.end, label %if.then45 46if.then: ; preds = %entry47 br label %return48 49if.end: ; preds = %entry50 %1 = load ptr, ptr %a.addr, align 851 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %1, i64 8, i1 false)52 %2 = load ptr, ptr %b.addr, align 853 %3 = load ptr, ptr %a.addr, align 854 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %3, ptr align 4 %2, i64 8, i1 false)55 %4 = load ptr, ptr %b.addr, align 856 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %4, ptr align 4 %tmp, i64 8, i1 false)57 br label %return58 59return: ; preds = %if.end, %if.then60 ret void61}62 63; Synthetic test case, meant to check that we do not reorder instructions past64; a load when attempting to hoist argument init insts.65; CHECK-LABEL: define {{.*}} @func_with_load_in_arginit_sequence66; CHECK: [[argA:%.*]] = alloca ptr,67; CHECK-NEXT: [[argB:%.*]] = alloca ptr,68; CHECK-NEXT: [[argDoit:%.*]] = alloca i8,69; CHECK-NEXT: %tmp = alloca %struct.S, align 470; CHECK-NEXT: store ptr {{.*}}, ptr [[argA]]71; CHECK-NEXT: store ptr {{.*}}, ptr [[argB]]72; CHECK-NEXT: %0 = load i8, ptr %doit.addr, align 173; CHECK-NEXT: %frombool = zext i1 %doit to i874; CHECK-NEXT: store i8 %frombool, ptr %doit.addr, align 175define void @func_with_load_in_arginit_sequence(ptr %a, ptr %b, i1 zeroext %doit) sanitize_address {76entry:77 %a.addr = alloca ptr, align 878 %b.addr = alloca ptr, align 879 %doit.addr = alloca i8, align 180 %tmp = alloca %struct.S, align 481 store ptr %a, ptr %a.addr, align 882 store ptr %b, ptr %b.addr, align 883 84 ; This load prevents the next argument init sequence from being moved.85 %0 = load i8, ptr %doit.addr, align 1 86 87 %frombool = zext i1 %doit to i888 store i8 %frombool, ptr %doit.addr, align 189 %tobool = trunc i8 %0 to i190 br i1 %tobool, label %if.end, label %if.then91 92if.then: ; preds = %entry93 br label %return94 95if.end: ; preds = %entry96 %1 = load ptr, ptr %a.addr, align 897 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %1, i64 8, i1 false)98 %2 = load ptr, ptr %b.addr, align 899 %3 = load ptr, ptr %a.addr, align 8100 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %3, ptr align 4 %2, i64 8, i1 false)101 %4 = load ptr, ptr %b.addr, align 8102 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %4, ptr align 4 %tmp, i64 8, i1 false)103 br label %return104 105return: ; preds = %if.end, %if.then106 ret void107}108 109; Synthetic test case, meant to check that we can handle functions with more110; than one interesting alloca.111; CHECK-LABEL: define {{.*}} @func_with_multiple_interesting_allocas112; CHECK: [[argA:%.*]] = alloca ptr,113; CHECK-NEXT: [[argB:%.*]] = alloca ptr,114; CHECK-NEXT: [[argDoit:%.*]] = alloca i8,115; CHECK-NEXT: %tmp = alloca %struct.S, align 4116; CHECK-NEXT: %tmp2 = alloca %struct.S, align 4117; CHECK-NEXT: store ptr {{.*}}, ptr [[argA]]118; CHECK-NEXT: store ptr {{.*}}, ptr [[argB]]119; CHECK-NEXT: [[frombool:%.*]] = zext i1 {{.*}} to i8120; CHECK-NEXT: store i8 [[frombool]], ptr [[argDoit]]121; CHECK-NEXT: %0 = load i8, ptr %doit.addr, align 1122define void @func_with_multiple_interesting_allocas(ptr %a, ptr %b, i1 zeroext %doit) sanitize_address {123entry:124 %a.addr = alloca ptr, align 8125 %b.addr = alloca ptr, align 8126 %doit.addr = alloca i8, align 1127 %tmp = alloca %struct.S, align 4128 %tmp2 = alloca %struct.S, align 4129 store ptr %a, ptr %a.addr, align 8130 store ptr %b, ptr %b.addr, align 8131 %frombool = zext i1 %doit to i8132 store i8 %frombool, ptr %doit.addr, align 1133 %0 = load i8, ptr %doit.addr, align 1134 %tobool = trunc i8 %0 to i1135 br i1 %tobool, label %if.end, label %if.then136 137if.then: ; preds = %entry138 br label %return139 140if.end: ; preds = %entry141 %1 = load ptr, ptr %a.addr, align 8142 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp, ptr align 4 %1, i64 8, i1 false)143 %2 = load ptr, ptr %b.addr, align 8144 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %tmp2, ptr align 4 %2, i64 8, i1 false)145 %3 = load ptr, ptr %b.addr, align 8146 %4 = load ptr, ptr %a.addr, align 8147 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %4, ptr align 4 %3, i64 8, i1 false)148 %5 = load ptr, ptr %b.addr, align 8149 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %5, ptr align 4 %tmp, i64 8, i1 false)150 %6 = load ptr, ptr %a.addr, align 8151 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %6, ptr align 4 %tmp2, i64 8, i1 false)152 br label %return153 154return: ; preds = %if.end, %if.then155 ret void156}157 158declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)159