• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc < %s -asm-verbose=false -wasm-keep-registers | FileCheck --check-prefix=CHECK --check-prefix=FINI --check-prefix=NULL %s
2
3target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
4target triple = "wasm32-unknown-unknown"
5
6; Test that @llvm.global_dtors is properly lowered into @llvm.global_ctors,
7; grouping dtor calls by priority and associated symbol.
8
9declare void @orig_ctor()
10declare void @orig_dtor0()
11declare void @orig_dtor1a()
12declare void @orig_dtor1b()
13declare void @orig_dtor1c0()
14declare void @orig_dtor1c1a()
15declare void @orig_dtor1c1b()
16declare void @orig_dtor1c2a()
17declare void @orig_dtor1c2b()
18declare void @orig_dtor1c3()
19declare void @orig_dtor1d()
20declare void @orig_dtor65535()
21declare void @orig_dtor65535c0()
22declare void @after_the_null()
23
24@associatedc0 = external global i8
25@associatedc1 = external global i8
26@associatedc2 = global i8 42
27@associatedc3 = global i8 84
28
29@llvm.global_ctors = appending global
30[1 x { i32, void ()*, i8* }]
31[
32  { i32, void ()*, i8* } { i32 200, void ()* @orig_ctor, i8* null }
33]
34
35@llvm.global_dtors = appending global
36[14 x { i32, void ()*, i8* }]
37[
38  { i32, void ()*, i8* } { i32 0, void ()* @orig_dtor0, i8* null },
39  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1a, i8* null },
40  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1b, i8* null },
41  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c0, i8* @associatedc0 },
42  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c1a, i8* @associatedc1 },
43  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c1b, i8* @associatedc1 },
44  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c2a, i8* @associatedc2 },
45  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c2b, i8* @associatedc2 },
46  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c3, i8* @associatedc3 },
47  { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1d, i8* null },
48  { i32, void ()*, i8* } { i32 65535, void ()* @orig_dtor65535c0, i8* @associatedc0 },
49  { i32, void ()*, i8* } { i32 65535, void ()* @orig_dtor65535, i8* null },
50  { i32, void ()*, i8* } { i32 65535, void ()* null, i8* null },
51  { i32, void ()*, i8* } { i32 65535, void ()* @after_the_null, i8* null }
52]
53
54; CHECK-LABEL: .Lcall_dtors.0:
55; CHECK-NEXT: .functype .Lcall_dtors.0 (i32) -> (){{$}}
56; CHECK-NEXT: call            orig_dtor0{{$}}
57
58; CHECK-LABEL: .Lregister_call_dtors.0:
59; CHECK:      block
60; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors.0{{$}}
61; CHECK-NEXT: i32.const       $push1=, 0
62; CHECK-NEXT: i32.const       $push0=, __dso_handle
63; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
64; CHECK-NEXT: i32.eqz         $push4=, $pop3
65; CHECK-NEXT: br_if           0, $pop4
66; CHECK-NEXT: unreachable
67;      CHECK: end_block
68
69; CHECK-LABEL: .Lcall_dtors.1$0:
70; CHECK-NEXT: .functype .Lcall_dtors.1$0 (i32) -> (){{$}}
71; CHECK-NEXT: call            orig_dtor1b{{$}}
72; CHECK-NEXT: call            orig_dtor1a{{$}}
73
74; CHECK-LABEL: .Lregister_call_dtors.1$0:
75; CHECK:      block
76; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors.1$0{{$}}
77; CHECK-NEXT: i32.const       $push1=, 0
78; CHECK-NEXT: i32.const       $push0=, __dso_handle
79; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
80; CHECK-NEXT: i32.eqz         $push4=, $pop3
81; CHECK-NEXT: br_if           0, $pop4
82; CHECK-NEXT: unreachable
83;      CHECK: end_block
84
85; CHECK-LABEL: .Lcall_dtors.1$1.associatedc0:
86; CHECK-NEXT: .functype .Lcall_dtors.1$1.associatedc0 (i32) -> (){{$}}
87; CHECK-NEXT: call            orig_dtor1c0{{$}}
88
89; CHECK-LABEL: .Lregister_call_dtors.1$1.associatedc0:
90; CHECK:      block
91; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors.1$1.associatedc0{{$}}
92; CHECK-NEXT: i32.const       $push1=, 0
93; CHECK-NEXT: i32.const       $push0=, __dso_handle
94; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
95; CHECK-NEXT: i32.eqz         $push4=, $pop3
96; CHECK-NEXT: br_if           0, $pop4
97; CHECK-NEXT: unreachable
98
99; CHECK-LABEL: .Lcall_dtors.1$2.associatedc1:
100; CHECK-NEXT: .functype .Lcall_dtors.1$2.associatedc1 (i32) -> (){{$}}
101; CHECK-NEXT: call            orig_dtor1c1b{{$}}
102; CHECK-NEXT: call            orig_dtor1c1a{{$}}
103
104; CHECK-LABEL: .Lregister_call_dtors.1$2.associatedc1:
105; CHECK:      block
106; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors.1$2.associatedc1{{$}}
107; CHECK-NEXT: i32.const       $push1=, 0
108; CHECK-NEXT: i32.const       $push0=, __dso_handle
109; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
110; CHECK-NEXT: i32.eqz         $push4=, $pop3
111; CHECK-NEXT: br_if           0, $pop4
112; CHECK-NEXT: unreachable
113
114; CHECK-LABEL: .Lcall_dtors.1$3.associatedc2:
115; CHECK-NEXT: .functype .Lcall_dtors.1$3.associatedc2 (i32) -> (){{$}}
116; CHECK-NEXT: call            orig_dtor1c2b{{$}}
117; CHECK-NEXT: call            orig_dtor1c2a{{$}}
118
119; CHECK-LABEL: .Lregister_call_dtors.1$3.associatedc2:
120; CHECK:      block
121; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors.1$3.associatedc2{{$}}
122; CHECK-NEXT: i32.const       $push1=, 0
123; CHECK-NEXT: i32.const       $push0=, __dso_handle
124; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
125; CHECK-NEXT: i32.eqz         $push4=, $pop3
126; CHECK-NEXT: br_if           0, $pop4
127; CHECK-NEXT: unreachable
128
129; CHECK-LABEL: .Lcall_dtors.1$4.associatedc3:
130; CHECK-NEXT: .functype .Lcall_dtors.1$4.associatedc3 (i32) -> (){{$}}
131; CHECK-NEXT: call            orig_dtor1c3{{$}}
132
133; CHECK-LABEL: .Lregister_call_dtors.1$4.associatedc3:
134; CHECK:      block
135; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors.1$4.associatedc3{{$}}
136; CHECK-NEXT: i32.const       $push1=, 0
137; CHECK-NEXT: i32.const       $push0=, __dso_handle
138; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
139; CHECK-NEXT: i32.eqz         $push4=, $pop3
140; CHECK-NEXT: br_if           0, $pop4
141; CHECK-NEXT: unreachable
142
143; CHECK-LABEL: .Lcall_dtors.1$5:
144; CHECK-NEXT: .functype .Lcall_dtors.1$5 (i32) -> (){{$}}
145; CHECK-NEXT: call            orig_dtor1d{{$}}
146
147; CHECK-LABEL: .Lregister_call_dtors.1$5:
148; CHECK:      block
149; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors.1$5{{$}}
150; CHECK-NEXT: i32.const       $push1=, 0
151; CHECK-NEXT: i32.const       $push0=, __dso_handle
152; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
153; CHECK-NEXT: i32.eqz         $push4=, $pop3
154; CHECK-NEXT: br_if           0, $pop4
155; CHECK-NEXT: unreachable
156
157; CHECK-LABEL: .Lcall_dtors$0.associatedc0:
158; CHECK-NEXT: .functype .Lcall_dtors$0.associatedc0 (i32) -> (){{$}}
159; CHECK-NEXT: call            orig_dtor65535c0
160
161; CHECK-LABEL: .Lcall_dtors$1:
162; CHECK-NEXT: .functype .Lcall_dtors$1 (i32) -> (){{$}}
163; CHECK-NEXT: call            orig_dtor65535{{$}}
164
165; CHECK-LABEL: .Lregister_call_dtors$1:
166; CHECK:      block
167; CHECK-NEXT: i32.const       $push2=, .Lcall_dtors$1{{$}}
168; CHECK-NEXT: i32.const       $push1=, 0
169; CHECK-NEXT: i32.const       $push0=, __dso_handle
170; CHECK-NEXT: call            $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
171; CHECK-NEXT: i32.eqz         $push4=, $pop3
172; CHECK-NEXT: br_if           0, $pop4
173; CHECK-NEXT: unreachable
174
175; CHECK-LABEL: .section .init_array.0,"",@
176;      CHECK: .int32  .Lregister_call_dtors.0{{$}}
177; CHECK-LABEL: .section .init_array.1,"",@
178;      CHECK: .int32  .Lregister_call_dtors.1$0{{$}}
179; CHECK-NEXT: .int32  .Lregister_call_dtors.1$3.associatedc2{{$}}
180; CHECK-NEXT: .int32  .Lregister_call_dtors.1$4.associatedc3{{$}}
181; CHECK-NEXT: .int32  .Lregister_call_dtors.1$5{{$}}
182; CHECK-LABEL: .section .init_array.200,"",@
183;      CHECK: .int32  orig_ctor{{$}}
184; CHECK-LABEL: .section .init_array,"",@
185;      CHECK: .int32  .Lregister_call_dtors$1{{$}}
186
187; CHECK-LABEL: .weak __dso_handle
188
189; CHECK-LABEL: .functype __cxa_atexit (i32, i32, i32) -> (i32){{$}}
190
191; We shouldn't make use of a .fini_array section.
192
193; FINI-NOT: fini_array
194
195; This function is listed after the null terminator, so it should
196; be excluded.
197
198; NULL-NOT: after_the_null
199