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_CG_H 17 #define MAPLEBE_INCLUDE_CG_CG_H 18 19 /* C++ headers. */ 20 #include <cstddef> 21 #include <string> 22 /* MapleIR headers. */ 23 #include "operand.h" 24 #include "insn.h" 25 #include "cgfunc.h" 26 #include "live.h" 27 #include "cg_option.h" 28 #include "opcode_info.h" 29 #include "global_tables.h" 30 #include "mir_function.h" 31 #include "mad.h" 32 #include "target_machine.h" 33 #include "proepilog.h" 34 35 namespace maplebe { 36 #define ADDTARGETPHASE(PhaseName, condition) \ 37 if (!CGOptions::IsSkipPhase(PhaseName)) { \ 38 pm->AddPhase(PhaseName, condition); \ 39 } 40 /* subtarget opt phase -- cyclic Dependency, use Forward declaring */ 41 class CGSSAInfo; 42 class PhiEliminate; 43 class DomAnalysis; 44 class CGProp; 45 class CGDce; 46 class AlignAnalysis; 47 class MoveRegArgs; 48 class MPISel; 49 class Standardize; 50 class LiveIntervalAnalysis; 51 class ValidBitOpt; 52 class CG; 53 class LocalOpt; 54 class CFGOptimizer; 55 class LocalSchedule; 56 class ControlDepAnalysis; 57 class DataDepAnalysis; 58 class CGPeepHole; 59 class GenProEpilog; 60 class LoopAnalysis; 61 62 class Globals { 63 public: GetInstance()64 static Globals *GetInstance() 65 { 66 static Globals instance; 67 return &instance; 68 } 69 70 ~Globals() = default; 71 SetBECommon(BECommon & bc)72 void SetBECommon(BECommon &bc) 73 { 74 beCommon = &bc; 75 } 76 GetBECommon()77 BECommon *GetBECommon() 78 { 79 return beCommon; 80 } 81 GetBECommon()82 const BECommon *GetBECommon() const 83 { 84 return beCommon; 85 } 86 SetMAD(MAD & m)87 void SetMAD(MAD &m) 88 { 89 mad = &m; 90 } 91 GetMAD()92 MAD *GetMAD() 93 { 94 return mad; 95 } 96 ClearMAD()97 void ClearMAD() 98 { 99 mad = nullptr; 100 } 101 GetMAD()102 const MAD *GetMAD() const 103 { 104 return mad; 105 } 106 SetOptimLevel(int32 opLevel)107 void SetOptimLevel(int32 opLevel) 108 { 109 optimLevel = opLevel; 110 } 111 GetOptimLevel()112 int32 GetOptimLevel() const 113 { 114 return optimLevel; 115 } 116 117 void SetTarget(CG &target); 118 const CG *GetTarget() const; 119 120 private: 121 BECommon *beCommon = nullptr; 122 MAD *mad = nullptr; 123 int32 optimLevel = 0; 124 CG *cg = nullptr; 125 Globals() = default; 126 }; 127 128 class GCTIBKey { 129 public: GCTIBKey(MapleAllocator & allocator,uint32 rcHeader,const std::vector<uint64> & patternWords)130 GCTIBKey(MapleAllocator &allocator, uint32 rcHeader, const std::vector<uint64> &patternWords) 131 : header(rcHeader), 132 bitMapWords(allocator.Adapter()) 133 { 134 (void)bitMapWords.insert(bitMapWords.cbegin(), patternWords.cbegin(), patternWords.cend()); 135 } 136 137 ~GCTIBKey() = default; 138 GetHeader()139 uint32 GetHeader() const 140 { 141 return header; 142 } 143 GetBitmapWords()144 const MapleVector<uint64> &GetBitmapWords() const 145 { 146 return bitMapWords; 147 } 148 149 private: 150 uint32 header; 151 MapleVector<uint64> bitMapWords; 152 }; 153 154 class Hasher { 155 public: operator()156 size_t operator()(const GCTIBKey *key) const 157 { 158 CHECK_NULL_FATAL(key); 159 size_t hash = key->GetHeader(); 160 return hash; 161 } 162 }; 163 164 class EqualFn { 165 public: operator()166 bool operator()(const GCTIBKey *firstKey, const GCTIBKey *secondKey) const 167 { 168 CHECK_NULL_FATAL(firstKey); 169 CHECK_NULL_FATAL(secondKey); 170 const MapleVector<uint64> &firstWords = firstKey->GetBitmapWords(); 171 const MapleVector<uint64> &secondWords = secondKey->GetBitmapWords(); 172 173 if ((firstKey->GetHeader() != secondKey->GetHeader()) || (firstWords.size() != secondWords.size())) { 174 return false; 175 } 176 177 for (size_t i = 0; i < firstWords.size(); ++i) { 178 if (firstWords[i] != secondWords[i]) { 179 return false; 180 } 181 } 182 return true; 183 } 184 }; 185 186 class GCTIBPattern { 187 public: GCTIBPattern(GCTIBKey & patternKey,MemPool & mp)188 GCTIBPattern(GCTIBKey &patternKey, MemPool &mp) 189 : name(&mp) 190 { 191 key = &patternKey; 192 id = GetId(); 193 name = GCTIB_PREFIX_STR + std::string("PTN_") + std::to_string(id); 194 } 195 196 ~GCTIBPattern() = default; 197 GetId()198 int GetId() const 199 { 200 static int createNum = 0; 201 return createNum++; 202 } 203 GetName()204 std::string GetName() const 205 { 206 return std::string(name.c_str()); 207 } 208 SetName(const std::string & ptnName)209 void SetName(const std::string &ptnName) 210 { 211 name = ptnName; 212 } 213 214 private: 215 int id = 0; 216 MapleString name; 217 GCTIBKey *key = nullptr; 218 }; 219 220 class CG { 221 public: 222 using GenerateFlag = uint64; 223 224 public: CG(MIRModule & mod,const CGOptions & cgOptions)225 CG(MIRModule &mod, const CGOptions &cgOptions) 226 : memPool(memPoolCtrler.NewMemPool("maplecg mempool", false /* isLocalPool */)), 227 allocator(memPool), 228 mirModule(&mod), 229 cgOption(cgOptions) 230 { 231 DefineDebugTraceFunctions(); 232 isLmbc = (mirModule->GetFlavor() == MIRFlavor::kFlavorLmbc); 233 } 234 235 virtual ~CG(); 236 237 /* enroll all code generator phases for target machine */ 238 virtual void EnrollTargetPhases(MaplePhaseManager *pm) const = 0; 239 240 void GenExtraTypeMetadata(const std::string &classListFileName, const std::string &outputBaseName); 241 void GenPrimordialObjectList(const std::string &outputBaseName); 242 const std::string ExtractFuncName(const std::string &str); 243 244 virtual Insn &BuildPhiInsn(RegOperand &defOpnd, Operand &listParam) = 0; 245 virtual PhiOperand &CreatePhiOperand(MemPool &mp, MapleAllocator &mAllocator) = 0; 246 247 virtual CGFunc *CreateCGFunc(MIRModule &mod, MIRFunction &, BECommon &, MemPool &, StackMemPool &, MapleAllocator &, 248 uint32) = 0; 249 IsExclusiveEH()250 bool IsExclusiveEH() const 251 { 252 return CGOptions::IsExclusiveEH(); 253 } 254 255 virtual bool IsExclusiveFunc(MIRFunction &mirFunc) = 0; 256 257 /* NOTE: Consider making be_common a field of CG. */ 258 virtual void GenerateObjectMaps(BECommon &beCommon) = 0; 259 260 /* Used for GCTIB pattern merging */ 261 virtual std::string FindGCTIBPatternName(const std::string &name) const = 0; 262 GenerateVerboseAsm()263 bool GenerateVerboseAsm() const 264 { 265 return cgOption.GenerateVerboseAsm(); 266 } 267 GenerateVerboseCG()268 bool GenerateVerboseCG() const 269 { 270 return cgOption.GenerateVerboseCG(); 271 } 272 DoPrologueEpilogue()273 bool DoPrologueEpilogue() const 274 { 275 return cgOption.DoPrologueEpilogue(); 276 } 277 DoTailCall()278 bool DoTailCall() const 279 { 280 return cgOption.DoTailCall(); 281 } 282 DoCheckSOE()283 bool DoCheckSOE() const 284 { 285 return cgOption.DoCheckSOE(); 286 } 287 GenerateDebugFriendlyCode()288 bool GenerateDebugFriendlyCode() const 289 { 290 return cgOption.GenerateDebugFriendlyCode(); 291 } 292 GetOptimizeLevel()293 int32 GetOptimizeLevel() const 294 { 295 return cgOption.GetOptimizeLevel(); 296 } 297 UseFastUnwind()298 bool UseFastUnwind() const 299 { 300 return true; 301 } 302 IsStackProtectorStrong()303 bool IsStackProtectorStrong() const 304 { 305 return cgOption.IsStackProtectorStrong(); 306 } 307 IsStackProtectorAll()308 bool IsStackProtectorAll() const 309 { 310 return cgOption.IsStackProtectorAll(); 311 } 312 NeedInsertInstrumentationFunction()313 bool NeedInsertInstrumentationFunction() const 314 { 315 return cgOption.NeedInsertInstrumentationFunction(); 316 } 317 318 void SetInstrumentationFunction(const std::string &name); GetInstrumentationFunction()319 const MIRSymbol *GetInstrumentationFunction() const 320 { 321 return instrumentationFunction; 322 } 323 InstrumentWithDebugTraceCall()324 bool InstrumentWithDebugTraceCall() const 325 { 326 return cgOption.InstrumentWithDebugTraceCall(); 327 } 328 InstrumentWithProfile()329 bool InstrumentWithProfile() const 330 { 331 return cgOption.InstrumentWithProfile(); 332 } 333 DoPatchLongBranch()334 bool DoPatchLongBranch() const 335 { 336 return cgOption.DoPatchLongBranch(); 337 } 338 GetRematLevel()339 uint8 GetRematLevel() const 340 { 341 return CGOptions::GetRematLevel(); 342 } 343 GenYieldPoint()344 bool GenYieldPoint() const 345 { 346 return cgOption.GenYieldPoint(); 347 } 348 GenLocalRC()349 bool GenLocalRC() const 350 { 351 return cgOption.GenLocalRC(); 352 } 353 GenerateExceptionHandlingCode()354 bool GenerateExceptionHandlingCode() const 355 { 356 return cgOption.GenerateExceptionHandlingCode(); 357 } 358 DoConstFold()359 bool DoConstFold() const 360 { 361 return cgOption.DoConstFold(); 362 } 363 364 void AddStackGuardvar(); 365 void DefineDebugTraceFunctions(); GetMIRModule()366 MIRModule *GetMIRModule() 367 { 368 return mirModule; 369 } 370 SetObjEmitter(Emitter & emitter)371 void SetObjEmitter(Emitter &emitter) 372 { 373 DEBUG_ASSERT(emitters.empty(), "ObjEmitter already exist"); 374 emitters.push_back(&emitter); 375 } 376 SetAsmEmitter(Emitter & emitter)377 void SetAsmEmitter(Emitter &emitter) 378 { 379 DEBUG_ASSERT(emitters.size() == 1U, "AsmEmitter need to be added after objEmmiter"); 380 emitters.push_back(&emitter); 381 } 382 383 enum EmitterType: uint8_t { 384 ObjEmiter = 0, 385 AsmEmitter = 1, 386 All 387 }; 388 389 // NOTE: It's would de better to remove EmmiterType and always use EmitterType::All, 390 // but it's need to unify interfaces. It's better because, it's harder to make a error. 391 template <EmitterType emitType = EmitterType::All> Emit(const std::function<void (Emitter *)> & cb)392 void Emit(const std::function<void(Emitter*)> &cb) const 393 { 394 if constexpr (emitType == EmitterType::All) { 395 EmitAllEmitters(cb); 396 } else if constexpr (emitType == EmitterType::AsmEmitter) { 397 EmitAsmEmitters(cb); 398 } else if constexpr (emitType == EmitterType::ObjEmiter) { 399 EmitObjEmitters(cb); 400 } 401 } 402 GetMIRModule()403 MIRModule *GetMIRModule() const 404 { 405 return mirModule; 406 } 407 SetTargetMachine(TargetMachine & targetMachine)408 void SetTargetMachine(TargetMachine &targetMachine) 409 { 410 this->targetMachine = &targetMachine; 411 } 412 GetTargetMachine()413 TargetMachine *GetTargetMachine() const 414 { 415 return targetMachine; 416 } 417 IncreaseLabelOrderCnt()418 void IncreaseLabelOrderCnt() 419 { 420 labelOrderCnt++; 421 } 422 GetLabelOrderCnt()423 LabelIDOrder GetLabelOrderCnt() const 424 { 425 return labelOrderCnt; 426 } 427 GetCGOptions()428 const CGOptions &GetCGOptions() const 429 { 430 return cgOption; 431 } 432 UpdateCGOptions(const CGOptions & newOption)433 void UpdateCGOptions(const CGOptions &newOption) 434 { 435 cgOption.SetOptionFlag(newOption.GetOptionFlag()); 436 } 437 IsLibcore()438 bool IsLibcore() const 439 { 440 return isLibcore; 441 } 442 IsLmbc()443 bool IsLmbc() const 444 { 445 return isLmbc; 446 } 447 GetDebugTraceEnterFunction()448 MIRSymbol *GetDebugTraceEnterFunction() 449 { 450 return dbgTraceEnter; 451 } 452 GetDebugTraceEnterFunction()453 const MIRSymbol *GetDebugTraceEnterFunction() const 454 { 455 return dbgTraceEnter; 456 } 457 GetProfileFunction()458 MIRSymbol *GetProfileFunction() 459 { 460 return dbgFuncProfile; 461 } 462 GetProfileFunction()463 const MIRSymbol *GetProfileFunction() const 464 { 465 return dbgFuncProfile; 466 } 467 GetDebugTraceExitFunction()468 const MIRSymbol *GetDebugTraceExitFunction() const 469 { 470 return dbgTraceExit; 471 } 472 473 /* Init SubTarget phase */ CreateLiveAnalysis(MemPool & mp,CGFunc & f)474 virtual LiveAnalysis *CreateLiveAnalysis(MemPool &mp, CGFunc &f) const 475 { 476 return nullptr; 477 }; CreateReachingDefinition(MemPool & mp,CGFunc & f)478 virtual ReachingDefinition *CreateReachingDefinition(MemPool &mp, CGFunc &f) const 479 { 480 return nullptr; 481 }; 482 virtual GenProEpilog *CreateGenProEpilog(CGFunc &func, MemPool &mp, MemPool *tempMemPool = nullptr) const = 0; 483 virtual CGPeepHole *CreateCGPeepHole(MemPool &mp, CGFunc &f) const = 0; CreateMoveRegArgs(MemPool & mp,CGFunc & f)484 virtual MoveRegArgs *CreateMoveRegArgs(MemPool &mp, CGFunc &f) const 485 { 486 return nullptr; 487 }; CreateAlignAnalysis(MemPool & mp,CGFunc & f,LoopAnalysis & loop)488 virtual AlignAnalysis *CreateAlignAnalysis(MemPool &mp, CGFunc &f, LoopAnalysis &loop) const 489 { 490 return nullptr; 491 }; CreateMPIsel(MemPool & mp,MapleAllocator & allocator,CGFunc & f)492 virtual MPISel *CreateMPIsel(MemPool &mp, MapleAllocator &allocator, CGFunc &f) const 493 { 494 return nullptr; 495 } CreateStandardize(MemPool & mp,CGFunc & f)496 virtual Standardize *CreateStandardize(MemPool &mp, CGFunc &f) const 497 { 498 return nullptr; 499 } CreateValidBitOpt(MemPool & mp,CGFunc & f,CGSSAInfo & ssaInfo)500 virtual ValidBitOpt *CreateValidBitOpt(MemPool &mp, CGFunc &f, CGSSAInfo &ssaInfo) const 501 { 502 return nullptr; 503 } 504 505 /* Init SubTarget optimization */ CreateCGSSAInfo(MemPool & mp,CGFunc & f,DomAnalysis & da,MemPool & tmp)506 virtual CGSSAInfo *CreateCGSSAInfo(MemPool &mp, CGFunc &f, DomAnalysis &da, MemPool &tmp) const 507 { 508 return nullptr; 509 }; CreateLLAnalysis(MemPool & mp,CGFunc & f)510 virtual LiveIntervalAnalysis *CreateLLAnalysis(MemPool &mp, CGFunc &f) const 511 { 512 return nullptr; 513 }; CreatePhiElimintor(MemPool & mp,CGFunc & f,CGSSAInfo & ssaInfo)514 virtual PhiEliminate *CreatePhiElimintor(MemPool &mp, CGFunc &f, CGSSAInfo &ssaInfo) const 515 { 516 return nullptr; 517 }; CreateCGProp(MemPool & mp,CGFunc & f,CGSSAInfo & ssaInfo,LiveIntervalAnalysis & ll)518 virtual CGProp *CreateCGProp(MemPool &mp, CGFunc &f, CGSSAInfo &ssaInfo, LiveIntervalAnalysis &ll) const 519 { 520 return nullptr; 521 }; CreateCGDce(MemPool & mp,CGFunc & f,CGSSAInfo & ssaInfo)522 virtual CGDce *CreateCGDce(MemPool &mp, CGFunc &f, CGSSAInfo &ssaInfo) const 523 { 524 return nullptr; 525 }; CreateLocalSchedule(MemPool & mp,CGFunc & f,ControlDepAnalysis & cda,DataDepAnalysis & dda)526 virtual LocalSchedule *CreateLocalSchedule(MemPool &mp, CGFunc &f, ControlDepAnalysis &cda, 527 DataDepAnalysis &dda) const 528 { 529 return nullptr; 530 } CreateLocalOpt(MemPool & mp,CGFunc & f,ReachingDefinition &)531 virtual LocalOpt *CreateLocalOpt(MemPool &mp, CGFunc &f, ReachingDefinition &) const 532 { 533 return nullptr; 534 }; CreateCFGOptimizer(MemPool & mp,CGFunc & f,LoopAnalysis & loop)535 virtual CFGOptimizer *CreateCFGOptimizer(MemPool &mp, CGFunc &f, LoopAnalysis &loop) const 536 { 537 return nullptr; 538 } 539 540 /* Object map generation helper */ 541 std::vector<int64> GetReferenceOffsets64(const BECommon &beCommon, MIRStructType &structType); 542 SetGP(MIRSymbol * sym)543 void SetGP(MIRSymbol *sym) 544 { 545 fileGP = sym; 546 } GetGP()547 MIRSymbol *GetGP() const 548 { 549 return fileGP; 550 } 551 IsInFuncWrapLabels(MIRFunction * func)552 static bool IsInFuncWrapLabels(MIRFunction *func) 553 { 554 return funcWrapLabels.find(func) != funcWrapLabels.end(); 555 } 556 SetFuncWrapLabels(MIRFunction * func,const std::pair<LabelIdx,LabelIdx> labels)557 static void SetFuncWrapLabels(MIRFunction *func, const std::pair<LabelIdx, LabelIdx> labels) 558 { 559 if (!IsInFuncWrapLabels(func)) { 560 funcWrapLabels[func] = labels; 561 } 562 } 563 GetFuncWrapLabels()564 static std::map<MIRFunction *, std::pair<LabelIdx, LabelIdx>> &GetFuncWrapLabels() 565 { 566 return funcWrapLabels; 567 } SetCurCGFunc(CGFunc & cgFunc)568 static void SetCurCGFunc(CGFunc &cgFunc) 569 { 570 currentCGFunction = &cgFunc; 571 } 572 GetCurCGFunc()573 static const CGFunc *GetCurCGFunc() 574 { 575 return currentCGFunction; 576 } 577 GetCurCGFuncNoConst()578 static CGFunc *GetCurCGFuncNoConst() 579 { 580 return currentCGFunction; 581 } 582 583 virtual const InsnDesc &GetTargetMd(MOperator mOp) const = 0; 584 virtual bool IsEffectiveCopy(Insn &insn) const = 0; 585 virtual bool IsTargetInsn(MOperator mOp) const = 0; 586 virtual bool IsClinitInsn(MOperator mOp) const = 0; 587 virtual bool IsPseudoInsn(MOperator mOp) const = 0; 588 virtual void DumpTargetOperand(Operand &opnd, const OpndDesc &opndDesc) const = 0; 589 590 protected: 591 MemPool *memPool; 592 MapleAllocator allocator; 593 594 private: 595 void EmitAllEmitters(const std::function<void(Emitter *)>& cb) const; 596 void EmitAsmEmitters(const std::function<void(Emitter *)>& cb) const; 597 void EmitObjEmitters(const std::function<void(Emitter *)>& cb) const; 598 599 private: 600 MIRModule *mirModule; 601 std::vector<Emitter *> emitters; 602 TargetMachine *targetMachine = nullptr; 603 LabelIDOrder labelOrderCnt = 0; 604 static CGFunc *currentCGFunction; /* current cg function being compiled */ 605 CGOptions cgOption; 606 MIRSymbol *instrumentationFunction = nullptr; 607 MIRSymbol *dbgTraceEnter = nullptr; 608 MIRSymbol *dbgTraceExit = nullptr; 609 MIRSymbol *dbgFuncProfile = nullptr; 610 MIRSymbol *fileGP = nullptr; /* for lmbc, one local %GP per file */ 611 static std::map<MIRFunction *, std::pair<LabelIdx, LabelIdx>> funcWrapLabels; 612 bool isLibcore = false; 613 bool isLmbc; 614 }; /* class CG */ 615 } /* namespace maplebe */ 616 617 #endif /* MAPLEBE_INCLUDE_CG_CG_H */ 618