• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 MAPLEBE_INCLUDE_CG_CGFUNC_H
17 #define MAPLEBE_INCLUDE_CG_CGFUNC_H
18 
19 #include "becommon.h"
20 #include "operand.h"
21 #include "memlayout.h"
22 #include "reg_info.h"
23 #include "cgbb.h"
24 #include "call_conv.h"
25 #include "cfi.h"
26 #include "cg_cfg.h"
27 #include "cg_irbuilder.h"
28 /* MapleIR headers. */
29 #include "mir_function.h"
30 
31 /* Maple MP header */
32 #include "mempool_allocator.h"
33 #include "triple.h"
34 
35 namespace maplebe {
36 constexpr int32 kBBLimit = 100000;
37 constexpr int32 kFreqBase = 100000;
38 struct MemOpndCmp {
operatorMemOpndCmp39     bool operator()(const MemOperand *lhs, const MemOperand *rhs) const
40     {
41         CHECK_FATAL(lhs != nullptr, "null ptr check");
42         CHECK_FATAL(rhs != nullptr, "null ptr check");
43         if (lhs == rhs) {
44             return false;
45         }
46         return (lhs->Less(*rhs));
47     }
48 };
49 
50 class SpillMemOperandSet {
51 public:
SpillMemOperandSet(MapleAllocator & mallocator)52     explicit SpillMemOperandSet(MapleAllocator &mallocator) : reuseSpillLocMem(mallocator.Adapter()) {}
53 
54     virtual ~SpillMemOperandSet() = default;
55 
Add(MemOperand & op)56     void Add(MemOperand &op)
57     {
58         (void)reuseSpillLocMem.insert(&op);
59     }
60 
Remove(MemOperand & op)61     void Remove(MemOperand &op)
62     {
63         reuseSpillLocMem.erase(&op);
64     }
65 
GetOne()66     MemOperand *GetOne()
67     {
68         if (!reuseSpillLocMem.empty()) {
69             MemOperand *res = *reuseSpillLocMem.begin();
70             reuseSpillLocMem.erase(res);
71             return res;
72         }
73         return nullptr;
74     }
75 
76 private:
77     MapleSet<MemOperand *, MemOpndCmp> reuseSpillLocMem;
78 };
79 
80 #if TARGARM32
81 class LiveRange;
82 #endif /* TARGARM32 */
83 constexpr uint32 kVRegisterNumber = 80;
84 class CGFunc {
85 public:
86     enum ShiftDirection : uint8 { kShiftLeft, kShiftAright, kShiftLright };
87 
88     CGFunc(MIRModule &mod, CG &cg, MIRFunction &mirFunc, BECommon &beCommon, MemPool &memPool, StackMemPool &stackMp,
89            MapleAllocator &allocator, uint32 funcId);
90     virtual ~CGFunc();
91 
GetName()92     const std::string &GetName() const
93     {
94         return func.GetName();
95     }
96 
GetLabelAndValueMap()97     const MapleMap<LabelIdx, uint64> &GetLabelAndValueMap() const
98     {
99         return labelMap;
100     }
101 
InsertLabelMap(LabelIdx idx,uint64 value)102     void InsertLabelMap(LabelIdx idx, uint64 value)
103     {
104         DEBUG_ASSERT(labelMap.find(idx) == labelMap.end(), "idx already exist");
105         labelMap[idx] = value;
106     }
107 
LayoutStackFrame()108     void LayoutStackFrame()
109     {
110         CHECK_FATAL(memLayout != nullptr, "memLayout should has been initialized in constructor");
111         memLayout->LayoutStackFrame(structCopySize, maxParamStackSize);
112     }
113 
HasCall()114     bool HasCall() const
115     {
116         return func.HasCall();
117     }
118 
HasVLAOrAlloca()119     bool HasVLAOrAlloca() const
120     {
121         return hasVLAOrAlloca;
122     }
123 
SetHasVLAOrAlloca(bool val)124     void SetHasVLAOrAlloca(bool val)
125     {
126         hasVLAOrAlloca = val;
127     }
128 
HasAlloca()129     bool HasAlloca() const
130     {
131         return hasAlloca;
132     }
133 
SetHasAlloca(bool val)134     void SetHasAlloca(bool val)
135     {
136         hasAlloca = val;
137     }
138 
GetInsnBuilder()139     InsnBuilder *GetInsnBuilder()
140     {
141         return insnBuilder;
142     }
GetOpndBuilder()143     OperandBuilder *GetOpndBuilder()
144     {
145         return opndBuilder;
146     }
147 
148     void RemoveUnreachableBB();
149     void GenerateInstruction();
150     void HandleFunction();
151     void ProcessExitBBVec();
152     void AddCommonExitBB();
153     virtual void MergeReturn() = 0;
GetMaxRegNum()154     uint32 GetMaxRegNum() const
155     {
156         return vReg.GetMaxRegCount();
157     };
SetMaxRegNum(uint32 num)158     void SetMaxRegNum(uint32 num)
159     {
160         vReg.SetMaxRegCount(num);
161     }
IncMaxRegNum(uint32 num)162     void IncMaxRegNum(uint32 num) const
163     {
164         vReg.IncMaxRegCount(num);
165     }
166     // Attention! Do not invoke this interface in other processes except unit-test
SetMaxVReg(uint32 num)167     void SetMaxVReg(uint32 num) const
168     {
169         vReg.SetCount(num);
170     }
171     void DumpCFG() const;
172     void DumpBBInfo(const BB *bb) const;
173     void DumpCGIR() const;
174     Operand *HandleExpr(const BaseNode &parent, BaseNode &expr);
175     /* select stmt */
176     virtual void SelectDassign(DassignNode &stmt, Operand &opnd0) = 0;
177     virtual void SelectRegassign(RegassignNode &stmt, Operand &opnd0) = 0;
178     virtual void SelectIassign(IassignNode &stmt) = 0;
179     virtual void SelectReturn(Operand *opnd) = 0;
180     virtual void SelectCondGoto(CondGotoNode &stmt, Operand &opnd0, Operand &opnd1) = 0;
181     virtual void SelectCondSpecialCase1(CondGotoNode &stmt, BaseNode &opnd0) = 0;
182     virtual void SelectCondSpecialCase2(const CondGotoNode &stmt, BaseNode &opnd0) = 0;
183     virtual void SelectGoto(GotoNode &stmt) = 0;
184     virtual void SelectCall(CallNode &callNode) = 0;
185     virtual void SelectIcall(IcallNode &icallNode) = 0;
186     virtual void SelectIntrinsicCall(IntrinsiccallNode &intrinsiccallNode) = 0;
187     virtual Operand *SelectCclz(IntrinsicopNode &intrinsicopNode) = 0;
188     virtual void SelectComment(CommentNode &comment) = 0;
189 
190     /* select expr */
191     virtual Operand *SelectDread(const BaseNode &parent, AddrofNode &expr) = 0;
192     virtual RegOperand *SelectRegread(RegreadNode &expr) = 0;
193     virtual Operand *SelectIread(const BaseNode &parent, IreadNode &expr, int extraOffset = 0,
194                                  PrimType finalBitFieldDestType = kPtyInvalid) = 0;
195     virtual Operand *SelectIntConst(const MIRIntConst &intConst, const BaseNode &parent) = 0;
196     virtual Operand *SelectFloatConst(MIRFloatConst &floatConst, const BaseNode &parent) = 0;
197     virtual Operand *SelectDoubleConst(MIRDoubleConst &doubleConst, const BaseNode &parent) = 0;
198     virtual void SelectAdd(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
199     virtual Operand *SelectAdd(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
200     virtual Operand *SelectShift(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
201     virtual void SelectMpy(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
202     virtual Operand *SelectMpy(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
203     virtual Operand *SelectRem(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
204     virtual void SelectDiv(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
205     virtual Operand *SelectDiv(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
206     virtual Operand *SelectSub(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
207     virtual void SelectSub(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
208     virtual Operand *SelectBand(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
209     virtual void SelectBand(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
210     virtual void SelectMin(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
211     virtual Operand *SelectMin(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
212     virtual void SelectMax(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
213     virtual Operand *SelectMax(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
214     virtual Operand *SelectCmpOp(CompareNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
215     virtual Operand *SelectBior(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
216     virtual void SelectBior(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
217     virtual Operand *SelectBxor(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) = 0;
218     virtual void SelectBxor(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) = 0;
219     virtual Operand *SelectAbs(UnaryNode &node, Operand &opnd0) = 0;
220     virtual Operand *SelectBnot(UnaryNode &node, Operand &opnd0, const BaseNode &parent) = 0;
221     virtual Operand *SelectExtractbits(ExtractbitsNode &node, Operand &opnd0, const BaseNode &parent) = 0;
222     virtual Operand *SelectRegularBitFieldLoad(ExtractbitsNode &node, const BaseNode &parent) = 0;
223     virtual Operand *SelectLnot(UnaryNode &node, Operand &opnd0, const BaseNode &parent) = 0;
224     virtual Operand *SelectNeg(UnaryNode &node, Operand &opnd0, const BaseNode &parent) = 0;
225     virtual Operand *SelectSqrt(UnaryNode &node, Operand &opnd0, const BaseNode &parent) = 0;
226     virtual Operand *SelectCeil(TypeCvtNode &node, Operand &opnd0, const BaseNode &parent) = 0;
227     virtual Operand *SelectFloor(TypeCvtNode &node, Operand &opnd0, const BaseNode &parent) = 0;
228     virtual Operand *SelectRetype(TypeCvtNode &node, Operand &opnd0) = 0;
229     virtual Operand *SelectCvt(const BaseNode &parent, TypeCvtNode &node, Operand &opnd0) = 0;
230     virtual Operand *SelectTrunc(TypeCvtNode &node, Operand &opnd0, const BaseNode &parent) = 0;
231     virtual RegOperand &SelectCopy(Operand &src, PrimType srcType, PrimType dstType) = 0;
232     virtual void SelectRangeGoto(RangeGotoNode &rangeGotoNode, Operand &opnd0) = 0;
233 
234     virtual Operand &GetOrCreateRflag() = 0;
235     virtual const Operand *GetRflag() const = 0;
236     virtual const LabelOperand *GetLabelOperand(LabelIdx labIdx) const = 0;
237     virtual LabelOperand &GetOrCreateLabelOperand(LabelIdx labIdx) = 0;
238     virtual LabelOperand &GetOrCreateLabelOperand(BB &bb) = 0;
239     virtual RegOperand &CreateVirtualRegisterOperand(regno_t vRegNO) = 0;
240     virtual RegOperand &GetOrCreateVirtualRegisterOperand(regno_t vRegNO) = 0;
241     virtual RegOperand &GetOrCreateFramePointerRegOperand() = 0;
242     virtual RegOperand &GetOrCreateStackBaseRegOperand() = 0;
243     virtual RegOperand *GetBaseReg(const SymbolAlloc &symAlloc) = 0;
244     virtual int32 GetBaseOffset(const SymbolAlloc &symbolAlloc) = 0;
245     virtual RegOperand &GetZeroOpnd(uint32 size) = 0;
246     virtual Operand &CreateCfiRegOperand(uint32 reg, uint32 size) = 0;
247     virtual Operand &CreateImmOperand(PrimType primType, int64 val) = 0;
248     virtual MemOperand *GetOrCreatSpillMem(regno_t vrNum, uint32 bitSize) = 0;
249 
250     /* ra */
251     virtual void AddtoCalleeSaved(regno_t reg) = 0;
252 
HandleFuncCfg(CGCFG * cfg)253     virtual void HandleFuncCfg(CGCFG *cfg)
254     {
255         AddCommonExitBB();
256     }
257 
258     LabelIdx CreateLabel();
259 
AddReferenceReg(regno_t regNO)260     void AddReferenceReg(regno_t regNO)
261     {
262         referenceVirtualRegs.insert(regNO);
263     }
264 
IsRegReference(regno_t regNO)265     bool IsRegReference(regno_t regNO) const
266     {
267         return referenceVirtualRegs.count(regNO) != 0;
268     }
269 
GetReferenceRegs()270     const MapleUnorderedSet<regno_t> &GetReferenceRegs() const
271     {
272         return referenceVirtualRegs;
273     }
274 
ReplaceRegReference(regno_t oldReg,regno_t newReg)275     void ReplaceRegReference(regno_t oldReg, regno_t newReg)
276     {
277         auto iter = referenceVirtualRegs.find(oldReg);
278         if (iter != referenceVirtualRegs.end()) {
279             referenceVirtualRegs.erase(iter);
280             referenceVirtualRegs.insert(newReg);
281         }
282     }
283 
GetOrCreateRegOpndFromPregIdx(PregIdx preg,PrimType type)284     virtual RegOperand *GetOrCreateRegOpndFromPregIdx(PregIdx preg, PrimType type)
285     {
286         DEBUG_ASSERT(preg > 0, "NIY, preg must be greater than 0.");
287         auto idx = static_cast<size_t>(preg);
288         if (pregIdx2Opnd[idx] == nullptr) {
289             pregIdx2Opnd[idx] = &GetOpndBuilder()->CreateVReg(GetVirtualRegNOFromPseudoRegIdx(preg),
290                 GetPrimTypeBitSize(type), GetRegTyFromPrimTy(type));
291         }
292         auto *regOpnd = pregIdx2Opnd[idx];
293         if (type == maple::PTY_ref) {
294             regOpnd->SetIsReference(true);
295             AddReferenceReg(regOpnd->GetRegisterNumber());
296         }
297         return regOpnd;
298     }
299 
CreateCfiImmOperand(int64 val,uint32 size)300     Operand &CreateCfiImmOperand(int64 val, uint32 size) const
301     {
302         return *memPool->New<cfi::ImmOperand>(val, size);
303     }
304 
IsSpecialPseudoRegister(PregIdx spr)305     bool IsSpecialPseudoRegister(PregIdx spr) const
306     {
307         return spr < 0;
308     }
309 
NewVReg(RegType regType,uint32 size)310     regno_t NewVReg(RegType regType, uint32 size)
311     {
312         if (CGOptions::UseGeneralRegOnly()) {
313             CHECK_FATAL(regType != kRegTyFloat, "cannot use float | SIMD register with --general-reg-only");
314         }
315         return vReg.GetNextVregNO(regType, size);
316     }
317 
NewVRflag()318     virtual regno_t NewVRflag()
319     {
320         return 0;
321     }
322 
GetRegTyFromPrimTy(PrimType primType)323     RegType GetRegTyFromPrimTy(PrimType primType) const
324     {
325         switch (primType) {
326             case PTY_u1:
327             case PTY_i8:
328             case PTY_u8:
329             case PTY_i16:
330             case PTY_u16:
331             case PTY_i32:
332             case PTY_u32:
333             case PTY_i64:
334             case PTY_u64:
335             case PTY_a64:
336             case PTY_ptr:
337             case PTY_ref:
338                 return kRegTyInt;
339             case PTY_f32:
340             case PTY_f64:
341                 return kRegTyFloat;
342             default:
343                 DEBUG_ASSERT(false, "Unexpected pty");
344                 return kRegTyUndef;
345         }
346     }
347 
348     /* return Register Type */
GetRegisterType(regno_t rNum)349     virtual RegType GetRegisterType(regno_t rNum) const
350     {
351         CHECK(rNum < vReg.VRegTableSize(), "index out of range in GetVRegSize");
352         return vReg.VRegTableGetType(rNum);
353     }
354 
355 #if defined(TARGX86_64) && TARGX86_64
GetMaxVReg()356     uint32 GetMaxVReg() const
357     {
358         return vReg.GetCount() + opndBuilder->GetCurrentVRegNum();
359     }
360 #else
GetMaxVReg()361     uint32 GetMaxVReg() const
362     {
363         return vReg.GetCount();
364     }
365 #endif
366 
367     void VerifyAllInsn();
368 
MaxCondBranchDistance()369     virtual uint32 MaxCondBranchDistance()
370     {
371         return INT_MAX;
372     }
373 
InsertJumpPad(Insn *)374     virtual void InsertJumpPad(Insn *)
375     {
376         return;
377     }
378 
GetLabelInInsn(Insn & insn)379     virtual LabelIdx GetLabelInInsn(Insn &insn)
380     {
381         return 0;
382     }
383 
NumBBs()384     uint32 NumBBs() const
385     {
386         return bbCnt;
387     }
388 
GetStructCopySize()389     int32 GetStructCopySize() const
390     {
391         return structCopySize;
392     }
393 
GetMaxParamStackSize()394     int32 GetMaxParamStackSize() const
395     {
396         return maxParamStackSize;
397     }
398 
399     /* Get And Set private members */
GetCG()400     CG *GetCG()
401     {
402         return cg;
403     }
404 
GetCG()405     const CG *GetCG() const
406     {
407         return cg;
408     }
409 
GetMirModule()410     MIRModule &GetMirModule()
411     {
412         return mirModule;
413     }
414 
GetMirModule()415     const MIRModule &GetMirModule() const
416     {
417         return mirModule;
418     }
419 
420     template <typename T>
NewMirConst(T & mirConst)421     MIRConst *NewMirConst(T &mirConst)
422     {
423         MIRConst *newConst = mirModule.GetMemPool()->New<T>(mirConst.GetValue(), mirConst.GetType());
424         return newConst;
425     }
426 
GetFunction()427     MIRFunction &GetFunction()
428     {
429         return func;
430     }
431 
GetFunction()432     const MIRFunction &GetFunction() const
433     {
434         return func;
435     }
436 
GetLabelIdx()437     uint32 GetLabelIdx() const
438     {
439         return labelIdx;
440     }
441 
SetLabelIdx(uint32 idx)442     void SetLabelIdx(uint32 idx)
443     {
444         labelIdx = idx;
445     }
446 
GetEndLabel()447     LabelNode *GetEndLabel()
448     {
449         return endLabel;
450     }
451 
GetEndLabel()452     const LabelNode *GetEndLabel() const
453     {
454         return endLabel;
455     }
456 
SetEndLabel(LabelNode & label)457     void SetEndLabel(LabelNode &label)
458     {
459         endLabel = &label;
460     }
461 
GetFirstBB()462     BB *GetFirstBB()
463     {
464         return firstBB;
465     }
466 
GetFirstBB()467     const BB *GetFirstBB() const
468     {
469         return firstBB;
470     }
471 
SetFirstBB(BB & bb)472     void SetFirstBB(BB &bb)
473     {
474         firstBB = &bb;
475     }
476 
GetLastBB()477     BB *GetLastBB()
478     {
479         return lastBB;
480     }
481 
GetLastBB()482     const BB *GetLastBB() const
483     {
484         return lastBB;
485     }
486 
SetLastBB(BB & bb)487     void SetLastBB(BB &bb)
488     {
489         lastBB = &bb;
490     }
491 
GetCurBB()492     BB *GetCurBB()
493     {
494         return curBB;
495     }
496 
GetCurBB()497     const BB *GetCurBB() const
498     {
499         return curBB;
500     }
501 
SetCurBB(BB & bb)502     void SetCurBB(BB &bb)
503     {
504         curBB = &bb;
505     }
506 
GetDummyBB()507     BB *GetDummyBB()
508     {
509         return dummyBB;
510     }
511 
GetDummyBB()512     const BB *GetDummyBB() const
513     {
514         return dummyBB;
515     }
516 
GetCommonExitBB()517     BB *GetCommonExitBB()
518     {
519         return commonExitBB;
520     }
521 
GetCommonEntryBB()522     BB *GetCommonEntryBB()
523     {
524         DEBUG_ASSERT(bbVec[0]->GetId() == 0 && bbVec[0] != firstBB, "there is no commonEntryBB");
525         return bbVec[0];
526     }
527 
GetExitBBsVec()528     MapleVector<BB *> &GetExitBBsVec()
529     {
530         return exitBBVec;
531     }
532 
GetExitBBsVec()533     const MapleVector<BB *> GetExitBBsVec() const
534     {
535         return exitBBVec;
536     }
537 
ExitBBsVecSize()538     size_t ExitBBsVecSize() const
539     {
540         return exitBBVec.size();
541     }
542 
IsExitBBsVecEmpty()543     bool IsExitBBsVecEmpty() const
544     {
545         return exitBBVec.empty();
546     }
547 
EraseExitBBsVec(MapleVector<BB * >::iterator it)548     void EraseExitBBsVec(MapleVector<BB *>::iterator it)
549     {
550         exitBBVec.erase(it);
551     }
552 
PushBackExitBBsVec(BB & bb)553     void PushBackExitBBsVec(BB &bb)
554     {
555         exitBBVec.emplace_back(&bb);
556     }
557 
ClearExitBBsVec()558     void ClearExitBBsVec()
559     {
560         exitBBVec.clear();
561     }
562 
IsExitBB(const BB & currentBB)563     bool IsExitBB(const BB &currentBB)
564     {
565         for (BB *exitBB : exitBBVec) {
566             if (exitBB == &currentBB) {
567                 return true;
568             }
569         }
570         return false;
571     }
572 
GetExitBB(int32 index)573     BB *GetExitBB(int32 index)
574     {
575         return exitBBVec.at(index);
576     }
577 
GetExitBB(int32 index)578     const BB *GetExitBB(int32 index) const
579     {
580         return exitBBVec.at(index);
581     }
582 
EraseNoReturnCallBB(MapleVector<BB * >::iterator it)583     MapleVector<BB *>::iterator EraseNoReturnCallBB(MapleVector<BB *>::iterator it)
584     {
585         return noReturnCallBBVec.erase(it);
586     }
587 
PushBackNoReturnCallBBsVec(BB & bb)588     void PushBackNoReturnCallBBsVec(BB &bb)
589     {
590         noReturnCallBBVec.emplace_back(&bb);
591     }
592 
GetNoRetCallBBVec()593     MapleVector<BB *> &GetNoRetCallBBVec()
594     {
595         return noReturnCallBBVec;
596     }
597 
SetLab2BBMap(int32 index,BB & bb)598     void SetLab2BBMap(int32 index, BB &bb)
599     {
600         lab2BBMap[index] = &bb;
601     }
602 
GetBBFromLab2BBMap(uint32 index)603     BB *GetBBFromLab2BBMap(uint32 index)
604     {
605         return lab2BBMap[index];
606     }
607 
GetLab2BBMap()608     MapleUnorderedMap<LabelIdx, BB *> &GetLab2BBMap()
609     {
610         return lab2BBMap;
611     }
612 
GetBecommon()613     BECommon &GetBecommon()
614     {
615         return beCommon;
616     }
617 
GetBecommon()618     const BECommon GetBecommon() const
619     {
620         return beCommon;
621     }
622 
GetMemlayout()623     MemLayout *GetMemlayout()
624     {
625         return memLayout;
626     }
627 
GetMemlayout()628     const MemLayout *GetMemlayout() const
629     {
630         return memLayout;
631     }
632 
SetMemlayout(MemLayout & layout)633     void SetMemlayout(MemLayout &layout)
634     {
635         memLayout = &layout;
636     }
637 
GetTargetRegInfo()638     RegisterInfo *GetTargetRegInfo()
639     {
640         return targetRegInfo;
641     }
642 
SetTargetRegInfo(RegisterInfo & regInfo)643     void SetTargetRegInfo(RegisterInfo &regInfo)
644     {
645         targetRegInfo = &regInfo;
646     }
647 
GetMemoryPool()648     MemPool *GetMemoryPool()
649     {
650         return memPool;
651     }
652 
GetMemoryPool()653     const MemPool *GetMemoryPool() const
654     {
655         return memPool;
656     }
657 
GetStackMemPool()658     StackMemPool &GetStackMemPool()
659     {
660         return stackMp;
661     }
662 
GetFuncScopeAllocator()663     MapleAllocator *GetFuncScopeAllocator()
664     {
665         return funcScopeAllocator;
666     }
667 
GetFuncScopeAllocator()668     const MapleAllocator *GetFuncScopeAllocator() const
669     {
670         return funcScopeAllocator;
671     }
672 
GetEmitStVec()673     const MapleMap<uint32, MIRSymbol *> GetEmitStVec() const
674     {
675         return emitStVec;
676     }
677 
GetEmitSt(uint32 id)678     MIRSymbol *GetEmitSt(uint32 id)
679     {
680         return emitStVec[id];
681     }
682 
AddEmitSt(uint32 id,MIRSymbol & symbol)683     void AddEmitSt(uint32 id, MIRSymbol &symbol)
684     {
685         CHECK_FATAL(symbol.GetKonst()->GetKind() == kConstAggConst, "not a kConstAggConst");
686         MIRAggConst *arrayConst = safe_cast<MIRAggConst>(symbol.GetKonst());
687         for (size_t i = 0; i < arrayConst->GetConstVec().size(); ++i) {
688             CHECK_FATAL(arrayConst->GetConstVecItem(i)->GetKind() == kConstLblConst, "not a kConstLblConst");
689             MIRLblConst *lblConst = safe_cast<MIRLblConst>(arrayConst->GetConstVecItem(i));
690             ++switchLabelCnt[lblConst->GetValue()];
691         }
692         emitStVec[id] = &symbol;
693     }
694 
DeleteEmitSt(uint32 id)695     void DeleteEmitSt(uint32 id)
696     {
697         MIRSymbol &symbol = *emitStVec[id];
698         CHECK_FATAL(symbol.GetKonst()->GetKind() == kConstAggConst, "not a kConstAggConst");
699         MIRAggConst *arrayConst = safe_cast<MIRAggConst>(symbol.GetKonst());
700         for (size_t i = 0; i < arrayConst->GetConstVec().size(); ++i) {
701             CHECK_FATAL(arrayConst->GetConstVecItem(i)->GetKind() == kConstLblConst, "not a kConstLblConst");
702             MIRLblConst *lblConst = safe_cast<MIRLblConst>(arrayConst->GetConstVecItem(i));
703 
704             LabelIdx labelIdx = lblConst->GetValue();
705             CHECK_FATAL(switchLabelCnt[labelIdx] > 0, "error labelIdx");
706             --switchLabelCnt[labelIdx];
707             if (switchLabelCnt[labelIdx] == 0) {
708                 switchLabelCnt.erase(labelIdx);
709             }
710         }
711         (void)emitStVec.erase(id);
712     }
713 
InSwitchTable(LabelIdx label)714     bool InSwitchTable(LabelIdx label) const
715     {
716         if (switchLabelCnt.empty()) {
717             return false;
718         }
719         return (switchLabelCnt.find(label) != switchLabelCnt.end());
720     }
721 
GetLocalSymLabelIndex(const MIRSymbol & symbol)722     LabelIdx GetLocalSymLabelIndex(const MIRSymbol &symbol) const
723     {
724         auto itr = funcLocalSym2Label.find(&symbol);
725         CHECK_FATAL(itr != funcLocalSym2Label.end(), "not assign labelIndex to sym");
726         return itr->second;
727     }
728 
SetLocalSymLabelIndex(const MIRSymbol & mirSymbol,LabelIdx labelIndex)729     void SetLocalSymLabelIndex(const MIRSymbol &mirSymbol, LabelIdx labelIndex)
730     {
731         funcLocalSym2Label[&mirSymbol] = labelIndex;
732     }
733 
GetAllBBs()734     MapleVector<BB *> &GetAllBBs()
735     {
736         return bbVec;
737     }
738 
GetAllBBSize()739     std::size_t GetAllBBSize() const
740     {
741         return bbVec.size();
742     }
743 
GetBBFromID(uint32 id)744     BB *GetBBFromID(uint32 id)
745     {
746         return bbVec[id];
747     }
ClearBBInVec(uint32 id)748     void ClearBBInVec(uint32 id)
749     {
750         bbVec[id] = nullptr;
751     }
752 
GetTheCFG()753     CGCFG *GetTheCFG()
754     {
755         return theCFG;
756     }
757 
SetTheCFG(CGCFG * cfg)758     void SetTheCFG(CGCFG *cfg)
759     {
760         theCFG = cfg;
761     }
762 
GetTheCFG()763     const CGCFG *GetTheCFG() const
764     {
765         return theCFG;
766     }
767 
GetVirtualRegNOFromPseudoRegIdx(PregIdx idx)768     regno_t GetVirtualRegNOFromPseudoRegIdx(PregIdx idx) const
769     {
770         return regno_t(idx + firstMapleIrVRegNO);
771     }
772 
GetHasProEpilogue()773     bool GetHasProEpilogue() const
774     {
775         return hasProEpilogue;
776     }
777 
SetHasProEpilogue(bool state)778     void SetHasProEpilogue(bool state)
779     {
780         hasProEpilogue = state;
781     }
782 
CreateNewBB()783     BB *CreateNewBB()
784     {
785         BB *bb = memPool->New<BB>(bbCnt++, *funcScopeAllocator);
786         bbVec.emplace_back(bb);
787         return bb;
788     }
789 
CreateNewBB(bool unreachable,BB::BBKind kind,uint32 frequency)790     BB *CreateNewBB(bool unreachable, BB::BBKind kind, uint32 frequency)
791     {
792         BB *newBB = CreateNewBB();
793         newBB->SetKind(kind);
794         newBB->SetUnreachable(unreachable);
795         newBB->SetFrequency(frequency);
796         return newBB;
797     }
798 
CreateNewBB(LabelIdx label,bool unreachable,BB::BBKind kind,uint32 frequency)799     BB *CreateNewBB(LabelIdx label, bool unreachable, BB::BBKind kind, uint32 frequency)
800     {
801         BB *newBB = CreateNewBB(unreachable, kind, frequency);
802         newBB->AddLabel(label);
803         SetLab2BBMap(label, *newBB);
804         return newBB;
805     }
806 
StartNewBBImpl(bool stmtIsCurBBLastStmt,StmtNode & stmt)807     BB *StartNewBBImpl(bool stmtIsCurBBLastStmt, StmtNode &stmt)
808     {
809         BB *newBB = CreateNewBB();
810         DEBUG_ASSERT(newBB != nullptr, "newBB should not be nullptr");
811         if (stmtIsCurBBLastStmt) {
812             DEBUG_ASSERT(curBB != nullptr, "curBB should not be nullptr");
813             curBB->SetLastStmt(stmt);
814             curBB->AppendBB(*newBB);
815             newBB->SetFirstStmt(*stmt.GetNext());
816         } else {
817             newBB->SetFirstStmt(stmt);
818             if (curBB != nullptr) {
819                 if (stmt.GetPrev() != nullptr) {
820                     DEBUG_ASSERT(stmt.GetPrev()->GetNext() == &stmt, " the next of stmt's prev should be stmt self");
821                 }
822                 curBB->SetLastStmt(*stmt.GetPrev());
823                 curBB->AppendBB(*newBB);
824             }
825         }
826         return newBB;
827     }
828 
StartNewBB(StmtNode & stmt)829     BB *StartNewBB(StmtNode &stmt)
830     {
831         BB *bb = curBB;
832         if (stmt.GetNext() != nullptr && stmt.GetNext()->GetOpCode() != OP_label) {
833             bb = StartNewBBImpl(true, stmt);
834         }
835         return bb;
836     }
837 
SetCurBBKind(BB::BBKind bbKind)838     void SetCurBBKind(BB::BBKind bbKind) const
839     {
840         curBB->SetKind(bbKind);
841     }
842 
IsAfterRegAlloc()843     bool IsAfterRegAlloc() const
844     {
845         return isAfterRegAlloc;
846     }
847 
SetIsAfterRegAlloc()848     void SetIsAfterRegAlloc()
849     {
850         isAfterRegAlloc = true;
851     }
852 
GetShortFuncName()853     const MapleString &GetShortFuncName() const
854     {
855         return shortFuncName;
856     }
857 
GetLSymSize()858     size_t GetLSymSize() const
859     {
860         return lSymSize;
861     }
862 
863     virtual InsnVisitor *NewInsnModifier() = 0;
864 
GenCfi()865     bool GenCfi() const
866     {
867         return (mirModule.GetSrcLang() != kSrcLangC) || mirModule.IsWithDbgInfo();
868     }
869 
GetUniqueID()870     uint32 GetUniqueID() const
871     {
872         return func.GetPuidx();
873     }
SetUseFP(bool canUseFP)874     void SetUseFP(bool canUseFP)
875     {
876         useFP = canUseFP;
877     }
878 
UseFP()879     bool UseFP() const
880     {
881         return useFP;
882     }
883 
UnsetSeenFP()884     void UnsetSeenFP()
885     {
886         seenFP = false;
887     }
888 
SeenFP()889     bool SeenFP() const
890     {
891         return seenFP;
892     }
893 
RegisterVregMapping(regno_t vRegNum,PregIdx pidx)894     void RegisterVregMapping(regno_t vRegNum, PregIdx pidx)
895     {
896         vregsToPregsMap[vRegNum] = pidx;
897     }
898 
GetStackMapInsns()899     const MapleList<Insn *> &GetStackMapInsns() const
900     {
901         return stackMapInsns;
902     }
903 
AppendStackMapInsn(Insn & insn)904     void AppendStackMapInsn(Insn &insn)
905     {
906         insn.InitStackMapInfo();
907         stackMapInsns.emplace_back(&insn);
908     }
909 
IsStackMapComputed()910     bool IsStackMapComputed()
911     {
912         return isStackMapComputed;
913     }
914 
SetStackMapComputed()915     void SetStackMapComputed()
916     {
917         isStackMapComputed = true;
918     }
919 
EraseUnreachableStackMapInsns()920     void EraseUnreachableStackMapInsns()
921     {
922         for (auto it = stackMapInsns.begin(); it != stackMapInsns.end();) {
923             if ((*it)->GetBB()->IsUnreachable()) {
924                 it = stackMapInsns.erase(it);
925             } else {
926                 ++it;
927             }
928         }
929     }
930 
GetFirstMapleIrVRegNO()931     uint32 GetFirstMapleIrVRegNO() const
932     {
933         return firstMapleIrVRegNO;
934     }
935 
SetStackProtectInfo(StackProtectKind kind)936     void SetStackProtectInfo(StackProtectKind kind)
937     {
938         stackProtectInfo |= kind;
939     }
940 
GetStackProtectInfo()941     uint8 GetStackProtectInfo() const
942     {
943         return stackProtectInfo;
944     }
945 
SetNeedStackProtect(bool val)946     void SetNeedStackProtect(bool val)
947     {
948         needStackProtect = val;
949     }
950 
GetNeedStackProtect()951     bool GetNeedStackProtect() const
952     {
953         return needStackProtect;
954     }
955 
GetCurCallConvKind()956     CallConvKind GetCurCallConvKind() const
957     {
958         return callingConventionKind;
959     }
960 
SetFuncEmitInfo(FuncEmitInfo * fnInfo)961     void SetFuncEmitInfo(FuncEmitInfo *fnInfo)
962     {
963         funcEmitInfo = fnInfo;
964     }
965 
GetFuncEmitInfo()966     FuncEmitInfo *GetFuncEmitInfo()
967     {
968         return funcEmitInfo;
969     }
970 
SetExitBBLost(bool val)971     void SetExitBBLost(bool val)
972     {
973         exitBBLost = val;
974     }
GetExitBBLost()975     bool GetExitBBLost()
976     {
977         return exitBBLost;
978     }
979 
SetHasBuiltCfg(bool hasBuilt)980     void SetHasBuiltCfg(bool hasBuilt)
981     {
982         hasBuiltCfg = hasBuilt;
983     }
984 
HasBuiltCfg()985     bool HasBuiltCfg() const
986     {
987         return hasBuiltCfg;
988     }
989 
GetWithSrc()990     bool GetWithSrc() const
991     {
992         return withSrc;
993     }
994 protected:
995     uint32 firstMapleIrVRegNO = 200; /* positioned after physical regs */
996     uint32 firstNonPregVRegNO;
997     VregInfo vReg;           /* for assigning a number for each CG virtual register */
998     size_t lSymSize;         /* size of local symbol table imported */
999     MapleVector<BB *> bbVec;
1000     MapleUnorderedSet<regno_t> referenceVirtualRegs;
1001     MapleVector<RegOperand *> pregIdx2Opnd;
1002     MapleUnorderedMap<PregIdx, MemOperand *> pRegSpillMemOperands;
1003     MapleUnorderedMap<regno_t, MemOperand *> spillRegMemOperands;
1004     MapleUnorderedMap<uint32, SpillMemOperandSet *> reuseSpillLocMem;
1005     MapleMap<LabelIdx, uint64> labelMap;
1006     MapleMap<regno_t, PregIdx> vregsToPregsMap;
1007     MapleList<Insn *> stackMapInsns;
1008     int32 structCopySize;
1009     int32 maxParamStackSize;
1010     static constexpr int kRegIncrStepLen = 80; /* reg number increate step length */
1011 
1012     bool hasVLAOrAlloca = false;
1013     bool hasAlloca = false;
1014     bool hasProEpilogue = false;
1015     bool isVolLoad = false;
1016     bool isVolStore = false;
1017     bool isAfterRegAlloc = false;
1018     bool isAggParamInReg = false;
1019     bool hasTakenLabel = false;
1020     bool hasLaidOutByPgoUse = false;
1021     bool withSrc = true;
1022     RegOperand *aggParamReg = nullptr;
1023     CG *cg;
1024     MIRModule &mirModule;
1025     MemPool *memPool;
1026     StackMemPool &stackMp;
1027 
GetPseudoRegIdxFromVirtualRegNO(const regno_t vRegNO)1028     PregIdx GetPseudoRegIdxFromVirtualRegNO(const regno_t vRegNO) const
1029     {
1030         if (IsVRegNOForPseudoRegister(vRegNO)) {
1031             return PregIdx(vRegNO - firstMapleIrVRegNO);
1032         }
1033         return VRegNOToPRegIdx(vRegNO);
1034     }
1035 
IsVRegNOForPseudoRegister(regno_t vRegNum)1036     bool IsVRegNOForPseudoRegister(regno_t vRegNum) const
1037     {
1038         /* 0 is not allowed for preg index */
1039         uint32 n = static_cast<uint32>(vRegNum);
1040         return (firstMapleIrVRegNO < n && n < firstNonPregVRegNO);
1041     }
1042 
VRegNOToPRegIdx(regno_t vRegNum)1043     PregIdx VRegNOToPRegIdx(regno_t vRegNum) const
1044     {
1045         auto it = vregsToPregsMap.find(vRegNum);
1046         if (it == vregsToPregsMap.end()) {
1047             return PregIdx(-1);
1048         }
1049         return it->second;
1050     }
1051 
GetVirtualRegNodeFromPseudoRegIdx(PregIdx idx)1052     VirtualRegNode &GetVirtualRegNodeFromPseudoRegIdx(PregIdx idx)
1053     {
1054         return vReg.VRegTableElementGet(GetVirtualRegNOFromPseudoRegIdx(idx));
1055     }
1056 
GetTypeFromPseudoRegIdx(PregIdx idx)1057     PrimType GetTypeFromPseudoRegIdx(PregIdx idx)
1058     {
1059         VirtualRegNode &vRegNode = GetVirtualRegNodeFromPseudoRegIdx(idx);
1060         RegType regType = vRegNode.GetType();
1061         DEBUG_ASSERT(regType == kRegTyInt || regType == kRegTyFloat, "");
1062         uint32 size = vRegNode.GetSize(); /* in bytes */
1063         return (regType == kRegTyInt ? (size <= sizeof(int32) ? PTY_i32 : PTY_i64)
1064                                      : (size <= sizeof(float) ? PTY_f32 : PTY_f64));
1065     }
1066 
GetPseudoRegisterSpillLocation(PregIdx idx)1067     int64 GetPseudoRegisterSpillLocation(PregIdx idx)
1068     {
1069         const SymbolAlloc *symLoc = memLayout->GetSpillLocOfPseduoRegister(idx);
1070         return static_cast<int64>(GetBaseOffset(*symLoc));
1071     }
1072 
GetOrCreatSpillRegLocation(regno_t vrNum,uint32 memByteSize)1073     int64 GetOrCreatSpillRegLocation(regno_t vrNum, uint32 memByteSize)
1074     {
1075         auto *symLoc = GetMemlayout()->GetLocOfSpillRegister(vrNum, memByteSize);
1076         return static_cast<int64>(GetBaseOffset(*symLoc));
1077     }
1078 
1079     virtual MemOperand *GetPseudoRegisterSpillMemoryOperand(PregIdx idx) = 0;
1080 
GetSpillLocation(uint32 size)1081     uint32 GetSpillLocation(uint32 size)
1082     {
1083         uint32 offset = RoundUp(nextSpillLocation, static_cast<uint64>(size));
1084         nextSpillLocation = offset + size;
1085         return offset;
1086     }
1087 
GetPrimTypeFromSize(uint32 byteSize,PrimType defaultType)1088     PrimType GetPrimTypeFromSize(uint32 byteSize, PrimType defaultType) const
1089     {
1090         constexpr uint32 oneByte = 1;
1091         constexpr uint32 twoByte = 2;
1092         constexpr uint32 fourByte = 4;
1093         switch (byteSize) {
1094             case oneByte:
1095                 return PTY_i8;
1096             case twoByte:
1097                 return PTY_i16;
1098             case fourByte:
1099                 return PTY_i32;
1100             default:
1101                 return defaultType;
1102         }
1103     }
1104 
1105     // clone old mem and add offset
1106     // oldMem: [base, imm:12] -> newMem: [base, imm:(12 + offset)]
GetMemOperandAddOffset(const MemOperand & oldMem,uint32 offset,uint32 newSize)1107     MemOperand &GetMemOperandAddOffset(const MemOperand &oldMem, uint32 offset, uint32 newSize)
1108     {
1109         auto &newMem = static_cast<MemOperand &>(*oldMem.Clone(*GetMemoryPool()));
1110         auto &oldOffset = *oldMem.GetOffsetOperand();
1111         auto &newOffst = static_cast<ImmOperand &>(*oldOffset.Clone(*GetMemoryPool()));
1112         newOffst.SetValue(oldOffset.GetValue() + offset);
1113         newMem.SetOffsetOperand(newOffst);
1114         newMem.SetSize(newSize);
1115         return newMem;
1116     }
1117 
1118 private:
1119     CGFunc &operator=(const CGFunc &cgFunc);
1120     CGFunc(const CGFunc &);
1121     StmtNode *HandleFirstStmt();
1122     MIRFunction &func;
1123 
1124     InsnBuilder *insnBuilder = nullptr;
1125     OperandBuilder *opndBuilder = nullptr;
1126 
1127     uint32 bbCnt = 0;
1128     uint32 labelIdx = 0;               /* local label index number */
1129     LabelNode *startLabel = nullptr;   /* start label of the function */
1130     LabelNode *returnLabel = nullptr;  /* return label of the function */
1131     LabelNode *endLabel = nullptr;     /* end label of the function */
1132 
1133     BB *firstBB = nullptr;
1134     BB *lastBB = nullptr;
1135     BB *curBB = nullptr;
1136     BB *dummyBB;                    /* use this bb for add some instructions to bb that is no curBB. */
1137     BB *commonExitBB = nullptr;     /* this post-dominate all BBs */
1138     MapleVector<BB *> exitBBVec;
1139     MapleVector<BB *> noReturnCallBBVec;
1140     MapleSet<regno_t> extendSet; /* use to mark regs which spilled 32 bits but loaded 64 bits. */
1141     MapleUnorderedMap<LabelIdx, BB *> lab2BBMap;
1142     BECommon &beCommon;
1143     CCImpl *callConv = nullptr;
1144     MemLayout *memLayout = nullptr;
1145     RegisterInfo *targetRegInfo = nullptr;
1146     MapleAllocator *funcScopeAllocator;
1147     MapleMap<uint32, MIRSymbol *> emitStVec; /* symbol that needs to be emit as a local symbol. i.e, switch table */
1148     MapleUnorderedMap<LabelIdx, int32> switchLabelCnt; /* label in switch table */
1149     std::map<const MIRSymbol *, LabelIdx> funcLocalSym2Label;
1150     CallConvKind callingConventionKind;
1151     CGCFG *theCFG = nullptr;
1152     FuncEmitInfo *funcEmitInfo = nullptr;
1153     uint32 nextSpillLocation = 0;
1154     regno_t spSaveReg = 0;
1155 
1156     const MapleString shortFuncName;
1157     bool hasAsm = false;
1158     bool useFP = true;
1159     bool seenFP = true;
1160     bool hasBuiltCfg = false;
1161     bool isStackMapComputed = false;
1162 
1163     /* save stack protect kinds which can trigger stack protect */
1164     uint8 stackProtectInfo = 0;
1165     bool needStackProtect = false;
1166 
1167     // mark exitBB is unreachable
1168     bool exitBBLost = false;
1169 }; /* class CGFunc */
1170 
1171 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgLayoutFrame, maplebe::CGFunc)
1172 MAPLE_FUNC_PHASE_DECLARE_END
1173 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgHandleFunction, maplebe::CGFunc)
1174 MAPLE_FUNC_PHASE_DECLARE_END
1175 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgVerify, maplebe::CGFunc)
1176 MAPLE_FUNC_PHASE_DECLARE_END
1177 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgGenCfi, maplebe::CGFunc)
1178 MAPLE_FUNC_PHASE_DECLARE_END
1179 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgEmission, maplebe::CGFunc)
1180 MAPLE_FUNC_PHASE_DECLARE_END
1181 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgGenProEpiLog, maplebe::CGFunc)
1182 MAPLE_FUNC_PHASE_DECLARE_END
1183 } /* namespace maplebe */
1184 #endif /* MAPLEBE_INCLUDE_CG_CGFUNC_H */
1185