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