• 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_AARCH64_AARCH64_CGFUNC_H
17 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_CGFUNC_H
18 
19 #include "cgfunc.h"
20 #include "call_conv.h"
21 #include "mpl_atomic.h"
22 #include "aarch64_abi.h"
23 #include "aarch64_operand.h"
24 #include "aarch64_insn.h"
25 #include "aarch64_memlayout.h"
26 #include "aarch64_reg_info.h"
27 #include "aarch64_optimize_common.h"
28 #include "aarch64_call_conv.h"
29 
30 namespace maplebe {
31 enum RematLevel { kRematOff = 0, kRematConst = 1, kRematAddr = 2, kRematDreadLocal = 3, kRematDreadGlobal = 4 };
32 
33 class LmbcArgInfo {
34 public:
LmbcArgInfo(MapleAllocator & mallocator)35     explicit LmbcArgInfo(MapleAllocator &mallocator)
36         : lmbcCallArgs(mallocator.Adapter()),
37           lmbcCallArgTypes(mallocator.Adapter()),
38           lmbcCallArgOffsets(mallocator.Adapter()),
39           lmbcCallArgNumOfRegs(mallocator.Adapter())
40     {
41     }
42     MapleVector<RegOperand *> lmbcCallArgs;
43     MapleVector<PrimType> lmbcCallArgTypes;
44     MapleVector<int32> lmbcCallArgOffsets;
45     MapleVector<int32> lmbcCallArgNumOfRegs;  // # of regs needed to complete struct
46     uint32 lmbcTotalStkUsed = -1;             // remove when explicit addr for large agg is available
47 };
48 
49 class AArch64CGFunc : public CGFunc {
50 public:
AArch64CGFunc(MIRModule & mod,CG & c,MIRFunction & f,BECommon & b,MemPool & memPool,StackMemPool & stackMp,MapleAllocator & mallocator,uint32 funcId)51     AArch64CGFunc(MIRModule &mod, CG &c, MIRFunction &f, BECommon &b, MemPool &memPool, StackMemPool &stackMp,
52                   MapleAllocator &mallocator, uint32 funcId)
53         : CGFunc(mod, c, f, b, memPool, stackMp, mallocator, funcId),
54           calleeSavedRegs(mallocator.Adapter()),
55           proEpilogSavedRegs(mallocator.Adapter()),
56           phyRegOperandTable(mallocator.Adapter()),
57           hashLabelOpndTable(mallocator.Adapter()),
58           hashOfstOpndTable(mallocator.Adapter()),
59           hashMemOpndTable(mallocator.Adapter()),
60           stIdx2OverflowResult(mallocator.Adapter()),
61           memOpndsRequiringOffsetAdjustment(mallocator.Adapter()),
62           memOpndsForStkPassedArguments(mallocator.Adapter()),
63           immOpndsRequiringOffsetAdjustment(mallocator.Adapter()),
64           immOpndsRequiringOffsetAdjustmentForRefloc(mallocator.Adapter()),
65           hashCCTable(mallocator.Adapter())
66     {
67         uCatch.regNOCatch = 0;
68         CGFunc::SetMemlayout(*memPool.New<AArch64MemLayout>(b, f, mallocator));
69         CGFunc::GetMemlayout()->SetCurrFunction(*this);
70         CGFunc::SetTargetRegInfo(*memPool.New<AArch64RegInfo>(mallocator));
71         CGFunc::GetTargetRegInfo()->SetCurrFunction(*this);
72         if (f.GetAttr(FUNCATTR_varargs) || f.HasVlaOrAlloca()) {
73             SetHasVLAOrAlloca(true);
74         }
75         SetHasAlloca(f.HasVlaOrAlloca());
76         SetUseFP(CGOptions::UseFramePointer() || HasVLAOrAlloca() || !f.GetModule()->IsCModule() ||
77                  f.GetModule()->GetFlavor() == MIRFlavor::kFlavorLmbc);
78     }
79 
80     ~AArch64CGFunc() override = default;
81 
GetRefCount()82     uint32 GetRefCount() const
83     {
84         return refCount;
85     }
86 
GetBeginOffset()87     int32 GetBeginOffset() const
88     {
89         return beginOffset;
90     }
91 
92     MOperator PickMovBetweenRegs(PrimType destType, PrimType srcType) const;
93     MOperator PickMovInsn(const RegOperand &lhs, const RegOperand &rhs) const;
94 
NewVRflag()95     regno_t NewVRflag() override
96     {
97         DEBUG_ASSERT(GetMaxRegNum() > kRFLAG, "CG internal error.");
98         constexpr uint8 size = 4;
99         if (GetMaxRegNum() <= kRFLAG) {
100             IncMaxRegNum(kRFLAG + kVRegisterNumber);
101             vReg.VRegTableResize(GetMaxRegNum());
102         }
103         vReg.VRegTableValuesSet(kRFLAG, kRegTyCc, size);
104         return kRFLAG;
105     }
106 
107     CCImpl *GetOrCreateLocator(CallConvKind cc);
108     MIRType *LmbcGetAggTyFromCallSite(StmtNode *stmt, std::vector<TyIdx> **parmList) const;
109     RegOperand &GetOrCreateResOperand(const BaseNode &parent, PrimType primType);
110     MIRStructType *GetLmbcStructArgType(BaseNode &stmt, size_t argNo) const;
111 
112     // struct for delayed phy regs copy in param list
113     struct RegMapForPhyRegCpy {
RegMapForPhyRegCpyRegMapForPhyRegCpy114         RegMapForPhyRegCpy(RegOperand *dReg, PrimType dType, RegOperand *sReg, PrimType sType)
115             : destReg(dReg), destType(dType), srcReg(sReg), srcType(sType)
116         {
117         }
118         RegOperand *destReg;
119         PrimType destType;
120         RegOperand *srcReg;
121         PrimType srcType;
122     };
123 
124     void IntrinsifyGetAndAddInt(ListOperand &srcOpnds, PrimType pty);
125     void IntrinsifyGetAndSetInt(ListOperand &srcOpnds, PrimType pty);
126     void IntrinsifyCompareAndSwapInt(ListOperand &srcOpnds, PrimType pty);
127     void GenSaveMethodInfoCode(BB &bb) override;
128     void HandleRCCall(bool begin, const MIRSymbol *retRef = nullptr) override;
129     bool GenRetCleanup(const IntrinsiccallNode *cleanupNode, bool forEA = false);
130     void HandleRetCleanup(NaryStmtNode &retNode) override;
131     void MergeReturn() override;
132     RegOperand *ExtractMemBaseAddr(const MemOperand &memOpnd);
133     void SelectDassign(DassignNode &stmt, Operand &opnd0) override;
134     void SelectDassignoff(DassignoffNode &stmt, Operand &opnd0) override;
135     void SelectRegassign(RegassignNode &stmt, Operand &opnd0) override;
136     void SelectAbort() override;
137     void SelectAssertNull(UnaryStmtNode &stmt) override;
138     void SelectAsm(AsmNode &stmt) override;
139     MemOperand *GenFormalMemOpndWithSymbol(const MIRSymbol &sym, int64 offset);
140     MemOperand *SelectRhsMemOpnd(BaseNode &rhsStmt, bool &isRefField);
141     MemOperand *SelectRhsMemOpnd(BaseNode &rhsStmt);
142     MemOperand *GenLargeAggFormalMemOpnd(const MIRSymbol &sym, uint32 alignUsed, int64 offset, bool needLow12 = false);
143     MemOperand *FixLargeMemOpnd(MemOperand &memOpnd, uint32 align);
144     MemOperand *FixLargeMemOpnd(MOperator mOp, MemOperand &memOpnd, uint32 dSize, uint32 opndIdx);
145     uint32 LmbcFindTotalStkUsed(std::vector<TyIdx> *paramList);
146     uint32 LmbcTotalRegsUsed();
147     bool LmbcSmallAggForRet(const BaseNode &bNode, const Operand *src, int32 offset = 0, bool skip1 = false);
148     bool LmbcSmallAggForCall(BlkassignoffNode &bNode, const Operand *src, std::vector<TyIdx> **parmList);
149     void SelectAggDassign(DassignNode &stmt) override;
150     void SelectIassign(IassignNode &stmt) override;
151     void SelectIassignoff(IassignoffNode &stmt) override;
152     void SelectIassignfpoff(IassignFPoffNode &stmt, Operand &opnd) override;
153     void SelectIassignspoff(PrimType pTy, int32 offset, Operand &opnd) override;
154     void SelectBlkassignoff(BlkassignoffNode &bNode, Operand *src) override;
155     void SelectAggIassign(IassignNode &stmt, Operand &lhsAddrOpnd) override;
156     void SelectReturnSendOfStructInRegs(BaseNode *x) override;
157     void SelectReturn(Operand *opnd0) override;
158     void SelectIgoto(Operand *opnd0) override;
159     bool DoCallerEnsureValidParm(RegOperand &destOpnd, RegOperand &srcOpnd, PrimType formalPType);
160     void SelectParmListSmallStruct(const MIRType &mirType, const CCLocInfo &ploc, Operand &addr, ListOperand &srcOpnds,
161                                    bool isSpecialArg, std::vector<RegMapForPhyRegCpy> &regMapForTmpBB);
162     void SelectParmListPassByStack(const MIRType &mirType, Operand &opnd, uint32 memOffset, bool preCopyed,
163                                    std::vector<Insn *> &insnForStackArgs);
164     void SelectCondGoto(CondGotoNode &stmt, Operand &opnd0, Operand &opnd1) override;
165     void SelectCondGoto(LabelOperand &targetOpnd, Opcode jmpOp, Opcode cmpOp, Operand &opnd0, Operand &opnd1,
166                         PrimType primType, bool signedCond);
167     void SelectCondSpecialCase1(CondGotoNode &stmt, BaseNode &opnd0) override;
168     void SelectCondSpecialCase2(const CondGotoNode &stmt, BaseNode &opnd0) override;
169     void SelectGoto(GotoNode &stmt) override;
170     void SelectCall(CallNode &callNode) override;
171     void SelectIcall(IcallNode &icallNode) override;
172     void SelectIntrinsicCall(IntrinsiccallNode &intrinsicCallNode) override;
173     Operand *SelectIntrinsicOpWithOneParam(IntrinsicopNode &intrinsicopNode, std::string name) override;
174     Operand *SelectIntrinsicOpWithNParams(IntrinsicopNode &intrinsicopNode, PrimType retType,
175                                           const std::string &name) override;
176     Operand *SelectCclz(IntrinsicopNode &intrinsicopNode) override;
177     Operand *SelectCctz(IntrinsicopNode &intrinsicopNode) override;
178     Operand *SelectCpopcount(IntrinsicopNode &intrinsicopNode) override;
179     Operand *SelectCparity(IntrinsicopNode &intrinsicopNode) override;
180     Operand *SelectCclrsb(IntrinsicopNode &intrinsicopNode) override;
181     Operand *SelectCisaligned(IntrinsicopNode &intrinsicopNode) override;
182     Operand *SelectCalignup(IntrinsicopNode &intrinsicopNode) override;
183     Operand *SelectCaligndown(IntrinsicopNode &intrinsicopNode) override;
184     Operand *SelectCSyncFetch(IntrinsicopNode &intrinsicopNode, Opcode op, bool fetchBefore) override;
185     Operand *SelectCSyncBoolCmpSwap(IntrinsicopNode &intrinsicopNode) override;
186     Operand *SelectCSyncValCmpSwap(IntrinsicopNode &intrinsicopNode) override;
187     Operand *SelectCSyncLockTestSet(IntrinsicopNode &intrinsicopNode, PrimType pty) override;
188     Operand *SelectCSyncSynchronize(IntrinsicopNode &intrinsicopNode) override;
189     AArch64isa::MemoryOrdering PickMemOrder(std::memory_order memOrder, bool isLdr) const;
190     Operand *SelectCAtomicLoadN(IntrinsicopNode &intrinsicopNode) override;
191     Operand *SelectCAtomicExchangeN(const IntrinsiccallNode &intrinsiccallNode) override;
192     Operand *SelectAtomicLoad(Operand &addrOpnd, PrimType primType, AArch64isa::MemoryOrdering memOrder);
193     Operand *SelectCReturnAddress(IntrinsicopNode &intrinsicopNode) override;
194     void SelectMembar(StmtNode &membar) override;
195     void SelectComment(CommentNode &comment) override;
196 
197     void HandleCatch() override;
198     Operand *SelectDread(const BaseNode &parent, AddrofNode &expr) override;
199     RegOperand *SelectRegread(RegreadNode &expr) override;
200 
201     void SelectAddrof(Operand &result, StImmOperand &stImm, FieldID field = 0);
202     void SelectAddrof(Operand &result, MemOperand &memOpnd, FieldID field = 0);
203     Operand *SelectCSyncCmpSwap(const IntrinsicopNode &intrinopNode, bool retBool = false);
204     Operand *SelectAddrof(AddrofNode &expr, const BaseNode &parent, bool isAddrofoff = false) override;
205     Operand *SelectAddrofoff(AddrofoffNode &expr, const BaseNode &parent) override;
206     Operand &SelectAddrofFunc(AddroffuncNode &expr, const BaseNode &parent) override;
207     Operand &SelectAddrofLabel(AddroflabelNode &expr, const BaseNode &parent) override;
208 
209     PrimType GetDestTypeFromAggSize(uint32 bitSize) const;
210 
211     Operand *SelectIread(const BaseNode &parent, IreadNode &expr, int extraOffset = 0,
212                          PrimType finalBitFieldDestType = kPtyInvalid) override;
213     Operand *SelectIreadoff(const BaseNode &parent, IreadoffNode &ireadoff) override;
214     Operand *SelectIreadfpoff(const BaseNode &parent, IreadFPoffNode &ireadoff) override;
215     Operand *SelectIntConst(const MIRIntConst &intConst, const BaseNode &parent) override;
216     Operand *SelectIntConst(const MIRIntConst &intConst);
217     Operand *HandleFmovImm(PrimType stype, int64 val, MIRConst &mirConst, const BaseNode &parent);
218     Operand *SelectFloatConst(MIRFloatConst &floatConst, const BaseNode &parent) override;
219     Operand *SelectDoubleConst(MIRDoubleConst &doubleConst, const BaseNode &parent) override;
220     Operand *SelectStrConst(MIRStrConst &strConst) override;
221     Operand *SelectStr16Const(MIRStr16Const &str16Const) override;
222 
223     void SelectAdd(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
224     Operand *SelectAdd(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
225     Operand &SelectCGArrayElemAdd(BinaryNode &node, const BaseNode &parent) override;
226     void SelectMadd(Operand &resOpnd, Operand &oM0, Operand &oM1, Operand &o1, PrimType primeType) override;
227     Operand *SelectMadd(BinaryNode &node, Operand &oM0, Operand &oM1, Operand &o1, const BaseNode &parent) override;
228     Operand *SelectRor(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
229     Operand *SelectShift(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
230     Operand *SelectSub(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
231     void SelectSub(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
232     Operand *SelectBand(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
233     void SelectBand(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
234     Operand *SelectBior(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
235     void SelectBior(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
236     Operand *SelectBxor(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
237     void SelectBxor(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
238 
239     void SelectBxorShift(Operand &resOpnd, Operand *o0, Operand *o1, Operand &o2, PrimType primType);
240     Operand *SelectLand(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
241     Operand *SelectLor(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent,
242                        bool parentIsBr = false) override;
243     Operand *SelectMin(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
244     void SelectMin(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
245     Operand *SelectMax(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
246     void SelectMax(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
247     void SelectFMinFMax(Operand &resOpnd, Operand &o0, Operand &o1, bool is64Bits, bool isMin);
248     void SelectCmpOp(Operand &resOpnd, Operand &o0, Operand &o1, Opcode opCode, PrimType primType,
249                      const BaseNode &parent);
250 
251     Operand *SelectCmpOp(CompareNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
252 
253     void SelectAArch64Cmp(Operand &o, Operand &i, bool isIntType, uint32 dsize);
254     void SelectTargetFPCmpQuiet(Operand &o0, Operand &o1, uint32 dsize);
255     void SelectAArch64CCmp(Operand &o, Operand &i, Operand &nzcv, CondOperand &cond, bool is64Bits);
256     void SelectAArch64CSet(Operand &o, CondOperand &cond, bool is64Bits);
257     void SelectAArch64CSINV(Operand &res, Operand &o0, Operand &o1, CondOperand &cond, bool is64Bits);
258     void SelectAArch64CSINC(Operand &res, Operand &o0, Operand &o1, CondOperand &cond, bool is64Bits);
259     void SelectShift(Operand &resOpnd, Operand &o0, Operand &o1, ShiftDirection direct, PrimType primType);
260     Operand *SelectMpy(BinaryNode &node, Operand &o0, Operand &o1, const BaseNode &parent) override;
261     void SelectMpy(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType) override;
262     /* method description contains method information which is metadata for reflection. */
263     MemOperand *AdjustMemOperandIfOffsetOutOfRange(MemOperand *memOpnd, regno_t regNO, bool isDest, Insn &insn,
264                                                    AArch64reg regNum, bool &isOutOfRange);
265     void SelectAddAfterInsn(Operand &resOpnd, Operand &o0, Operand &o1, PrimType primType, bool isDest, Insn &insn);
266     bool IsImmediateOffsetOutOfRange(const MemOperand &memOpnd, uint32 bitLen);
267     bool IsOperandImmValid(MOperator mOp, Operand *o, uint32 opndIdx) const;
268     Operand *SelectRem(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) override;
269     void SelectDiv(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType) override;
270     Operand *SelectDiv(BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) override;
271     Operand *SelectAbsSub(Insn &lastInsn, const UnaryNode &node, Operand &newOpnd0);
272     Operand *SelectAbs(UnaryNode &node, Operand &opnd0) override;
273     Operand *SelectBnot(UnaryNode &node, Operand &opnd0, const BaseNode &parent) override;
274     Operand *SelectBswap(IntrinsicopNode &node, Operand &opnd0, const BaseNode &parent) override;
275     Operand *SelectExtractbits(ExtractbitsNode &node, Operand &opnd0, const BaseNode &parent) override;
276     Operand *SelectRegularBitFieldLoad(ExtractbitsNode &node, const BaseNode &parent) override;
277     Operand *SelectDepositBits(DepositbitsNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent) override;
278     Operand *SelectLnot(UnaryNode &node, Operand &opnd0, const BaseNode &parent) override;
279     Operand *SelectNeg(UnaryNode &node, Operand &opnd0, const BaseNode &parent) override;
280     void SelectNeg(Operand &dest, Operand &opnd0, PrimType primType);
281     void SelectMvn(Operand &dest, Operand &opnd0, PrimType primType);
282     Operand *SelectRecip(UnaryNode &node, Operand &opnd0, const BaseNode &parent) override;
283     Operand *SelectSqrt(UnaryNode &node, Operand &opnd0, const BaseNode &parent) override;
284     Operand *SelectCeil(TypeCvtNode &node, Operand &opnd0, const BaseNode &parent) override;
285     Operand *SelectFloor(TypeCvtNode &node, Operand &opnd0, const BaseNode &parent) override;
286     Operand *SelectRetype(TypeCvtNode &node, Operand &opnd0) override;
287     Operand *SelectRound(TypeCvtNode &node, Operand &opnd0, const BaseNode &parent) override;
288     Operand *SelectCvt(const BaseNode &parent, TypeCvtNode &node, Operand &opnd0) override;
289     Operand *SelectTrunc(TypeCvtNode &node, Operand &opnd0, const BaseNode &parent) override;
290     Operand *SelectSelect(TernaryNode &node, Operand &opnd0, Operand &opnd1, Operand &opnd2, const BaseNode &parent,
291                           bool hasCompare = false) override;
292     Operand *SelectMalloc(UnaryNode &call, Operand &opnd0) override;
293     Operand *SelectAlloca(UnaryNode &call, Operand &opnd0) override;
294     Operand *SelectGCMalloc(GCMallocNode &call) override;
295     Operand *SelectJarrayMalloc(JarrayMallocNode &call, Operand &opnd0) override;
296     void SelectSelect(Operand &resOpnd, Operand &condOpnd, Operand &trueOpnd, Operand &falseOpnd, PrimType dtype,
297                       PrimType ctype, bool hasCompare = false, ConditionCode cc = CC_NE);
298     void SelectAArch64Select(Operand &dest, Operand &opnd0, Operand &opnd1, CondOperand &cond, bool isIntType,
299                              uint32 is64bits);
300     void SelectRangeGoto(RangeGotoNode &rangeGotoNode, Operand &opnd0) override;
301     Operand *SelectLazyLoad(Operand &opnd0, PrimType primType) override;
302     Operand *SelectLazyLoadStatic(MIRSymbol &st, int64 offset, PrimType primType) override;
303     Operand *SelectLoadArrayClassCache(MIRSymbol &st, int64 offset, PrimType primType) override;
304     RegOperand &SelectCopy(Operand &src, PrimType stype, PrimType dtype) override;
305     void SelectCopy(Operand &dest, PrimType dtype, Operand &src, PrimType stype, BaseNode *baseNode = nullptr);
306     void SelectCopyImm(Operand &dest, PrimType dType, ImmOperand &src, PrimType sType);
307     void SelectCopyImm(Operand &dest, ImmOperand &src, PrimType dtype);
308     void SelectLibCall(const std::string &, std::vector<Operand *> &, PrimType, PrimType, bool is2ndRet = false);
309     void SelectLibCallNArg(const std::string &funcName, std::vector<Operand *> &opndVec, std::vector<PrimType> pt,
310                            PrimType retPrimType, bool is2ndRet);
311     bool IsRegRematCand(const RegOperand &reg) const;
312     void ClearRegRematInfo(const RegOperand &reg) const;
313     bool IsRegSameRematInfo(const RegOperand &regDest, const RegOperand &regSrc) const;
314     void ReplaceOpndInInsn(RegOperand &regDest, RegOperand &regSrc, Insn &insn, regno_t destNO) override;
315     void CleanupDeadMov(bool dump = false) override;
316     void GetRealCallerSaveRegs(const Insn &insn, std::set<regno_t> &realSaveRegs) override;
317     Operand &GetTargetRetOperand(PrimType primType, int32 sReg) override;
318     Operand &GetOrCreateRflag() override;
319     MemOperand *GetOrCreatSpillMem(regno_t vrNum, uint32 bitSize = k64BitSize) override;
320     const Operand *GetRflag() const override;
321     RegOperand &GetOrCreatevaryreg();
322     RegOperand &CreateRegisterOperandOfType(PrimType primType);
323     RegOperand &CreateRegisterOperandOfType(RegType regType, uint32 byteLen);
324     RegOperand &CreateRflagOperand();
325     RegOperand &GetOrCreateSpecialRegisterOperand(PregIdx sregIdx, PrimType primType);
326     void FreeSpillRegMem(regno_t vrNum);
327     RegOperand &GetOrCreatePhysicalRegisterOperand(AArch64reg regNO, uint32 size, RegType type, uint32 flag = 0);
328     RegOperand &GetOrCreatePhysicalRegisterOperand(std::string &asmAttr);
329     RegOperand *CreateVirtualRegisterOperand(regno_t vRegNO, uint32 size, RegType kind, uint32 flg = 0) const;
330     RegOperand &CreateVirtualRegisterOperand(regno_t vregNO) override;
331     RegOperand &GetOrCreateVirtualRegisterOperand(regno_t vregNO) override;
332     RegOperand &GetOrCreateVirtualRegisterOperand(RegOperand &regOpnd) override;
333     const LabelOperand *GetLabelOperand(LabelIdx labIdx) const override;
334     LabelOperand &GetOrCreateLabelOperand(LabelIdx labIdx) override;
335     LabelOperand &GetOrCreateLabelOperand(BB &bb) override;
336     uint32 GetAggCopySize(uint32 offset1, uint32 offset2, uint32 alignment) const;
337 
338     RegOperand *SelectVectorAddLong(PrimType rTy, Operand *o1, Operand *o2, PrimType oty, bool isLow) override;
339     RegOperand *SelectVectorAddWiden(Operand *o1, PrimType otyp1, Operand *o2, PrimType otyp2, bool isLow) override;
340     RegOperand *SelectVectorAbs(PrimType rType, Operand *o1) override;
341     RegOperand *SelectVectorBinOp(PrimType rType, Operand *o1, PrimType oTyp1, Operand *o2, PrimType oTyp2,
342                                   Opcode opc) override;
343     RegOperand *SelectVectorBitwiseOp(PrimType rType, Operand *o1, PrimType oTyp1, Operand *opnd2, PrimType oTyp2,
344                                       Opcode opc) override;
345     RegOperand *SelectVectorCompare(Operand *o1, PrimType oty1, Operand *o2, PrimType oty2, Opcode opc) override;
346     RegOperand *SelectVectorCompareZero(Operand *o1, PrimType oty1, Operand *o2, Opcode opc) override;
347     RegOperand *SelectOneElementVectorCopy(Operand *opnd, PrimType sType);
348     RegOperand *SelectVectorImmMov(PrimType rType, Operand *src, PrimType sType);
349     RegOperand *SelectVectorRegMov(PrimType rType, Operand *src, PrimType sType);
350     RegOperand *SelectVectorFromScalar(PrimType pType, Operand *opnd, PrimType sType) override;
351     RegOperand *SelectVectorGetElement(PrimType rType, Operand *src, PrimType sType, int32 lane) override;
352     RegOperand *SelectVectorDup(PrimType rType, Operand *src, bool getLow) override;
353     RegOperand *SelectVectorAbsSubL(PrimType rType, Operand *o1, Operand *o2, PrimType oTy, bool isLow) override;
354     RegOperand *SelectVectorMadd(Operand *o1, PrimType oTyp1, Operand *o2, PrimType oTyp2, Operand *o3,
355                                  PrimType oTyp3) override;
356     RegOperand *SelectVectorMerge(PrimType rTyp, Operand *o1, Operand *o2, int32 iNum) override;
357     RegOperand *SelectVectorMull(PrimType rType, Operand *o1, PrimType oTyp1, Operand *o2, PrimType oTyp2,
358                                  bool isLow) override;
359     RegOperand *SelectVectorNarrow(PrimType rType, Operand *o1, PrimType otyp) override;
360     RegOperand *SelectVectorNarrow2(PrimType rType, Operand *o1, PrimType oty1, Operand *o2, PrimType oty2) override;
361     RegOperand *SelectVectorNeg(PrimType rType, Operand *o1) override;
362     RegOperand *SelectVectorNot(PrimType rType, Operand *o1) override;
363     RegOperand *SelectVectorPairwiseAdalp(Operand *src1, PrimType sty1, Operand *src2, PrimType sty2) override;
364     RegOperand *SelectVectorPairwiseAdd(PrimType rType, Operand *src, PrimType sType) override;
365     RegOperand *SelectVectorReverse(PrimType rtype, Operand *src, PrimType stype, uint32 size) override;
366     RegOperand *SelectVectorSetElement(Operand *eOp, PrimType eTyp, Operand *vOpd, PrimType vTyp, int32 lane) override;
367     RegOperand *SelectVectorSelect(Operand &cond, PrimType rType, Operand &o0, Operand &o1);
368     RegOperand *SelectVectorShift(PrimType rType, Operand *o1, PrimType oty1, Operand *o2, PrimType oty2,
369                                   Opcode opc) override;
370     RegOperand *SelectVectorShiftImm(PrimType rType, Operand *o1, Operand *imm, int32 sVal, Opcode opc) override;
371     RegOperand *SelectVectorShiftRNarrow(PrimType rType, Operand *o1, PrimType oTyp, Operand *o2, bool isLow) override;
372     RegOperand *SelectVectorSubWiden(PrimType resType, Operand *o1, PrimType otyp1, Operand *o2, PrimType otyp2,
373                                      bool isLow, bool isWide) override;
374     RegOperand *SelectVectorSum(PrimType rtype, Operand *o1, PrimType oType) override;
375     RegOperand *SelectVectorTableLookup(PrimType rType, Operand *o1, Operand *o2) override;
376     RegOperand *SelectVectorWiden(PrimType rType, Operand *o1, PrimType otyp, bool isLow) override;
377 
378     void SelectVectorCvt(Operand *res, PrimType rType, Operand *o1, PrimType oType);
379     void SelectVectorZip(PrimType rType, Operand *o1, Operand *o2);
380     void PrepareVectorOperands(Operand **o1, PrimType &oty1, Operand **o2, PrimType &oty2);
381     RegOperand *AdjustOneElementVectorOperand(PrimType oType, RegOperand *opnd);
382     bool DistanceCheck(const BB &bb, LabelIdx targLabIdx, uint32 targId, uint32 maxDistance) const;
383 
FilterOneElementVectorType(PrimType origTyp)384     PrimType FilterOneElementVectorType(PrimType origTyp) const
385     {
386         PrimType nType = origTyp;
387         if (origTyp == PTY_i64 || origTyp == PTY_u64) {
388             nType = PTY_f64;
389         }
390         return nType;
391     }
392 
CreateImmOperand(PrimType ptyp,int64 val)393     ImmOperand &CreateImmOperand(PrimType ptyp, int64 val) override
394     {
395         return CreateImmOperand(val, GetPrimTypeBitSize(ptyp), IsSignedInteger(ptyp));
396     }
397 
GetFloatRflag()398     const Operand *GetFloatRflag() const override
399     {
400         return nullptr;
401     }
402     /* create an integer immediate operand */
403     ImmOperand &CreateImmOperand(int64 val, uint32 size, bool isSigned, VaryType varyType = kNotVary,
404                                  bool isFmov = false) const
405     {
406         return *memPool->New<ImmOperand>(val, size, isSigned, varyType, isFmov);
407     }
408 
CreateImmOperand(Operand::OperandType type,int64 val,uint32 size,bool isSigned)409     ImmOperand &CreateImmOperand(Operand::OperandType type, int64 val, uint32 size, bool isSigned)
410     {
411         return *memPool->New<ImmOperand>(type, val, size, isSigned);
412     }
413 
CreateListOpnd(MapleAllocator & allocator)414     ListOperand *CreateListOpnd(MapleAllocator &allocator)
415     {
416         return memPool->New<ListOperand>(allocator);
417     }
418 
419     OfstOperand &GetOrCreateOfstOpnd(uint64 offset, uint32 size);
420 
CreateOfstOpnd(uint64 offset,uint32 size)421     OfstOperand &CreateOfstOpnd(uint64 offset, uint32 size) const
422     {
423         return *memPool->New<OfstOperand>(offset, size);
424     }
425 
CreateOfstOpnd(const MIRSymbol & mirSymbol,int32 relocs)426     OfstOperand &CreateOfstOpnd(const MIRSymbol &mirSymbol, int32 relocs) const
427     {
428         return *memPool->New<OfstOperand>(mirSymbol, 0, relocs);
429     }
430 
CreateOfstOpnd(const MIRSymbol & mirSymbol,int64 offset,int32 relocs)431     OfstOperand &CreateOfstOpnd(const MIRSymbol &mirSymbol, int64 offset, int32 relocs) const
432     {
433         return *memPool->New<OfstOperand>(mirSymbol, 0, offset, relocs);
434     }
435 
CreateStImmOperand(const MIRSymbol & mirSymbol,int64 offset,int32 relocs)436     StImmOperand &CreateStImmOperand(const MIRSymbol &mirSymbol, int64 offset, int32 relocs) const
437     {
438         return *memPool->New<StImmOperand>(mirSymbol, offset, relocs);
439     }
440 
GetOrCreateFramePointerRegOperand()441     RegOperand &GetOrCreateFramePointerRegOperand() override
442     {
443         return GetOrCreateStackBaseRegOperand();
444     }
445 
GetOrCreateStackBaseRegOperand()446     RegOperand &GetOrCreateStackBaseRegOperand() override
447     {
448         AArch64reg reg;
449         if (GetMirModule().GetFlavor() == MIRFlavor::kFlavorLmbc) {
450             reg = RSP;
451         } else {
452             reg = RFP;
453         }
454         return GetOrCreatePhysicalRegisterOperand(reg, GetPointerSize() * kBitsPerByte, kRegTyInt);
455     }
456 
457     struct SplittedInt128 {
458         Operand &low;
459         Operand &high;
460     };
461 
462     void SetMemReferenceOfInsn(Insn &insn, BaseNode *baseNode);
463     struct SplittedInt128 SplitInt128(Operand &opnd);
464     RegOperand &CombineInt128(const SplittedInt128 parts);
465     void CombineInt128(Operand &resOpnd, const SplittedInt128 parts);
466     RegOperand &GenStructParamIndex(RegOperand &base, const BaseNode &indexExpr, int shift, PrimType baseType);
467     void SelectParmListForInt128(Operand &opnd, ListOperand &srcOpnds, const CCLocInfo &ploc, bool isSpecialArg,
468                                  std::vector<RegMapForPhyRegCpy> &regMapForTmpBB);
469     void SelectAddrofAfterRa(Operand &result, StImmOperand &stImm, std::vector<Insn *> &rematInsns);
470     MemOperand &GetOrCreateMemOpndAfterRa(const MIRSymbol &symbol, int32 offset, uint32 size, bool needLow12,
471                                           RegOperand *regOp, std::vector<Insn *> &rematInsns);
472 
473     MemOperand &GetOrCreateMemOpnd(const MIRSymbol &symbol, int64 offset, uint32 size, bool forLocalRef = false,
474                                    bool needLow12 = false, RegOperand *regOp = nullptr);
475 
476     MemOperand &HashMemOpnd(MemOperand &tMemOpnd);
477 
478     MemOperand &GetOrCreateMemOpnd(MemOperand::AArch64AddressingMode mode, uint32 size, RegOperand *base,
479                                    RegOperand *index, ImmOperand *offset, const MIRSymbol *st);
480 
481     MemOperand &GetOrCreateMemOpnd(MemOperand::AArch64AddressingMode, uint32 size, RegOperand *base, RegOperand *index,
482                                    int32 shift, bool isSigned = false);
483 
484     MemOperand &GetOrCreateMemOpnd(MemOperand &oldMem);
485 
CreateMemOpnd(AArch64reg reg,int64 offset,uint32 size)486     MemOperand &CreateMemOpnd(AArch64reg reg, int64 offset, uint32 size)
487     {
488         RegOperand &baseOpnd = GetOrCreatePhysicalRegisterOperand(reg, GetPointerSize() * kBitsPerByte, kRegTyInt);
489         return CreateMemOpnd(baseOpnd, offset, size);
490     }
491 
492     MemOperand &CreateMemOpnd(RegOperand &baseOpnd, int64 offset, uint32 size);
493 
494     MemOperand &CreateMemOpnd(RegOperand &baseOpnd, int64 offset, uint32 size, const MIRSymbol &sym);
495 
496     MemOperand &CreateMemOpnd(PrimType ptype, const BaseNode &parent, BaseNode &addrExpr, int64 offset = 0,
497                               AArch64isa::MemoryOrdering memOrd = AArch64isa::kMoNone);
498 
499     MemOperand *CreateMemOpndOrNull(PrimType ptype, const BaseNode &parent, BaseNode &addrExpr, int64 offset = 0,
500                                     AArch64isa::MemoryOrdering memOrd = AArch64isa::kMoNone);
501 
GetCondOperand(ConditionCode op)502     CondOperand &GetCondOperand(ConditionCode op) const
503     {
504         return ccOperands[op];
505     }
506 
507     BitShiftOperand *GetLogicalShiftLeftOperand(uint32 shiftAmount, bool is64bits) const;
508 
CreateBitShiftOperand(BitShiftOperand::ShiftOp op,uint32 amount,int32 bitLen)509     BitShiftOperand &CreateBitShiftOperand(BitShiftOperand::ShiftOp op, uint32 amount, int32 bitLen) const
510     {
511         return *memPool->New<BitShiftOperand>(op, amount, bitLen);
512     }
513 
CreateExtendShiftOperand(ExtendShiftOperand::ExtendOp op,uint32 amount,int32 bitLen)514     ExtendShiftOperand &CreateExtendShiftOperand(ExtendShiftOperand::ExtendOp op, uint32 amount, int32 bitLen) const
515     {
516         return *memPool->New<ExtendShiftOperand>(op, amount, bitLen);
517     }
518 
519     void SplitMovImmOpndInstruction(int64 immVal, RegOperand &destReg, Insn *curInsn = nullptr);
520 
521     Operand &GetOrCreateFuncNameOpnd(const MIRSymbol &symbol) const;
522     void GenerateYieldpoint(BB &bb) override;
523     void GenerateCleanupCode(BB &bb) override;
524     bool NeedCleanup() override;
525     void GenerateCleanupCodeForExtEpilog(BB &bb) override;
526     uint32 FloatParamRegRequired(MIRStructType *structType, uint32 &fpSize) override;
527     void AssignLmbcFormalParams() override;
528     void LmbcGenSaveSpForAlloca() override;
529     MemOperand *GenLmbcFpMemOperand(int32 offset, uint32 byteSize, AArch64reg base = RFP);
530     RegOperand *GenLmbcParamLoad(int32 offset, uint32 byteSize, RegType regType, PrimType primType,
531                                  AArch64reg baseRegno = RFP);
532     RegOperand *LmbcStructReturnLoad(int32 offset);
533     RegOperand *GetBaseReg(const SymbolAlloc &symAlloc) override;
534     int32 GetBaseOffset(const SymbolAlloc &symAlloc) override;
535 
CreateCommentOperand(const std::string & s)536     Operand &CreateCommentOperand(const std::string &s) const
537     {
538         return *memPool->New<CommentOperand>(s, *memPool);
539     }
540 
CreateCommentOperand(const MapleString & s)541     Operand &CreateCommentOperand(const MapleString &s) const
542     {
543         return *memPool->New<CommentOperand>(s.c_str(), *memPool);
544     }
545 
CreateStringOperand(const std::string & s)546     Operand &CreateStringOperand(const std::string &s) const
547     {
548         return *memPool->New<StringOperand>(s, *memPool);
549     }
550 
CreateStringOperand(const MapleString & s)551     Operand &CreateStringOperand(const MapleString &s) const
552     {
553         return *memPool->New<StringOperand>(s.c_str(), *memPool);
554     }
555 
AddtoCalleeSaved(regno_t reg)556     void AddtoCalleeSaved(regno_t reg) override
557     {
558         if (!UseFP() && reg == R29) {
559             reg = RFP;
560         }
561         if (find(calleeSavedRegs.begin(), calleeSavedRegs.end(), reg) != calleeSavedRegs.end()) {
562             return;
563         }
564         calleeSavedRegs.emplace_back(static_cast<AArch64reg>(reg));
565         DEBUG_ASSERT((AArch64isa::IsGPRegister(static_cast<AArch64reg>(reg)) ||
566                       AArch64isa::IsFPSIMDRegister(static_cast<AArch64reg>(reg))),
567                      "Int or FP registers are expected");
568         if (AArch64isa::IsGPRegister(static_cast<AArch64reg>(reg))) {
569             ++numIntregToCalleeSave;
570         } else {
571             ++numFpregToCalleeSave;
572         }
573     }
574 
SizeOfCalleeSaved()575     uint32 SizeOfCalleeSaved() const
576     {
577         /* npairs = num / 2 + num % 2 */
578         uint32 nPairs = (numIntregToCalleeSave >> 1) + (numIntregToCalleeSave & 0x1);
579         nPairs += (numFpregToCalleeSave >> 1) + (numFpregToCalleeSave & 0x1);
580         return (nPairs * (kAarch64IntregBytelen << 1));
581     }
582 
583     void DBGFixCallFrameLocationOffsets() override;
584 
NoteFPLRAddedToCalleeSavedList()585     void NoteFPLRAddedToCalleeSavedList()
586     {
587         fplrAddedToCalleeSaved = true;
588     }
589 
IsFPLRAddedToCalleeSavedList()590     bool IsFPLRAddedToCalleeSavedList() const
591     {
592         return fplrAddedToCalleeSaved;
593     }
594 
IsIntrnCallForC()595     bool IsIntrnCallForC() const
596     {
597         return isIntrnCallForC;
598     }
599 
UsedStpSubPairForCallFrameAllocation()600     bool UsedStpSubPairForCallFrameAllocation() const
601     {
602         return usedStpSubPairToAllocateCallFrame;
603     }
SetUsedStpSubPairForCallFrameAllocation(bool val)604     void SetUsedStpSubPairForCallFrameAllocation(bool val)
605     {
606         usedStpSubPairToAllocateCallFrame = val;
607     }
608 
GetCalleeSavedRegs()609     const MapleVector<AArch64reg> &GetCalleeSavedRegs() const
610     {
611         return calleeSavedRegs;
612     }
613 
GetYieldPointInsn()614     Insn *GetYieldPointInsn()
615     {
616         return yieldPointInsn;
617     }
618 
GetYieldPointInsn()619     const Insn *GetYieldPointInsn() const
620     {
621         return yieldPointInsn;
622     }
623 
GetCleanEANode()624     IntrinsiccallNode *GetCleanEANode()
625     {
626         return cleanEANode;
627     }
628 
629     MemOperand &CreateStkTopOpnd(uint32 offset, uint32 size);
630     MemOperand *CreateStackMemOpnd(regno_t preg, int32 offset, uint32 size);
631     MemOperand *CreateMemOperand(uint32 size, RegOperand &base, ImmOperand &ofstOp, bool isVolatile,
632                                  MemOperand::AArch64AddressingMode mode = MemOperand::kAddrModeBOi) const;
633     MemOperand *CreateMemOperand(MemOperand::AArch64AddressingMode mode, uint32 size, RegOperand &base,
634                                  RegOperand *index, ImmOperand *offset, const MIRSymbol *symbol) const;
635     MemOperand *CreateMemOperand(MemOperand::AArch64AddressingMode mode, uint32 size, RegOperand &base,
636                                  RegOperand &index, ImmOperand *offset, const MIRSymbol &symbol, bool noExtend);
637     MemOperand *CreateMemOperand(MemOperand::AArch64AddressingMode mode, uint32 dSize, RegOperand &base,
638                                  RegOperand &indexOpnd, uint32 shift, bool isSigned = false) const;
639     MemOperand *CreateMemOperand(MemOperand::AArch64AddressingMode mode, uint32 dSize, const MIRSymbol &sym);
640 
641     /* if offset < 0, allocation; otherwise, deallocation */
642     MemOperand &CreateCallFrameOperand(int32 offset, uint32 size);
643 
644     void AppendCall(const MIRSymbol &func);
645     Insn &AppendCall(const MIRSymbol &func, ListOperand &srcOpnds);
646 
647     static constexpr uint32 kDwarfFpRegBegin = 64;
648     static constexpr int32 kBitLenOfShift64Bits =
649         6; /* for 64 bits register, shift amount is 0~63, use 6 bits to store */
650     static constexpr int32 kBitLenOfShift32Bits =
651         5; /* for 32 bits register, shift amount is 0~31, use 5 bits to store */
652     static constexpr int32 kHighestBitOf64Bits = 63; /* 63 is highest bit of a 64 bits number */
653     static constexpr int32 kHighestBitOf32Bits = 31; /* 31 is highest bit of a 32 bits number */
654     static constexpr int32 k16ValidBit = 16;
655 
656     /* CFI directives related stuffs */
CreateCfiRegOperand(uint32 reg,uint32 size)657     Operand &CreateCfiRegOperand(uint32 reg, uint32 size) override
658     {
659         /*
660          * DWARF for ARM Architecture (ARM IHI 0040B) 3.1 Table 1
661          * Having kRinvalid=0 (see arm32_isa.h) means
662          * each register gets assigned an id number one greater than
663          * its physical number
664          */
665         if (reg < V0) {
666             return *memPool->New<cfi::RegOperand>((reg - R0), size);
667         } else {
668             return *memPool->New<cfi::RegOperand>((reg - V0) + kDwarfFpRegBegin, size);
669         }
670     }
671 
SetCatchRegno(regno_t regNO)672     void SetCatchRegno(regno_t regNO)
673     {
674         uCatch.regNOCatch = regNO;
675     }
676 
GetCatchRegno()677     regno_t GetCatchRegno() const
678     {
679         return uCatch.regNOCatch;
680     }
681 
SetCatchOpnd(Operand & opnd)682     void SetCatchOpnd(Operand &opnd)
683     {
684         uCatch.opndCatch = &opnd;
685     }
686 
687     AArch64reg GetReturnRegisterNumber();
688 
689     MOperator PickStInsn(uint32 bitSize, PrimType primType,
690                          AArch64isa::MemoryOrdering memOrd = AArch64isa::kMoNone) const;
691     MOperator PickLdInsn(uint32 bitSize, PrimType primType,
692                          AArch64isa::MemoryOrdering memOrd = AArch64isa::kMoNone) const;
693     MOperator PickExtInsn(PrimType dtype, PrimType stype) const;
694 
695     bool CheckIfSplitOffsetWithAdd(const MemOperand &memOpnd, uint32 bitLen) const;
696     RegOperand *GetBaseRegForSplit(uint32 baseRegNum);
697 
698     MemOperand &ConstraintOffsetToSafeRegion(uint32 bitLen, const MemOperand &memOpnd, const MIRSymbol *symbol);
699     MemOperand &SplitOffsetWithAddInstruction(const MemOperand &memOpnd, uint32 bitLen,
700                                               uint32 baseRegNum = AArch64reg::kRinvalid, bool isDest = false,
701                                               Insn *insn = nullptr, bool forPair = false);
702     ImmOperand &SplitAndGetRemained(const MemOperand &memOpnd, uint32 bitLen, RegOperand *resOpnd, int64 ofstVal,
703                                     bool isDest = false, Insn *insn = nullptr, bool forPair = false);
704     MemOperand &CreateReplacementMemOperand(uint32 bitLen, RegOperand &baseReg, int64 offset);
705 
706     bool HasStackLoadStore();
707 
708     MemOperand &LoadStructCopyBase(const MIRSymbol &symbol, int64 offset, int datasize);
709 
GetSplitBaseOffset()710     int32 GetSplitBaseOffset() const
711     {
712         return splitStpldpBaseOffset;
713     }
SetSplitBaseOffset(int32 val)714     void SetSplitBaseOffset(int32 val)
715     {
716         splitStpldpBaseOffset = val;
717     }
718 
CreateCommentInsn(const std::string & comment)719     Insn &CreateCommentInsn(const std::string &comment)
720     {
721         Insn &insn = GetInsnBuilder()->BuildInsn(abstract::MOP_comment, InsnDesc::GetAbstractId(abstract::MOP_comment));
722         insn.AddOperand(CreateCommentOperand(comment));
723         return insn;
724     }
725 
CreateCommentInsn(const MapleString & comment)726     Insn &CreateCommentInsn(const MapleString &comment)
727     {
728         Insn &insn = GetInsnBuilder()->BuildInsn(abstract::MOP_comment, InsnDesc::GetAbstractId(abstract::MOP_comment));
729         insn.AddOperand(CreateCommentOperand(comment));
730         return insn;
731     }
732 
CreateCfiRestoreInsn(uint32 reg,uint32 size)733     Insn &CreateCfiRestoreInsn(uint32 reg, uint32 size)
734     {
735         return GetInsnBuilder()->BuildCfiInsn(cfi::OP_CFI_restore).AddOpndChain(CreateCfiRegOperand(reg, size));
736     }
737 
CreateCfiOffsetInsn(uint32 reg,int64 val,uint32 size)738     Insn &CreateCfiOffsetInsn(uint32 reg, int64 val, uint32 size)
739     {
740         return GetInsnBuilder()
741             ->BuildCfiInsn(cfi::OP_CFI_offset)
742             .AddOpndChain(CreateCfiRegOperand(reg, size))
743             .AddOpndChain(CreateCfiImmOperand(val, size));
744     }
CreateCfiDefCfaInsn(uint32 reg,int64 val,uint32 size)745     Insn &CreateCfiDefCfaInsn(uint32 reg, int64 val, uint32 size)
746     {
747         return GetInsnBuilder()
748             ->BuildCfiInsn(cfi::OP_CFI_def_cfa)
749             .AddOpndChain(CreateCfiRegOperand(reg, size))
750             .AddOpndChain(CreateCfiImmOperand(val, size));
751     }
752 
NewInsnModifier()753     InsnVisitor *NewInsnModifier() override
754     {
755         return memPool->New<AArch64InsnVisitor>(*this);
756     }
757 
758     RegType GetRegisterType(regno_t reg) const override;
759 
MaxCondBranchDistance()760     uint32 MaxCondBranchDistance() override
761     {
762         return AArch64Abi::kMaxInstrForCondBr;
763     }
764 
765     void InsertJumpPad(Insn *insn) override;
766 
767     MIRPreg *GetPseudoRegFromVirtualRegNO(const regno_t vRegNO, bool afterSSA = false) const;
768 
GetProEpilogSavedRegs()769     MapleVector<AArch64reg> &GetProEpilogSavedRegs()
770     {
771         return proEpilogSavedRegs;
772     }
773 
GetDefaultAlignPow()774     uint32 GetDefaultAlignPow() const
775     {
776         return alignPow;
777     }
778 
GetLmbcArgInfo()779     LmbcArgInfo *GetLmbcArgInfo()
780     {
781         return lmbcArgInfo;
782     }
783 
SetLmbcArgInfo(LmbcArgInfo * p)784     void SetLmbcArgInfo(LmbcArgInfo *p)
785     {
786         lmbcArgInfo = p;
787     }
788 
SetLmbcArgInfo(RegOperand * reg,PrimType pTy,int32 ofst,int32 regs)789     void SetLmbcArgInfo(RegOperand *reg, PrimType pTy, int32 ofst, int32 regs)
790     {
791         (void)GetLmbcCallArgs().emplace_back(reg);
792         (void)GetLmbcCallArgTypes().emplace_back(pTy);
793         (void)GetLmbcCallArgOffsets().emplace_back(ofst);
794         (void)GetLmbcCallArgNumOfRegs().emplace_back(regs);
795     }
796 
ResetLmbcArgInfo()797     void ResetLmbcArgInfo()
798     {
799         GetLmbcCallArgs().clear();
800         GetLmbcCallArgTypes().clear();
801         GetLmbcCallArgOffsets().clear();
802         GetLmbcCallArgNumOfRegs().clear();
803     }
804 
GetLmbcCallArgs()805     MapleVector<RegOperand *> &GetLmbcCallArgs() const
806     {
807         return lmbcArgInfo->lmbcCallArgs;
808     }
809 
GetLmbcCallArgTypes()810     MapleVector<PrimType> &GetLmbcCallArgTypes() const
811     {
812         return lmbcArgInfo->lmbcCallArgTypes;
813     }
814 
GetLmbcCallArgOffsets()815     MapleVector<int32> &GetLmbcCallArgOffsets() const
816     {
817         return lmbcArgInfo->lmbcCallArgOffsets;
818     }
819 
GetLmbcCallArgNumOfRegs()820     MapleVector<int32> &GetLmbcCallArgNumOfRegs() const
821     {
822         return lmbcArgInfo->lmbcCallArgNumOfRegs;
823     }
824 
GetLmbcTotalStkUsed()825     int32 GetLmbcTotalStkUsed() const
826     {
827         return lmbcArgInfo->lmbcTotalStkUsed;
828     }
829 
SetLmbcTotalStkUsed(int32 offset)830     void SetLmbcTotalStkUsed(int32 offset)
831     {
832         lmbcArgInfo->lmbcTotalStkUsed = static_cast<uint32>(offset);
833     }
834 
SetLmbcCallReturnType(MIRType * ty)835     void SetLmbcCallReturnType(MIRType *ty)
836     {
837         lmbcCallReturnType = ty;
838     }
839 
GetLmbcCallReturnType()840     MIRType *GetLmbcCallReturnType()
841     {
842         return lmbcCallReturnType;
843     }
844 
845     bool IsSPOrFP(const RegOperand &opnd) const override;
846     bool IsReturnReg(const RegOperand &opnd) const override;
847     bool IsSaveReg(const RegOperand &reg, MIRType &mirType, BECommon &cgBeCommon) override;
848 
849     RegOperand &GetZeroOpnd(uint32 size) override;
850 
GetStoreFP()851     bool GetStoreFP() const
852     {
853         return storeFP;
854     }
SetStoreFP(bool val)855     void SetStoreFP(bool val)
856     {
857         storeFP = val;
858     }
859 
GetLabelInInsn(Insn & insn)860     LabelIdx GetLabelInInsn(Insn &insn) override
861     {
862         return static_cast<LabelOperand &>(insn.GetOperand(AArch64isa::GetJumpTargetIdx(insn))).GetLabelIndex();
863     }
864 
865 private:
866     enum RelationOperator : uint8 { kAND, kIOR, kEOR };
867 
868     enum RelationOperatorOpndPattern : uint8 { kRegReg, kRegImm };
869 
870     enum RoundType : uint8 { kCeil, kFloor, kRound, kTrunc };
871 
872     static constexpr int32 kMaxMovkLslEntries = 8;
873     using MovkLslOperandArray = std::array<BitShiftOperand, kMaxMovkLslEntries>;
874 
875     MapleVector<AArch64reg> calleeSavedRegs;
876     MapleVector<AArch64reg> proEpilogSavedRegs;
877     uint32 refCount = 0;            /* Ref count number. 0 if function don't have "bl MCC_InitializeLocalStackRef" */
878     int32 beginOffset = 0;          /* Begin offset based x29. */
879     Insn *yieldPointInsn = nullptr; /* The insn of yield point at the entry of the func. */
880     IntrinsiccallNode *cleanEANode = nullptr;
881 
882     MapleUnorderedMap<phyRegIdx, RegOperand *> phyRegOperandTable; /* machine register operand table */
883     MapleUnorderedMap<LabelIdx, LabelOperand *> hashLabelOpndTable;
884     MapleUnorderedMap<OfstRegIdx, OfstOperand *> hashOfstOpndTable;
885     MapleUnorderedMap<MemOperand, MemOperand *> hashMemOpndTable;
886     MapleUnorderedMap<StIdx, std::pair<RegOperand *, RegOperand *>> stIdx2OverflowResult;
887     /*
888      * Local variables, formal parameters that are passed via registers
889      * need offset adjustment after callee-saved registers are known.
890      */
891     MapleUnorderedMap<StIdx, MemOperand *> memOpndsRequiringOffsetAdjustment;
892     MapleUnorderedMap<StIdx, MemOperand *> memOpndsForStkPassedArguments;
893     MapleUnorderedMap<AArch64SymbolAlloc *, ImmOperand *> immOpndsRequiringOffsetAdjustment;
894     MapleUnorderedMap<AArch64SymbolAlloc *, ImmOperand *> immOpndsRequiringOffsetAdjustmentForRefloc;
895     MapleUnorderedMap<CallConvKind, CCImpl *> hashCCTable;
896     union {
897         regno_t regNOCatch; /* For O2. */
898         Operand *opndCatch; /* For O0-O1. */
899     } uCatch;
900     enum fpParamState {
901         kNotFp,
902         kFp32Bit,
903         kFp64Bit,
904         kStateUnknown,
905     };
906     Operand *rcc = nullptr;
907     RegOperand *vary = nullptr;
908     RegOperand *fsp = nullptr; /* used to point the address of local variables and formal parameters */
909 
910     static CondOperand ccOperands[kCcLast];
911     static MovkLslOperandArray movkLslOperands;
912     uint32 numIntregToCalleeSave = 0;
913     uint32 numFpregToCalleeSave = 0;
914     bool fplrAddedToCalleeSaved = false;
915     bool isIntrnCallForC = false;
916     bool usedStpSubPairToAllocateCallFrame = false;
917     int32 splitStpldpBaseOffset = 0;
918     regno_t methodHandleVreg = -1;
919     uint32 alignPow = 5; /* function align pow defaults to 5   i.e. 2^5*/
920     LmbcArgInfo *lmbcArgInfo = nullptr;
921     MIRType *lmbcCallReturnType = nullptr;
922     bool storeFP = false;
923 
924     void SelectLoadAcquire(Operand &dest, PrimType dtype, Operand &src, PrimType stype,
925                            AArch64isa::MemoryOrdering memOrd, bool isDirect);
926     void SelectStoreRelease(Operand &dest, PrimType dtype, Operand &src, PrimType stype,
927                             AArch64isa::MemoryOrdering memOrd, bool isDirect);
928     MOperator PickJmpInsn(Opcode brOp, Opcode cmpOp, bool isFloat, bool isSigned) const;
929     bool IsFrameReg(const RegOperand &opnd) const override;
930 
GetOperandTy(bool isIntty,uint32 dsize,bool isSigned)931     PrimType GetOperandTy(bool isIntty, uint32 dsize, bool isSigned) const
932     {
933         DEBUG_ASSERT(!isSigned || isIntty, "");
934         return (isIntty ? ((dsize == k64BitSize) ? (isSigned ? PTY_i64 : PTY_u64) : (isSigned ? PTY_i32 : PTY_u32))
935                         : ((dsize == k64BitSize) ? PTY_f64 : PTY_f32));
936     }
937 
938     RegOperand &LoadIntoRegister(Operand &o, bool isIntty, uint32 dsize, bool asSigned = false)
939     {
940         PrimType pTy;
941         if (o.GetKind() == Operand::kOpdRegister && static_cast<RegOperand &>(o).GetRegisterType() == kRegTyFloat) {
942             // f128 is a vector placeholder, no use for now
943             pTy = dsize == k32BitSize ? PTY_f32 : (dsize == k64BitSize ? PTY_f64 : PTY_f128);
944         } else {
945             pTy = GetOperandTy(isIntty, dsize, asSigned);
946         }
947         return LoadIntoRegister(o, pTy);
948     }
949 
LoadIntoRegister(Operand & o,PrimType oty)950     RegOperand &LoadIntoRegister(Operand &o, PrimType oty)
951     {
952         return (o.IsRegister() ? static_cast<RegOperand &>(o) : SelectCopy(o, oty, oty));
953     }
954 
LoadIntoRegister(Operand & o,PrimType dty,PrimType sty)955     RegOperand &LoadIntoRegister(Operand &o, PrimType dty, PrimType sty)
956     {
957         return (o.IsRegister() ? static_cast<RegOperand &>(o) : SelectCopy(o, sty, dty));
958     }
959 
960     bool MarkParmListCall(BaseNode &expr);
961 
962     struct ParamDesc {
963         ParamDesc(MIRType *type, BaseNode *expr, uint32 ofst = 0, bool copyed = false)
mirTypeParamDesc964             : mirType(type), argExpr(expr), offset(ofst), preCopyed(copyed)
965         {
966         }
967         MIRType *mirType = nullptr;
968         BaseNode *argExpr = nullptr;  // expr node
969         uint32 offset = 0;            // agg offset, for preCopyed struct, RSP-based offset
970         bool preCopyed = false;       // for large struct, pre copyed to strack
971         bool isSpecialArg = false;    // such as : tls
972     };
973 
974     std::pair<MIRFunction *, MIRFuncType *> GetCalleeFunction(StmtNode &naryNode) const;
975     void SelectLibMemCopy(RegOperand &destOpnd, RegOperand &srcOpnd, uint32 structSize);
976     void SelectInsnMemCopy(const MemOperand &destOpnd, const MemOperand &srcOpnd, uint32 size, bool isRefField = false,
977                            BaseNode *destNode = nullptr, BaseNode *srcNode = nullptr);
978     void SelectMemCopy(const MemOperand &destOpnd, const MemOperand &srcOpnd, uint32 size, bool isRefField = false,
979                        BaseNode *destNode = nullptr, BaseNode *srcNode = nullptr);
980     void SelectParmListPreprocessForAggregate(BaseNode &argExpr, int32 &structCopyOffset,
981                                               std::vector<ParamDesc> &argsDesc, bool isArgUnused);
982     bool SelectParmListPreprocess(StmtNode &naryNode, size_t start, std::vector<ParamDesc> &argsDesc,
983                                   const MIRFunction *callee = nullptr);
984     void SelectParmList(StmtNode &naryNode, ListOperand &srcOpnds, bool isCallNative = false);
985     void SelectParmListNotC(StmtNode &naryNode, ListOperand &srcOpnds);
986     Operand *SelectClearStackCallParam(const AddrofNode &expr, int64 &offsetValue);
987     void SelectClearStackCallParmList(const StmtNode &naryNode, ListOperand &srcOpnds,
988                                       std::vector<int64> &stackPostion);
989     void SelectRem(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType, bool isSigned, bool is64Bits);
990     void SelectCvtInt2Int(const BaseNode *parent, Operand *&resOpnd, Operand *opnd0, PrimType fromType,
991                           PrimType toType);
992     void SelectCvtFloat2Float(Operand &resOpnd, Operand &opnd0, PrimType fromType, PrimType toType);
993     void SelectCvtFloat2Int(Operand &resOpnd, Operand &opnd0, PrimType itype, PrimType ftype);
994     void SelectCvtInt2Float(Operand &resOpnd, Operand &opnd0, PrimType toType, PrimType fromType);
995     Operand *SelectRelationOperator(RelationOperator operatorCode, const BinaryNode &node, Operand &opnd0,
996                                     Operand &opnd1, const BaseNode &parent);
997     void SelectRelationOperator(RelationOperator operatorCode, Operand &resOpnd, Operand &opnd0, Operand &opnd1,
998                                 PrimType primType);
999     MOperator SelectRelationMop(RelationOperator operatorType, RelationOperatorOpndPattern opndPattern, bool is64Bits,
1000                                 bool IsBitmaskImmediate, bool isBitNumLessThan16) const;
1001     Operand *SelectMinOrMax(bool isMin, const BinaryNode &node, Operand &opnd0, Operand &opnd1, const BaseNode &parent);
1002     void SelectMinOrMax(bool isMin, Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType);
1003     Operand *SelectRoundLibCall(RoundType roundType, const TypeCvtNode &node, Operand &opnd0);
1004     Operand *SelectRoundOperator(RoundType roundType, const TypeCvtNode &node, Operand &opnd0, const BaseNode &parent);
1005     Operand *SelectAArch64ffs(Operand &argOpnd, PrimType argType);
1006     Operand *SelectAArch64align(const IntrinsicopNode &intrnNode, bool isUp /* false for align down */);
1007     void SelectCopyMemOpnd(Operand &dest, PrimType dtype, uint32 dsize, Operand &src, PrimType stype);
1008     void SelectCopyRegOpnd(Operand &dest, PrimType dtype, Operand::OperandType opndType, uint32 dsize, Operand &src,
1009                            PrimType stype);
1010     bool GenerateCompareWithZeroInstruction(Opcode jmpOp, Opcode cmpOp, bool is64Bits, PrimType primType,
1011                                             LabelOperand &targetOpnd, Operand &opnd0);
1012     void GenCVaStartIntrin(RegOperand &opnd, uint32 stkSize);
1013     void SelectCDIVException();
1014     void SelectCVaStart(const IntrinsiccallNode &intrnNode);
1015     void SelectOverFlowCall(const IntrinsiccallNode &intrnNode);
1016     void SelectCAtomicStoreN(const IntrinsiccallNode &intrinsiccallNode);
1017     void SelectCSyncLockRelease(const IntrinsiccallNode &intrinsiccallNode, PrimType primType);
1018     void SelectAtomicStore(Operand &srcOpnd, Operand &addrOpnd, PrimType primType, AArch64isa::MemoryOrdering memOrder);
1019     void SelectAddrofThreadLocal(Operand &result, StImmOperand &stImm);
1020     void SelectCTlsLocalDesc(Operand &result, StImmOperand &stImm);
1021     void SelectCTlsGlobalDesc(Operand &result, StImmOperand &stImm);
1022     void SelectMPLClinitCheck(const IntrinsiccallNode &);
1023     void SelectMPLProfCounterInc(const IntrinsiccallNode &intrnNode);
1024     void SelectArithmeticAndLogical(Operand &resOpnd, Operand &opnd0, Operand &opnd1, PrimType primType, Opcode op);
1025 
1026     Operand *SelectAArch64CSyncFetch(const maple::IntrinsicopNode &intrinsicopNode, Opcode op, bool fetchBefore);
1027     /* Helper functions for translating complex Maple IR instructions/inrinsics */
1028     void SelectDassign(StIdx stIdx, FieldID fieldId, PrimType rhsPType, Operand &opnd0);
1029     LabelIdx CreateLabeledBB(StmtNode &stmt);
1030     void SaveReturnValueInLocal(CallReturnVector &retVals, size_t index, PrimType primType, Operand &value,
1031                                 StmtNode &parentStmt);
1032     /* Translation for load-link store-conditional, and atomic RMW operations. */
1033     MemOrd OperandToMemOrd(Operand &opnd) const;
1034     MOperator PickLoadStoreExclInsn(uint32 byteP2Size, bool store, bool acqRel) const;
1035     RegOperand *SelectLoadExcl(PrimType valPrimType, MemOperand &loc, bool acquire);
1036     RegOperand *SelectStoreExcl(PrimType valPty, MemOperand &loc, RegOperand &newVal, bool release);
1037 
1038     MemOperand *GetPseudoRegisterSpillMemoryOperand(PregIdx i) override;
1039     void ProcessLazyBinding() override;
1040     bool CanLazyBinding(const Insn &insn) const;
1041     void ConvertAdrpl12LdrToLdr();
1042     void ConvertAdrpLdrToIntrisic();
1043     bool IsStoreMop(MOperator mOp) const;
1044     bool IsImmediateValueInRange(MOperator mOp, int64 immVal, bool is64Bits, bool isIntactIndexed, bool isPostIndexed,
1045                                  bool isPreIndexed) const;
1046     Insn &GenerateGlobalLongCallAfterInsn(const MIRSymbol &func, ListOperand &srcOpnds);
1047     Insn &GenerateLocalLongCallAfterInsn(const MIRSymbol &func, ListOperand &srcOpnds);
1048     bool IsDuplicateAsmList(const MIRSymbol &sym) const;
1049     RegOperand *CheckStringIsCompressed(BB &bb, RegOperand &str, int32 countOffset, PrimType countPty,
1050                                         LabelIdx jumpLabIdx);
1051     RegOperand *CheckStringLengthLessThanEight(BB &bb, RegOperand &countOpnd, PrimType countPty, LabelIdx jumpLabIdx);
1052     void GenerateIntrnInsnForStrIndexOf(BB &bb, RegOperand &srcString, RegOperand &patternString,
1053                                         RegOperand &srcCountOpnd, RegOperand &patternLengthOpnd, PrimType countPty,
1054                                         LabelIdx jumpLabIdx);
1055     MemOperand *CheckAndCreateExtendMemOpnd(PrimType ptype, const BaseNode &addrExpr, int64 offset,
1056                                             AArch64isa::MemoryOrdering memOrd);
1057     MemOperand &CreateNonExtendMemOpnd(PrimType ptype, const BaseNode &parent, BaseNode &addrExpr, int64 offset);
1058     std::string GenerateMemOpndVerbose(const Operand &src) const;
1059     RegOperand *PrepareMemcpyParamOpnd(bool isLo12, const MIRSymbol &symbol, int64 offsetVal, RegOperand &BaseReg);
1060     RegOperand *PrepareMemcpyParamOpnd(int64 offset, Operand &exprOpnd);
1061     RegOperand *PrepareMemcpyParamOpnd(uint64 copySize);
1062     MemOperand &CreateMemOpndForStatic(const MIRSymbol &symbol, int64 offset, uint32 size, bool needLow12,
1063                                        RegOperand *regOp);
1064     Insn *AggtStrLdrInsert(bool bothUnion, Insn *lastStrLdr, Insn &newStrLdr);
1065     void SelectParmListWrapper(StmtNode &naryNode, ListOperand &srcOpnds, bool isCallNative);
1066 };
1067 } /* namespace maplebe */
1068 
1069 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_CGFUNC_H */
1070