1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#ifndef COMPILER_TESTS_UNIT_TEST_H 17b1994897Sopenharmony_ci#define COMPILER_TESTS_UNIT_TEST_H 18b1994897Sopenharmony_ci 19b1994897Sopenharmony_ci#include <numeric> 20b1994897Sopenharmony_ci#include <unordered_map> 21b1994897Sopenharmony_ci#include "gtest/gtest.h" 22b1994897Sopenharmony_ci#include "optimizer/ir/ir_constructor.h" 23b1994897Sopenharmony_ci#include "mem/arena_allocator.h" 24b1994897Sopenharmony_ci#include "mem/pool_manager.h" 25b1994897Sopenharmony_ci#include "compiler.h" 26b1994897Sopenharmony_ci#include "compiler_logger.h" 27b1994897Sopenharmony_ci#include "graph_comparator.h" 28b1994897Sopenharmony_ci#include "include/runtime.h" 29b1994897Sopenharmony_ci 30b1994897Sopenharmony_cinamespace panda::compiler { 31b1994897Sopenharmony_cistruct RuntimeInterfaceMock : public compiler::RuntimeInterface { 32b1994897Sopenharmony_ci DataType::Type GetMethodReturnType(MethodPtr /* unsuded */) const override 33b1994897Sopenharmony_ci { 34b1994897Sopenharmony_ci return return_type; 35b1994897Sopenharmony_ci } 36b1994897Sopenharmony_ci 37b1994897Sopenharmony_ci DataType::Type GetMethodTotalArgumentType(MethodPtr /* unused */, size_t index) const override 38b1994897Sopenharmony_ci { 39b1994897Sopenharmony_ci if (arg_types == nullptr || index >= arg_types->size()) { 40b1994897Sopenharmony_ci return DataType::NO_TYPE; 41b1994897Sopenharmony_ci } 42b1994897Sopenharmony_ci return arg_types->at(index); 43b1994897Sopenharmony_ci } 44b1994897Sopenharmony_ci 45b1994897Sopenharmony_ci size_t GetMethodTotalArgumentsCount(MethodPtr /* unused */) const override 46b1994897Sopenharmony_ci { 47b1994897Sopenharmony_ci if (arg_types == nullptr) { 48b1994897Sopenharmony_ci return args_count; 49b1994897Sopenharmony_ci } 50b1994897Sopenharmony_ci return arg_types->size(); 51b1994897Sopenharmony_ci } 52b1994897Sopenharmony_ci size_t GetMethodArgumentsCount(MethodPtr /* unused */) const override 53b1994897Sopenharmony_ci { 54b1994897Sopenharmony_ci return args_count; 55b1994897Sopenharmony_ci } 56b1994897Sopenharmony_ci 57b1994897Sopenharmony_ci size_t GetMethodRegistersCount(MethodPtr /* unused */) const override 58b1994897Sopenharmony_ci { 59b1994897Sopenharmony_ci return vregs_count; 60b1994897Sopenharmony_ci } 61b1994897Sopenharmony_ci 62b1994897Sopenharmony_ci size_t args_count {0}; 63b1994897Sopenharmony_ci size_t vregs_count {0}; 64b1994897Sopenharmony_ci DataType::Type return_type {DataType::NO_TYPE}; 65b1994897Sopenharmony_ci ArenaVector<DataType::Type> *arg_types {nullptr}; 66b1994897Sopenharmony_ci}; 67b1994897Sopenharmony_ci 68b1994897Sopenharmony_ciclass CommonTest : public ::testing::Test { 69b1994897Sopenharmony_cipublic: 70b1994897Sopenharmony_ci CommonTest() 71b1994897Sopenharmony_ci { 72b1994897Sopenharmony_ci#if defined(PANDA_TARGET_ARM64) || defined(PANDA_TARGET_32) 73b1994897Sopenharmony_ci // We have issue with QEMU - so reduce memory heap 74b1994897Sopenharmony_ci panda::mem::MemConfig::Initialize(32_MB, 64_MB, 200_MB, 32_MB); 75b1994897Sopenharmony_ci#else 76b1994897Sopenharmony_ci panda::mem::MemConfig::Initialize(32_MB, 64_MB, 256_MB, 32_MB); 77b1994897Sopenharmony_ci#endif 78b1994897Sopenharmony_ci PoolManager::Initialize(); 79b1994897Sopenharmony_ci allocator_ = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER); 80b1994897Sopenharmony_ci object_allocator_ = new ArenaAllocator(SpaceType::SPACE_TYPE_OBJECT); 81b1994897Sopenharmony_ci local_allocator_ = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER); 82b1994897Sopenharmony_ci builder_ = new IrConstructor(); 83b1994897Sopenharmony_ci } 84b1994897Sopenharmony_ci ~CommonTest() override; 85b1994897Sopenharmony_ci 86b1994897Sopenharmony_ci ArenaAllocator *GetAllocator() const 87b1994897Sopenharmony_ci { 88b1994897Sopenharmony_ci return allocator_; 89b1994897Sopenharmony_ci } 90b1994897Sopenharmony_ci 91b1994897Sopenharmony_ci ArenaAllocator *GetObjectAllocator() const 92b1994897Sopenharmony_ci { 93b1994897Sopenharmony_ci return object_allocator_; 94b1994897Sopenharmony_ci } 95b1994897Sopenharmony_ci 96b1994897Sopenharmony_ci ArenaAllocator *GetLocalAllocator() const 97b1994897Sopenharmony_ci { 98b1994897Sopenharmony_ci return local_allocator_; 99b1994897Sopenharmony_ci } 100b1994897Sopenharmony_ci 101b1994897Sopenharmony_ci Arch GetArch() const 102b1994897Sopenharmony_ci { 103b1994897Sopenharmony_ci return arch_; 104b1994897Sopenharmony_ci } 105b1994897Sopenharmony_ci 106b1994897Sopenharmony_ci Graph *CreateEmptyGraph(bool is_osr = false) const 107b1994897Sopenharmony_ci { 108b1994897Sopenharmony_ci return GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_, is_osr); 109b1994897Sopenharmony_ci } 110b1994897Sopenharmony_ci 111b1994897Sopenharmony_ci Graph *CreateEmptyGraph(Arch arch) const 112b1994897Sopenharmony_ci { 113b1994897Sopenharmony_ci return GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch, false); 114b1994897Sopenharmony_ci } 115b1994897Sopenharmony_ci 116b1994897Sopenharmony_ci Graph *CreateGraphStartEndBlocks(bool is_dynamic = false) const 117b1994897Sopenharmony_ci { 118b1994897Sopenharmony_ci auto graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_, is_dynamic, false); 119b1994897Sopenharmony_ci graph->CreateStartBlock(); 120b1994897Sopenharmony_ci graph->CreateEndBlock(); 121b1994897Sopenharmony_ci return graph; 122b1994897Sopenharmony_ci } 123b1994897Sopenharmony_ci Graph *CreateDynEmptyGraph() const 124b1994897Sopenharmony_ci { 125b1994897Sopenharmony_ci return GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_, true, false); 126b1994897Sopenharmony_ci } 127b1994897Sopenharmony_ci Graph *CreateEmptyBytecodeGraph() const 128b1994897Sopenharmony_ci { 129b1994897Sopenharmony_ci return GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), Arch::NONE, false, true); 130b1994897Sopenharmony_ci } 131b1994897Sopenharmony_ci Graph *CreateEmptyFastpathGraph(Arch arch) const 132b1994897Sopenharmony_ci { 133b1994897Sopenharmony_ci auto graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch, false); 134b1994897Sopenharmony_ci graph->SetMode(GraphMode::FastPath()); 135b1994897Sopenharmony_ci return graph; 136b1994897Sopenharmony_ci } 137b1994897Sopenharmony_ci 138b1994897Sopenharmony_ci BasicBlock *CreateEmptyBlock(Graph *graph) const 139b1994897Sopenharmony_ci { 140b1994897Sopenharmony_ci auto block = graph->GetAllocator()->New<BasicBlock>(graph); 141b1994897Sopenharmony_ci graph->AddBlock(block); 142b1994897Sopenharmony_ci return block; 143b1994897Sopenharmony_ci } 144b1994897Sopenharmony_ci 145b1994897Sopenharmony_ci ArenaVector<BasicBlock *> GetBlocksById(Graph *graph, std::vector<size_t> &&ids) const 146b1994897Sopenharmony_ci { 147b1994897Sopenharmony_ci ArenaVector<BasicBlock *> blocks(graph->GetAllocator()->Adapter()); 148b1994897Sopenharmony_ci for (auto id : ids) { 149b1994897Sopenharmony_ci blocks.push_back(&BB(id)); 150b1994897Sopenharmony_ci } 151b1994897Sopenharmony_ci return blocks; 152b1994897Sopenharmony_ci } 153b1994897Sopenharmony_ci 154b1994897Sopenharmony_ci bool CheckInputs(Inst &inst, std::initializer_list<size_t> list) const 155b1994897Sopenharmony_ci { 156b1994897Sopenharmony_ci if (inst.GetInputs().Size() != list.size()) { 157b1994897Sopenharmony_ci return false; 158b1994897Sopenharmony_ci } 159b1994897Sopenharmony_ci auto it2 = list.begin(); 160b1994897Sopenharmony_ci for (auto it = inst.GetInputs().begin(); it != inst.GetInputs().end(); ++it, ++it2) { 161b1994897Sopenharmony_ci if (it->GetInst() != &INS(*it2)) { 162b1994897Sopenharmony_ci return false; 163b1994897Sopenharmony_ci } 164b1994897Sopenharmony_ci } 165b1994897Sopenharmony_ci return true; 166b1994897Sopenharmony_ci } 167b1994897Sopenharmony_ci 168b1994897Sopenharmony_ci bool CheckUsers(Inst &inst, std::initializer_list<int> list) const 169b1994897Sopenharmony_ci { 170b1994897Sopenharmony_ci std::unordered_map<int, size_t> users_map; 171b1994897Sopenharmony_ci for (auto l : list) 172b1994897Sopenharmony_ci ++users_map[l]; 173b1994897Sopenharmony_ci for (auto &user : inst.GetUsers()) { 174b1994897Sopenharmony_ci EXPECT_EQ(user.GetInst()->GetInput(user.GetIndex()).GetInst(), &inst); 175b1994897Sopenharmony_ci if (users_map[user.GetInst()->GetId()]-- == 0) 176b1994897Sopenharmony_ci return false; 177b1994897Sopenharmony_ci } 178b1994897Sopenharmony_ci auto rest = std::accumulate(users_map.begin(), users_map.end(), 0, [](int a, auto &x) { return a + x.second; }); 179b1994897Sopenharmony_ci EXPECT_EQ(rest, 0); 180b1994897Sopenharmony_ci return (rest == 0) ? true : false; 181b1994897Sopenharmony_ci } 182b1994897Sopenharmony_ci 183b1994897Sopenharmony_ciprotected: 184b1994897Sopenharmony_ci IrConstructor *builder_; 185b1994897Sopenharmony_ci 186b1994897Sopenharmony_ciprivate: 187b1994897Sopenharmony_ci ArenaAllocator *allocator_; 188b1994897Sopenharmony_ci ArenaAllocator *object_allocator_; 189b1994897Sopenharmony_ci ArenaAllocator *local_allocator_; 190b1994897Sopenharmony_ci#ifdef PANDA_TARGET_ARM32 191b1994897Sopenharmony_ci Arch arch_ {Arch::AARCH32}; 192b1994897Sopenharmony_ci#else 193b1994897Sopenharmony_ci Arch arch_ {Arch::AARCH64}; 194b1994897Sopenharmony_ci#endif 195b1994897Sopenharmony_ci}; 196b1994897Sopenharmony_ci 197b1994897Sopenharmony_ciclass GraphTest : public CommonTest { 198b1994897Sopenharmony_cipublic: 199b1994897Sopenharmony_ci GraphTest() : graph_(CreateEmptyGraph()) 200b1994897Sopenharmony_ci { 201b1994897Sopenharmony_ci graph_->SetRuntime(&runtime_); 202b1994897Sopenharmony_ci } 203b1994897Sopenharmony_ci ~GraphTest() override {} 204b1994897Sopenharmony_ci 205b1994897Sopenharmony_ci Graph *GetGraph() const 206b1994897Sopenharmony_ci { 207b1994897Sopenharmony_ci return graph_; 208b1994897Sopenharmony_ci } 209b1994897Sopenharmony_ci 210b1994897Sopenharmony_ci void ResetGraph() 211b1994897Sopenharmony_ci { 212b1994897Sopenharmony_ci graph_ = CreateEmptyGraph(); 213b1994897Sopenharmony_ci graph_->SetRuntime(&runtime_); 214b1994897Sopenharmony_ci } 215b1994897Sopenharmony_ci 216b1994897Sopenharmony_ci void SetNumVirtRegs(size_t num) 217b1994897Sopenharmony_ci { 218b1994897Sopenharmony_ci runtime_.vregs_count = num; 219b1994897Sopenharmony_ci graph_->SetVRegsCount(std::max(graph_->GetVRegsCount(), runtime_.vregs_count + runtime_.args_count + 1)); 220b1994897Sopenharmony_ci } 221b1994897Sopenharmony_ci 222b1994897Sopenharmony_ci void SetNumArgs(size_t num) 223b1994897Sopenharmony_ci { 224b1994897Sopenharmony_ci runtime_.args_count = num; 225b1994897Sopenharmony_ci graph_->SetVRegsCount(std::max(graph_->GetVRegsCount(), runtime_.vregs_count + runtime_.args_count + 1)); 226b1994897Sopenharmony_ci } 227b1994897Sopenharmony_ci 228b1994897Sopenharmony_ciprotected: 229b1994897Sopenharmony_ci RuntimeInterfaceMock runtime_; 230b1994897Sopenharmony_ci Graph *graph_ {nullptr}; 231b1994897Sopenharmony_ci}; 232b1994897Sopenharmony_ci 233b1994897Sopenharmony_ciclass PandaRuntimeTest : public ::testing::Test, public PandaRuntimeInterface { 234b1994897Sopenharmony_cipublic: 235b1994897Sopenharmony_ci PandaRuntimeTest(); 236b1994897Sopenharmony_ci 237b1994897Sopenharmony_ci ~PandaRuntimeTest() override; 238b1994897Sopenharmony_ci 239b1994897Sopenharmony_ci static void Initialize(int argc, char **argv); 240b1994897Sopenharmony_ci 241b1994897Sopenharmony_ci Graph *CreateGraph() 242b1994897Sopenharmony_ci { 243b1994897Sopenharmony_ci auto graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_); 244b1994897Sopenharmony_ci graph->SetRuntime(this); 245b1994897Sopenharmony_ci return graph; 246b1994897Sopenharmony_ci } 247b1994897Sopenharmony_ci 248b1994897Sopenharmony_ci Graph *CreateGraphOsr() 249b1994897Sopenharmony_ci { 250b1994897Sopenharmony_ci Graph *graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_, true); 251b1994897Sopenharmony_ci graph->SetRuntime(this); 252b1994897Sopenharmony_ci return graph; 253b1994897Sopenharmony_ci } 254b1994897Sopenharmony_ci 255b1994897Sopenharmony_ci // this method is needed to create a graph with a working dump 256b1994897Sopenharmony_ci Graph *CreateGraphWithDefaultRuntime() 257b1994897Sopenharmony_ci { 258b1994897Sopenharmony_ci auto *graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_); 259b1994897Sopenharmony_ci graph->SetRuntime(GetDefaultRuntime()); 260b1994897Sopenharmony_ci return graph; 261b1994897Sopenharmony_ci } 262b1994897Sopenharmony_ci 263b1994897Sopenharmony_ci Graph *CreateGraphDynWithDefaultRuntime() 264b1994897Sopenharmony_ci { 265b1994897Sopenharmony_ci auto *graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_); 266b1994897Sopenharmony_ci graph->SetRuntime(GetDefaultRuntime()); 267b1994897Sopenharmony_ci graph->SetDynamicMethod(); 268b1994897Sopenharmony_ci return graph; 269b1994897Sopenharmony_ci } 270b1994897Sopenharmony_ci 271b1994897Sopenharmony_ci // this method is needed to create a graph with a working dump 272b1994897Sopenharmony_ci Graph *CreateGraphOsrWithDefaultRuntime() 273b1994897Sopenharmony_ci { 274b1994897Sopenharmony_ci auto *graph = GetAllocator()->New<Graph>(GetAllocator(), GetLocalAllocator(), arch_, true); 275b1994897Sopenharmony_ci graph->SetRuntime(GetDefaultRuntime()); 276b1994897Sopenharmony_ci return graph; 277b1994897Sopenharmony_ci } 278b1994897Sopenharmony_ci 279b1994897Sopenharmony_ci ArenaAllocator *GetAllocator() 280b1994897Sopenharmony_ci { 281b1994897Sopenharmony_ci return allocator_; 282b1994897Sopenharmony_ci } 283b1994897Sopenharmony_ci 284b1994897Sopenharmony_ci ArenaAllocator *GetLocalAllocator() 285b1994897Sopenharmony_ci { 286b1994897Sopenharmony_ci return local_allocator_; 287b1994897Sopenharmony_ci } 288b1994897Sopenharmony_ci 289b1994897Sopenharmony_ci virtual Graph *GetGraph() 290b1994897Sopenharmony_ci { 291b1994897Sopenharmony_ci return graph_; 292b1994897Sopenharmony_ci } 293b1994897Sopenharmony_ci 294b1994897Sopenharmony_ci auto GetClassLinker() 295b1994897Sopenharmony_ci { 296b1994897Sopenharmony_ci return panda::Runtime::GetCurrent()->GetClassLinker(); 297b1994897Sopenharmony_ci } 298b1994897Sopenharmony_ci 299b1994897Sopenharmony_ci void EnableLogs(Logger::Level level = Logger::Level::DEBUG) 300b1994897Sopenharmony_ci { 301b1994897Sopenharmony_ci Logger::EnableComponent(Logger::Component::COMPILER); 302b1994897Sopenharmony_ci Logger::SetLevel(level); 303b1994897Sopenharmony_ci } 304b1994897Sopenharmony_ci 305b1994897Sopenharmony_ci const char *GetExecPath() const 306b1994897Sopenharmony_ci { 307b1994897Sopenharmony_ci return exec_path_; 308b1994897Sopenharmony_ci } 309b1994897Sopenharmony_ci 310b1994897Sopenharmony_ci static RuntimeInterface *GetDefaultRuntime(); 311b1994897Sopenharmony_ci 312b1994897Sopenharmony_ciprotected: 313b1994897Sopenharmony_ci IrConstructor *builder_; 314b1994897Sopenharmony_ci 315b1994897Sopenharmony_ciprivate: 316b1994897Sopenharmony_ci Graph *graph_ {nullptr}; 317b1994897Sopenharmony_ci ArenaAllocator *allocator_ {nullptr}; 318b1994897Sopenharmony_ci ArenaAllocator *local_allocator_ {nullptr}; 319b1994897Sopenharmony_ci static inline const char *exec_path_ {nullptr}; 320b1994897Sopenharmony_ci Arch arch_ {RUNTIME_ARCH}; 321b1994897Sopenharmony_ci}; 322b1994897Sopenharmony_ci 323b1994897Sopenharmony_ciclass AsmTest : public PandaRuntimeTest { 324b1994897Sopenharmony_cipublic: 325b1994897Sopenharmony_ci std::unique_ptr<const panda_file::File> ParseToFile(const char *source, const char *file_name = "test.pb"); 326b1994897Sopenharmony_ci bool Parse(const char *source, const char *file_name = "test.pb"); 327b1994897Sopenharmony_ci Graph *BuildGraph(const char *method_name, Graph *graph = nullptr); 328b1994897Sopenharmony_ci void CleanUp(Graph *graph); 329b1994897Sopenharmony_ci 330b1994897Sopenharmony_ci virtual ~AsmTest() = default; 331b1994897Sopenharmony_ci 332b1994897Sopenharmony_ci template <bool with_cleanup = false> 333b1994897Sopenharmony_ci bool ParseToGraph(const char *source, const char *method_name, Graph *graph = nullptr) 334b1994897Sopenharmony_ci { 335b1994897Sopenharmony_ci if (!Parse(source)) { 336b1994897Sopenharmony_ci return false; 337b1994897Sopenharmony_ci } 338b1994897Sopenharmony_ci if (graph == nullptr) { 339b1994897Sopenharmony_ci graph = GetGraph(); 340b1994897Sopenharmony_ci } 341b1994897Sopenharmony_ci if (BuildGraph(method_name, graph) == nullptr) { 342b1994897Sopenharmony_ci return false; 343b1994897Sopenharmony_ci } 344b1994897Sopenharmony_ci if constexpr (with_cleanup) { 345b1994897Sopenharmony_ci CleanUp(graph); 346b1994897Sopenharmony_ci } 347b1994897Sopenharmony_ci return true; 348b1994897Sopenharmony_ci } 349b1994897Sopenharmony_ci}; 350b1994897Sopenharmony_ci 351b1994897Sopenharmony_cistruct TmpFile { 352b1994897Sopenharmony_ci explicit TmpFile(const char *file_name) : file_name_(file_name) {} 353b1994897Sopenharmony_ci ~TmpFile() 354b1994897Sopenharmony_ci { 355b1994897Sopenharmony_ci ASSERT(file_name_ != nullptr); 356b1994897Sopenharmony_ci remove(file_name_); 357b1994897Sopenharmony_ci } 358b1994897Sopenharmony_ci const char *GetFileName() const 359b1994897Sopenharmony_ci { 360b1994897Sopenharmony_ci return file_name_; 361b1994897Sopenharmony_ci } 362b1994897Sopenharmony_ci 363b1994897Sopenharmony_ciprivate: 364b1994897Sopenharmony_ci const char *file_name_ {nullptr}; 365b1994897Sopenharmony_ci}; 366b1994897Sopenharmony_ci} // namespace panda::compiler 367b1994897Sopenharmony_ci 368b1994897Sopenharmony_ci#endif // COMPILER_TESTS_UNIT_TEST_H 369