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 ®) const; 293 void ClearRegRematInfo(const RegOperand ®) const; 294 bool IsRegSameRematInfo(const RegOperand ®Dest, const RegOperand ®Src) const; 295 void ReplaceOpndInInsn(RegOperand ®Dest, RegOperand ®Src, 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 ®Opnd) 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 ®, 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