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