1; RUN: opt < %s -passes=dfsan -dfsan-event-callbacks=true -S | FileCheck %s --check-prefixes=CHECK,EVENT_CALLBACKS 2; RUN: opt < %s -passes=dfsan -S | FileCheck %s --check-prefixes=CHECK,FAST 3; RUN: opt < %s -passes=dfsan -dfsan-combine-pointer-labels-on-load=false -S | FileCheck %s --check-prefixes=CHECK,NO_COMBINE_LOAD_PTR 4; RUN: opt < %s -passes=dfsan -dfsan-combine-pointer-labels-on-store=true -S | FileCheck %s --check-prefixes=CHECK,COMBINE_STORE_PTR 5; RUN: opt < %s -passes=dfsan -dfsan-track-select-control-flow=false -S | FileCheck %s --check-prefixes=CHECK,NO_SELECT_CONTROL 6; RUN: opt < %s -passes=dfsan -dfsan-debug-nonzero-labels -S | FileCheck %s --check-prefixes=CHECK,DEBUG_NONZERO_LABELS 7target 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" 8target triple = "x86_64-unknown-linux-gnu" 9 10; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]] 11; CHECK: @__dfsan_retval_tls = external thread_local(initialexec) global [[TLS_ARR]] 12define {ptr, i32} @pass_struct({ptr, i32} %s) { 13 ; NO_COMBINE_LOAD_PTR: @pass_struct.dfsan 14 ; NO_COMBINE_LOAD_PTR: [[L:%.*]] = load { i8, i8 }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 15 ; NO_COMBINE_LOAD_PTR: store { i8, i8 } [[L]], ptr @__dfsan_retval_tls, align [[ALIGN]] 16 17 ; DEBUG_NONZERO_LABELS: @pass_struct.dfsan 18 ; DEBUG_NONZERO_LABELS: [[L:%.*]] = load { i8, i8 }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 19 ; DEBUG_NONZERO_LABELS: [[L0:%.*]] = extractvalue { i8, i8 } [[L]], 0 20 ; DEBUG_NONZERO_LABELS: [[L1:%.*]] = extractvalue { i8, i8 } [[L]], 1 21 ; DEBUG_NONZERO_LABELS: [[L01:%.*]] = or i8 [[L0]], [[L1]] 22 ; DEBUG_NONZERO_LABELS: {{.*}} = icmp ne i8 [[L01]], 0 23 ; DEBUG_NONZERO_LABELS: call void @__dfsan_nonzero_label() 24 ; DEBUG_NONZERO_LABELS: store { i8, i8 } [[L]], ptr @__dfsan_retval_tls, align [[ALIGN]] 25 26 ret {ptr, i32} %s 27} 28 29%StructOfAggr = type {ptr, [4 x i2], <4 x i3>, {i1, i1}} 30 31define %StructOfAggr @pass_struct_of_aggregate(%StructOfAggr %s) { 32 ; NO_COMBINE_LOAD_PTR: @pass_struct_of_aggregate.dfsan 33 ; NO_COMBINE_LOAD_PTR: %1 = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 34 ; NO_COMBINE_LOAD_PTR: store { i8, [4 x i8], i8, { i8, i8 } } %1, ptr @__dfsan_retval_tls, align [[ALIGN]] 35 36 ret %StructOfAggr %s 37} 38 39define {} @load_empty_struct(ptr %p) { 40 ; NO_COMBINE_LOAD_PTR: @load_empty_struct.dfsan 41 ; NO_COMBINE_LOAD_PTR: store {} zeroinitializer, ptr @__dfsan_retval_tls, align 2 42 43 %a = load {}, ptr %p 44 ret {} %a 45} 46 47@Y = constant {i1, i32} {i1 1, i32 1} 48 49define {i1, i32} @load_global_struct() { 50 ; NO_COMBINE_LOAD_PTR: @load_global_struct.dfsan 51 ; NO_COMBINE_LOAD_PTR: store { i8, i8 } zeroinitializer, ptr @__dfsan_retval_tls, align 2 52 53 %a = load {i1, i32}, ptr @Y 54 ret {i1, i32} %a 55} 56 57define {i1, i32} @select_struct(i1 %c, {i1, i32} %a, {i1, i32} %b) { 58 ; NO_SELECT_CONTROL: @select_struct.dfsan 59 ; NO_SELECT_CONTROL: [[B:%.*]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align [[ALIGN:2]] 60 ; NO_SELECT_CONTROL: [[A:%.*]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN]] 61 ; NO_SELECT_CONTROL: [[C:%.*]] = load i8, ptr @__dfsan_arg_tls, align [[ALIGN]] 62 ; NO_SELECT_CONTROL: [[S:%.*]] = select i1 %c, { i8, i8 } [[A]], { i8, i8 } [[B]] 63 ; NO_SELECT_CONTROL: store { i8, i8 } [[S]], ptr @__dfsan_retval_tls, align [[ALIGN]] 64 65 ; FAST: @select_struct.dfsan 66 ; FAST: %[[#R:]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align [[ALIGN:2]] 67 ; FAST: %[[#R+1]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN]] 68 ; FAST: %[[#R+2]] = load i8, ptr @__dfsan_arg_tls, align [[ALIGN]] 69 ; FAST: %[[#R+3]] = select i1 %c, { i8, i8 } %[[#R+1]], { i8, i8 } %[[#R]] 70 ; FAST: %[[#R+4]] = extractvalue { i8, i8 } %[[#R+3]], 0 71 ; FAST: %[[#R+5]] = extractvalue { i8, i8 } %[[#R+3]], 1 72 ; FAST: %[[#R+6]] = or i8 %[[#R+4]], %[[#R+5]] 73 ; FAST: %[[#R+7]] = or i8 %[[#R+2]], %[[#R+6]] 74 ; FAST: %[[#R+8]] = insertvalue { i8, i8 } undef, i8 %[[#R+7]], 0 75 ; FAST: %[[#R+9]] = insertvalue { i8, i8 } %[[#R+8]], i8 %[[#R+7]], 1 76 ; FAST: store { i8, i8 } %[[#R+9]], ptr @__dfsan_retval_tls, align [[ALIGN]] 77 78 %s = select i1 %c, {i1, i32} %a, {i1, i32} %b 79 ret {i1, i32} %s 80} 81 82define { i32, i32 } @asm_struct(i32 %0, i32 %1) { 83 ; FAST: @asm_struct.dfsan 84 ; FAST: [[E1:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN:2]] 85 ; FAST: [[E0:%.*]] = load i8, ptr @__dfsan_arg_tls, align [[ALIGN]] 86 ; FAST: [[E01:%.*]] = or i8 [[E0]], [[E1]] 87 ; FAST: [[S0:%.*]] = insertvalue { i8, i8 } undef, i8 [[E01]], 0 88 ; FAST: [[S1:%.*]] = insertvalue { i8, i8 } [[S0]], i8 [[E01]], 1 89 ; FAST: store { i8, i8 } [[S1]], ptr @__dfsan_retval_tls, align [[ALIGN]] 90 91entry: 92 %a = call { i32, i32 } asm "", "=r,=r,r,r,~{dirflag},~{fpsr},~{flags}"(i32 %0, i32 %1) 93 ret { i32, i32 } %a 94} 95 96define {i32, i32} @const_struct() { 97 ; FAST: @const_struct.dfsan 98 ; FAST: store { i8, i8 } zeroinitializer, ptr @__dfsan_retval_tls, align 2 99 ret {i32, i32} { i32 42, i32 11 } 100} 101 102define i1 @extract_struct({i1, i5} %s) { 103 ; FAST: @extract_struct.dfsan 104 ; FAST: [[SM:%.*]] = load { i8, i8 }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 105 ; FAST: [[EM:%.*]] = extractvalue { i8, i8 } [[SM]], 0 106 ; FAST: store i8 [[EM]], ptr @__dfsan_retval_tls, align [[ALIGN]] 107 108 %e2 = extractvalue {i1, i5} %s, 0 109 ret i1 %e2 110} 111 112define {i1, i5} @insert_struct({i1, i5} %s, i5 %e1) { 113 ; FAST: @insert_struct.dfsan 114 ; FAST: [[EM:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN:2]] 115 ; FAST: [[SM:%.*]] = load { i8, i8 }, ptr @__dfsan_arg_tls, align [[ALIGN]] 116 ; FAST: [[SM1:%.*]] = insertvalue { i8, i8 } [[SM]], i8 [[EM]], 1 117 ; FAST: store { i8, i8 } [[SM1]], ptr @__dfsan_retval_tls, align [[ALIGN]] 118 %s1 = insertvalue {i1, i5} %s, i5 %e1, 1 119 ret {i1, i5} %s1 120} 121 122define {i1, i1} @load_struct(ptr %p) { 123 ; NO_COMBINE_LOAD_PTR: @load_struct.dfsan 124 ; NO_COMBINE_LOAD_PTR: [[OL:%.*]] = or i8 125 ; NO_COMBINE_LOAD_PTR: [[S0:%.*]] = insertvalue { i8, i8 } undef, i8 [[OL]], 0 126 ; NO_COMBINE_LOAD_PTR: [[S1:%.*]] = insertvalue { i8, i8 } [[S0]], i8 [[OL]], 1 127 ; NO_COMBINE_LOAD_PTR: store { i8, i8 } [[S1]], ptr @__dfsan_retval_tls, align 2 128 129 ; EVENT_CALLBACKS: @load_struct.dfsan 130 ; EVENT_CALLBACKS: [[OL0:%.*]] = or i8 131 ; EVENT_CALLBACKS: [[OL1:%.*]] = or i8 [[OL0]], 132 ; EVENT_CALLBACKS: [[S0:%.*]] = insertvalue { i8, i8 } undef, i8 [[OL1]], 0 133 ; EVENT_CALLBACKS: call void @__dfsan_load_callback(i8 zeroext [[OL1]] 134 135 %s = load {i1, i1}, ptr %p 136 ret {i1, i1} %s 137} 138 139define void @store_struct(ptr %p, {i1, i1} %s) { 140 ; FAST: @store_struct.dfsan 141 ; FAST: [[S:%.*]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN:2]] 142 ; FAST: [[E0:%.*]] = extractvalue { i8, i8 } [[S]], 0 143 ; FAST: [[E1:%.*]] = extractvalue { i8, i8 } [[S]], 1 144 ; FAST: [[E:%.*]] = or i8 [[E0]], [[E1]] 145 ; FAST: [[P0:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 0 146 ; FAST: store i8 [[E]], ptr [[P0]], align 1 147 ; FAST: [[P1:%.*]] = getelementptr i8, ptr [[P]], i32 1 148 ; FAST: store i8 [[E]], ptr [[P1]], align 1 149 150 ; EVENT_CALLBACKS: @store_struct.dfsan 151 ; EVENT_CALLBACKS: [[OL:%.*]] = or i8 152 ; EVENT_CALLBACKS: call void @__dfsan_store_callback(i8 zeroext [[OL]] 153 154 ; COMBINE_STORE_PTR: @store_struct.dfsan 155 ; COMBINE_STORE_PTR: [[PL:%.*]] = load i8, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 156 ; COMBINE_STORE_PTR: [[SL:%.*]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN]] 157 ; COMBINE_STORE_PTR: [[SL0:%.*]] = extractvalue { i8, i8 } [[SL]], 0 158 ; COMBINE_STORE_PTR: [[SL1:%.*]] = extractvalue { i8, i8 } [[SL]], 1 159 ; COMBINE_STORE_PTR: [[SL01:%.*]] = or i8 [[SL0]], [[SL1]] 160 ; COMBINE_STORE_PTR: [[E:%.*]] = or i8 [[SL01]], [[PL]] 161 ; COMBINE_STORE_PTR: [[P0:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 0 162 ; COMBINE_STORE_PTR: store i8 [[E]], ptr [[P0]], align 1 163 ; COMBINE_STORE_PTR: [[P1:%.*]] = getelementptr i8, ptr [[P]], i32 1 164 ; COMBINE_STORE_PTR: store i8 [[E]], ptr [[P1]], align 1 165 166 store {i1, i1} %s, ptr %p 167 ret void 168} 169 170define i2 @extract_struct_of_aggregate11(%StructOfAggr %s) { 171 ; FAST: @extract_struct_of_aggregate11.dfsan 172 ; FAST: [[E:%.*]] = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 173 ; FAST: [[E11:%.*]] = extractvalue { i8, [4 x i8], i8, { i8, i8 } } [[E]], 1, 1 174 ; FAST: store i8 [[E11]], ptr @__dfsan_retval_tls, align [[ALIGN]] 175 176 %e11 = extractvalue %StructOfAggr %s, 1, 1 177 ret i2 %e11 178} 179 180define [4 x i2] @extract_struct_of_aggregate1(%StructOfAggr %s) { 181 ; FAST: @extract_struct_of_aggregate1.dfsan 182 ; FAST: [[E:%.*]] = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 183 ; FAST: [[E1:%.*]] = extractvalue { i8, [4 x i8], i8, { i8, i8 } } [[E]], 1 184 ; FAST: store [4 x i8] [[E1]], ptr @__dfsan_retval_tls, align [[ALIGN]] 185 %e1 = extractvalue %StructOfAggr %s, 1 186 ret [4 x i2] %e1 187} 188 189define <4 x i3> @extract_struct_of_aggregate2(%StructOfAggr %s) { 190 ; FAST: @extract_struct_of_aggregate2.dfsan 191 ; FAST: [[E:%.*]] = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 192 ; FAST: [[E2:%.*]] = extractvalue { i8, [4 x i8], i8, { i8, i8 } } [[E]], 2 193 ; FAST: store i8 [[E2]], ptr @__dfsan_retval_tls, align [[ALIGN]] 194 %e2 = extractvalue %StructOfAggr %s, 2 195 ret <4 x i3> %e2 196} 197 198define { i1, i1 } @extract_struct_of_aggregate3(%StructOfAggr %s) { 199 ; FAST: @extract_struct_of_aggregate3.dfsan 200 ; FAST: [[E:%.*]] = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 201 ; FAST: [[E3:%.*]] = extractvalue { i8, [4 x i8], i8, { i8, i8 } } [[E]], 3 202 ; FAST: store { i8, i8 } [[E3]], ptr @__dfsan_retval_tls, align [[ALIGN]] 203 %e3 = extractvalue %StructOfAggr %s, 3 204 ret { i1, i1 } %e3 205} 206 207define i1 @extract_struct_of_aggregate31(%StructOfAggr %s) { 208 ; FAST: @extract_struct_of_aggregate31.dfsan 209 ; FAST: [[E:%.*]] = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 210 ; FAST: [[E31:%.*]] = extractvalue { i8, [4 x i8], i8, { i8, i8 } } [[E]], 3, 1 211 ; FAST: store i8 [[E31]], ptr @__dfsan_retval_tls, align [[ALIGN]] 212 %e31 = extractvalue %StructOfAggr %s, 3, 1 213 ret i1 %e31 214} 215 216define %StructOfAggr @insert_struct_of_aggregate11(%StructOfAggr %s, i2 %e11) { 217 ; FAST: @insert_struct_of_aggregate11.dfsan 218 ; FAST: [[E11:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 8) to ptr), align [[ALIGN:2]] 219 ; FAST: [[S:%.*]] = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_arg_tls, align [[ALIGN]] 220 ; FAST: [[S1:%.*]] = insertvalue { i8, [4 x i8], i8, { i8, i8 } } [[S]], i8 [[E11]], 1, 1 221 ; FAST: store { i8, [4 x i8], i8, { i8, i8 } } [[S1]], ptr @__dfsan_retval_tls, align [[ALIGN]] 222 223 %s1 = insertvalue %StructOfAggr %s, i2 %e11, 1, 1 224 ret %StructOfAggr %s1 225} 226 227define {ptr, i32} @call_struct({ptr, i32} %s) { 228 ; FAST: @call_struct.dfsan 229 ; FAST: [[S:%.*]] = load { i8, i8 }, ptr @__dfsan_arg_tls, align [[ALIGN:2]] 230 ; FAST: store { i8, i8 } [[S]], ptr @__dfsan_arg_tls, align [[ALIGN]] 231 ; FAST: %_dfsret = load { i8, i8 }, ptr @__dfsan_retval_tls, align [[ALIGN]] 232 ; FAST: store { i8, i8 } %_dfsret, ptr @__dfsan_retval_tls, align [[ALIGN]] 233 234 %r = call {ptr, i32} @pass_struct({ptr, i32} %s) 235 ret {ptr, i32} %r 236} 237 238declare %StructOfAggr @fun_with_many_aggr_args(<2 x i7> %v, [2 x i5] %a, {i3, i3} %s) 239 240define %StructOfAggr @call_many_aggr_args(<2 x i7> %v, [2 x i5] %a, {i3, i3} %s) { 241 ; FAST: @call_many_aggr_args.dfsan 242 ; FAST: [[S:%.*]] = load { i8, i8 }, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align [[ALIGN:2]] 243 ; FAST: [[A:%.*]] = load [2 x i8], ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN]] 244 ; FAST: [[V:%.*]] = load i8, ptr @__dfsan_arg_tls, align [[ALIGN]] 245 ; FAST: store i8 [[V]], ptr @__dfsan_arg_tls, align [[ALIGN]] 246 ; FAST: store [2 x i8] [[A]], ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN]] 247 ; FAST: store { i8, i8 } [[S]], ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align [[ALIGN]] 248 ; FAST: %_dfsret = load { i8, [4 x i8], i8, { i8, i8 } }, ptr @__dfsan_retval_tls, align [[ALIGN]] 249 ; FAST: store { i8, [4 x i8], i8, { i8, i8 } } %_dfsret, ptr @__dfsan_retval_tls, align [[ALIGN]] 250 251 %r = call %StructOfAggr @fun_with_many_aggr_args(<2 x i7> %v, [2 x i5] %a, {i3, i3} %s) 252 ret %StructOfAggr %r 253} 254