blob: 663fff325d4e39ca97ae925c68dfb9bbe2defcdb [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 Ahn78297632019-02-26 03:29:59 +000021; CHECK: block
Heejin Ahnd6f48782019-01-30 03:21:57 +000022; CHECK: try
Heejin Ahn78297632019-02-26 03:29:59 +000023; CHECK: call foo
24; CHECK: br 0 # 0: down to label1
25; CHECK: catch
26; CHECK: block
27; CHECK: br_if 0, {{.*}} # 0: down to label3
28; CHECK: i32.call $drop=, __cxa_begin_catch
29; CHECK: call __cxa_end_catch
30; CHECK: br 1 # 1: down to label1
31; CHECK: end_block # label3:
32; CHECK: block
33; CHECK: br_if 0, {{.*}} # 0: down to label4
34; CHECK: i32.call $drop=, __cxa_begin_catch
35; CHECK: call __cxa_end_catch
36; CHECK: br 1 # 1: down to label1
37; CHECK: end_block # label4:
38; CHECK: call __cxa_rethrow
39; CHECK: end_try # label1:
40; CHECK: end_block
Heejin Ahn7fb68d22018-08-07 20:19:23 +000041define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
42entry:
43 invoke void @foo()
44 to label %try.cont unwind label %catch.dispatch
45
46catch.dispatch: ; preds = %entry
47 %0 = catchswitch within none [label %catch.start] unwind to caller
48
49catch.start: ; preds = %catch.dispatch
50 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
51 %2 = call i8* @llvm.wasm.get.exception(token %1)
52 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
53 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
54 %matches = icmp eq i32 %3, %4
55 br i1 %matches, label %catch2, label %catch.fallthrough
56
57catch2: ; preds = %catch.start
58 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +000059 call void @__cxa_end_catch() [ "funclet"(token %1) ]
60 catchret from %1 to label %try.cont
61
62catch.fallthrough: ; preds = %catch.start
Heejin Ahn78297632019-02-26 03:29:59 +000063 %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
64 %matches1 = icmp eq i32 %3, %6
Heejin Ahn7fb68d22018-08-07 20:19:23 +000065 br i1 %matches1, label %catch, label %rethrow
66
67catch: ; preds = %catch.fallthrough
Heejin Ahn78297632019-02-26 03:29:59 +000068 %7 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
Heejin Ahn7fb68d22018-08-07 20:19:23 +000069 call void @__cxa_end_catch() [ "funclet"(token %1) ]
70 catchret from %1 to label %try.cont
71
72rethrow: ; preds = %catch.fallthrough
73 call void @__cxa_rethrow() [ "funclet"(token %1) ]
74 unreachable
75
76try.cont: ; preds = %entry, %catch, %catch2
77 ret void
78}
79
80; Nested try-catches within a catch
Heejin Ahnd6f48782019-01-30 03:21:57 +000081; void test1() {
82; try {
83; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000084; } catch (int) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000085; try {
86; foo();
Heejin Ahn78297632019-02-26 03:29:59 +000087; } catch (int) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000088; foo();
89; }
90; }
91; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +000092
93; CHECK-LABEL: test1
Heejin Ahn78297632019-02-26 03:29:59 +000094; TODO Fill in CHECK lines once we fix ScopeTops info bug in D58605
Heejin Ahnd6f48782019-01-30 03:21:57 +000095define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
Heejin Ahn7fb68d22018-08-07 20:19:23 +000096entry:
97 invoke void @foo()
98 to label %try.cont11 unwind label %catch.dispatch
99
100catch.dispatch: ; preds = %entry
101 %0 = catchswitch within none [label %catch.start] unwind to caller
102
103catch.start: ; preds = %catch.dispatch
104 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
105 %2 = call i8* @llvm.wasm.get.exception(token %1)
106 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
107 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
108 %matches = icmp eq i32 %3, %4
109 br i1 %matches, label %catch, label %rethrow
110
111catch: ; preds = %catch.start
112 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
113 %6 = bitcast i8* %5 to i32*
114 %7 = load i32, i32* %6, align 4
115 invoke void @foo() [ "funclet"(token %1) ]
116 to label %try.cont unwind label %catch.dispatch2
117
118catch.dispatch2: ; preds = %catch
119 %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
120
121catch.start3: ; preds = %catch.dispatch2
122 %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
123 %10 = call i8* @llvm.wasm.get.exception(token %9)
124 %11 = call i32 @llvm.wasm.get.ehselector(token %9)
125 %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
126 %matches4 = icmp eq i32 %11, %12
127 br i1 %matches4, label %catch6, label %rethrow5
128
129catch6: ; preds = %catch.start3
130 %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
131 %14 = bitcast i8* %13 to i32*
132 %15 = load i32, i32* %14, align 4
133 invoke void @foo() [ "funclet"(token %9) ]
134 to label %invoke.cont8 unwind label %ehcleanup
135
136invoke.cont8: ; preds = %catch6
137 call void @__cxa_end_catch() [ "funclet"(token %9) ]
138 catchret from %9 to label %try.cont
139
140rethrow5: ; preds = %catch.start3
141 invoke void @__cxa_rethrow() [ "funclet"(token %9) ]
142 to label %unreachable unwind label %ehcleanup9
143
144try.cont: ; preds = %catch, %invoke.cont8
145 call void @__cxa_end_catch() [ "funclet"(token %1) ]
146 catchret from %1 to label %try.cont11
147
148rethrow: ; preds = %catch.start
149 call void @__cxa_rethrow() [ "funclet"(token %1) ]
150 unreachable
151
152try.cont11: ; preds = %entry, %try.cont
153 ret void
154
155ehcleanup: ; preds = %catch6
156 %16 = cleanuppad within %9 []
157 call void @__cxa_end_catch() [ "funclet"(token %16) ]
158 cleanupret from %16 unwind label %ehcleanup9
159
160ehcleanup9: ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
161 %17 = cleanuppad within %1 []
162 call void @__cxa_end_catch() [ "funclet"(token %17) ]
163 cleanupret from %17 unwind to caller
164
165unreachable: ; preds = %rethrow5
166 unreachable
167}
168
169; Nested loop within a catch clause
Heejin Ahnd6f48782019-01-30 03:21:57 +0000170; void test2() {
171; try {
172; foo();
173; } catch (...) {
174; for (int i = 0; i < 50; i++)
175; foo();
176; }
177; }
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000178
179; CHECK-LABEL: test2
Heejin Ahn78297632019-02-26 03:29:59 +0000180; CHECK: block
Heejin Ahnd6f48782019-01-30 03:21:57 +0000181; CHECK: try
Heejin Ahn78297632019-02-26 03:29:59 +0000182; CHECK: call foo
183; CHECK: br 0 # 0: down to label17
Heejin Ahnd6f48782019-01-30 03:21:57 +0000184; CHECK: catch
Heejin Ahn78297632019-02-26 03:29:59 +0000185; CHECK: i32.call $drop=, __cxa_begin_catch
186; CHECK: loop # label19:
187; CHECK: block
188; CHECK: block
189; CHECK: br_if 0, {{.*}} # 0: down to label21
190; CHECK: try
191; CHECK: call foo
192; CHECK: br 2 # 2: down to label20
193; CHECK: catch
194; CHECK: block
195; CHECK: try
196; CHECK: call __cxa_end_catch
197; CHECK: br 0 # 0: down to label24
198; CHECK: catch
199; CHECK: call __clang_call_terminate
200; CHECK: unreachable
201; CHECK: end_try # label24:
202; CHECK: end_block
203; CHECK: rethrow # to caller
204; CHECK: end_try
205; CHECK: end_block # label21:
206; CHECK: call __cxa_end_catch
207; CHECK: br 2 # 2: down to label17
208; CHECK: end_block # label20:
209; CHECK: br 0 # 0: up to label19
210; CHECK: end_loop
211; CHECK: end_try # label17:
212; CHECK: end_block
Heejin Ahn7fb68d22018-08-07 20:19:23 +0000213define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
214entry:
215 invoke void @foo()
216 to label %try.cont unwind label %catch.dispatch
217
218catch.dispatch: ; preds = %entry
219 %0 = catchswitch within none [label %catch.start] unwind to caller
220
221catch.start: ; preds = %catch.dispatch
222 %1 = catchpad within %0 [i8* null]
223 %2 = call i8* @llvm.wasm.get.exception(token %1)
224 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
225 %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
226 br label %for.cond
227
228for.cond: ; preds = %for.inc, %catch.start
229 %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
230 %cmp = icmp slt i32 %i.0, 50
231 br i1 %cmp, label %for.body, label %for.end
232
233for.body: ; preds = %for.cond
234 invoke void @foo() [ "funclet"(token %1) ]
235 to label %for.inc unwind label %ehcleanup
236
237for.inc: ; preds = %for.body
238 %inc = add nsw i32 %i.0, 1
239 br label %for.cond
240
241for.end: ; preds = %for.cond
242 call void @__cxa_end_catch() [ "funclet"(token %1) ]
243 catchret from %1 to label %try.cont
244
245try.cont: ; preds = %for.end, %entry
246 ret void
247
248ehcleanup: ; preds = %for.body
249 %5 = cleanuppad within %1 []
250 invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
251 to label %invoke.cont2 unwind label %terminate
252
253invoke.cont2: ; preds = %ehcleanup
254 cleanupret from %5 unwind to caller
255
256terminate: ; preds = %ehcleanup
257 %6 = cleanuppad within %5 []
258 %7 = call i8* @llvm.wasm.get.exception(token %6)
259 call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
260 unreachable
261}
262
263declare void @foo()
264declare void @bar()
265declare i32 @__gxx_wasm_personality_v0(...)
266declare i8* @llvm.wasm.get.exception(token)
267declare i32 @llvm.wasm.get.ehselector(token)
268declare i32 @llvm.eh.typeid.for(i8*)
269declare i8* @__cxa_begin_catch(i8*)
270declare void @__cxa_end_catch()
271declare void @__cxa_rethrow()
272declare void @__clang_call_terminate(i8*)
273declare void @_ZSt9terminatev()