• 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     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 *> &registers,
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 *> &registers, IRNode *ins, ArenaList<IRNode *> &newInsns,
126                         const std::vector<OperandKind> &regsKind);
127     void AdjustRangeInsSpill(Span<VReg *> &registers, 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