brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.9 KiB · e21a307 Raw
324 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks %s -emit-llvm -o - | FileCheck %s -check-prefix=UNINIT2// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=pattern %s -emit-llvm -o - | FileCheck %s -check-prefix=PATTERN3// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fblocks -ftrivial-auto-var-init=zero %s -emit-llvm -o - | FileCheck %s -check-prefix=ZERO4 5// None of the synthesized globals should contain `undef`.6// PATTERN-NOT: undef7// ZERO-NOT: undef8 9template<typename T> void used(T &) noexcept;10 11extern "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:!.+]]18void 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:!.+]]28void 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 we34// can be nice: they imply extra book-keeping and we can do the auto-init before35// 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 840// ZERO:          %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured, ptr %captured, i32 0, i32 441// 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 845// PATTERN:       %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured, ptr %captured, i32 0, i32 446// PATTERN-NEXT:  store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %captured1, align 8, !annotation [[AUTO_INIT:!.+]]47// PATTERN:       %call = call ptr @create(48using Block = void (^)();49typedef struct XYZ {50  Block block;51} * xyz_t;52void 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 864// ZERO:          %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured.1, ptr %captured, i32 0, i32 465// 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 869// PATTERN:       %captured1 = getelementptr inbounds nuw %struct.__block_byref_captured.1, ptr %captured, i32 0, i32 470// PATTERN-NEXT:  store ptr inttoptr (i64 -6148914691236517206 to ptr), ptr %captured1, align 8, !annotation [[AUTO_INIT:!.+]]71// PATTERN:       %call = call ptr @create(72void 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 {{.*}}%oops85// PATTERN-LABEL: test_goto_unreachable_value(86// PATTERN-NOT: store {{.*}}%oops87void 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 %jump100// ZERO: store i32 0, ptr %oops, align 4, !annotation [[AUTO_INIT:!.+]]101// ZERO: br label %jump102// ZERO: jump:103// PATTERN-LABEL: test_goto(104// PATTERN: if.then:105// PATTERN: br label %jump106// PATTERN: store i32 -1431655766, ptr %oops, align 4, !annotation [[AUTO_INIT:!.+]]107// PATTERN: br label %jump108// PATTERN: jump:109void 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 @{{.*}}used125// 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 @{{.*}}used130void 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 %{{.*}}, 4143// 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 %{{.*}}, 0146// PATTERN:  br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop147// PATTERN: vla-setup.loop:148// PATTERN:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 4149// PATTERN:  %vla.end = getelementptr inbounds i8, ptr %vla, i64 %[[SIZE]]150// PATTERN:  br label %vla-init.loop151// 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 4155// PATTERN:  %vla-init.isdone = icmp eq ptr %vla.next, %vla.end156// PATTERN:  br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop157// PATTERN: vla-init.cont:158// PATTERN:  call void @{{.*}}used159void 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 and164  // doesn't use them. clang makes these share locations with other stack165  // 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 i64178// 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 i64182// 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:!.+]]184void 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 i64192// ZERO-NEXT:     %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128193// 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 i64196// PATTERN-NEXT:  %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128197// PATTERN-NEXT:  call void @llvm.memset{{.*}}(ptr align 128 %[[ALLOCA]], i8 -86, i64 %[[SIZE]], i1 false), !annotation [[AUTO_INIT:!.+]]198void 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 i64206// ZERO-NEXT:     %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]207// ZERO-NOT:      call void @llvm.memset208// PATTERN-LABEL: test_alloca_uninitialized(209// PATTERN:       %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64210// PATTERN-NEXT:  %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align [[ALIGN:[0-9]+]]211// PATTERN-NOT:   call void @llvm.memset212void 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 i64220// ZERO-NEXT:     %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128221// ZERO-NOT:      call void @llvm.memset222// PATTERN-LABEL: test_alloca_with_align_uninitialized(223// PATTERN:       %[[SIZE:[a-z0-9]+]] = sext i32 %{{.*}} to i64224// PATTERN-NEXT:  %[[ALLOCA:[a-z0-9]+]] = alloca i8, i64 %[[SIZE]], align 128225// PATTERN-NOT:   call void @llvm.memset226void 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 %{{.*}}, 16234// 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 %{{.*}}, 0237// PATTERN:  br i1 %vla.iszerosized, label %vla-init.cont, label %vla-setup.loop238// PATTERN: vla-setup.loop:239// PATTERN:  %[[SIZE:[0-9]+]] = mul nuw i64 %{{.*}}, 16240// PATTERN:  %vla.end = getelementptr inbounds i8, ptr %vla, i64 %[[SIZE]]241// PATTERN:  br label %vla-init.loop242// 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 16246// PATTERN:  %vla-init.isdone = icmp eq ptr %vla.next, %vla.end247// PATTERN:  br i1 %vla-init.isdone, label %vla-init.cont, label %vla-init.loop248// PATTERN: vla-init.cont:249// PATTERN:  call void @{{.*}}used250void 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 4264// ZERO-NOT: %zsa265// ZERO:  call void @{{.*}}used266// PATTERN-LABEL: test_zsa(267// PATTERN: %zsa = alloca [0 x i32], align 4268// PATTERN-NOT: %zsa269// PATTERN:  call void @{{.*}}used270void test_zsa(int size) {271  // Technically not valid, but as long as clang accepts them we should do272  // 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:!.+]]282void test_huge_uninit() {283  // We can't emit this as an inline constant to a store instruction because284  // 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: !annotation293// 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: !annotation300// PATTERN: store i8 97,301// PATTERN: store i8 98,302// PATTERN: store i8 99,303// PATTERN: store i8 100,304void 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: !annotation313// PATTERN-LABEL: test_huge_larger_init(314// PATTERN:  call void @llvm.memcpy{{.*}} @__const.test_huge_larger_init.big, i64 65536,315// PATTERN-NOT: !annotation316void 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