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, i32* %self, align 4 16 // PATTERN-LABEL: test_selfinit( 17 // PATTERN: store i32 -1431655766, i32* %self, align 4 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, i32* %block 26 // PATTERN-LABEL: test_block( 27 // PATTERN: store i32 -1431655766, i32* %block 28 void test_block() { 29 __block int block; 30 used(block); 31 } 32 33 // This type of code is currently not handled by zero / pattern initialization. 34 // The test will break when that is fixed. 35 // UNINIT-LABEL: test_goto_unreachable_value( 36 // ZERO-LABEL: test_goto_unreachable_value( 37 // ZERO-NOT: store {{.*}}%oops 38 // PATTERN-LABEL: test_goto_unreachable_value( 39 // PATTERN-NOT: store {{.*}}%oops 40 void test_goto_unreachable_value() { 41 goto jump; 42 int oops; 43 jump: 44 used(oops); 45 } 46 47 // This type of code is currently not handled by zero / pattern initialization. 48 // The test will break when that is fixed. 49 // UNINIT-LABEL: test_goto( 50 // ZERO-LABEL: test_goto( 51 // ZERO: if.then: 52 // ZERO: br label %jump 53 // ZERO: store i32 0, i32* %oops, align 4 54 // ZERO: br label %jump 55 // ZERO: jump: 56 // PATTERN-LABEL: test_goto( 57 // PATTERN: if.then: 58 // PATTERN: br label %jump 59 // PATTERN: store i32 -1431655766, i32* %oops, align 4 60 // PATTERN: br label %jump 61 // PATTERN: jump: 62 void test_goto(int i) { 63 if (i) 64 goto jump; 65 int oops; 66 jump: 67 used(oops); 68 } 69 70 // This type of code is currently not handled by zero / pattern initialization. 71 // The test will break when that is fixed. 72 // UNINIT-LABEL: test_switch( 73 // ZERO-LABEL: test_switch( 74 // ZERO: sw.bb: 75 // ZERO-NEXT: store i32 0, i32* %oops, align 4 76 // ZERO: sw.bb1: 77 // ZERO-NEXT: call void @{{.*}}used 78 // PATTERN-LABEL: test_switch( 79 // PATTERN: sw.bb: 80 // PATTERN-NEXT: store i32 -1431655766, i32* %oops, align 4 81 // PATTERN: sw.bb1: 82 // PATTERN-NEXT: call void @{{.*}}used 83 void test_switch(int i) { 84 switch (i) { 85 case 0: 86 int oops; 87 break; 88 case 1: 89 used(oops); 90 } 91 } 92 93 // UNINIT-LABEL: test_vla( 94 // ZERO-LABEL: test_vla( 95 // ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4 96 // ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false) 97 // PATTERN-LABEL: test_vla( 98 // PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0 99 // PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop 100 // PATTERN: vla-setup.loop: 101 // PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4 102 // PATTERN: %vla.begin = bitcast i32* %vla to i8* 103 // PATTERN: %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]] 104 // PATTERN: br label %vla-init.loop 105 // PATTERN: vla-init.loop: 106 // PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ] 107 // PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_vla.vla 108 // PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 4 109 // PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end 110 // PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop 111 // PATTERN: vla-init.cont: 112 // PATTERN: call void @{{.*}}used 113 void test_vla(int size) { 114 // Variable-length arrays can't have a zero size according to C11 6.7.6.2/5. 115 // Neither can they be negative-sized. 116 // 117 // We don't use the former fact because some code creates zero-sized VLAs and 118 // doesn't use them. clang makes these share locations with other stack 119 // values, which leads to initialization of the wrong values. 120 // 121 // We rely on the later fact because it generates better code. 122 // 123 // Both cases are caught by UBSan. 124 int vla[size]; 125 int *ptr = vla; 126 used(ptr); 127 } 128 129 // UNINIT-LABEL: test_struct_vla( 130 // ZERO-LABEL: test_struct_vla( 131 // ZERO: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 132 // ZERO: call void @llvm.memset{{.*}}(i8* align 16 %{{.*}}, i8 0, i64 %[[SIZE]], i1 false) 133 // PATTERN-LABEL: test_struct_vla( 134 // PATTERN: %vla.iszerosized = icmp eq i64 %{{.*}}, 0 135 // PATTERN: br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop 136 // PATTERN: vla-setup.loop: 137 // PATTERN: %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16 138 // PATTERN: %vla.begin = bitcast %struct.anon* %vla to i8* 139 // PATTERN: %vla.end = getelementptr inbounds i8, i8* %vla.begin, i64 %[[SIZE]] 140 // PATTERN: br label %vla-init.loop 141 // PATTERN: vla-init.loop: 142 // PATTERN: %vla.cur = phi i8* [ %vla.begin, %vla-setup.loop ], [ %vla.next, %vla-init.loop ] 143 // PATTERN: call void @llvm.memcpy{{.*}} %vla.cur, {{.*}}@__const.test_struct_vla.vla 144 // PATTERN: %vla.next = getelementptr inbounds i8, i8* %vla.cur, i64 16 145 // PATTERN: %vla-init.isdone = icmp eq i8* %vla.next, %vla.end 146 // PATTERN: br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop 147 // PATTERN: vla-init.cont: 148 // PATTERN: call void @{{.*}}used 149 void test_struct_vla(int size) { 150 // Same as above, but with a struct that doesn't just memcpy. 151 struct { 152 float f; 153 char c; 154 void *ptr; 155 } vla[size]; 156 void *ptr = static_cast<void*>(vla); 157 used(ptr); 158 } 159 160 // UNINIT-LABEL: test_zsa( 161 // ZERO-LABEL: test_zsa( 162 // ZERO: %zsa = alloca [0 x i32], align 4 163 // ZERO-NOT: %zsa 164 // ZERO: call void @{{.*}}used 165 // PATTERN-LABEL: test_zsa( 166 // PATTERN: %zsa = alloca [0 x i32], align 4 167 // PATTERN-NOT: %zsa 168 // PATTERN: call void @{{.*}}used 169 void test_zsa(int size) { 170 // Technically not valid, but as long as clang accepts them we should do 171 // something sensible (i.e. not store to the zero-size array). 172 int zsa[0]; 173 used(zsa); 174 } 175 176 // UNINIT-LABEL: test_huge_uninit( 177 // ZERO-LABEL: test_huge_uninit( 178 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, 179 // PATTERN-LABEL: test_huge_uninit( 180 // PATTERN: call void @llvm.memset{{.*}}, i8 -86, i64 65536, 181 void test_huge_uninit() { 182 // We can't emit this as an inline constant to a store instruction because 183 // SDNode hits an internal size limit. 184 char big[65536]; 185 used(big); 186 } 187 188 // UNINIT-LABEL: test_huge_small_init( 189 // ZERO-LABEL: test_huge_small_init( 190 // ZERO: call void @llvm.memset{{.*}}, i8 0, i64 65536, 191 // ZERO: store i8 97, 192 // ZERO: store i8 98, 193 // ZERO: store i8 99, 194 // ZERO: store i8 100, 195 // PATTERN-LABEL: test_huge_small_init( 196 // PATTERN: call void @llvm.memset{{.*}}, i8 0, i64 65536, 197 // PATTERN: store i8 97, 198 // PATTERN: store i8 98, 199 // PATTERN: store i8 99, 200 // PATTERN: store i8 100, 201 void test_huge_small_init() { 202 char big[65536] = { 'a', 'b', 'c', 'd' }; 203 used(big); 204 } 205 206 // UNINIT-LABEL: test_huge_larger_init( 207 // ZERO-LABEL: test_huge_larger_init( 208 // ZERO: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536, 209 // PATTERN-LABEL: test_huge_larger_init( 210 // PATTERN: call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, {{.*}}, i64 65536, 211 void test_huge_larger_init() { 212 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' }; 213 used(big); 214 } 215 216 } // extern "C" 217