Home | History | Annotate | Download | only in CodeGenCXX
      1 // RUN: %clang_cc1 -fexceptions -fcxx-exceptions -fms-extensions -fms-compatibility -fms-compatibility-version=19 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
      2 // REQUIRES: asserts
      3 
      4 struct S {
      5   S();
      6   ~S();
      7 };
      8 
      9 // CHECK-DAG: @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
     10 // CHECK-DAG: @"\01??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
     11 // CHECK-DAG: @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr global %struct.S zeroinitializer
     12 // CHECK-DAG: @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" = linkonce_odr global i32 0
     13 // CHECK-DAG: @_Init_thread_epoch = external thread_local global i32, align 4
     14 // CHECK-DAG: @"\01?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr thread_local global %struct.S zeroinitializer
     15 // CHECK-DAG: @"\01??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0
     16 // CHECK-DAG: @"\01?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr global %struct.S zeroinitializer
     17 // CHECK-DAG: @"\01?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 0
     18 // CHECK-DAG: @"\01?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
     19 // CHECK-DAG: @"\01?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
     20 
     21 // CHECK-LABEL: define {{.*}} @"\01?f@@YAAAUS@@XZ"()
     22 // CHECK-SAME:  personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
     23 extern inline S &f() {
     24   static thread_local S s;
     25 // CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
     26 // CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], 1
     27 // CHECK-NEXT:  %[[cmp:.*]] = icmp ne i32 %[[mask]], 0
     28 // CHECK-NEXT:  br i1 %[[cmp]], label %[[init_end:.*]], label %[[init:.*]]
     29 //
     30 // CHECK:     [[init]]:
     31 // CHECK-NEXT:  %[[or:.*]] = or i32 %[[guard]], 1
     32 // CHECK-NEXT:  store i32 %[[or]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
     33 // CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A")
     34 // CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
     35 //
     36 // CHECK:     [[invoke_cont]]:
     37 // CHECK-NEXT:  call i32 @__tlregdtor(void ()* @"\01??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
     38 // CHECK-NEXT:  br label %[[init_end:.*]]
     39 
     40 // CHECK:     [[init_end]]:
     41 // CHECK-NEXT:  ret %struct.S* @"\01?s@?1??f@@YAAAUS@@XZ@4U2@A"
     42 
     43 // CHECK:     [[lpad:.*]]:
     44 // CHECK-NEXT: cleanuppad within none []
     45 // CHECK:       %[[guard:.*]] = load i32, i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
     46 // CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], -2
     47 // CHECK-NEXT:  store i32 %[[mask]], i32* @"\01??__J?1??f@@YAAAUS@@XZ@51"
     48 // CHECK-NEXT:  cleanupret {{.*}} unwind to caller
     49   return s;
     50 }
     51 
     52 
     53 // CHECK-LABEL: define {{.*}} @"\01?g@@YAAAUS@@XZ"()
     54 extern inline S &g() {
     55   static S s;
     56 // CHECK:  %[[guard:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
     57 // CHECK-NEXT:  %[[epoch:.*]] = load i32, i32* @_Init_thread_epoch
     58 // CHECK-NEXT:  %[[cmp:.*]] = icmp sgt i32 %[[guard]], %[[epoch]]
     59 // CHECK-NEXT:  br i1 %[[cmp]], label %[[init_attempt:.*]], label %[[init_end:.*]]
     60 //
     61 // CHECK:     [[init_attempt]]:
     62 // CHECK-NEXT:  call void @_Init_thread_header(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
     63 // CHECK-NEXT:  %[[guard2:.*]] = load atomic i32, i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA" unordered, align 4
     64 // CHECK-NEXT:  %[[cmp2:.*]] = icmp eq i32 %[[guard2]], -1
     65 // CHECK-NEXT:  br i1 %[[cmp2]], label %[[init:.*]], label %[[init_end:.*]]
     66 //
     67 // CHECK:     [[init]]:
     68 // CHECK-NEXT:  invoke {{.*}} @"\01??0S@@QAE@XZ"(%struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A")
     69 // CHECK-NEXT:    to label %[[invoke_cont:.*]] unwind label %[[lpad:.*]]
     70 //
     71 // CHECK:     [[invoke_cont]]:
     72 // CHECK-NEXT:  call i32 @atexit(void ()* @"\01??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
     73 // CHECK-NEXT:  call void @_Init_thread_footer(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
     74 // CHECK-NEXT:  br label %init.end
     75 //
     76 // CHECK:     [[init_end]]:
     77 // CHECK-NEXT:  ret %struct.S* @"\01?s@?1??g@@YAAAUS@@XZ@4U2@A"
     78 //
     79 // CHECK:     [[lpad]]:
     80 // CHECK-NEXT: cleanuppad within none []
     81 // CHECK:       call void @_Init_thread_abort(i32* @"\01?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
     82 // CHECK-NEXT:  cleanupret {{.*}} unwind to caller
     83   return s;
     84 }
     85 
     86 extern inline S&h(bool b) {
     87   static thread_local S j;
     88   static S i;
     89   return b ? j : i;
     90 }
     91 
     92 // CHECK-LABEL: define i32 @"\01?g1@@YAHXZ"()
     93 int f1();
     94 int g1() {
     95   static int i = f1();
     96   return i;
     97 }
     98