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/file.h"
24 #include "libpandafile/method_data_accessor.h"
25 #include "libpandabase/mem/arena_allocator.h"
26 #include "libpandabase/mem/pool_manager.h"
27 #include "optimizer/ir/graph.h"
28 #include "optimizer/ir/runtime_interface.h"
29 #include "optimizer/ir_builder/ir_builder.h"
30 
31 namespace panda::compiler {
32 
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 
45     template <class Callback>
TestBuildGraphFromFile(const std::string &pfile_name, const Callback &cb)46     void TestBuildGraphFromFile(const std::string &pfile_name, const Callback &cb)
47     {
48         auto pfile = panda_file::OpenPandaFile(pfile_name);
49         for (uint32_t id : pfile->GetClasses()) {
50             panda_file::File::EntityId record_id {id};
51             if (pfile->IsExternal(record_id)) {
52                 continue;
53             }
54 
55             panda_file::ClassDataAccessor cda {*pfile, record_id};
56             cda.EnumerateMethods([&pfile, &cb](panda_file::MethodDataAccessor &mda) {
57                 if (!mda.IsExternal()) {
58                     ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER};
59                     ArenaAllocator local_allocator {SpaceType::SPACE_TYPE_COMPILER, nullptr, true};
60 
61                     auto method_ptr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(
62                         mda.GetMethodId().GetOffset());
63                     panda::BytecodeOptimizerRuntimeAdapter adapter(mda.GetPandaFile());
64                     auto *graph = allocator.New<Graph>(&allocator, &local_allocator, Arch::NONE, method_ptr, &adapter,
65                                                         false, nullptr, true, true);
66                     graph->RunPass<panda::compiler::IrBuilder>();
67 
68                     auto method_name = std::string(utf::Mutf8AsCString(pfile->GetStringData(mda.GetNameId()).data));
69                     auto pos = method_name.find_last_of("#");
70                     if (pos != std::string::npos) {
71                         method_name = method_name.substr(pos + 1);
72                     }
73                     cb(graph, method_name);
74                 }
75             });
76         }
77     }
78 
79     template <class Callback>
TestBuildGraphFromFunc(pandasm::Program &prog, const char *method_name, pandasm::AsmEmitter::PandaFileToPandaAsmMaps &maps, bytecodeopt::BytecodeOptIrInterface &ir_interface, const Callback &cb)80     void TestBuildGraphFromFunc(pandasm::Program &prog, const char *method_name,
81         pandasm::AsmEmitter::PandaFileToPandaAsmMaps &maps, bytecodeopt::BytecodeOptIrInterface &ir_interface,
82         const Callback &cb)
83     {
84         auto pfile = pandasm::AsmEmitter::Emit(prog, &maps);
85         for (uint32_t id : pfile->GetClasses()) {
86             panda_file::File::EntityId record_id {id};
87             panda_file::ClassDataAccessor cda {*pfile, record_id};
88             cda.EnumerateMethods([maps, method_name, ir_interface, &cb](panda_file::MethodDataAccessor &mda) {
89                 auto func_name = ir_interface.GetMethodIdByOffset(mda.GetMethodId().GetOffset());
90                 if (func_name != method_name) {
91                     return;
92                 }
93 
94                 ArenaAllocator allocator {SpaceType::SPACE_TYPE_COMPILER};
95                 ArenaAllocator local_allocator {SpaceType::SPACE_TYPE_COMPILER, nullptr, true};
96 
97                 auto method_ptr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(
98                     mda.GetMethodId().GetOffset());
99                 panda::BytecodeOptimizerRuntimeAdapter adapter(mda.GetPandaFile());
100                 auto *graph = allocator.New<Graph>(&allocator, &local_allocator, Arch::NONE, method_ptr, &adapter,
101                                                    false, nullptr, true, true);
102                 graph->RunPass<panda::compiler::IrBuilder>();
103                 cb(graph);
104             });
105         }
106     }
107 };
108 
109 } // namespace panda::compiler
110 
111 #endif  // GRAPH_TEST_H