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