1 /** 2 * Copyright (c) 2021-2022 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 ES2PANDA_COMPILER_CORE_REG_ALLOCATOR_H 17 #define ES2PANDA_COMPILER_CORE_REG_ALLOCATOR_H 18 19 #include <gen/isa.h> 20 #include <lexer/token/sourceLocation.h> 21 #include <macros.h> 22 23 namespace panda::es2panda::ir { 24 class AstNode; 25 } // namespace panda::es2panda::ir 26 27 namespace panda::es2panda::compiler { 28 29 class PandaGen; 30 31 class RegAllocator { 32 public: RegAllocator(PandaGen *pg)33 explicit RegAllocator(PandaGen *pg) 34 : pg_(pg), sourceLocationFlag_(lexer::SourceLocationFlag::VALID_SOURCE_LOCATION) 35 { 36 } 37 NO_COPY_SEMANTIC(RegAllocator); 38 NO_MOVE_SEMANTIC(RegAllocator); 39 ~RegAllocator() = default; 40 SetSourceLocationFlag(lexer::SourceLocationFlag flag)41 void SetSourceLocationFlag(lexer::SourceLocationFlag flag) 42 { 43 sourceLocationFlag_ = flag; 44 } 45 GetSourceLocationFlag() const46 lexer::SourceLocationFlag GetSourceLocationFlag() const 47 { 48 return sourceLocationFlag_; 49 } 50 51 ArenaAllocator *Allocator() const; 52 bool HasSpill() const; 53 uint16_t GetSpillRegsCount() const; 54 55 void AdjustInsRegWhenHasSpill(); 56 57 Label *AllocLabel(std::string &&id); AddLabel(Label *label)58 void AddLabel(Label *label) 59 { 60 PushBack(label); 61 } 62 63 template <typename T, typename... Args> Emit(const ir::AstNode *node, Args &&... args)64 void Emit(const ir::AstNode *node, Args &&... args) 65 { 66 auto *ins = Alloc<T>(node, std::forward<Args>(args)...); 67 Run(ins); 68 } 69 70 template <typename T, typename... Args> EmitRange(const ir::AstNode *node, size_t argCount, Args &&... args)71 void EmitRange(const ir::AstNode *node, size_t argCount, Args &&... args) 72 { 73 auto *ins = Alloc<T>(node, std::forward<Args>(args)...); 74 Run(ins, argCount); 75 } 76 77 private: CheckRegIndices(IRNode *ins, const Span<VReg *> ®isters, std::vector<OperandKind> *regsKind = nullptr)78 bool CheckRegIndices(IRNode *ins, const Span<VReg *> ®isters, 79 std::vector<OperandKind> *regsKind = nullptr) 80 { 81 CHECK_NOT_NULL(ins); 82 Formats formats = ins->GetFormats(); 83 84 for (const auto &format : formats) { 85 limit_ = 0; 86 for (const auto &formatItem : format.GetFormatItem()) { 87 if (regsKind && formatItem.IsVReg()) { 88 regsKind->push_back(formatItem.Kind()); 89 } 90 91 if (formatItem.IsVReg() && limit_ == 0) { 92 limit_ = 1 << formatItem.Bitwidth(); 93 } 94 } 95 96 if (std::all_of(registers.begin(), registers.end(), 97 [this](const VReg *reg) { return IsRegisterCorrect(reg); })) { 98 return true; 99 } 100 } 101 return false; 102 } 103 IsRegisterCorrect(const VReg *reg) const104 inline bool IsRegisterCorrect(const VReg *reg) const 105 { 106 return *reg < limit_; 107 } 108 FreeSpill()109 inline void FreeSpill() 110 { 111 spillIndex_ = 0; 112 } 113 114 void PushBack(IRNode *ins); 115 void UpdateIcSlot(IRNode *node); 116 void Run(IRNode *ins); 117 void Run(IRNode *ins, size_t argCount); 118 void AdjustInsSpill(const Span<VReg *> ®isters, IRNode *ins, ArenaList<IRNode *> &newInsns, 119 const std::vector<OperandKind> ®sKind); 120 void AdjustRangeInsSpill(Span<VReg *> ®isters, IRNode *ins, ArenaList<IRNode *> &newInsns); 121 122 template <typename T, typename... Args> Alloc(const ir::AstNode *node, Args &&... args)123 T *Alloc(const ir::AstNode *node, Args &&... args) 124 { 125 ir::AstNode *invalidNode = nullptr; 126 bool isInvalid = GetSourceLocationFlag() == lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION; 127 auto *ret = Allocator()->New<T>(isInvalid ? invalidNode : node, std::forward<Args>(args)...); 128 UpdateIcSlot(ret); 129 return ret; 130 } 131 132 template <typename T, typename... Args> Add(ArenaList<IRNode *> &insns, const ir::AstNode *node, Args &&... args)133 void Add(ArenaList<IRNode *> &insns, const ir::AstNode *node, Args &&... args) 134 { 135 insns.push_back(Alloc<T>(node, std::forward<Args>(args)...)); 136 } 137 138 PandaGen *pg_; 139 lexer::SourceLocationFlag sourceLocationFlag_; // for instructions that need to be set with invalid debuginfo 140 size_t limit_ {0}; 141 uint16_t spillRegs_ {0}; 142 VReg spillIndex_ {0}; 143 bool hasSpill_ {false}; 144 std::vector<std::pair<VReg, VReg>> dstRegSpills_ {}; 145 }; 146 147 class FrontAllocator { 148 public: 149 explicit FrontAllocator(PandaGen *pg); 150 NO_COPY_SEMANTIC(FrontAllocator); 151 NO_MOVE_SEMANTIC(FrontAllocator); 152 ~FrontAllocator(); 153 154 private: 155 PandaGen *pg_; 156 ArenaList<IRNode *> insn_; 157 }; 158 } // namespace panda::es2panda::compiler 159 160 #endif 161