1 /*
2  * Copyright (c) 2023 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 MAPLE_IR_INCLUDE_MIR_PREG_H
17 #define MAPLE_IR_INCLUDE_MIR_PREG_H
18 #if MIR_FEATURE_FULL
19 #include <climits>
20 #include "mir_module.h"
21 #include "global_tables.h"
22 #endif  // MIR_FEATURE_FULL
23 
24 namespace maple {
25 extern void PrintIndentation(int32 indent);
26 
27 // these special registers are encoded by negating the enumeration
28 enum SpecialReg : signed int {
29     kSregSp = 1,
30     kSregFp = 2,
31     kSregRetval0 = 3,
32     kSregRetval1 = 4,
33     kSregRetval2 = 5,
34     kSregRetval3 = 6,
35     kSregLast = 7,
36 };
37 #if MIR_FEATURE_FULL
38 class MIRPreg {
39 public:
MIRPreg(uint32 n = 0)40     explicit MIRPreg(uint32 n = 0) : MIRPreg(n, kPtyInvalid, nullptr) {}
41 
MIRPreg(uint32 n, PrimType ptyp)42     MIRPreg(uint32 n, PrimType ptyp) : primType(ptyp), pregNo(n) {}
43 
MIRPreg(uint32 n, PrimType ptyp, MIRType *mType)44     MIRPreg(uint32 n, PrimType ptyp, MIRType *mType) : primType(ptyp), pregNo(n), mirType(mType) {}
45 
46     ~MIRPreg() = default;
SetNeedRC(bool newNeedRC = true)47     void SetNeedRC(bool newNeedRC = true)
48     {
49         this->needRC = newNeedRC;
50     }
51 
NeedRC() const52     bool NeedRC() const
53     {
54         return needRC;
55     }
56 
IsRef() const57     bool IsRef() const
58     {
59         return mirType != nullptr && primType == PTY_ref;
60     }
61 
GetPrimType() const62     PrimType GetPrimType() const
63     {
64         return primType;
65     }
66 
SetPrimType(PrimType pty)67     void SetPrimType(PrimType pty)
68     {
69         primType = pty;
70     }
71 
GetOp() const72     Opcode GetOp() const
73     {
74         return op;
75     }
76 
SetOp(Opcode o)77     void SetOp(Opcode o)
78     {
79         this->op = o;
80     }
81 
GetPregNo() const82     int32 GetPregNo() const
83     {
84         return pregNo;
85     }
86 
SetPregNo(int32 newPregNo)87     void SetPregNo(int32 newPregNo)
88     {
89         this->pregNo = newPregNo;
90     }
91 
GetMIRType() const92     MIRType *GetMIRType() const
93     {
94         return mirType;
95     }
96 
SetMIRType(MIRType *newMirType)97     void SetMIRType(MIRType *newMirType)
98     {
99         this->mirType = newMirType;
100     }
101 
102 private:
103     PrimType primType = kPtyInvalid;
104     bool needRC = false;
105     Opcode op = OP_undef;  // OP_constval, OP_addrof or OP_dread if rematerializable
106     int32 pregNo;          // the number in maple IR after the %
107     MIRType *mirType = nullptr;
108 
109 public:
110     union RematInfo {
111         const MIRConst *mirConst;  // used only when op is OP_constval
112         const MIRSymbol *sym;      // used only when op is OP_addrof or OP_dread
113     } rematInfo;
114     FieldID fieldID = 0;     // used only when op is OP_addrof or OP_dread
115     bool addrUpper = false;  // used only when op is OP_addrof to indicate upper bits of address
116 };
117 
118 class MIRPregTable {
119 public:
MIRPregTable(MapleAllocator *allocator)120     explicit MIRPregTable(MapleAllocator *allocator)
121         : pregNoToPregIdxMap(allocator->Adapter()), pregTable(allocator->Adapter()), mAllocator(allocator)
122     {
123         pregTable.push_back(nullptr);
124         specPregTable[0].SetPregNo(0);
125         specPregTable[kSregSp].SetPregNo(-kSregSp);
126         specPregTable[kSregFp].SetPregNo(-kSregFp);
127         specPregTable[kSregRetval0].SetPregNo(-kSregRetval0);
128         specPregTable[kSregRetval1].SetPregNo(-kSregRetval1);
129         for (uint32 i = 0; i < kSregLast; ++i) {
130             specPregTable[i].SetPrimType(PTY_unknown);
131         }
132     }
133 
134     ~MIRPregTable();
135 
CreatePreg(PrimType primType, MIRType *mtype = nullptr)136     PregIdx CreatePreg(PrimType primType, MIRType *mtype = nullptr)
137     {
138         DEBUG_ASSERT(!mtype || mtype->GetPrimType() == PTY_ref || mtype->GetPrimType() == PTY_ptr, "ref or ptr type");
139         uint32 index = ++maxPregNo;
140         auto *preg = mAllocator->GetMemPool()->New<MIRPreg>(index, primType, mtype);
141         return AddPreg(*preg);
142     }
143 
ClonePreg(const MIRPreg &rfpreg)144     PregIdx ClonePreg(const MIRPreg &rfpreg)
145     {
146         PregIdx idx = CreatePreg(rfpreg.GetPrimType(), rfpreg.GetMIRType());
147         MIRPreg *preg = pregTable[static_cast<uint32>(idx)];
148         preg->SetNeedRC(rfpreg.NeedRC());
149         return idx;
150     }
151 
PregFromPregIdx(PregIdx pregidx)152     MIRPreg *PregFromPregIdx(PregIdx pregidx)
153     {
154         if (pregidx < 0) {  // special register
155             return &specPregTable[-pregidx];
156         } else {
157             return pregTable.at(static_cast<uint32>(pregidx));
158         }
159     }
160 
GetPregIdxFromPregno(uint32 pregNo)161     PregIdx GetPregIdxFromPregno(uint32 pregNo)
162     {
163         auto it = pregNoToPregIdxMap.find(pregNo);
164         return (it == pregNoToPregIdxMap.end()) ? PregIdx(0) : it->second;
165     }
166 #ifdef ARK_LITECG_DEBUG
DumpPregsWithTypes(int32 indent)167     void DumpPregsWithTypes(int32 indent)
168     {
169         MapleVector<MIRPreg *> &pregtable = pregTable;
170         for (uint32 i = 1; i < pregtable.size(); i++) {
171             MIRPreg *mirpreg = pregtable[i];
172             if (mirpreg->GetMIRType() == nullptr) {
173                 continue;
174             }
175             PrintIndentation(indent);
176             LogInfo::MapleLogger() << "reg ";
177             LogInfo::MapleLogger() << "%" << mirpreg->GetPregNo();
178             LogInfo::MapleLogger() << " ";
179             mirpreg->GetMIRType()->Dump(0);
180             LogInfo::MapleLogger() << " " << (mirpreg->NeedRC() ? 1 : 0);
181             LogInfo::MapleLogger() << "\n";
182         }
183     }
184 #endif
Size() const185     size_t Size() const
186     {
187         return pregTable.size();
188     }
189 
AddPreg(MIRPreg &preg)190     PregIdx AddPreg(MIRPreg &preg)
191     {
192         PregIdx idx = static_cast<PregIdx>(pregTable.size());
193         pregTable.push_back(&preg);
194         DEBUG_ASSERT(pregNoToPregIdxMap.find(preg.GetPregNo()) == pregNoToPregIdxMap.end(),
195                      "The same pregno is already taken");
196         pregNoToPregIdxMap[preg.GetPregNo()] = idx;
197         return idx;
198     }
199 
EnterPregNo(uint32 pregNo, PrimType ptyp, MIRType *ty = nullptr)200     PregIdx EnterPregNo(uint32 pregNo, PrimType ptyp, MIRType *ty = nullptr)
201     {
202         PregIdx idx = GetPregIdxFromPregno(pregNo);
203         if (idx == 0) {
204             if (pregNo > maxPregNo) {
205                 maxPregNo = pregNo;
206             }
207             MIRPreg *preg = mAllocator->GetMemPool()->New<MIRPreg>(pregNo, ptyp, ty);
208             return AddPreg(*preg);
209         }
210         return idx;
211     }
212 
GetPregTable()213     MapleVector<MIRPreg *> &GetPregTable()
214     {
215         return pregTable;
216     }
217 
GetPregTable() const218     const MapleVector<MIRPreg *> &GetPregTable() const
219     {
220         return pregTable;
221     }
222 
GetPregTableItem(const uint32 index) const223     const MIRPreg *GetPregTableItem(const uint32 index) const
224     {
225         CHECK_FATAL(index < pregTable.size(), "array index out of range");
226         return pregTable[index];
227     }
228 
229     void SetPregNoToPregIdxMapItem(uint32 key, PregIdx value)
230     {
231         pregNoToPregIdxMap[key] = value;
232     }
233 
234     uint32 GetMaxPregNo() const
235     {
236         return maxPregNo;
237     }
238 
239     void SetMaxPregNo(uint32 index)
240     {
241         maxPregNo = index;
242     }
243 
244     size_t SpecPregSize()
245     {
246         return kSregLast;
247     }
248 
249 private:
250     uint32 maxPregNo = 0;                          //  the max pregNo that has been allocated
251     MapleMap<uint32, PregIdx> pregNoToPregIdxMap;  // for quick lookup based on pregno
252     MapleVector<MIRPreg *> pregTable;
253     MIRPreg specPregTable[kSregLast];  // for the MIRPreg nodes corresponding to special registers
254     MapleAllocator *mAllocator;
255 };
256 
257 #endif  // MIR_FEATURE_FULL
258 }  // namespace maple
259 #endif  // MAPLE_IR_INCLUDE_MIR_PREG_H
260