• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 <gtest/gtest.h>
17 
18 #include "assembly-parser.h"
19 #include "bytecode_optimizer/ir_interface.h"
20 #include "bytecode_optimizer/runtime_adapter.h"
21 #include "libpandabase/mem/arena_allocator.h"
22 #include "libpandabase/mem/pool_manager.h"
23 #include "libpandafile/class_data_accessor.h"
24 #include "libpandafile/class_data_accessor-inl.h"
25 #include "libpandafile/method_data_accessor.h"
26 #include "libpandafile/file.h"
27 #include "macros.h"
28 #include "optimizer/ir/graph.h"
29 #include "optimizer/ir/inst.h"
30 #include "optimizer/ir/runtime_interface.h"
31 #include "optimizer/ir_builder/ir_builder.h"
32 
33 namespace panda::compiler {
34 class IrBuilderTest : public testing::Test {
35 public:
SetUpTestCase(void)36     static void SetUpTestCase(void) {};
TearDownTestCase(void)37     static void TearDownTestCase(void) {};
SetUp()38     void SetUp() {};
TearDown()39     void TearDown() {};
40 
IrBuilderTest()41     IrBuilderTest()
42     {
43         PoolManager::Initialize(PoolType::MALLOC);
44     }
45 
~IrBuilderTest()46     ~IrBuilderTest()
47     {
48         PoolManager::Finalize();
49     }
50 
51     template <class Callback>
TestBuildGraphFromFunc(pandasm::Program & prog,const char * methodName,const Callback & cb)52     void TestBuildGraphFromFunc(pandasm::Program &prog, const char *methodName, const Callback &cb)
53     {
54         pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {};
55         auto pfile = pandasm::AsmEmitter::Emit(prog, &maps);
56         for (uint32_t id : pfile->GetClasses()) {
57             panda_file::File::EntityId record_id {id};
58             panda_file::ClassDataAccessor cda {*pfile, record_id};
59 
60             cda.EnumerateMethods([&prog, maps, methodName, &cb](panda_file::MethodDataAccessor &mda) {
61                 auto ir_interface = panda::bytecodeopt::BytecodeOptIrInterface(&maps, &prog);
62                 auto func_name = ir_interface.GetMethodIdByOffset(mda.GetMethodId().GetOffset());
63                 if (func_name != methodName) {
64                     return;
65                 }
66 
67                 ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER};
68                 ArenaAllocator local_allocator {SpaceType::SPACE_TYPE_COMPILER, nullptr, true};
69 
70                 auto method_ptr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(
71                     mda.GetMethodId().GetOffset());
72                 panda::BytecodeOptimizerRuntimeAdapter adapter(mda.GetPandaFile());
73                 auto *graph = allocator.New<Graph>(&allocator, &local_allocator, Arch::NONE, method_ptr, &adapter,
74                                                    false, nullptr, true, true);
75                 graph->RunPass<panda::compiler::IrBuilder>();
76                 cb(graph);
77             });
78         }
79     }
80 
81     template <class Callback>
TestBuildGraphFromFile(const std::string & pFileName,const Callback & cb)82     void TestBuildGraphFromFile(const std::string &pFileName, const Callback &cb)
83     {
84         auto pfile = panda_file::OpenPandaFile(pFileName);
85         for (uint32_t id : pfile->GetClasses()) {
86             panda_file::File::EntityId record_id {id};
87 
88             if (pfile->IsExternal(record_id)) {
89                 continue;
90             }
91 
92             panda_file::ClassDataAccessor cda {*pfile, record_id};
93             cda.EnumerateMethods([&pfile, &cb](panda_file::MethodDataAccessor &mda) {
94                 if (!mda.IsExternal()) {
95                     ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER};
96                     ArenaAllocator local_allocator {SpaceType::SPACE_TYPE_COMPILER, nullptr, true};
97 
98                     auto method_ptr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(
99                         mda.GetMethodId().GetOffset());
100                     panda::BytecodeOptimizerRuntimeAdapter adapter(mda.GetPandaFile());
101                     auto *graph = allocator.New<Graph>(&allocator, &local_allocator, Arch::NONE, method_ptr, &adapter,
102                                                        false, nullptr, true, true);
103                     graph->RunPass<panda::compiler::IrBuilder>();
104 
105                     auto methodName = std::string(utf::Mutf8AsCString(pfile->GetStringData(mda.GetNameId()).data));
106 
107                     cb(graph, methodName);
108                 }
109             });
110         }
111     }
112 };
113 
114 HWTEST_F(IrBuilderTest, simpleTryCatchAsm, testing::ext::TestSize.Level1)
115 {
116     /**
117      *  try {
118      *      a = 1;
119      *  } catch(e) {
120      *      a = 2;
121      *  }
122      */
123     const auto source = R"(
124         .language ECMAScript
125         .function any foo(any a0, any a1, any a2) {
126             mov v0, a0
127             mov v1, a1
128             mov v2, a2
129         try_begin:
130             ldai 0x1
131             trystglobalbyname 0x0, "a"
132         try_end:
133             jmp catch_end
134         catch_begin:
135             sta v4
136             tryldglobalbyname 0x1, "a"
137         catch_end:
138             returnundefined
139         }
140     )";
141 
142     panda::pandasm::Parser parser;
143     auto res = parser.Parse(source);
144     auto &prog = res.Value();
145     for (auto &[name, func] : prog.function_table) {
146         auto &catchBlock = func.catch_blocks.emplace_back();
147         catchBlock.try_begin_label = "try_begin";
148         catchBlock.try_end_label = "try_end";
149         catchBlock.catch_begin_label = "catch_begin";
150         catchBlock.catch_end_label = "catch_end";
151     }
152 
__anon32a3985d0302(Graph* graph) 153     TestBuildGraphFromFunc(prog, "foo:(any,any,any)", [](Graph* graph) {
154         EXPECT_NE(graph, nullptr);
155         for (auto bb : graph->GetBlocksRPO()) {
156             EXPECT_NE(bb, nullptr);
157             if (bb->IsTryBegin()) {
158                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
159                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
160                 EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
161                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
162                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
163 
164                 EXPECT_TRUE(bb->GetFirstInst()->IsTry());
165                 continue;
166             }
167 
168             if (bb->IsTry()) {
169                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
170                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
171                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
172 
173                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
174                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
175                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
176                             RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
177                 continue;
178             }
179 
180             if (bb->IsTryEnd()) {
181                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
182                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
183                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
184                 EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
185                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatch());
186                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatchBegin());
187                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
188                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
189 
190                 EXPECT_TRUE(bb->IsEmpty());
191                 continue;
192             }
193 
194             if (bb->IsCatchBegin()) {
195                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
196                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
197                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
198                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
199 
200                 EXPECT_TRUE(bb->IsEmpty());
201                 continue;
202             }
203 
204             if (bb->IsCatch() && !bb->IsCatchBegin()) {
205                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
206                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
207 
208                 EXPECT_TRUE(bb->GetSuccessor(0)->GetFirstInst()->IsSaveState());
209                 EXPECT_TRUE(bb->GetSuccessor(0)->GetLastInst()->IsIntrinsic());
210                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetSuccessor(0)->GetLastInst()))->GetIntrinsicId() ==
211                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
212 
213                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
214                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
215                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
216                             RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
217                 continue;
218             }
219         }
220     });
221 }
222 
223 HWTEST_F(IrBuilderTest, nestedTryCatchAsm, testing::ext::TestSize.Level1)
224 {
225     /**
226      *  try {
227      *      try {
228      *          a = 1;
229      *      } catch(e) {
230      *          a;
231      *      }
232      *  } catch(e) {
233      *      print(e);
234      *  }
235      */
236     const auto source = R"(
237         .language ECMAScript
238         .function any foo(any a0, any a1, any a2) {
239             mov v2, a2
240             mov v1, a1
241             mov v0, a0
242             lda.str "use strict"
243         LABEL_0:
244         LABEL_1:
245             ldai 1
246             trystglobalbyname 0, "a"
247         LABEL_2:
248             jmp LABEL_3
249         LABEL_4:
250             sta v3
251             tryldglobalbyname 1, "a"
252         LABEL_3:
253         LABEL_5:
254             jmp LABEL_6
255         LABEL_7:
256             sta v4
257             tryldglobalbyname 2, "print"
258             sta v5
259             lda v4
260             sta v6
261             lda v5
262             callarg1 3, v6
263         LABEL_6:
264             returnundefined
265         }
266     )";
267 
268     panda::pandasm::Parser parser;
269     auto res = parser.Parse(source);
270     auto &prog = res.Value();
271     EXPECT_TRUE(prog.function_table.size() == 1);
272     for (auto &[name, func] : prog.function_table) {
273         auto &catchBlock1 = func.catch_blocks.emplace_back();
274         catchBlock1.try_begin_label = "LABEL_0";
275         catchBlock1.try_end_label = "LABEL_1";
276         catchBlock1.catch_begin_label = "LABEL_7";
277         catchBlock1.catch_end_label = "LABEL_6";
278 
279         auto &catchBlock2 = func.catch_blocks.emplace_back();
280         catchBlock2.try_begin_label = "LABEL_1";
281         catchBlock2.try_end_label = "LABEL_2";
282         catchBlock2.catch_begin_label = "LABEL_4";
283         catchBlock2.catch_end_label = "LABEL_3";
284 
285         auto &catchBlock3 = func.catch_blocks.emplace_back();
286         catchBlock3.try_begin_label = "LABEL_2";
287         catchBlock3.try_end_label = "LABEL_5";
288         catchBlock3.catch_begin_label = "LABEL_7";
289         catchBlock3.catch_end_label = "LABEL_6";
290     }
291 
__anon32a3985d0402(Graph* graph) 292     TestBuildGraphFromFunc(prog, "foo:(any,any,any)", [](Graph* graph) {
293         EXPECT_NE(graph, nullptr);
294         int32_t numOfTry = 0;
295         for (auto bb : graph->GetBlocksRPO()) {
296             EXPECT_NE(bb, nullptr);
297             if (bb->IsTryBegin()) {
298                 numOfTry++;
299 
300                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
301 
302                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
303                 EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
304                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
305                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
306 
307                 EXPECT_TRUE(bb->GetSuccessor(0)->GetTryId() == bb->GetTryId());
308                 continue;
309             }
310 
311             if (bb->IsTry()) {
312                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
313                 if (!bb->GetPredecessor(0)->IsTryBegin()) {
314                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
315                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
316 
317                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
318                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
319                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
320                                 RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
321                     continue;
322                 }
323 
324 
325                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
326                 EXPECT_TRUE(bb->GetPredecessor(0)->GetGuestPc() == bb->GetGuestPc());
327                 if (bb->GetPredecessor(0)->GetTryId() == 1) {
328                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
329                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
330 
331                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
332                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
333                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
334                                 RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
335                     continue;
336                 }
337 
338                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == 2);
339                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
340                 EXPECT_TRUE(bb->IsEmpty());
341 
342                 for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
343                     EXPECT_TRUE(inst->IsPhi());
344                 }
345                 continue;
346             }
347 
348             if (bb->IsTryEnd()) {
349                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
350                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
351                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
352 
353                 EXPECT_TRUE(bb->IsEmpty());
354 
355                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
356                 if (bb->GetTryId() == 1) {
357                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryBegin());
358                     EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
359 
360                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
361                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
362 
363                     for (auto inst : bb->GetSuccessor(1)->AllInsts()) {
364                         EXPECT_TRUE(inst->IsCatchPhi());
365                     }
366                     continue;
367                 }
368 
369                 EXPECT_TRUE(bb->GetTryId() == 2);
370                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
371                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
372                 for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
373                     EXPECT_TRUE(inst->IsPhi());
374                 }
375                 continue;
376             }
377 
378             if (bb->IsCatchBegin()) {
379                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
380                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
381                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
382 
383                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
384                 continue;
385             }
386 
387             if (bb->IsCatch() && !bb->IsCatchBegin()) {
388                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
389 
390                 if (bb->IsTry()) {
391                     EXPECT_TRUE(bb->GetTryId() == 2);
392 
393                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
394                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
395                     EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
396 
397                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
398                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
399                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
400                                 RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
401                     continue;
402                 }
403 
404                 if (bb->IsTryEnd()) {
405                     EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
406                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
407 
408                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
409                     for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
410                         EXPECT_TRUE(inst->IsPhi());
411                     }
412                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
413                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
414 
415                     EXPECT_TRUE(bb->IsEmpty());
416                     continue;
417                 }
418 
419                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
420                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
421 
422                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
423                 auto *successor = bb->GetSuccessor(0);
424                 EXPECT_TRUE(successor->GetFirstInst()->IsSaveState());
425                 EXPECT_TRUE(successor->GetLastInst()->IsIntrinsic());
426                 EXPECT_TRUE((static_cast<IntrinsicInst *>(successor->GetLastInst()))->GetIntrinsicId() ==
427                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
428                 for (auto inst : successor->GetPredecessor(0)->AllInsts()) {
429                     EXPECT_TRUE(inst->IsPhi());
430                 }
431 
432                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
433                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
434                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
435                             RuntimeInterface::IntrinsicId::CALLARG1_IMM8_V8);
436             }
437         }
438 
439         EXPECT_EQ(numOfTry, 2);
440     });
441 }
442 
443 HWTEST_F(IrBuilderTest, simpleTryCatchAbc, testing::ext::TestSize.Level1)
444 {
445     std::string pFile = GRAPH_TEST_ABC_DIR "simpleTryCatch.abc";
446     const char *testMethodName = "func_main_0";
__anon32a3985d0502(Graph* graph, std::string &methodName) 447     TestBuildGraphFromFile(pFile, [&testMethodName](Graph* graph, std::string &methodName) {
448         if (testMethodName != methodName) {
449             return;
450         }
451 
452         EXPECT_NE(graph, nullptr);
453         for (auto bb : graph->GetBlocksRPO()) {
454             EXPECT_NE(bb, nullptr);
455             if (bb->IsTryBegin()) {
456                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
457                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
458                 EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
459                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
460                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
461 
462                 EXPECT_TRUE(bb->GetFirstInst()->IsTry());
463                 continue;
464             }
465 
466             if (bb->IsTry()) {
467                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
468                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
469                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
470 
471                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
472                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
473                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
474                             RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
475                 continue;
476             }
477 
478             if (bb->IsTryEnd()) {
479                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
480                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
481                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
482                 EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
483                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatch());
484                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatchBegin());
485                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
486                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
487 
488                 EXPECT_TRUE(bb->IsEmpty());
489                 continue;
490             }
491 
492             if (bb->IsCatchBegin()) {
493                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
494                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
495                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
496                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
497 
498                 EXPECT_TRUE(bb->IsEmpty());
499                 continue;
500             }
501 
502             if (bb->IsCatch() && !bb->IsCatchBegin()) {
503                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
504                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
505 
506                 EXPECT_TRUE(bb->GetSuccessor(0)->GetFirstInst()->IsSaveState());
507                 EXPECT_TRUE(bb->GetSuccessor(0)->GetLastInst()->IsIntrinsic());
508                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetSuccessor(0)->GetLastInst()))->GetIntrinsicId() ==
509                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
510 
511                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
512                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
513                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
514                             RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
515                 continue;
516             }
517         }
518     });
519 }
520 
521 HWTEST_F(IrBuilderTest, nestedTryCatchAbc, testing::ext::TestSize.Level1)
522 {
523     std::string pFile = GRAPH_TEST_ABC_DIR "nestedTryCatch.abc";
524     const char *testMethodName = "func_main_0";
__anon32a3985d0602(Graph* graph, std::string &methodName) 525     TestBuildGraphFromFile(pFile, [testMethodName](Graph* graph, std::string &methodName) {
526         if (testMethodName != methodName) {
527             return;
528         }
529 
530         EXPECT_NE(graph, nullptr);
531         int32_t numOfTry = 0;
532         for (auto bb : graph->GetBlocksRPO()) {
533             EXPECT_NE(bb, nullptr);
534             if (bb->IsTryBegin()) {
535                 numOfTry++;
536 
537                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
538 
539                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
540 
541                 if (bb->GetTryId() == 0) {
542                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
543                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
544                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
545                     EXPECT_TRUE(bb->GetSuccessor(0)->GetTryId() == bb->GetTryId());
546                 }
547 
548                 if (bb->GetTryId() == 1) {
549                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryBegin());
550                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
551                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
552                 }
553 
554                 continue;
555             }
556 
557             if (bb->IsTry()) {
558                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
559                 if (bb->GetPredecessor(0)->IsTryBegin()) {
560                     EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
561                     EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == 0);
562                     EXPECT_TRUE(bb->GetPredecessor(0)->GetGuestPc() == bb->GetGuestPc());
563 
564                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
565                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
566 
567                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
568                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
569                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
570                                 RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
571                     continue;
572                 }
573 
574                 if (bb->GetPredecessor(0)->IsTryEnd()) {
575                     EXPECT_FALSE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
576                     EXPECT_TRUE(bb->GetPredecessor(0)->GetGuestPc() == bb->GetGuestPc());
577 
578                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
579                     for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
580                         EXPECT_TRUE(inst->IsPhi());
581                     }
582                     continue;
583                 }
584 
585                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
586                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
587 
588                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
589                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
590 
591                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
592                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
593                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
594                             RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
595                 continue;
596             }
597 
598             if (bb->IsTryEnd()) {
599                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
600                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
601                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
602 
603                 EXPECT_TRUE(bb->IsEmpty());
604 
605                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
606                 if (bb->GetTryId() == 0) {
607                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
608                     EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
609 
610                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
611                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
612 
613                     for (auto inst : bb->GetSuccessor(1)->AllInsts()) {
614                         EXPECT_TRUE(inst->IsCatchPhi());
615                     }
616                     continue;
617                 }
618 
619                 EXPECT_TRUE(bb->GetTryId() == 1);
620                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
621                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
622                 for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
623                     EXPECT_TRUE(inst->IsPhi());
624                 }
625                 continue;
626             }
627 
628             if (bb->IsCatchBegin()) {
629                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
630                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
631                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
632 
633                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
634                 continue;
635             }
636 
637             if (bb->IsCatch() && !bb->IsCatchBegin()) {
638                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
639 
640                 if (bb->IsTry()) {
641                     EXPECT_TRUE(bb->GetTryId() == 2);
642 
643                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
644                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
645                     EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
646 
647                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
648                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
649                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
650                                 RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
651                     continue;
652                 }
653 
654                 if (bb->IsTryEnd()) {
655                     EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
656                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
657 
658                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
659                     for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
660                         EXPECT_TRUE(inst->IsPhi());
661                     }
662                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
663                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
664 
665                     EXPECT_TRUE(bb->IsEmpty());
666                     continue;
667                 }
668 
669                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
670                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
671 
672                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
673                 auto *successor = bb->GetSuccessor(0);
674                 EXPECT_TRUE(successor->GetFirstInst()->IsSaveState());
675                 EXPECT_TRUE(successor->GetLastInst()->IsIntrinsic());
676                 EXPECT_TRUE((static_cast<IntrinsicInst *>(successor->GetLastInst()))->GetIntrinsicId() ==
677                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
678                 for (auto inst : successor->GetPredecessor(0)->AllInsts()) {
679                     EXPECT_TRUE(inst->IsPhi());
680                 }
681 
682                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
683                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
684                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
685                             RuntimeInterface::IntrinsicId::CALLARG1_IMM8_V8);
686             }
687         }
688 
689         EXPECT_EQ(numOfTry, 2);
690     });
691 }
692 } // namespace panda::compiler