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