1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT 2 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN 3 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO 4 5 // None of the synthesized globals should contain `undef`. 6 // PATTERN-NOT: undef 7 // ZERO-NOT: undef 8 9 template<typename T> void used(T &) noexcept; 10 11 extern "C" { 12 13 // UNINIT-LABEL: test_selfinit( 14 // ZERO-LABEL: test_selfinit( 15 // ZERO: store i32 0, ptr %self, align 4, !annotation [[AUTO_INIT:!.+]] 16 // PATTERN-LABEL: test_selfinit( 17 // PATTERN: store i32 -1431655766, ptr %self, align 4, !annotation [[AUTO_INIT:!.+]] 18 void test_selfinit() { 19 int self = self + 1; 20 used(self); 21 } 22 23 // UNINIT-LABEL: test_block( 24 // ZERO-LABEL: test_block( 25 // ZERO: store i32 0, ptr %block, align 4, !annotation [[AUTO_INIT:!.+]] 26 // PATTERN-LABEL: test_block( 27 // PATTERN: store i32 -1431655766, ptr %block, align 4, !annotation [[AUTO_INIT:!.+]] 28 void test_block() { 29 __block int block; 30 used(block); 31 } 32 33 // Using the variable being initialized is typically UB in C, but for blocks we 34 // can be nice: they imply extra book-keeping and we can do the auto-init before 35 // any of said book-keeping. 36 // 37 // UNINIT-LABEL: test_block_self_init( 38 // ZERO-LABEL: test_block_self_init( 39 // ZERO: %block = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8 40 // ZERO: %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured, ptr %captured, i32 0, i32 4 41 // ZERO-NEXT: store ptr null, ptr %captured1, align 8, !annotation [[AUTO_INIT:!.+]] 42 // ZERO: %call = call ptr @create( 43 // PATTERN-LABEL: test_block_self_init( 44 // PATTERN: %block = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8 45 // PATTERN: %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured, ptr %captured, i32 0, i32 4 46 // PATTERN-NEXT: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %captured1, align 8, !annotation [[AUTO_INIT:!.+]] 47 // PATTERN: %call = call ptr @create( 48 using Block = void (^)(); 49 typedef struct XYZ { 50 Block block; 51 } * xyz_t; 52 void test_block_self_init() { 53 extern xyz_t create(Block block); 54 __block xyz_t captured = create(^() { 55 used(captured); 56 }); 57 } 58 59 // Capturing with escape after initialization is also an edge case. 60 // 61 // UNINIT-LABEL: test_block_captures_self_after_init( 62 // ZERO-LABEL: test_block_captures_self_after_init( 63 // ZERO: %block = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8 64 // ZERO: %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured.1, ptr %captured, i32 0, i32 4 65 // ZERO-NEXT: store ptr null, ptr %captured1, align 8, !annotation [[AUTO_INIT:!.+]] 66 // ZERO: %call = call ptr @create( 67 // PATTERN-LABEL: test_block_captures_self_after_init( 68 // PATTERN: %block = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8 69 // PATTERN: %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured.1, ptr %captured, i32 0, i32 4 70 // PATTERN-NEXT: store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %captured1, align 8, !annotation [[AUTO_INIT:!.+]] 71 // PATTERN: %call = call ptr @create( 72 void test_block_captures_self_after_init() { 73 extern xyz_t create(Block block); 74 __block xyz_t captured; 75 captured = create(^() { 76 used(captured); 77 }); 78 } 79 80 // This type of code is currently not handled by zero / pattern initialization. 81 // The test will break when that is fixed. 82 // UNINIT-LABEL: test_goto_unreachable_value( 83 // ZERO-LABEL: test_goto_unreachable_value( 84 // ZERO-NOT: store {{.*}}%oops 85 // PATTERN-LABEL: test_goto_unreachable_value( 86 // PATTERN-NOT: store {{.*}}%oops 87 void test_goto_unreachable_value() { 88 goto jump; 89 int oops; 90 jump: 91 used(oops); 92 } 93 94 // This type of code is currently not handled by zero / pattern initialization. 95 // The test will break when that is fixed. 96 // UNINIT-LABEL: test_goto( 97 // ZERO-LABEL: test_goto( 98 // ZERO: if.then: 99 // ZERO: br label %jump 100 // ZERO: store i32 0, ptr %oops, align 4, !annotation [[AUTO_INIT:!.+]] 101 // ZERO: br label %jump 102 // ZERO: jump: 103 // PATTERN-LABEL: test_goto( 104 // PATTERN: if.then: 105 // PATTERN: br label %jump 106 // PATTERN: store i32 -1431655766, ptr %oops, align 4, !annotation [[AUTO_INIT:!.+]] 107 // PATTERN: br label %jump 108 // PATTERN: jump: 109 void test_goto(int i) { 110 if (i) 111 goto jump; 112 int oops; 113 jump: 114 used(oops); 115 } 116 117 // This type of code is currently not handled by zero / pattern initialization. 118 // The test will break when that is fixed. 119 // UNINIT-LABEL: test_switch( 120 // ZERO-LABEL: test_switch( 121 // ZERO: sw.bb: 122 // ZERO-NEXT: store i32 0, ptr %oops, align 4, !annotation [[AUTO_INIT:!.+]] 123 // ZERO: sw.bb1: 124 // ZERO-NEXT: call void @{{.*}}used 125 // PATTERN-LABEL: test_switch( 126 // PATTERN: sw.bb: 127 // PATTERN-NEXT: store i32 -1431655766, ptr %oops, align 4, !annotation [[AUTO_INIT:!.+]] 128 // PATTERN: sw.bb1: 129 // PATTERN-NEXT: call void @{{.*}}used 130 void test_switch(int i) { 131 switch (i) { 132 case 0: 133 int oops; 134 break; 135 case 1: 136 used(oops); 137 } 138 } 139 140 // UNINIT-LABEL: test_vla( 141 // ZERO-LABEL: test_vla( 142 // ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4 143 // ZERO: call void @llvm.memset{{.*}}(ptr align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]] 144 // PATTERN-LABEL: test_vla( 145 // PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0 146 // PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop 147 // PATTERN: vla-setup.loop: 148 // PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4 149 // PATTERN: %vla.end = getelementptr inbounds i8, ptr %vla, i64 %[[SIZE]] 150 // PATTERN: br label %vla-init.loop 151 // PATTERN: vla-init.loop: 152 // PATTERN: %vla.cur = phi ptr [ %vla, %vla-setup.loop ], [ %vla.next, %vla-init.loop ] 153 // PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla{{.*}}), !annotation [[AUTO_INIT:!.+]] 154 // PATTERN: %vla.next = getelementptr inbounds i8, ptr %vla.cur, i64 4 155 // PATTERN: %vla-init.isdone = icmp eq ptr %vla.next, %vla.end 156 // PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop 157 // PATTERN: vla-init.cont: 158 // PATTERN: call void @{{.*}}used 159 void test_vla(int size) { 160 // Variable-length arrays can't have a zero size according to C11 6.7.6.2/5. 161 // Neither can they be negative-sized. 162 // 163 // We don't use the former fact because some code creates zero-sized VLAs and 164 // doesn't use them. clang makes these share locations with other stack 165 // values, which leads to initialization of the wrong values. 166 // 167 // We rely on the later fact because it generates better code. 168 // 169 // Both cases are caught by UBSan. 170 int vla[size]; 171 int *ptr = vla; 172 used(ptr); 173 } 174 175 // UNINIT-LABEL: test_alloca( 176 // ZERO-LABEL: test_alloca( 177 // ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 178 // ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]] 179 // ZERO-NEXT: call void @llvm.memset{{.*}}(ptr align [[ALIGN]] %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]] 180 // PATTERN-LABEL: test_alloca( 181 // PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 182 // PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]] 183 // PATTERN-NEXT: call void @llvm.memset{{.*}}(ptr align [[ALIGN]] %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]] 184 void test_alloca(int size) { 185 void *ptr = __builtin_alloca(size); 186 used(ptr); 187 } 188 189 // UNINIT-LABEL: test_alloca_with_align( 190 // ZERO-LABEL: test_alloca_with_align( 191 // ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 192 // ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128 193 // ZERO-NEXT: call void @llvm.memset{{.*}}(ptr align 128 %[[ALLOCA]], i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]] 194 // PATTERN-LABEL: test_alloca_with_align( 195 // PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 196 // PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128 197 // PATTERN-NEXT: call void @llvm.memset{{.*}}(ptr align 128 %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]] 198 void test_alloca_with_align(int size) { 199 void *ptr = __builtin_alloca_with_align(size, 1024); 200 used(ptr); 201 } 202 203 // UNINIT-LABEL: test_alloca_uninitialized( 204 // ZERO-LABEL: test_alloca_uninitialized( 205 // ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 206 // ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]] 207 // ZERO-NOT: call void @llvm.memset 208 // PATTERN-LABEL: test_alloca_uninitialized( 209 // PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 210 // PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]] 211 // PATTERN-NOT: call void @llvm.memset 212 void test_alloca_uninitialized(int size) { 213 void *ptr = __builtin_alloca_uninitialized(size); 214 used(ptr); 215 } 216 217 // UNINIT-LABEL: test_alloca_with_align_uninitialized( 218 // ZERO-LABEL: test_alloca_with_align_uninitialized( 219 // ZERO: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 220 // ZERO-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128 221 // ZERO-NOT: call void @llvm.memset 222 // PATTERN-LABEL: test_alloca_with_align_uninitialized( 223 // PATTERN: %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64 224 // PATTERN-NEXT: %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128 225 // PATTERN-NOT: call void @llvm.memset 226 void test_alloca_with_align_uninitialized(int size) { 227 void *ptr = __builtin_alloca_with_align_uninitialized(size, 1024); 228 used(ptr); 229 } 230 231 // UNINIT-LABEL: test_struct_vla( 232 // ZERO-LABEL: test_struct_vla( 233 // ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 234 // ZERO: call void @llvm.memset{{.*}}(ptr align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]] 235 // PATTERN-LABEL: test_struct_vla( 236 // PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0 237 // PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop 238 // PATTERN: vla-setup.loop: 239 // PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 240 // PATTERN: %vla.end = getelementptr inbounds i8, ptr %vla, i64 %[[SIZE]] 241 // PATTERN: br label %vla-init.loop 242 // PATTERN: vla-init.loop: 243 // PATTERN: %vla.cur = phi ptr [ %vla, %vla-setup.loop ], [ %vla.next, %vla-init.loop ] 244 // PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla{{.*}}), !annotation [[AUTO_INIT:!.+]] 245 // PATTERN: %vla.next = getelementptr inbounds i8, ptr %vla.cur, i64 16 246 // PATTERN: %vla-init.isdone = icmp eq ptr %vla.next, %vla.end 247 // PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop 248 // PATTERN: vla-init.cont: 249 // PATTERN: call void @{{.*}}used 250 void test_struct_vla(int size) { 251 // Same as above, but with a struct that doesn't just memcpy. 252 struct { 253 float f; 254 char c; 255 void *ptr; 256 } vla[size]; 257 void *ptr = static_cast<void*>(vla); 258 used(ptr); 259 } 260 261 // UNINIT-LABEL: test_zsa( 262 // ZERO-LABEL: test_zsa( 263 // ZERO: %zsa = alloca [0 x i32], align 4 264 // ZERO-NOT: %zsa 265 // ZERO: call void @{{.*}}used 266 // PATTERN-LABEL: test_zsa( 267 // PATTERN: %zsa = alloca [0 x i32], align 4 268 // PATTERN-NOT: %zsa 269 // PATTERN: call void @{{.*}}used 270 void test_zsa(int size) { 271 // Technically not valid, but as long as clang accepts them we should do 272 // something sensible (i.e. not store to the zero-size array). 273 int zsa[0]; 274 used(zsa); 275 } 276 277 // UNINIT-LABEL: test_huge_uninit( 278 // ZERO-LABEL: test_huge_uninit( 279 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, {{.*}}), !annotation [[AUTO_INIT:!.+]] 280 // PATTERN-LABEL: test_huge_uninit( 281 // PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536, {{.*}}), !annotation [[AUTO_INIT:!.+]] 282 void test_huge_uninit() { 283 // We can't emit this as an inline constant to a store instruction because 284 // SDNode hits an internal size limit. 285 char big[65536]; 286 used(big); 287 } 288 289 // UNINIT-LABEL: test_huge_small_init( 290 // ZERO-LABEL: test_huge_small_init( 291 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, 292 // ZERO-NOT: !annotation 293 // ZERO: store i8 97, 294 // ZERO: store i8 98, 295 // ZERO: store i8 99, 296 // ZERO: store i8 100, 297 // PATTERN-LABEL: test_huge_small_init( 298 // PATTERN: call void @llvm.memset{{.*}}, i8 0, i64 65536, 299 // PATTERN-NOT: !annotation 300 // PATTERN: store i8 97, 301 // PATTERN: store i8 98, 302 // PATTERN: store i8 99, 303 // PATTERN: store i8 100, 304 void test_huge_small_init() { 305 char big[65536] = { 'a', 'b', 'c', 'd' }; 306 used(big); 307 } 308 309 // UNINIT-LABEL: test_huge_larger_init( 310 // ZERO-LABEL: test_huge_larger_init( 311 // ZERO: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, i64 65536, 312 // ZERO-NOT: !annotation 313 // PATTERN-LABEL: test_huge_larger_init( 314 // PATTERN: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, i64 65536, 315 // PATTERN-NOT: !annotation 316 void test_huge_larger_init() { 317 char big[65536] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; 318 used(big); 319 } 320 321 } // extern "C" 322 323 // CHECK: [[AUTO_INIT]] = !{ !"auto-init" } 324