xref: /llvm-project/clang/test/CodeGenCXX/aix-static-init.cpp (revision f193bcc701de8311e9f40730f2187d6df2e8667c)
1 // RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -S -emit-llvm -x c++ \
2 // RUN:     -std=c++2a < %s | \
3 // RUN:   FileCheck --check-prefixes=CHECK,CHECK32 %s
4 
5 // RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -S -emit-llvm -x c++ \
6 // RUN:     -std=c++2a < %s | \
7 // RUN:   FileCheck --check-prefixes=CHECK,CHECK64 %s
8 
9 namespace test1 {
10   struct Test1 {
11     Test1();
12     ~Test1();
13   } t1, t2;
14 } // namespace test1
15 
16 namespace test2 {
17   int foo() { return 3; }
18   int x = foo();
19 } // namespace test2
20 
21 namespace test3 {
22   struct Test3 {
23     constexpr Test3() {};
24     ~Test3() {};
25   };
26 
27   constinit Test3 t;
28 } // namespace test3
29 
30 namespace test4 {
31   struct Test4 {
32     Test4();
33     ~Test4();
34   };
35 
36   void f() {
37     static Test4 staticLocal;
38   }
39 } // namespace test4
40 
41 // CHECK: @_ZGVZN5test41fEvE11staticLocal = internal global i64 0, align 8
42 // CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I__, i8* null }]
43 // CHECK: @llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__D_a, i8* null }]
44 
45 // CHECK: define internal void @__cxx_global_var_init() [[ATTR:#[0-9]+]] {
46 // CHECK: entry:
47 // CHECK:   call void @_ZN5test15Test1C1Ev(%"struct.test1::Test1"* {{[^,]*}} @_ZN5test12t1E)
48 // CHECK:   %0 = call i32 @atexit(void ()* @__dtor__ZN5test12t1E)
49 // CHECK:   ret void
50 // CHECK: }
51 
52 // CHECK: define internal void @__dtor__ZN5test12t1E() [[ATTR:#[0-9]+]] {
53 // CHECK: entry:
54 // CHECK:   call void @_ZN5test15Test1D1Ev(%"struct.test1::Test1"* @_ZN5test12t1E)
55 // CHECK:   ret void
56 // CHECK: }
57 
58 // CHECK: declare i32 @atexit(void ()*)
59 
60 // CHECK: define internal void @__finalize__ZN5test12t1E() [[ATTR:#[0-9]+]] {
61 // CHECK: entry:
62 // CHECK:   %0 = call i32 @unatexit(void ()* @__dtor__ZN5test12t1E)
63 // CHECK:   %needs_destruct = icmp eq i32 %0, 0
64 // CHECK:   br i1 %needs_destruct, label %destruct.call, label %destruct.end
65 
66 // CHECK: destruct.call:
67 // CHECK:   call void @__dtor__ZN5test12t1E()
68 // CHECK:   br label %destruct.end
69 
70 // CHECK: destruct.end:
71 // CHECK:   ret void
72 // CHECK: }
73 
74 // CHECK: declare i32 @unatexit(void ()*)
75 
76 // CHECK: define internal void @__cxx_global_var_init.1() [[ATTR:#[0-9]+]] {
77 // CHECK: entry:
78 // CHECK:   call void @_ZN5test15Test1C1Ev(%"struct.test1::Test1"* {{[^,]*}} @_ZN5test12t2E)
79 // CHECK:   %0 = call i32 @atexit(void ()* @__dtor__ZN5test12t2E)
80 // CHECK:   ret void
81 // CHECK: }
82 
83 // CHECK: define internal void @__dtor__ZN5test12t2E() [[ATTR:#[0-9]+]] {
84 // CHECK: entry:
85 // CHECK:   call void @_ZN5test15Test1D1Ev(%"struct.test1::Test1"* @_ZN5test12t2E)
86 // CHECK:   ret void
87 // CHECK: }
88 
89 // CHECK: define internal void @__finalize__ZN5test12t2E() [[ATTR:#[0-9]+]] {
90 // CHECK: entry:
91 // CHECK:   %0 = call i32 @unatexit(void ()* @__dtor__ZN5test12t2E)
92 // CHECK:   %needs_destruct = icmp eq i32 %0, 0
93 // CHECK:   br i1 %needs_destruct, label %destruct.call, label %destruct.end
94 
95 // CHECK: destruct.call:
96 // CHECK:   call void @__dtor__ZN5test12t2E()
97 // CHECK:   br label %destruct.end
98 
99 // CHECK: destruct.end:
100 // CHECK:   ret void
101 // CHECK: }
102 
103 // CHECK: define internal void @__cxx_global_var_init.2() [[ATTR:#[0-9]+]] {
104 // CHECK: entry:
105 // CHECK32: %call = call i32 @_ZN5test23fooEv()
106 // CHECK64: %call = call signext i32 @_ZN5test23fooEv()
107 // CHECK:   store i32 %call, i32* @_ZN5test21xE
108 // CHECK:   ret void
109 // CHECK: }
110 
111 // CHECK: define internal void @__cxx_global_var_init.3() [[ATTR:#[0-9]+]] {
112 // CHECK: entry:
113 // CHECK:   %0 = call i32 @atexit(void ()* @__dtor__ZN5test31tE)
114 // CHECK:   ret void
115 // CHECK: }
116 
117 // CHECK: define internal void @__dtor__ZN5test31tE() [[ATTR:#[0-9]+]] {
118 // CHECK: entry:
119 // CHECK:   call void @_ZN5test35Test3D1Ev(%"struct.test3::Test3"* @_ZN5test31tE)
120 // CHECK:   ret void
121 // CHECK: }
122 
123 // CHECK: define internal void @__finalize__ZN5test31tE() [[ATTR:#[0-9]+]] {
124 // CHECK: entry:
125 // CHECK:   %0 = call i32 @unatexit(void ()* @__dtor__ZN5test31tE)
126 // CHECK:   %needs_destruct = icmp eq i32 %0, 0
127 // CHECK:   br i1 %needs_destruct, label %destruct.call, label %destruct.end
128 
129 // CHECK: destruct.call:
130 // CHECK:   call void @__dtor__ZN5test31tE()
131 // CHECK:   br label %destruct.end
132 
133 // CHECK: destruct.end:
134 // CHECK:   ret void
135 // CHECK: }
136 
137 // CHECK: define void @_ZN5test41fEv() [[ATTR:#[0-9]+]] {
138 // CHECK: entry:
139 // CHECK:   %0 = load atomic i8, i8* bitcast (i64* @_ZGVZN5test41fEvE11staticLocal to i8*) acquire, align 8
140 // CHECK:   %guard.uninitialized = icmp eq i8 %0, 0
141 // CHECK:   br i1 %guard.uninitialized, label %init.check, label %init.end
142 
143 // CHECK: init.check:
144 // CHECK:   %1 = call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test41fEvE11staticLocal)
145 // CHECK:   %tobool = icmp ne i32 %1, 0
146 // CHECK:   br i1 %tobool, label %init, label %init.end
147 
148 // CHECK: init:
149 // CHECK:   call void @_ZN5test45Test4C1Ev(%"struct.test4::Test4"* {{[^,]*}} @_ZZN5test41fEvE11staticLocal)
150 // CHECK:   %2 = call i32 @atexit(void ()* @__dtor__ZZN5test41fEvE11staticLocal)
151 // CHECK:   call void @__cxa_guard_release(i64* @_ZGVZN5test41fEvE11staticLocal)
152 // CHECK:   br label %init.end
153 
154 // CHECK: init.end:
155 // CHECK:   ret void
156 // CHECK: }
157 
158 // CHECK: define internal void @__dtor__ZZN5test41fEvE11staticLocal() [[ATTR:#[0-9]+]] {
159 // CHECK: entry:
160 // CHECK:   call void @_ZN5test45Test4D1Ev(%"struct.test4::Test4"* @_ZZN5test41fEvE11staticLocal)
161 // CHECK:   ret void
162 // CHECK: }
163 
164 // CHECK: define internal void @__finalize__ZZN5test41fEvE11staticLocal() [[ATTR:#[0-9]+]] {
165 // CHECK: entry:
166 // CHECK:   %0 = call i32 @unatexit(void ()* @__dtor__ZZN5test41fEvE11staticLocal)
167 // CHECK:   %needs_destruct = icmp eq i32 %0, 0
168 // CHECK:   br i1 %needs_destruct, label %destruct.call, label %destruct.end
169 
170 // CHECK: destruct.call:
171 // CHECK:   call void @__dtor__ZZN5test41fEvE11staticLocal()
172 // CHECK:   br label %destruct.end
173 
174 // CHECK: destruct.end:
175 // CHECK:   ret void
176 // CHECK: }
177 
178 // CHECK: define internal void @_GLOBAL__sub_I__() [[ATTR:#[0-9]+]] {
179 // CHECK: entry:
180 // CHECK:   call void @__cxx_global_var_init()
181 // CHECK:   call void @__cxx_global_var_init.1()
182 // CHECK:   call void @__cxx_global_var_init.2()
183 // CHECK:   call void @__cxx_global_var_init.3()
184 // CHECK:   ret void
185 // CHECK: }
186 
187 // CHECK: define internal void @_GLOBAL__D_a() [[ATTR:#[0-9]+]] {
188 // CHECK: entry:
189 // CHECK:   call void @__finalize__ZZN5test41fEvE11staticLocal()
190 // CHECK:   call void @__finalize__ZN5test31tE()
191 // CHECK:   call void @__finalize__ZN5test12t2E()
192 // CHECK:   call void @__finalize__ZN5test12t1E()
193 // CHECK:   ret void
194 // CHECK: }
195