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#ifndef GRAPH_TEST_H 17#define GRAPH_TEST_H 18 19#include "bytecode_optimizer/ir_interface.h" 20#include "bytecode_optimizer/runtime_adapter.h" 21#include "libpandafile/class_data_accessor.h" 22#include "libpandafile/class_data_accessor-inl.h" 23#include "libpandafile/code_data_accessor-inl.h" 24#include "libpandafile/file.h" 25#include "libpandafile/method_data_accessor.h" 26#include "libpandabase/mem/arena_allocator.h" 27#include "libpandabase/mem/pool_manager.h" 28#include "optimizer/ir/graph.h" 29#include "optimizer/ir/runtime_interface.h" 30#include "optimizer/ir_builder/ir_builder.h" 31 32namespace panda::compiler { 33class GraphTest { 34public: 35 GraphTest() 36 { 37 PoolManager::Initialize(PoolType::MALLOC); 38 } 39 40 ~GraphTest() 41 { 42 PoolManager::Finalize(); 43 } 44 45 static bool HasTryCatch(const panda_file::File &panda_file, panda_file::File::EntityId code_id) 46 { 47 panda_file::CodeDataAccessor cda(panda_file, code_id); 48 return cda.GetTriesSize() != 0; 49 } 50 51 template <class Callback> 52 void TestBuildGraphFromFile(const std::string &pfile_name, const Callback &cb, bool skip_try_catch = false) 53 { 54 auto pfile = panda_file::OpenPandaFile(pfile_name); 55 for (uint32_t id : pfile->GetClasses()) { 56 panda_file::File::EntityId record_id {id}; 57 if (pfile->IsExternal(record_id)) { 58 continue; 59 } 60 61 panda_file::ClassDataAccessor cda {*pfile, record_id}; 62 cda.EnumerateMethods([&pfile, &cb, &skip_try_catch](panda_file::MethodDataAccessor &mda) { 63 if (mda.IsExternal()) { 64 return; 65 } 66 67 // `skip_try_catch` is required for tests like draw_cfg_test. Currently try-catch optimizations 68 // are disabled, and building graphs directly from abc files containing try-catch blocks may fail. 69 if (skip_try_catch && HasTryCatch(*pfile, mda.GetCodeId().value())) { 70 return; 71 } 72 73 ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER}; 74 ArenaAllocator local_allocator {SpaceType::SPACE_TYPE_COMPILER, nullptr, true}; 75 76 auto method_ptr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>( 77 mda.GetMethodId().GetOffset()); 78 panda::BytecodeOptimizerRuntimeAdapter adapter(mda.GetPandaFile()); 79 auto *graph = allocator.New<Graph>(&allocator, &local_allocator, Arch::NONE, method_ptr, &adapter, 80 false, nullptr, true, true); 81 graph->RunPass<panda::compiler::IrBuilder>(); 82 83 auto method_name = std::string(utf::Mutf8AsCString(pfile->GetStringData(mda.GetNameId()).data)); 84 auto pos = method_name.find_last_of("#"); 85 if (pos != std::string::npos) { 86 method_name = method_name.substr(pos + 1); 87 } 88 cb(graph, method_name); 89 }); 90 } 91 } 92}; 93 94} // namespace panda::compiler 95 96#endif // GRAPH_TEST_H