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