blob: e3c34f87e13e7526f0429a05e09787660a2b4580 [file] [log] [blame]
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +00001; RUN: llc < %s -asm-verbose=false -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
10
11; CHECK-LABEL: test0
12; CHECK: call foo@FUNCTION
13; CHECK: .LBB0_1:
14; CHECK: i32.catch
15; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION
16; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION
17; CHECK: call bar@FUNCTION
18; CHECK: call __cxa_end_catch@FUNCTION
19; CHECK: .LBB0_3:
20; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION
21; CHECK: call __cxa_end_catch@FUNCTION
22; CHECK: .LBB0_5:
23; CHECK: call __cxa_rethrow@FUNCTION
24; CHECK: .LBB0_6:
25; CHECK: return
26define void @test0() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
27entry:
28 invoke void @foo()
29 to label %try.cont unwind label %catch.dispatch
30
31catch.dispatch: ; preds = %entry
32 %0 = catchswitch within none [label %catch.start] unwind to caller
33
34catch.start: ; preds = %catch.dispatch
35 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTId to i8*)]
36 %2 = call i8* @llvm.wasm.get.exception(token %1)
37 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
38 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
39 %matches = icmp eq i32 %3, %4
40 br i1 %matches, label %catch2, label %catch.fallthrough
41
42catch2: ; preds = %catch.start
43 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
44 %6 = bitcast i8* %5 to i32*
45 %7 = load i32, i32* %6, align 4
46 call void @bar() [ "funclet"(token %1) ]
47 call void @__cxa_end_catch() [ "funclet"(token %1) ]
48 catchret from %1 to label %try.cont
49
50catch.fallthrough: ; preds = %catch.start
51 %8 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTId to i8*))
52 %matches1 = icmp eq i32 %3, %8
53 br i1 %matches1, label %catch, label %rethrow
54
55catch: ; preds = %catch.fallthrough
56 %9 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
57 %10 = bitcast i8* %9 to double*
58 %11 = load double, double* %10, align 8
59 call void @__cxa_end_catch() [ "funclet"(token %1) ]
60 catchret from %1 to label %try.cont
61
62rethrow: ; preds = %catch.fallthrough
63 call void @__cxa_rethrow() [ "funclet"(token %1) ]
64 unreachable
65
66try.cont: ; preds = %entry, %catch, %catch2
67 ret void
68}
69
70; Nested try-catches within a catch
71
72; CHECK-LABEL: test1
73; CHECK: call foo@FUNCTION
74; CHECK: .LBB1_1:
75; CHECK: i32.catch $0=, 0
76; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION, $0
77; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION, $0
78; CHECK: call foo@FUNCTION
79; CHECK: .LBB1_3:
80; CHECK: i32.catch $0=, 0
81; CHECK: i32.call $drop=, _Unwind_CallPersonality@FUNCTION, $0
82; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION, $0
83; CHECK: call foo@FUNCTION
84; CHECK: .LBB1_5:
85; CHECK: catch_all
86; CHECK: call __cxa_end_catch@FUNCTION
87; CHECK: rethrow
88; CHECK: .LBB1_6:
89; CHECK: call __cxa_rethrow@FUNCTION
90; CHECK: rethrow
91; CHECK: .LBB1_7:
92; CHECK: call __cxa_end_catch@FUNCTION
93; CHECK: .LBB1_8:
94; CHECK: catch_all
95; CHECK: call __cxa_end_catch@FUNCTION
96; CHECK: .LBB1_9:
97; CHECK: call __cxa_rethrow@FUNCTION
98; CHECK: rethrow
99; CHECK: .LBB1_10:
100; CHECK: call __cxa_end_catch@FUNCTION
101; CHECK: .LBB1_11:
102; CHECK: return
103define hidden void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
104entry:
105 invoke void @foo()
106 to label %try.cont11 unwind label %catch.dispatch
107
108catch.dispatch: ; preds = %entry
109 %0 = catchswitch within none [label %catch.start] unwind to caller
110
111catch.start: ; preds = %catch.dispatch
112 %1 = catchpad within %0 [i8* bitcast (i8** @_ZTIi to i8*)]
113 %2 = call i8* @llvm.wasm.get.exception(token %1)
114 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
115 %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
116 %matches = icmp eq i32 %3, %4
117 br i1 %matches, label %catch, label %rethrow
118
119catch: ; preds = %catch.start
120 %5 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
121 %6 = bitcast i8* %5 to i32*
122 %7 = load i32, i32* %6, align 4
123 invoke void @foo() [ "funclet"(token %1) ]
124 to label %try.cont unwind label %catch.dispatch2
125
126catch.dispatch2: ; preds = %catch
127 %8 = catchswitch within %1 [label %catch.start3] unwind label %ehcleanup9
128
129catch.start3: ; preds = %catch.dispatch2
130 %9 = catchpad within %8 [i8* bitcast (i8** @_ZTIi to i8*)]
131 %10 = call i8* @llvm.wasm.get.exception(token %9)
132 %11 = call i32 @llvm.wasm.get.ehselector(token %9)
133 %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
134 %matches4 = icmp eq i32 %11, %12
135 br i1 %matches4, label %catch6, label %rethrow5
136
137catch6: ; preds = %catch.start3
138 %13 = call i8* @__cxa_begin_catch(i8* %10) [ "funclet"(token %9) ]
139 %14 = bitcast i8* %13 to i32*
140 %15 = load i32, i32* %14, align 4
141 invoke void @foo() [ "funclet"(token %9) ]
142 to label %invoke.cont8 unwind label %ehcleanup
143
144invoke.cont8: ; preds = %catch6
145 call void @__cxa_end_catch() [ "funclet"(token %9) ]
146 catchret from %9 to label %try.cont
147
148rethrow5: ; preds = %catch.start3
149 invoke void @__cxa_rethrow() [ "funclet"(token %9) ]
150 to label %unreachable unwind label %ehcleanup9
151
152try.cont: ; preds = %catch, %invoke.cont8
153 call void @__cxa_end_catch() [ "funclet"(token %1) ]
154 catchret from %1 to label %try.cont11
155
156rethrow: ; preds = %catch.start
157 call void @__cxa_rethrow() [ "funclet"(token %1) ]
158 unreachable
159
160try.cont11: ; preds = %entry, %try.cont
161 ret void
162
163ehcleanup: ; preds = %catch6
164 %16 = cleanuppad within %9 []
165 call void @__cxa_end_catch() [ "funclet"(token %16) ]
166 cleanupret from %16 unwind label %ehcleanup9
167
168ehcleanup9: ; preds = %ehcleanup, %rethrow5, %catch.dispatch2
169 %17 = cleanuppad within %1 []
170 call void @__cxa_end_catch() [ "funclet"(token %17) ]
171 cleanupret from %17 unwind to caller
172
173unreachable: ; preds = %rethrow5
174 unreachable
175}
176
177; Nested loop within a catch clause
178
179; CHECK-LABEL: test2
180; CHECK: call foo@FUNCTION
181; CHECK: .LBB2_1:
182; CHECK: i32.catch
183; CHECK: i32.call $drop=, __cxa_begin_catch@FUNCTION
184; CHECK: .LBB2_2:
185; CHECK: call foo@FUNCTION
186; CHECK: .LBB2_4:
187; CHECK: catch_all
188; CHECK: call __cxa_end_catch@FUNCTION
189; CHECK: .LBB2_5:
190; CHECK: i32.catch
191; CHECK: call __clang_call_terminate@FUNCTION
192; CHECK: unreachable
193; CHECK: .LBB2_6:
194; CHECK: catch_all
195; CHECK: call _ZSt9terminatev@FUNCTION
196; CHECK: unreachable
197; CHECK: .LBB2_7:
198; CHECK: rethrow
199; CHECK: .LBB2_8:
200; CHECK: call __cxa_end_catch@FUNCTION
201; CHECK: .LBB2_10:
202; CHECK: return
203define void @test2() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) {
204entry:
205 invoke void @foo()
206 to label %try.cont unwind label %catch.dispatch
207
208catch.dispatch: ; preds = %entry
209 %0 = catchswitch within none [label %catch.start] unwind to caller
210
211catch.start: ; preds = %catch.dispatch
212 %1 = catchpad within %0 [i8* null]
213 %2 = call i8* @llvm.wasm.get.exception(token %1)
214 %3 = call i32 @llvm.wasm.get.ehselector(token %1)
215 %4 = call i8* @__cxa_begin_catch(i8* %2) [ "funclet"(token %1) ]
216 br label %for.cond
217
218for.cond: ; preds = %for.inc, %catch.start
219 %i.0 = phi i32 [ 0, %catch.start ], [ %inc, %for.inc ]
220 %cmp = icmp slt i32 %i.0, 50
221 br i1 %cmp, label %for.body, label %for.end
222
223for.body: ; preds = %for.cond
224 invoke void @foo() [ "funclet"(token %1) ]
225 to label %for.inc unwind label %ehcleanup
226
227for.inc: ; preds = %for.body
228 %inc = add nsw i32 %i.0, 1
229 br label %for.cond
230
231for.end: ; preds = %for.cond
232 call void @__cxa_end_catch() [ "funclet"(token %1) ]
233 catchret from %1 to label %try.cont
234
235try.cont: ; preds = %for.end, %entry
236 ret void
237
238ehcleanup: ; preds = %for.body
239 %5 = cleanuppad within %1 []
240 invoke void @__cxa_end_catch() [ "funclet"(token %5) ]
241 to label %invoke.cont2 unwind label %terminate
242
243invoke.cont2: ; preds = %ehcleanup
244 cleanupret from %5 unwind to caller
245
246terminate: ; preds = %ehcleanup
247 %6 = cleanuppad within %5 []
248 %7 = call i8* @llvm.wasm.get.exception(token %6)
249 call void @__clang_call_terminate(i8* %7) [ "funclet"(token %6) ]
250 unreachable
251}
252
253declare void @foo()
254declare void @bar()
255declare i32 @__gxx_wasm_personality_v0(...)
256declare i8* @llvm.wasm.get.exception(token)
257declare i32 @llvm.wasm.get.ehselector(token)
258declare i32 @llvm.eh.typeid.for(i8*)
259declare i8* @__cxa_begin_catch(i8*)
260declare void @__cxa_end_catch()
261declare void @__cxa_rethrow()
262declare void @__clang_call_terminate(i8*)
263declare void @_ZSt9terminatev()