1; RUN: opt < %s -dfsan -dfsan-track-origins=1 -S | FileCheck %s 2; RUN: opt < %s -dfsan -dfsan-track-origins=1 -dfsan-combine-pointer-labels-on-store -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR 3target 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" 4target triple = "x86_64-unknown-linux-gnu" 5 6; CHECK: @__dfsan_shadow_width_bits = weak_odr constant i32 [[#SBITS:]] 7; CHECK: @__dfsan_shadow_width_bytes = weak_odr constant i32 [[#SBYTES:]] 8 9define void @store_zero_to_non_escaped_alloca() { 10 ; CHECK-LABEL: @store_zero_to_non_escaped_alloca.dfsan 11 ; CHECK-NEXT: [[A:%.*]] = alloca i[[#SBITS]], align [[#SBYTES]] 12 ; CHECK-NEXT: %_dfsa = alloca i32, align 4 13 ; CHECK-NEXT: %p = alloca i16, align 2 14 ; CHECK-NEXT: store i[[#SBITS]] 0, i[[#SBITS]]* [[A]], align [[#SBYTES]] 15 ; CHECK-NEXT: store i16 1, i16* %p, align 2 16 ; CHECK-NEXT: ret void 17 18 %p = alloca i16 19 store i16 1, i16* %p 20 ret void 21} 22 23define void @store_nonzero_to_non_escaped_alloca(i16 %a) { 24 ; CHECK-LABEL: @store_nonzero_to_non_escaped_alloca.dfsan 25 ; CHECK: %[[#AO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 26 ; CHECK: %_dfsa = alloca i32, align 4 27 ; CHECK: store i32 %[[#AO]], i32* %_dfsa, align 4 28 29 %p = alloca i16 30 store i16 %a, i16* %p 31 ret void 32} 33 34declare void @foo(i16* %p) 35 36define void @store_zero_to_escaped_alloca() { 37 ; CHECK-LABEL: @store_zero_to_escaped_alloca.dfsan 38 ; CHECK: %[[#SA:]] = bitcast i[[#SBITS]]* {{.*}} to i[[#NUM_BITS:mul(SBITS,2)]]* 39 ; CHECK-NEXT: store i[[#NUM_BITS]] 0, i[[#NUM_BITS]]* %[[#SA]], align [[#SBYTES]] 40 ; CHECK-NEXT: store i16 1, i16* %p, align 2 41 ; CHECK-NEXT: store i[[#SBITS]] 0, i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN:2]] 42 ; CHECK-NEXT: call void @foo.dfsan(i16* %p) 43 44 %p = alloca i16 45 store i16 1, i16* %p 46 call void @foo(i16* %p) 47 ret void 48} 49 50define void @store_nonzero_to_escaped_alloca(i16 %a) { 51 ; CHECK-LABEL: @store_nonzero_to_escaped_alloca.dfsan 52 ; CHECK-NEXT: %[[#AO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 53 ; CHECK-NEXT: %[[#AS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]] 54 ; CHECK: %[[#INTP:]] = ptrtoint i16* %p to i64 55 ; CHECK-NEXT: %[[#SHADOW_OFFSET:]] = xor i64 %[[#INTP]], [[#%.10d,MASK:]] 56 ; CHECK-NEXT: %[[#SHADOW_PTR0:]] = inttoptr i64 %[[#SHADOW_OFFSET]] to i[[#SBITS]]* 57 ; CHECK-NEXT: %[[#ORIGIN_OFFSET:]] = add i64 %[[#SHADOW_OFFSET]], [[#%.10d,ORIGIN_BASE:]] 58 ; CHECK-NEXT: %[[#ORIGIN_ADDR:]] = and i64 %[[#ORIGIN_OFFSET]], -4 59 ; CHECK-NEXT: %[[#ORIGIN_PTR:]] = inttoptr i64 %[[#ORIGIN_ADDR]] to i32* 60 ; CHECK: %_dfscmp = icmp ne i[[#SBITS]] %[[#AS]], 0 61 ; CHECK-NEXT: br i1 %_dfscmp, label %[[L1:.*]], label %[[L2:.*]], 62 ; CHECK: [[L1]]: 63 ; CHECK-NEXT: %[[#NO:]] = call i32 @__dfsan_chain_origin(i32 %[[#AO]]) 64 ; CHECK-NEXT: store i32 %[[#NO]], i32* %[[#ORIGIN_PTR]], align 4 65 ; CHECK-NEXT: br label %[[L2]] 66 ; CHECK: [[L2]]: 67 ; CHECK-NEXT: store i16 %a, i16* %p, align 2 68 69 %p = alloca i16 70 store i16 %a, i16* %p 71 call void @foo(i16* %p) 72 ret void 73} 74 75define void @store64_align8(i64* %p, i64 %a) { 76 ; CHECK-LABEL: @store64_align8.dfsan 77 78 ; COMBINE_STORE_PTR-NEXT: %[[#PO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 79 ; COMBINE_STORE_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]] 80 81 ; CHECK-NEXT: %[[#AO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 82 ; CHECK-NEXT: %[[#AS:]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]] 83 84 ; COMBINE_STORE_PTR-NEXT: %[[#AS:]] = or i[[#SBITS]] %[[#AS]], %[[#PS]] 85 ; COMBINE_STORE_PTR-NEXT: %[[#NE:]] = icmp ne i[[#SBITS]] %[[#PS]], 0 86 ; COMBINE_STORE_PTR-NEXT: %[[#AO:]] = select i1 %[[#NE]], i32 %[[#PO]], i32 %[[#AO]] 87 88 ; CHECK: %_dfscmp = icmp ne i[[#SBITS]] %[[#AS]], 0 89 ; CHECK-NEXT: br i1 %_dfscmp, label %[[L1:.*]], label %[[L2:.*]], 90 ; CHECK: [[L1]]: 91 ; CHECK-NEXT: %[[#NO:]] = call i32 @__dfsan_chain_origin(i32 %[[#AO]]) 92 ; CHECK-NEXT: %[[#NO_ZEXT:]] = zext i32 %[[#NO]] to i64 93 ; CHECK-NEXT: %[[#NO_SHL:]] = shl i64 %[[#NO_ZEXT]], 32 94 ; CHECK-NEXT: %[[#NO2:]] = or i64 %[[#NO_ZEXT]], %[[#NO_SHL]] 95 ; CHECK-NEXT: %[[#O_PTR:]] = bitcast i32* {{.*}} to i64* 96 ; CHECK-NEXT: store i64 %[[#NO2]], i64* %[[#O_PTR]], align 8 97 ; CHECK-NEXT: br label %[[L2]] 98 ; CHECK: [[L2]]: 99 ; CHECK-NEXT: store i64 %a, i64* %p, align 8 100 101 store i64 %a, i64* %p 102 ret void 103} 104 105define void @store64_align2(i64* %p, i64 %a) { 106 ; CHECK-LABEL: @store64_align2.dfsan 107 108 ; COMBINE_STORE_PTR-NEXT: %[[#PO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 109 ; COMBINE_STORE_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]] 110 111 ; CHECK-NEXT: %[[#AO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 112 ; CHECK-NEXT: %[[#AS:]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]] 113 114 ; COMBINE_STORE_PTR-NEXT: %[[#AS:]] = or i[[#SBITS]] %[[#AS]], %[[#PS]] 115 ; COMBINE_STORE_PTR-NEXT: %[[#NE:]] = icmp ne i[[#SBITS]] %[[#PS]], 0 116 ; COMBINE_STORE_PTR-NEXT: %[[#AO:]] = select i1 %[[#NE]], i32 %[[#PO]], i32 %[[#AO]] 117 118 ; CHECK: %_dfscmp = icmp ne i[[#SBITS]] %[[#AS]], 0 119 ; CHECK-NEXT: br i1 %_dfscmp, label %[[L1:.*]], label %[[L2:.*]], 120 ; CHECK: [[L1]]: 121 ; CHECK-NEXT: %[[#NO:]] = call i32 @__dfsan_chain_origin(i32 %[[#AO]]) 122 ; CHECK-NEXT: store i32 %[[#NO]], i32* %[[#O_PTR0:]], align 4 123 ; CHECK-NEXT: %[[#O_PTR1:]] = getelementptr i32, i32* %[[#O_PTR0]], i32 1 124 ; CHECK-NEXT: store i32 %[[#NO]], i32* %[[#O_PTR1]], align 4 125 ; CHECK: [[L2]]: 126 ; CHECK-NEXT: store i64 %a, i64* %p, align 2 127 128 store i64 %a, i64* %p, align 2 129 ret void 130} 131 132define void @store96_align8(i96* %p, i96 %a) { 133 ; CHECK-LABEL: @store96_align8.dfsan 134 135 ; COMBINE_STORE_PTR-NEXT: %[[#PO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 0), align 4 136 ; COMBINE_STORE_PTR-NEXT: %[[#PS:]] = load i[[#SBITS]], i[[#SBITS]]* bitcast ([100 x i64]* @__dfsan_arg_tls to i[[#SBITS]]*), align [[ALIGN]] 137 138 ; CHECK-NEXT: %[[#AO:]] = load i32, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__dfsan_arg_origin_tls, i64 0, i64 1), align 4 139 ; CHECK-NEXT: %[[#AS:]] = load i[[#SBITS]], i[[#SBITS]]* inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__dfsan_arg_tls to i64), i64 2) to i[[#SBITS]]*), align [[ALIGN]] 140 141 ; COMBINE_STORE_PTR-NEXT: %[[#AS:]] = or i[[#SBITS]] %[[#AS]], %[[#PS]] 142 ; COMBINE_STORE_PTR-NEXT: %[[#NE:]] = icmp ne i[[#SBITS]] %[[#PS]], 0 143 ; COMBINE_STORE_PTR-NEXT: %[[#AO:]] = select i1 %[[#NE]], i32 %[[#PO]], i32 %[[#AO]] 144 145 ; CHECK: %_dfscmp = icmp ne i[[#SBITS]] %[[#AS]], 0 146 ; CHECK-NEXT: br i1 %_dfscmp, label %[[L1:.*]], label %[[L2:.*]], 147 ; CHECK: [[L1]]: 148 ; CHECK-NEXT: %[[#NO:]] = call i32 @__dfsan_chain_origin(i32 %[[#AO]]) 149 ; CHECK-NEXT: %[[#NO_ZEXT:]] = zext i32 %[[#NO]] to i64 150 ; CHECK-NEXT: %[[#NO_SHL:]] = shl i64 %[[#NO_ZEXT]], 32 151 ; CHECK-NEXT: %[[#NO2:]] = or i64 %[[#NO_ZEXT]], %[[#NO_SHL]] 152 ; CHECK-NEXT: %[[#O_PTR64:]] = bitcast i32* %[[#O_PTR0:]] to i64* 153 ; CHECK-NEXT: store i64 %[[#NO2]], i64* %[[#O_PTR64]], align 8 154 ; CHECK-NEXT: %[[#O_PTR1:]] = getelementptr i32, i32* %[[#O_PTR0]], i32 2 155 ; CHECK-NEXT: store i32 %[[#NO]], i32* %[[#O_PTR1]], align 8 156 ; CHECK: [[L2]]: 157 ; CHECK-NEXT: store i96 %a, i96* %p, align 8 158 159 store i96 %a, i96* %p, align 8 160 ret void 161} 162