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 33namespace panda::compiler { 34class IrBuilderTest : public testing::Test { 35public: 36 static void SetUpTestCase(void) {}; 37 static void TearDownTestCase(void) {}; 38 void SetUp() {}; 39 void TearDown() {}; 40 41 IrBuilderTest() 42 { 43 PoolManager::Initialize(PoolType::MALLOC); 44 } 45 46 ~IrBuilderTest() 47 { 48 PoolManager::Finalize(); 49 } 50 51 template <class Callback> 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> 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 117HWTEST_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 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 226HWTEST_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 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 446HWTEST_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"; 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 524HWTEST_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"; 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