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