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