• 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 method_name = std::string(utf::Mutf8AsCString(pfile->GetStringData(mda.GetNameId()).data));
106                     auto pos = method_name.find_last_of("#");
107                     if (pos != std::string::npos) {
108                         method_name = method_name.substr(pos + 1);
109                     }
110                     cb(graph, method_name);
111                 }
112             });
113         }
114     }
115 };
116 
117 HWTEST_F(IrBuilderTest, simpleTryCatchAsm, testing::ext::TestSize.Level1)
118 {
119     /**
120      *  try {
121      *      a = 1;
122      *  } catch(e) {
123      *      a = 2;
124      *  }
125      */
126     const auto source = R"(
127         .language ECMAScript
128         .function any foo(any a0, any a1, any a2) {
129             mov v0, a0
130             mov v1, a1
131             mov v2, a2
132         try_begin:
133             ldai 0x1
134             trystglobalbyname 0x0, "a"
135         try_end:
136             jmp catch_end
137         catch_begin:
138             sta v4
139             tryldglobalbyname 0x1, "a"
140         catch_end:
141             returnundefined
142         }
143     )";
144 
145     panda::pandasm::Parser parser;
146     auto res = parser.Parse(source);
147     auto &prog = res.Value();
148     for (auto &[name, func] : prog.function_table) {
149         auto &catchBlock = func.catch_blocks.emplace_back();
150         catchBlock.try_begin_label = "try_begin";
151         catchBlock.try_end_label = "try_end";
152         catchBlock.catch_begin_label = "catch_begin";
153         catchBlock.catch_end_label = "catch_end";
154     }
155 
__anon4126c63d0302(Graph* graph) 156     TestBuildGraphFromFunc(prog, "foo:(any,any,any)", [](Graph* graph) {
157         EXPECT_NE(graph, nullptr);
158         for (auto bb : graph->GetBlocksRPO()) {
159             EXPECT_NE(bb, nullptr);
160             if (bb->IsTryBegin()) {
161                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
162                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
163                 EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
164                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
165                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
166 
167                 EXPECT_TRUE(bb->GetFirstInst()->IsTry());
168                 continue;
169             }
170 
171             if (bb->IsTry()) {
172                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
173                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
174                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
175 
176                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
177                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
178                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
179                             RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
180                 continue;
181             }
182 
183             if (bb->IsTryEnd()) {
184                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
185                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
186                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
187                 EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
188                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatch());
189                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatchBegin());
190                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
191                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
192 
193                 EXPECT_TRUE(bb->IsEmpty());
194                 continue;
195             }
196 
197             if (bb->IsCatchBegin()) {
198                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
199                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
200                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
201                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
202 
203                 EXPECT_TRUE(bb->IsEmpty());
204                 continue;
205             }
206 
207             if (bb->IsCatch() && !bb->IsCatchBegin()) {
208                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
209                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
210 
211                 EXPECT_TRUE(bb->GetSuccessor(0)->GetFirstInst()->IsSaveState());
212                 EXPECT_TRUE(bb->GetSuccessor(0)->GetLastInst()->IsIntrinsic());
213                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetSuccessor(0)->GetLastInst()))->GetIntrinsicId() ==
214                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
215 
216                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
217                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
218                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
219                             RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
220                 continue;
221             }
222         }
223     });
224 }
225 
226 HWTEST_F(IrBuilderTest, nestedTryCatchAsm, testing::ext::TestSize.Level1)
227 {
228     /**
229      *  try {
230      *      try {
231      *          a = 1;
232      *      } catch(e) {
233      *          a;
234      *      }
235      *  } catch(e) {
236      *      print(e);
237      *  }
238      */
239     const auto source = R"(
240         .language ECMAScript
241         .function any foo(any a0, any a1, any a2) {
242             mov v2, a2
243             mov v1, a1
244             mov v0, a0
245             lda.str "use strict"
246         LABEL_0:
247         LABEL_1:
248             ldai 1
249             trystglobalbyname 0, "a"
250         LABEL_2:
251             jmp LABEL_3
252         LABEL_4:
253             sta v3
254             tryldglobalbyname 1, "a"
255         LABEL_3:
256         LABEL_5:
257             jmp LABEL_6
258         LABEL_7:
259             sta v4
260             tryldglobalbyname 2, "print"
261             sta v5
262             lda v4
263             sta v6
264             lda v5
265             callarg1 3, v6
266         LABEL_6:
267             returnundefined
268         }
269     )";
270 
271     panda::pandasm::Parser parser;
272     auto res = parser.Parse(source);
273     auto &prog = res.Value();
274     EXPECT_TRUE(prog.function_table.size() == 1);
275     for (auto &[name, func] : prog.function_table) {
276         auto &catchBlock1 = func.catch_blocks.emplace_back();
277         catchBlock1.try_begin_label = "LABEL_0";
278         catchBlock1.try_end_label = "LABEL_1";
279         catchBlock1.catch_begin_label = "LABEL_7";
280         catchBlock1.catch_end_label = "LABEL_6";
281 
282         auto &catchBlock2 = func.catch_blocks.emplace_back();
283         catchBlock2.try_begin_label = "LABEL_1";
284         catchBlock2.try_end_label = "LABEL_2";
285         catchBlock2.catch_begin_label = "LABEL_4";
286         catchBlock2.catch_end_label = "LABEL_3";
287 
288         auto &catchBlock3 = func.catch_blocks.emplace_back();
289         catchBlock3.try_begin_label = "LABEL_2";
290         catchBlock3.try_end_label = "LABEL_5";
291         catchBlock3.catch_begin_label = "LABEL_7";
292         catchBlock3.catch_end_label = "LABEL_6";
293     }
294 
__anon4126c63d0402(Graph* graph) 295     TestBuildGraphFromFunc(prog, "foo:(any,any,any)", [](Graph* graph) {
296         EXPECT_NE(graph, nullptr);
297         int32_t numOfTry = 0;
298         for (auto bb : graph->GetBlocksRPO()) {
299             EXPECT_NE(bb, nullptr);
300             if (bb->IsTryBegin()) {
301                 numOfTry++;
302 
303                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
304 
305                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
306                 EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
307                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
308                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
309 
310                 EXPECT_TRUE(bb->GetSuccessor(0)->GetTryId() == bb->GetTryId());
311                 continue;
312             }
313 
314             if (bb->IsTry()) {
315                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
316                 if (!bb->GetPredecessor(0)->IsTryBegin()) {
317                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
318                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
319 
320                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
321                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
322                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
323                                 RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
324                     continue;
325                 }
326 
327 
328                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
329                 EXPECT_TRUE(bb->GetPredecessor(0)->GetGuestPc() == bb->GetGuestPc());
330                 if (bb->GetPredecessor(0)->GetTryId() == 1) {
331                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
332                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
333 
334                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
335                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
336                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
337                                 RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
338                     continue;
339                 }
340 
341                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == 2);
342                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
343                 EXPECT_TRUE(bb->IsEmpty());
344 
345                 for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
346                     EXPECT_TRUE(inst->IsPhi());
347                 }
348                 continue;
349             }
350 
351             if (bb->IsTryEnd()) {
352                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
353                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
354                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
355 
356                 EXPECT_TRUE(bb->IsEmpty());
357 
358                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
359                 if (bb->GetTryId() == 1) {
360                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryBegin());
361                     EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
362 
363                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
364                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
365 
366                     for (auto inst : bb->GetSuccessor(1)->AllInsts()) {
367                         EXPECT_TRUE(inst->IsCatchPhi());
368                     }
369                     continue;
370                 }
371 
372                 EXPECT_TRUE(bb->GetTryId() == 2);
373                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
374                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
375                 for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
376                     EXPECT_TRUE(inst->IsPhi());
377                 }
378                 continue;
379             }
380 
381             if (bb->IsCatchBegin()) {
382                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
383                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
384                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
385 
386                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
387                 continue;
388             }
389 
390             if (bb->IsCatch() && !bb->IsCatchBegin()) {
391                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
392 
393                 if (bb->IsTry()) {
394                     EXPECT_TRUE(bb->GetTryId() == 2);
395 
396                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
397                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
398                     EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
399 
400                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
401                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
402                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
403                                 RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
404                     continue;
405                 }
406 
407                 if (bb->IsTryEnd()) {
408                     EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
409                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
410 
411                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
412                     for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
413                         EXPECT_TRUE(inst->IsPhi());
414                     }
415                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
416                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
417 
418                     EXPECT_TRUE(bb->IsEmpty());
419                     continue;
420                 }
421 
422                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
423                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
424 
425                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
426                 auto *successor = bb->GetSuccessor(0);
427                 EXPECT_TRUE(successor->GetFirstInst()->IsSaveState());
428                 EXPECT_TRUE(successor->GetLastInst()->IsIntrinsic());
429                 EXPECT_TRUE((static_cast<IntrinsicInst *>(successor->GetLastInst()))->GetIntrinsicId() ==
430                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
431                 for (auto inst : successor->GetPredecessor(0)->AllInsts()) {
432                     EXPECT_TRUE(inst->IsPhi());
433                 }
434 
435                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
436                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
437                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
438                             RuntimeInterface::IntrinsicId::CALLARG1_IMM8_V8);
439             }
440         }
441 
442         EXPECT_EQ(numOfTry, 2);
443     });
444 }
445 
446 HWTEST_F(IrBuilderTest, simpleTryCatchAbc, testing::ext::TestSize.Level1)
447 {
448     std::string pFile = GRAPH_TEST_ABC_DIR "simpleTryCatch.abc";
449     const char *testMethodName = "func_main_0";
__anon4126c63d0502(Graph* graph, std::string &methodName) 450     TestBuildGraphFromFile(pFile, [&testMethodName](Graph* graph, std::string &methodName) {
451         if (testMethodName != methodName) {
452             return;
453         }
454 
455         EXPECT_NE(graph, nullptr);
456         for (auto bb : graph->GetBlocksRPO()) {
457             EXPECT_NE(bb, nullptr);
458             if (bb->IsTryBegin()) {
459                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
460                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
461                 EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
462                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
463                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
464 
465                 EXPECT_TRUE(bb->GetFirstInst()->IsTry());
466                 continue;
467             }
468 
469             if (bb->IsTry()) {
470                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
471                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
472                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
473 
474                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
475                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
476                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
477                             RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
478                 continue;
479             }
480 
481             if (bb->IsTryEnd()) {
482                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
483                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
484                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
485                 EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
486                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatch());
487                 EXPECT_TRUE(!bb->GetSuccessor(0)->IsCatchBegin());
488                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
489                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
490 
491                 EXPECT_TRUE(bb->IsEmpty());
492                 continue;
493             }
494 
495             if (bb->IsCatchBegin()) {
496                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
497                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
498                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
499                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
500 
501                 EXPECT_TRUE(bb->IsEmpty());
502                 continue;
503             }
504 
505             if (bb->IsCatch() && !bb->IsCatchBegin()) {
506                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
507                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
508 
509                 EXPECT_TRUE(bb->GetSuccessor(0)->GetFirstInst()->IsSaveState());
510                 EXPECT_TRUE(bb->GetSuccessor(0)->GetLastInst()->IsIntrinsic());
511                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetSuccessor(0)->GetLastInst()))->GetIntrinsicId() ==
512                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
513 
514                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
515                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
516                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
517                             RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
518                 continue;
519             }
520         }
521     });
522 }
523 
524 HWTEST_F(IrBuilderTest, nestedTryCatchAbc, testing::ext::TestSize.Level1)
525 {
526     std::string pFile = GRAPH_TEST_ABC_DIR "nestedTryCatch.abc";
527     const char *testMethodName = "func_main_0";
__anon4126c63d0602(Graph* graph, std::string &methodName) 528     TestBuildGraphFromFile(pFile, [testMethodName](Graph* graph, std::string &methodName) {
529         if (testMethodName != methodName) {
530             return;
531         }
532 
533         EXPECT_NE(graph, nullptr);
534         int32_t numOfTry = 0;
535         for (auto bb : graph->GetBlocksRPO()) {
536             EXPECT_NE(bb, nullptr);
537             if (bb->IsTryBegin()) {
538                 numOfTry++;
539 
540                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
541 
542                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
543 
544                 if (bb->GetTryId() == 0) {
545                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
546                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
547                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
548                     EXPECT_TRUE(bb->GetSuccessor(0)->GetTryId() == bb->GetTryId());
549                 }
550 
551                 if (bb->GetTryId() == 1) {
552                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryBegin());
553                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
554                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
555                 }
556 
557                 continue;
558             }
559 
560             if (bb->IsTry()) {
561                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
562                 if (bb->GetPredecessor(0)->IsTryBegin()) {
563                     EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
564                     EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == 0);
565                     EXPECT_TRUE(bb->GetPredecessor(0)->GetGuestPc() == bb->GetGuestPc());
566 
567                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
568                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
569 
570                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
571                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
572                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
573                                 RuntimeInterface::IntrinsicId::TRYSTGLOBALBYNAME_IMM8_ID16);
574                     continue;
575                 }
576 
577                 if (bb->GetPredecessor(0)->IsTryEnd()) {
578                     EXPECT_FALSE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
579                     EXPECT_TRUE(bb->GetPredecessor(0)->GetGuestPc() == bb->GetGuestPc());
580 
581                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
582                     for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
583                         EXPECT_TRUE(inst->IsPhi());
584                     }
585                     continue;
586                 }
587 
588                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
589                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
590 
591                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
592                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
593 
594                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
595                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
596                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
597                             RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
598                 continue;
599             }
600 
601             if (bb->IsTryEnd()) {
602                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
603                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
604                 EXPECT_TRUE(bb->GetPredecessor(0)->GetTryId() == bb->GetTryId());
605 
606                 EXPECT_TRUE(bb->IsEmpty());
607 
608                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
609                 if (bb->GetTryId() == 0) {
610                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTry());
611                     EXPECT_TRUE(bb->GetSuccessor(0)->GetGuestPc() == bb->GetGuestPc());
612 
613                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
614                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
615 
616                     for (auto inst : bb->GetSuccessor(1)->AllInsts()) {
617                         EXPECT_TRUE(inst->IsCatchPhi());
618                     }
619                     continue;
620                 }
621 
622                 EXPECT_TRUE(bb->GetTryId() == 1);
623                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
624                 EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
625                 for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
626                     EXPECT_TRUE(inst->IsPhi());
627                 }
628                 continue;
629             }
630 
631             if (bb->IsCatchBegin()) {
632                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 2);
633                 EXPECT_TRUE(bb->GetPredecessor(0)->IsTryBegin());
634                 EXPECT_TRUE(bb->GetPredecessor(1)->IsTryEnd());
635 
636                 EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
637                 continue;
638             }
639 
640             if (bb->IsCatch() && !bb->IsCatchBegin()) {
641                 EXPECT_TRUE(bb->GetPredsBlocks().size() == 1);
642 
643                 if (bb->IsTry()) {
644                     EXPECT_TRUE(bb->GetTryId() == 2);
645 
646                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
647                     EXPECT_TRUE(bb->GetSuccessor(0)->IsTryEnd());
648                     EXPECT_TRUE(bb->GetSuccessor(0)->IsCatch());
649 
650                     EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
651                     EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
652                     EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
653                                 RuntimeInterface::IntrinsicId::TRYLDGLOBALBYNAME_IMM8_ID16);
654                     continue;
655                 }
656 
657                 if (bb->IsTryEnd()) {
658                     EXPECT_TRUE(bb->GetPredecessor(0)->IsTry());
659                     EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
660 
661                     EXPECT_TRUE(bb->GetSuccsBlocks().size() == 2);
662                     for (auto inst : bb->GetSuccessor(0)->AllInsts()) {
663                         EXPECT_TRUE(inst->IsPhi());
664                     }
665                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatchBegin());
666                     EXPECT_TRUE(bb->GetSuccessor(1)->IsCatch());
667 
668                     EXPECT_TRUE(bb->IsEmpty());
669                     continue;
670                 }
671 
672                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatchBegin());
673                 EXPECT_TRUE(bb->GetPredecessor(0)->IsCatch());
674 
675                 EXPECT_TRUE(bb->GetSuccsBlocks().size() == 1);
676                 auto *successor = bb->GetSuccessor(0);
677                 EXPECT_TRUE(successor->GetFirstInst()->IsSaveState());
678                 EXPECT_TRUE(successor->GetLastInst()->IsIntrinsic());
679                 EXPECT_TRUE((static_cast<IntrinsicInst *>(successor->GetLastInst()))->GetIntrinsicId() ==
680                             RuntimeInterface::IntrinsicId::RETURNUNDEFINED);
681                 for (auto inst : successor->GetPredecessor(0)->AllInsts()) {
682                     EXPECT_TRUE(inst->IsPhi());
683                 }
684 
685                 EXPECT_TRUE(bb->GetFirstInst()->IsSaveState());
686                 EXPECT_TRUE(bb->GetLastInst()->IsIntrinsic());
687                 EXPECT_TRUE((static_cast<IntrinsicInst *>(bb->GetLastInst()))->GetIntrinsicId() ==
688                             RuntimeInterface::IntrinsicId::CALLARG1_IMM8_V8);
689             }
690         }
691 
692         EXPECT_EQ(numOfTry, 2);
693     });
694 }
695 } // namespace panda::compiler