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