blob: b67579087faefbd00df9f76463858d7bedf357bf [file] [log] [blame]
Heejin Ahne76fa9e2018-08-16 23:50:59 +00001# RUN: llc -mtriple=wasm32-unknown-unknown -exception-model=wasm -run-pass wasm-cfg-stackify %s -o - | FileCheck %s
2
3--- |
4 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
5 target triple = "wasm32-unknown-unknown"
6
7 @__wasm_lpad_context = external global { i32, i8*, i32 }
8
9 declare void @may_throw()
10 ; Function Attrs: nounwind
11 declare void @dont_throw() #0
12 declare i8* @__cxa_begin_catch(i8*)
13 declare void @__cxa_end_catch()
14 declare void @__cxa_rethrow()
15 ; Function Attrs: nounwind
16 declare i32 @__gxx_wasm_personality_v0(...)
17 declare i32 @_Unwind_CallPersonality(i8*) #0
18
19 define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
20 unreachable
21 }
22 define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
23 unreachable
24 }
25 define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
26 unreachable
27 }
28 define void @test3() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
29 unreachable
30 }
31
32 attributes #0 = { nounwind }
33
34---
35# Simplest try-catch
36# try {
37# may_throw();
38# } catch (...) {
39# }
40name: test0
41# CHECK-LABEL: name: test0
42liveins:
43 - { reg: '$arguments', reg: '$value_stack' }
44body: |
45 bb.0:
46 successors: %bb.2, %bb.1
47
48 CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
49 BR %bb.2, implicit-def $arguments
50 ; CHECK-LABEL: bb.0:
51 ; CHECK: TRY
52 ; CHECK-NEXT: CALL_VOID @may_throw
53
54 bb.1 (landing-pad):
55 ; predecessors: %bb.0
56 successors: %bb.2
57
58 %2:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
59 %3:i32 = CALL_I32 @__cxa_begin_catch, %2:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack
60 DROP_I32 killed %3:i32, implicit-def $arguments
61 CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
62
63 bb.2:
64 ; predecessors: %bb.0, %bb.1
65
66 RETURN_VOID implicit-def dead $arguments
67 ; CHECK-LABEL: bb.2:
68 ; CHECK-NEXT: END_TRY
69 ; CHECK: RETURN_VOID
70...
71---
72
73# Nested try-catch inside another catch
74# try {
75# may_throw();
76# } catch (int n) {
77# try {
78# may_throw();
79# } catch (int n) {
80# }
81# }
82name: test1
83# CHECK-LABEL: name: test1
84liveins:
85 - { reg: '$arguments', reg: '$value_stack' }
86body: |
87 bb.0:
88 successors: %bb.9, %bb.1
89
90 CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
91 BR %bb.9, implicit-def $arguments
92 ; CHECK-LABEL: bb.0:
93 ; CHECK: TRY
94 ; CHECK-NEXT: CALL_VOID @may_throw
95
96 bb.1 (landing-pad):
97 ; predecessors: %bb.0
98 successors: %bb.2, %bb.7
99
100 %30:i32 = CATCH_I32 0, implicit-def dead $arguments
101 SET_LOCAL_I32 0, %30:i32, implicit-def $arguments
102 %16:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
103 %27:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
104 STORE_I32 2, @__wasm_lpad_context + 4, %16:i32, %27:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i8** getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 1)`)
105 %26:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
106 %25:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
107 STORE_I32 2, @__wasm_lpad_context, %26:i32, %25:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0)`)
108 %32:i32 = GET_LOCAL_I32 0, implicit-def $arguments
109 %31:i32 = CALL_I32 @_Unwind_CallPersonality, %32:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
110 DROP_I32 killed %31:i32, implicit-def $arguments
111 %24:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
112 %17:i32 = LOAD_I32 2, @__wasm_lpad_context + 8, %24:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (dereferenceable load 4 from `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 2)`)
113 %18:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
114 %19:i32 = NE_I32 %17:i32, %18:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
115 BR_IF %bb.7, %19:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
116
117 bb.2:
118 ; predecessors: %bb.1
119 successors: %bb.8, %bb.3, %bb.6
120
121 %34:i32 = GET_LOCAL_I32 0, implicit-def $arguments
122 %33:i32 = CALL_I32 @__cxa_begin_catch, %34:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
123 DROP_I32 killed %33:i32, implicit-def $arguments
124 CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
125 BR %bb.8, implicit-def $arguments
126 ; CHECK-LABEL: bb.2:
127 ; CHECK: DROP_I32
128 ; CHECK-NEXT: TRY
129 ; CHECK-NEXT: TRY
130 ; CHECK-NEXT: CALL_VOID @may_throw
131
132 bb.3 (landing-pad):
133 ; predecessors: %bb.2
134 successors: %bb.4, %bb.5
135
136 %35:i32 = CATCH_I32 0, implicit-def dead $arguments
137 SET_LOCAL_I32 0, %35:i32, implicit-def $arguments
138 %21:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
139 %20:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
140 STORE_I32 2, @__wasm_lpad_context, %21:i32, %20:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (store 4 into `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 0)`)
141 %37:i32 = GET_LOCAL_I32 0, implicit-def $arguments
142 %36:i32 = CALL_I32 @_Unwind_CallPersonality, %37:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
143 DROP_I32 killed %36:i32, implicit-def $arguments
144 %29:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
145 %22:i32 = LOAD_I32 2, @__wasm_lpad_context + 8, %29:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack :: (dereferenceable load 4 from `i32* getelementptr inbounds ({ i32, i8*, i32 }, { i32, i8*, i32 }* @__wasm_lpad_context, i32 0, i32 2)`)
146 %28:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
147 %23:i32 = NE_I32 %22:i32, %28:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
148 BR_IF %bb.5, %23:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
149
150 bb.4:
151 ; predecessors: %bb.3
152 successors: %bb.8
153
154 %39:i32 = GET_LOCAL_I32 0, implicit-def $arguments
155 %38:i32 = CALL_I32 @__cxa_begin_catch, %39:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64
156 DROP_I32 killed %38:i32, implicit-def $arguments
157 CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
158 BR %bb.8, implicit-def $arguments
159
160 bb.5:
161 ; predecessors: %bb.3
162 successors: %bb.6
163
164 CALL_VOID @__cxa_rethrow, implicit-def dead $arguments, implicit $sp32, implicit $sp64
165 RETHROW %bb.6, implicit-def $arguments
166
167 bb.6 (landing-pad):
168 ; predecessors: %bb.2, %bb.5
169
170 CATCH_ALL implicit-def $arguments
171 CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
172 RETHROW_TO_CALLER implicit-def $arguments
173 ; CHECK-LABEL: bb.6 (landing-pad):
174 ; CHECK-NEXT: END_TRY
175
176 bb.7:
177 ; predecessors: %bb.1
178
179 CALL_VOID @__cxa_rethrow, implicit-def dead $arguments, implicit $sp32, implicit $sp64
180 RETHROW_TO_CALLER implicit-def $arguments
181 ; CHECK-LABEL: bb.7:
182 ; CHECK-NEXT: END_TRY
Heejin Ahnac764aa2018-10-24 23:31:24 +0000183 ; CHECK: RETHROW 0
Heejin Ahne76fa9e2018-08-16 23:50:59 +0000184
185 bb.8:
186 ; predecessors: %bb.2, %bb.4
187 successors: %bb.9
188
189 CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
190
191 bb.9:
192 ; predecessors: %bb.0, %bb.8
193
194 RETURN_VOID implicit-def dead $arguments
195 ; CHECK-LABEL: bb.9:
196 ; CHECK-NEXT: END_TRY
197...
198---
199
200# A loop within a try.
201# try {
202# for (int i = 0; i < n; ++i)
203# may_throw();
204# } catch (...) {
205# }
206name: test2
207# CHECK-LABEL: name: test2
208liveins:
209 - { reg: '$arguments', reg: '$value_stack' }
210body: |
211 bb.0:
212 successors: %bb.1, %bb.4
213
214 %18:i32 = CONST_I32 0, implicit-def dead $arguments
215 SET_LOCAL_I32 1, %18:i32, implicit-def $arguments
216 %14:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
217 %19:i32 = GET_LOCAL_I32 0, implicit-def $arguments
218 %9:i32 = GE_S_I32 %14:i32, %19:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
219 BR_IF %bb.4, %9:i32, implicit-def $arguments
220
221 bb.1:
222 ; predecessors: %bb.0, %bb.3
223 successors: %bb.3, %bb.2
224
225 CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
226 BR %bb.3, implicit-def $arguments
227 ; CHECK-LABEL: bb.1:
228 ; CHECK: LOOP
229 ; CHECK: TRY
230 ; CHECK-NEXT: CALL_VOID @may_throw
231
232 bb.2 (landing-pad):
233 ; predecessors: %bb.1
234 successors: %bb.4
235
236 %11:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
237 %22:i32 = CALL_I32 @__cxa_begin_catch, %11:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack
238 DROP_I32 killed %22:i32, implicit-def $arguments
239 CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
240 BR %bb.4, implicit-def $arguments
241
242 bb.3:
243 ; predecessors: %bb.1
244 successors: %bb.1, %bb.4
245
246 %20:i32 = GET_LOCAL_I32 1, implicit-def $arguments
247 %17:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
248 %16:i32 = ADD_I32 %20:i32, %17:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
249 %15:i32 = TEE_LOCAL_I32 1, %16:i32, implicit-def $arguments
250 %21:i32 = GET_LOCAL_I32 0, implicit-def $arguments
251 %10:i32 = GE_S_I32 %15:i32, %21:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
252 BR_UNLESS %bb.1, %10:i32, implicit-def $arguments
253 ; CHECK-LABEL: bb.3:
254 ; CHECK: END_TRY
255
256 bb.4:
257 ; predecessors: %bb.2, %bb.0, %bb.3
258
259 RETURN_VOID implicit-def dead $arguments
260...
261---
262
263# A loop within a catch
264# try {
265# may_throw();
266# } catch (...) {
267# for (int i = 0; i < n; ++i)
268# dont_throw();
269# }
270name: test3
271# CHECK-LABEL: name: test3
272liveins:
273 - { reg: '$arguments', reg: '$value_stack' }
274body: |
275 bb.0:
276 successors: %bb.4, %bb.1
277
278 CALL_VOID @may_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
279 BR %bb.4, implicit-def $arguments
280 ; CHECK-LABEL: bb.0:
281 ; CHECK: TRY
282 ; CHECK-NEXT: CALL_VOID @may_throw
283
284 bb.1 (landing-pad):
285 ; predecessors: %bb.0
286 successors: %bb.2, %bb.3
287
288 %9:i32 = CATCH_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
289 %18:i32 = CALL_I32 @__cxa_begin_catch, %9:i32, implicit-def dead $arguments, implicit $sp32, implicit $sp64, implicit-def $value_stack, implicit $value_stack
290 DROP_I32 killed %18:i32, implicit-def $arguments
291 %19:i32 = CONST_I32 0, implicit-def dead $arguments
292 SET_LOCAL_I32 1, %19:i32, implicit-def $arguments
293 %14:i32 = CONST_I32 0, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
294 %20:i32 = GET_LOCAL_I32 0, implicit-def $arguments
295 %10:i32 = GE_S_I32 %14:i32, %20:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
296 BR_IF %bb.3, %10:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
297
298 bb.2:
299 ; predecessors: %bb.1, %bb.2
300 successors: %bb.2, %bb.3
301
302 CALL_VOID @dont_throw, implicit-def dead $arguments, implicit $sp32, implicit $sp64
303 %21:i32 = GET_LOCAL_I32 1, implicit-def $arguments
304 %17:i32 = CONST_I32 1, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
305 %16:i32 = ADD_I32 %21:i32, %17:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
306 %15:i32 = TEE_LOCAL_I32 1, %16:i32, implicit-def $arguments
307 %22:i32 = GET_LOCAL_I32 0, implicit-def $arguments
308 %11:i32 = GE_S_I32 %15:i32, %22:i32, implicit-def dead $arguments, implicit-def $value_stack, implicit $value_stack
309 BR_UNLESS %bb.2, %11:i32, implicit-def $arguments, implicit-def $value_stack, implicit $value_stack
310
311 bb.3:
312 ; predecessors: %bb.1, %bb.2
313 successors: %bb.4
314
315 CALL_VOID @__cxa_end_catch, implicit-def dead $arguments, implicit $sp32, implicit $sp64
316
317 bb.4:
318 ; predecessors: %bb.0, %bb.3
319
320 RETURN_VOID implicit-def dead $arguments
321 ; CHECK-LABEL: bb.4:
322 ; CHECK: END_TRY