• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *> &registers,
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 *> &registers, IRNode *ins, ArenaList<IRNode *> &newInsns,
125                         const std::vector<OperandKind> &regsKind);
126     void AdjustRangeInsSpill(Span<VReg *> &registers, 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