blob: 247118b1599dcd28c3c563501490f1dfb2b7a87c [file] [log] [blame]
Derek Schufff41f67d2016-08-01 21:34:04 +00001; RUN: opt < %s -wasm-lower-em-exceptions -S | FileCheck %s
2
3@_ZTIi = external constant i8*
4@_ZTIc = external constant i8*
5; CHECK: @[[__THREW__:__THREW__.*]] = global i1 false
6; CHECK: @[[THREWVALUE:threwValue.*]] = global i32 0
7; CHECK: @[[TEMPRET0:tempRet0.*]] = global i32 0
8
9; Test invoke instruction with clauses (try-catch block)
10define void @clause() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
11; CHECK-LABEL: @clause(
12entry:
13 invoke void @foo(i32 3)
14 to label %invoke.cont unwind label %lpad
15; CHECK: entry:
16; CHECK-NEXT: store i1 false, i1* @[[__THREW__]]
17; CHECK-NEXT: call void @__invoke_void_i32(void (i32)* @foo, i32 3)
18; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i1, i1* @[[__THREW__]]
19; CHECK-NEXT: store i1 false, i1* @[[__THREW__]]
20; CHECK-NEXT: br i1 %[[__THREW__VAL]], label %lpad, label %invoke.cont
21
22invoke.cont: ; preds = %entry
23 br label %try.cont
24
25lpad: ; preds = %entry
26 %0 = landingpad { i8*, i32 }
27 catch i8* bitcast (i8** @_ZTIi to i8*)
28 catch i8* null
29 %1 = extractvalue { i8*, i32 } %0, 0
30 %2 = extractvalue { i8*, i32 } %0, 1
31 br label %catch.dispatch
32; CHECK: lpad:
33; CHECK-NEXT: %[[FMC:.*]] = call i8* @___cxa_find_matching_catch_4(i8* bitcast (i8** @_ZTIi to i8*), i8* null)
34; CHECK-NEXT: %[[IVI1:.*]] = insertvalue { i8*, i32 } undef, i8* %[[FMC]], 0
35; CHECK-NEXT: %[[TEMPRET0_VAL:.*]] = load i32, i32* @[[TEMPRET0]]
36; CHECK-NEXT: %[[IVI2:.*]] = insertvalue { i8*, i32 } %[[IVI1]], i32 %[[TEMPRET0_VAL]], 1
37; CHECK-NEXT: extractvalue { i8*, i32 } %[[IVI2]], 0
38; CHECK-NEXT: extractvalue { i8*, i32 } %[[IVI2]], 1
39
40catch.dispatch: ; preds = %lpad
41 %3 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*))
42 %matches = icmp eq i32 %2, %3
43 br i1 %matches, label %catch1, label %catch
44
45catch1: ; preds = %catch.dispatch
46 %4 = call i8* @__cxa_begin_catch(i8* %1)
47 %5 = bitcast i8* %4 to i32*
48 %6 = load i32, i32* %5, align 4
49 call void @__cxa_end_catch()
50 br label %try.cont
51
52try.cont: ; preds = %catch, %catch1, %invoke.cont
53 ret void
54
55catch: ; preds = %catch.dispatch
56 %7 = call i8* @__cxa_begin_catch(i8* %1)
57 call void @__cxa_end_catch()
58 br label %try.cont
59}
60
61; Test invoke instruction with filters (functions with throw(...) declaration)
62define void @filter() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
63; CHECK-LABEL: @filter(
64entry:
65 invoke void @foo(i32 3)
66 to label %invoke.cont unwind label %lpad
67; CHECK: entry:
68; CHECK-NEXT: store i1 false, i1* @[[__THREW__]]
69; CHECK-NEXT: call void @__invoke_void_i32(void (i32)* @foo, i32 3)
70; CHECK-NEXT: %[[__THREW__VAL:.*]] = load i1, i1* @[[__THREW__]]
71; CHECK-NEXT: store i1 false, i1* @[[__THREW__]]
72; CHECK-NEXT: br i1 %[[__THREW__VAL]], label %lpad, label %invoke.cont
73
74invoke.cont: ; preds = %entry
75 ret void
76
77lpad: ; preds = %entry
78 %0 = landingpad { i8*, i32 }
79 filter [2 x i8*] [i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTIc to i8*)]
80 %1 = extractvalue { i8*, i32 } %0, 0
81 %2 = extractvalue { i8*, i32 } %0, 1
82 br label %filter.dispatch
83; CHECK: lpad:
84; CHECK-NEXT: %[[FMC:.*]] = call i8* @___cxa_find_matching_catch_4(i8* bitcast (i8** @_ZTIi to i8*), i8* bitcast (i8** @_ZTIc to i8*))
85; CHECK-NEXT: %[[IVI1:.*]] = insertvalue { i8*, i32 } undef, i8* %[[FMC]], 0
86; CHECK-NEXT: %[[TEMPRET0_VAL:.*]] = load i32, i32* @[[TEMPRET0]]
87; CHECK-NEXT: %[[IVI2:.*]] = insertvalue { i8*, i32 } %[[IVI1]], i32 %[[TEMPRET0_VAL]], 1
88; CHECK-NEXT: extractvalue { i8*, i32 } %[[IVI2]], 0
89; CHECK-NEXT: extractvalue { i8*, i32 } %[[IVI2]], 1
90
91filter.dispatch: ; preds = %lpad
92 %ehspec.fails = icmp slt i32 %2, 0
93 br i1 %ehspec.fails, label %ehspec.unexpected, label %eh.resume
94
95ehspec.unexpected: ; preds = %filter.dispatch
96 call void @__cxa_call_unexpected(i8* %1) #4
97 unreachable
98
99eh.resume: ; preds = %filter.dispatch
100 %lpad.val = insertvalue { i8*, i32 } undef, i8* %1, 0
101 %lpad.val3 = insertvalue { i8*, i32 } %lpad.val, i32 %2, 1
102 resume { i8*, i32 } %lpad.val3
103; CHECK: eh.resume:
104; CHECK-NEXT: insertvalue
105; CHECK-NEXT: %[[LPAD_VAL:.*]] = insertvalue
106; CHECK-NEXT: %[[LOW:.*]] = extractvalue { i8*, i32 } %[[LPAD_VAL]], 0
107; CHECK-NEXT: call void @___resumeException(i8* %[[LOW]])
108; CHECK-NEXT: unreachable
109}
110
111declare void @foo(i32)
112
113declare i32 @__gxx_personality_v0(...)
114declare i32 @llvm.eh.typeid.for(i8*)
115declare i8* @__cxa_begin_catch(i8*)
116declare void @__cxa_end_catch()
117declare void @__cxa_call_unexpected(i8*)
118
119; JS glue functions and invoke wrappers registration
120; CHECK: declare void @___resumeException(i8*)
121; CHECK: declare void @__invoke_void_i32(void (i32)*, i32)
122; CHECK: declare i8* @___cxa_find_matching_catch_4(i8*, i8*)
123
124; setThrew function creation
125; CHECK-LABEL: define void @setThrew(i1 %threw, i32 %value) {
126; CHECK: entry:
127; CHECK-NEXT: %__THREW__.val = load i1, i1* @__THREW__
128; CHECK-NEXT: %cmp = icmp eq i1 %__THREW__.val, false
129; CHECK-NEXT: br i1 %cmp, label %if.then, label %if.end
130; CHECK: if.then:
131; CHECK-NEXT: store i1 %threw, i1* @__THREW__
132; CHECK-NEXT: store i32 %value, i32* @threwValue
133; CHECK-NEXT: br label %if.end
134; CHECK: if.end:
135; CHECK-NEXT: ret void
136; CHECK: }
137
138; setTempRet0 function creation
139; CHECK-LABEL: define void @setTempRet0(i32 %value) {
140; CHECK: entry:
141; CHECK-NEXT: store i32 %value, i32* @tempRet0
142; CHECK-NEXT: ret void
143; CHECK: }