blob: ed1996f72849631e1c67a4abe186dece7bccf86a [file] [log] [blame]
Heejin Ahn78297632019-02-26 03:29:59 +00001; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -disable-block-placement -verify-machineinstrs -fast-isel=false -machine-sink-split-probability-threshold=0 -cgp-freq-ratio-to-skip-merge=1000 -exception-model=wasm -mattr=+exception-handling | FileCheck %s
Heejin Ahn7fb68d22018-08-07 20:19:23 +00002
3target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
4target triple = "wasm32-unknown-unknown"
5
6@_ZTIi = external constant i8*
7@_ZTId = external constant i8*
8
9; Simple test case with two catch clauses
Heejin Ahn78297632019-02-26 03:29:59 +000010;
11; void foo();
Heejin Ahnd6f48782019-01-30 03:21:57 +000012; void test0() {
13; try {
14; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000015; } catch (int) {
16; } catch (double) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000017; }
18; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +000019
20; CHECK-LABEL: test0
Heejin Ahncf699b42019-02-27 00:50:53 +000021; CHECK: try
22; CHECK: call foo
23; CHECK: catch
24; CHECK: block
25; CHECK: br_if 0, {{.*}} # 0: down to label2
26; CHECK: i32.call $drop=, __cxa_begin_catch
27; CHECK: call __cxa_end_catch
28; CHECK: br 1 # 1: down to label0
29; CHECK: end_block # label2:
30; CHECK: block
31; CHECK: br_if 0, {{.*}} # 0: down to label3
32; CHECK: i32.call $drop=, __cxa_begin_catch
33; CHECK: call __cxa_end_catch
34; CHECK: br 1 # 1: down to label0
35; CHECK: end_block # label3:
36; CHECK: call __cxa_rethrow
37; CHECK: end_try # label0:
Heejin Ahn7fb68d22018-08-07 20:19:23 +000038define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
39entry:
40 invoke void @foo()
41 to label %try.cont unwind label %catch.dispatch
42
43catch.dispatch: ; preds = %entry
44 %0 = catchswitch within none [label %catch.start] unwind to caller
45
46catch.start: ; preds = %catch.dispatch
47 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
48 %2 = call i8* @llvm.wasm.get.exception(token %1)
49 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
50 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
51 %matches = icmp eq i32 %3, %4
52 br i1 %matches, label %catch2, label %catch.fallthrough
53
54catch2: ; preds = %catch.start
55 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +000056 call void @__cxa_end_catch() [ "funclet"(token %1) ]
57 catchret from %1 to label %try.cont
58
59catch.fallthrough: ; preds = %catch.start
Heejin Ahn78297632019-02-26 03:29:59 +000060 %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
61 %matches1 = icmp eq i32 %3, %6
Heejin Ahn7fb68d22018-08-07 20:19:23 +000062 br i1 %matches1, label %catch, label %rethrow
63
64catch: ; preds = %catch.fallthrough
Heejin Ahn78297632019-02-26 03:29:59 +000065 %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +000066 call void @__cxa_end_catch() [ "funclet"(token %1) ]
67 catchret from %1 to label %try.cont
68
69rethrow: ; preds = %catch.fallthrough
70 call void @__cxa_rethrow() [ "funclet"(token %1) ]
71 unreachable
72
73try.cont: ; preds = %entry, %catch, %catch2
74 ret void
75}
76
77; Nested try-catches within a catch
Heejin Ahnd6f48782019-01-30 03:21:57 +000078; void test1() {
79; try {
80; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000081; } catch (int) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000082; try {
83; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000084; } catch (int) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000085; foo();
86; }
87; }
88; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +000089
90; CHECK-LABEL: test1
Heejin Ahn82da1ff2019-02-27 01:35:14 +000091; CHECK: try
92; CHECK: call foo
93; CHECK: catch
94; CHECK: block
95; CHECK: block
96; CHECK: br_if 0, {{.*}} # 0: down to label7
97; CHECK: i32.call $drop=, __cxa_begin_catch
98; CHECK: try
99; CHECK: call foo
100; CHECK: br 2 # 2: down to label6
101; CHECK: catch
102; CHECK: try
103; CHECK: block
104; CHECK: br_if 0, {{.*}} # 0: down to label11
105; CHECK: i32.call $drop=, __cxa_begin_catch
106; CHECK: try
107; CHECK: call foo
108; CHECK: br 2 # 2: down to label10
109; CHECK: catch
110; CHECK: call __cxa_end_catch
111; CHECK: rethrow # down to catch3
112; CHECK: end_try
113; CHECK: end_block # label11:
114; CHECK: call __cxa_rethrow
115; CHECK: unreachable
116; CHECK: catch {{.*}} # catch3:
117; CHECK: call __cxa_end_catch
118; CHECK: rethrow # to caller
119; CHECK: end_try # label10:
120; CHECK: call __cxa_end_catch
121; CHECK: br 2 # 2: down to label6
122; CHECK: end_try
123; CHECK: end_block # label7:
124; CHECK: call __cxa_rethrow
125; CHECK: unreachable
126; CHECK: end_block # label6:
127; CHECK: call __cxa_end_catch
128; CHECK: end_try
Heejin Ahnd6f48782019-01-30 03:21:57 +0000129define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000130entry:
131 invoke void @foo()
132 to label %try.cont11 unwind label %catch.dispatch
133
134catch.dispatch: ; preds = %entry
135 %0 = catchswitch within none [label %catch.start] unwind to caller
136
137catch.start: ; preds = %catch.dispatch
138 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
139 %2 = call i8* @llvm.wasm.get.exception(token %1)
140 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
141 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
142 %matches = icmp eq i32 %3, %4
143 br i1 %matches, label %catch, label %rethrow
144
145catch: ; preds = %catch.start
146 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
147 %6 = bitcast i8* %5 to i32*
148 %7 = load i32, i32* %6, align 4
149 invoke void @foo() [ "funclet"(token %1) ]
150 to label %try.cont unwind label %catch.dispatch2
151
152catch.dispatch2: ; preds = %catch
153 %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
154
155catch.start3: ; preds = %catch.dispatch2
156 %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
157 %10 = call i8* @llvm.wasm.get.exception(token %9)
158 %11 = call i32 @llvm.wasm.get.ehselector(token %9)
159 %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
160 %matches4 = icmp eq i32 %11, %12
161 br i1 %matches4, label %catch6, label %rethrow5
162
163catch6: ; preds = %catch.start3
164 %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
165 %14 = bitcast i8* %13 to i32*
166 %15 = load i32, i32* %14, align 4
167 invoke void @foo() [ "funclet"(token %9) ]
168 to label %invoke.cont8 unwind label %ehcleanup
169
170invoke.cont8: ; preds = %catch6
171 call void @__cxa_end_catch() [ "funclet"(token %9) ]
172 catchret from %9 to label %try.cont
173
174rethrow5: ; preds = %catch.start3
175 invoke void @__cxa_rethrow() [ "funclet"(token %9) ]
176 to label %unreachable unwind label %ehcleanup9
177
178try.cont: ; preds = %catch, %invoke.cont8
179 call void @__cxa_end_catch() [ "funclet"(token %1) ]
180 catchret from %1 to label %try.cont11
181
182rethrow: ; preds = %catch.start
183 call void @__cxa_rethrow() [ "funclet"(token %1) ]
184 unreachable
185
186try.cont11: ; preds = %entry, %try.cont
187 ret void
188
189ehcleanup: ; preds = %catch6
190 %16 = cleanuppad within %9 []
191 call void @__cxa_end_catch() [ "funclet"(token %16) ]
192 cleanupret from %16 unwind label %ehcleanup9
193
194ehcleanup9: ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
195 %17 = cleanuppad within %1 []
196 call void @__cxa_end_catch() [ "funclet"(token %17) ]
197 cleanupret from %17 unwind to caller
198
199unreachable: ; preds = %rethrow5
200 unreachable
201}
202
203; Nested loop within a catch clause
Heejin Ahnd6f48782019-01-30 03:21:57 +0000204; void test2() {
205; try {
206; foo();
207; } catch (...) {
208; for (int i = 0; i < 50; i++)
209; foo();
210; }
211; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000212
213; CHECK-LABEL: test2
Heejin Ahncf699b42019-02-27 00:50:53 +0000214; CHECK: try
215; CHECK: call foo
216; CHECK: catch
217; CHECK: i32.call $drop=, __cxa_begin_catch
218; CHECK: loop # label15:
219; CHECK: block
Heejin Ahn78297632019-02-26 03:29:59 +0000220; CHECK: block
Heejin Ahncf699b42019-02-27 00:50:53 +0000221; CHECK: br_if 0, {{.*}} # 0: down to label17
222; CHECK: try
223; CHECK: call foo
224; CHECK: br 2 # 2: down to label16
225; CHECK: catch
Heejin Ahn78297632019-02-26 03:29:59 +0000226; CHECK: try
Heejin Ahncf699b42019-02-27 00:50:53 +0000227; CHECK: call __cxa_end_catch
Heejin Ahn78297632019-02-26 03:29:59 +0000228; CHECK: catch
Heejin Ahncf699b42019-02-27 00:50:53 +0000229; CHECK: call __clang_call_terminate
230; CHECK: unreachable
Heejin Ahn78297632019-02-26 03:29:59 +0000231; CHECK: end_try
Heejin Ahncf699b42019-02-27 00:50:53 +0000232; CHECK: rethrow # to caller
233; CHECK: end_try
234; CHECK: end_block # label17:
235; CHECK: call __cxa_end_catch
236; CHECK: br 2 # 2: down to label13
237; CHECK: end_block # label16:
238; CHECK: br 0 # 0: up to label15
239; CHECK: end_loop
240; CHECK: end_try # label13:
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000241define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
242entry:
243 invoke void @foo()
244 to label %try.cont unwind label %catch.dispatch
245
246catch.dispatch: ; preds = %entry
247 %0 = catchswitch within none [label %catch.start] unwind to caller
248
249catch.start: ; preds = %catch.dispatch
250 %1 = catchpad within %0 [i8* null]
251 %2 = call i8* @llvm.wasm.get.exception(token %1)
252 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
253 %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
254 br label %for.cond
255
256for.cond: ; preds = %for.inc, %catch.start
257 %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
258 %cmp = icmp slt i32 %i.0, 50
259 br i1 %cmp, label %for.body, label %for.end
260
261for.body: ; preds = %for.cond
262 invoke void @foo() [ "funclet"(token %1) ]
263 to label %for.inc unwind label %ehcleanup
264
265for.inc: ; preds = %for.body
266 %inc = add nsw i32 %i.0, 1
267 br label %for.cond
268
269for.end: ; preds = %for.cond
270 call void @__cxa_end_catch() [ "funclet"(token %1) ]
271 catchret from %1 to label %try.cont
272
273try.cont: ; preds = %for.end, %entry
274 ret void
275
276ehcleanup: ; preds = %for.body
277 %5 = cleanuppad within %1 []
278 invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
279 to label %invoke.cont2 unwind label %terminate
280
281invoke.cont2: ; preds = %ehcleanup
282 cleanupret from %5 unwind to caller
283
284terminate: ; preds = %ehcleanup
285 %6 = cleanuppad within %5 []
286 %7 = call i8* @llvm.wasm.get.exception(token %6)
287 call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
288 unreachable
289}
290
291declare void @foo()
292declare void @bar()
293declare i32 @__gxx_wasm_personality_v0(...)
294declare i8* @llvm.wasm.get.exception(token)
295declare i32 @llvm.wasm.get.ehselector(token)
296declare i32 @llvm.eh.typeid.for(i8*)
297declare i8* @__cxa_begin_catch(i8*)
298declare void @__cxa_end_catch()
299declare void @__cxa_rethrow()
300declare void @__clang_call_terminate(i8*)
301declare void @_ZSt9terminatev()