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 
32 namespace panda::compiler {
33 class GraphTest {
34 public:
GraphTest()35     GraphTest()
36     {
37         PoolManager::Initialize(PoolType::MALLOC);
38     }
39 
~GraphTest()40     ~GraphTest()
41     {
42         PoolManager::Finalize();
43     }
44 
HasTryCatch(const panda_file::File &panda_file, panda_file::File::EntityId code_id)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>
TestBuildGraphFromFile(const std::string &pfile_name, const Callback &cb, bool skip_try_catch = false)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