1 /**
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "unit_test.h"
17 #include "optimizer/analysis/loop_analyzer.h"
18 #include "optimizer/optimizations/try_catch_resolving.h"
19 #include "optimizer/optimizations/cleanup.h"
20
21 namespace panda::compiler {
22 class TryCatchResolvingTest : public AsmTest {
23 public:
TryCatchResolvingTest()24 TryCatchResolvingTest() : default_compiler_non_optimizing_(options.IsCompilerNonOptimizing())
25 {
26 options.SetCompilerNonOptimizing(false);
27 }
28
~TryCatchResolvingTest()29 ~TryCatchResolvingTest() override
30 {
31 options.SetCompilerNonOptimizing(default_compiler_non_optimizing_);
32 }
33
34 private:
35 bool default_compiler_non_optimizing_;
36 };
37
TEST_F(TryCatchResolvingTest,ThrowNewObject)38 TEST_F(TryCatchResolvingTest, ThrowNewObject)
39 {
40 auto source = R"(
41 .record E1 {}
42
43 .function u1 main() {
44 newobj v0, E1
45 try_begin:
46 throw v0
47 ldai 2
48 try_end:
49 return
50
51
52 catch_block1_begin:
53 ldai 0
54 return
55
56 catch_block2_begin:
57 ldai 10
58 return
59
60 .catchall try_begin, try_end, catch_block1_begin
61 .catch E1, try_begin, try_end, catch_block2_begin
62 }
63 )";
64
65 auto graph = GetGraph();
66 ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
67 graph->RunPass<TryCatchResolving>();
68 graph->RunPass<Cleanup>();
69
70 auto expected_graph = CreateGraphWithDefaultRuntime();
71 GRAPH(expected_graph)
72 {
73 CONSTANT(1, 0);
74
75 BASIC_BLOCK(2, -1)
76 {
77 INST(2, Opcode::SaveState).Inputs().SrcVregs({});
78 INST(3, Opcode::LoadAndInitClass).ref().Inputs(2);
79 INST(4, Opcode::NewObject).ref().Inputs(3, 2);
80 INST(5, Opcode::Return).Inputs(1).b();
81 }
82 }
83 ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
84 }
85
TEST_F(TryCatchResolvingTest,RemoveAllCatchHandlers)86 TEST_F(TryCatchResolvingTest, RemoveAllCatchHandlers)
87 {
88 auto source = R"(
89 .record E0 {}
90 .record E1 {}
91 .record E2 {}
92 .record E3 {}
93
94 .function u1 main() {
95 try_begin:
96 newobj v0, E0
97 throw v0
98 ldai 3
99 try_end:
100 return
101
102
103 catch_block1:
104 ldai 0
105 return
106
107 catch_block2:
108 ldai 1
109 return
110
111 catch_block3:
112 ldai 2
113 return
114
115 .catch E1, try_begin, try_end, catch_block1
116 .catch E2, try_begin, try_end, catch_block2
117 .catch E3, try_begin, try_end, catch_block3
118
119 }
120 )";
121
122 auto graph = GetGraph();
123 ASSERT_TRUE(ParseToGraph<true>(source, "main", graph));
124 graph->RunPass<TryCatchResolving>();
125 graph->RunPass<Cleanup>();
126
127 auto expected_graph = CreateGraphWithDefaultRuntime();
128 GRAPH(expected_graph)
129 {
130 BASIC_BLOCK(2, -1)
131 {
132 INST(7, Opcode::SaveState).Inputs().SrcVregs({});
133 INST(8, Opcode::LoadAndInitClass).ref().Inputs(7);
134 INST(9, Opcode::NewObject).ref().Inputs(8, 7);
135 INST(10, Opcode::SaveState).Inputs(9).SrcVregs({0});
136 INST(11, Opcode::Throw).Inputs(9, 10);
137 }
138 }
139 ASSERT_TRUE(GraphComparator().Compare(graph, expected_graph));
140 }
141 } // namespace panda::compiler
142