Clang Project

clang_source_code/test/CodeGenCXX/microsoft-abi-thread-safe-statics.cpp
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
4struct S {
5  S();
6  ~S();
7};
8
9// CHECK-DAG: @"?s@?1??f@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
10// CHECK-DAG: @"??__J?1??f@@YAAAUS@@XZ@51" = linkonce_odr thread_local global i32 0
11// CHECK-DAG: @"?s@?1??g@@YAAAUS@@XZ@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
12// CHECK-DAG: @"?$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: @"?j@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local thread_local global %struct.S zeroinitializer
15// CHECK-DAG: @"??__J?1??h@@YAAAUS@@_N@Z@51" = linkonce_odr thread_local global i32 0
16// CHECK-DAG: @"?i@?1??h@@YAAAUS@@_N@Z@4U2@A" = linkonce_odr dso_local global %struct.S zeroinitializer
17// CHECK-DAG: @"?$TSS0@?1??h@@YAAAUS@@_N@Z@4HA" = linkonce_odr global i32 0
18// CHECK-DAG: @"?i@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
19// CHECK-DAG: @"?$TSS0@?1??g1@@YAHXZ@4HA" = internal global i32 0, align 4
20
21// CHECK-LABEL: define {{.*}} @"?f@@YAAAUS@@XZ"()
22// CHECK-SAME:  personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
23extern inline S &f() {
24  static thread_local S s;
25// CHECK:       %[[guard:.*]] = load i32, i32* @"??__J?1??f@@YAAAUS@@XZ@51"
26// CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], 1
27// CHECK-NEXT:  %[[cmp:.*]] = icmp eq i32 %[[mask]], 0
28// CHECK-NEXT:  br i1 %[[cmp]], label %[[init:.*]], label %[[init_end:.*]], !prof ![[unlikely_threadlocal:.*]]
29//
30// CHECK:     [[init]]:
31// CHECK-NEXT:  %[[or:.*]] = or i32 %[[guard]], 1
32// CHECK-NEXT:  store i32 %[[or]], i32* @"??__J?1??f@@YAAAUS@@XZ@51"
33// CHECK-NEXT:  invoke {{.*}} @"??0S@@QAE@XZ"(%struct.S* @"?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 ()* @"??__Fs@?1??f@@YAAAUS@@XZ@YAXXZ")
38// CHECK-NEXT:  br label %[[init_end:.*]]
39
40// CHECK:     [[init_end]]:
41// CHECK-NEXT:  ret %struct.S* @"?s@?1??f@@YAAAUS@@XZ@4U2@A"
42
43// CHECK:     [[lpad:.*]]:
44// CHECK-NEXT: cleanuppad within none []
45// CHECK:       %[[guard:.*]] = load i32, i32* @"??__J?1??f@@YAAAUS@@XZ@51"
46// CHECK-NEXT:  %[[mask:.*]] = and i32 %[[guard]], -2
47// CHECK-NEXT:  store i32 %[[mask]], i32* @"??__J?1??f@@YAAAUS@@XZ@51"
48// CHECK-NEXT:  cleanupret {{.*}} unwind to caller
49  return s;
50}
51
52
53// CHECK-LABEL: define {{.*}} @"?g@@YAAAUS@@XZ"()
54extern inline S &g() {
55  static S s;
56// CHECK:  %[[guard:.*]] = load atomic i32, i32* @"?$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:.*]], !prof ![[unlikely_staticlocal:.*]]
60//
61// CHECK:     [[init_attempt]]:
62// CHECK-NEXT:  call void @_Init_thread_header(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
63// CHECK-NEXT:  %[[guard2:.*]] = load atomic i32, i32* @"?$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 {{.*}} @"??0S@@QAE@XZ"(%struct.S* @"?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 ()* @"??__Fs@?1??g@@YAAAUS@@XZ@YAXXZ")
73// CHECK-NEXT:  call void @_Init_thread_footer(i32* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
74// CHECK-NEXT:  br label %init.end
75//
76// CHECK:     [[init_end]]:
77// CHECK-NEXT:  ret %struct.S* @"?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* @"?$TSS0@?1??g@@YAAAUS@@XZ@4HA")
82// CHECK-NEXT:  cleanupret {{.*}} unwind to caller
83  return s;
84}
85
86extern 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 dso_local i32 @"?g1@@YAHXZ"()
93int f1();
94int g1() {
95  static int i = f1();
96  return i;
97}
98
99// CHECK-DAG: ![[unlikely_threadlocal]] = !{!"branch_weights", i32 1, i32 1023}
100// CHECK-DAG: ![[unlikely_staticlocal]] = !{!"branch_weights", i32 1, i32 1048575}
101