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 #include "mir_builder.h" 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 DomAnalysis; 42 class MoveRegArgs; 43 class MPISel; 44 class Standardize; 45 class CG; 46 class CFGOptimizer; 47 class CGPeepHole; 48 class GenProEpilog; 49 class LoopAnalysis; 50 51 class Globals { 52 public: GetInstance()53 static Globals *GetInstance() 54 { 55 static Globals instance; 56 return &instance; 57 } 58 59 ~Globals() = default; 60 SetBECommon(BECommon & bc)61 void SetBECommon(BECommon &bc) 62 { 63 beCommon = &bc; 64 } 65 GetBECommon()66 BECommon *GetBECommon() 67 { 68 return beCommon; 69 } 70 GetBECommon()71 const BECommon *GetBECommon() const 72 { 73 return beCommon; 74 } 75 SetOptimLevel(int32 opLevel)76 void SetOptimLevel(int32 opLevel) 77 { 78 optimLevel = opLevel; 79 } 80 GetOptimLevel()81 int32 GetOptimLevel() const 82 { 83 return optimLevel; 84 } 85 86 void SetTarget(CG &target); 87 const CG *GetTarget() const; 88 89 private: 90 BECommon *beCommon = nullptr; 91 int32 optimLevel = 0; 92 CG *cg = nullptr; 93 Globals() = default; 94 }; 95 96 class GCTIBKey { 97 public: GCTIBKey(MapleAllocator & allocator,uint32 rcHeader,const std::vector<uint64> & patternWords)98 GCTIBKey(MapleAllocator &allocator, uint32 rcHeader, const std::vector<uint64> &patternWords) 99 : header(rcHeader), 100 bitMapWords(allocator.Adapter()) 101 { 102 (void)bitMapWords.insert(bitMapWords.cbegin(), patternWords.cbegin(), patternWords.cend()); 103 } 104 105 ~GCTIBKey() = default; 106 GetHeader()107 uint32 GetHeader() const 108 { 109 return header; 110 } 111 GetBitmapWords()112 const MapleVector<uint64> &GetBitmapWords() const 113 { 114 return bitMapWords; 115 } 116 117 private: 118 uint32 header; 119 MapleVector<uint64> bitMapWords; 120 }; 121 122 class Hasher { 123 public: operator()124 size_t operator()(const GCTIBKey *key) const 125 { 126 CHECK_NULL_FATAL(key); 127 size_t hash = key->GetHeader(); 128 return hash; 129 } 130 }; 131 132 class EqualFn { 133 public: operator()134 bool operator()(const GCTIBKey *firstKey, const GCTIBKey *secondKey) const 135 { 136 CHECK_NULL_FATAL(firstKey); 137 CHECK_NULL_FATAL(secondKey); 138 const MapleVector<uint64> &firstWords = firstKey->GetBitmapWords(); 139 const MapleVector<uint64> &secondWords = secondKey->GetBitmapWords(); 140 141 if ((firstKey->GetHeader() != secondKey->GetHeader()) || (firstWords.size() != secondWords.size())) { 142 return false; 143 } 144 145 for (size_t i = 0; i < firstWords.size(); ++i) { 146 if (firstWords[i] != secondWords[i]) { 147 return false; 148 } 149 } 150 return true; 151 } 152 }; 153 154 class GCTIBPattern { 155 public: GCTIBPattern(GCTIBKey & patternKey,MemPool & mp)156 GCTIBPattern(GCTIBKey &patternKey, MemPool &mp) 157 : name(&mp) 158 { 159 key = &patternKey; 160 id = GetId(); 161 name = GCTIB_PREFIX_STR + std::string("PTN_") + std::to_string(id); 162 } 163 164 ~GCTIBPattern() = default; 165 GetId()166 int GetId() const 167 { 168 static int createNum = 0; 169 return createNum++; 170 } 171 GetName()172 std::string GetName() const 173 { 174 return std::string(name.c_str()); 175 } 176 SetName(const std::string & ptnName)177 void SetName(const std::string &ptnName) 178 { 179 name = ptnName; 180 } 181 182 private: 183 int id = 0; 184 MapleString name; 185 GCTIBKey *key = nullptr; 186 }; 187 188 class CG { 189 public: 190 using GenerateFlag = uint64; 191 192 public: CG(MIRModule & mod,const CGOptions & cgOptions)193 CG(MIRModule &mod, const CGOptions &cgOptions) 194 : memPool(memPoolCtrler.NewMemPool("maplecg mempool", false /* isLocalPool */)), 195 allocator(memPool), 196 mirModule(&mod), 197 cgOption(cgOptions) 198 { 199 isLmbc = (mirModule->GetFlavor() == MIRFlavor::kFlavorLmbc); 200 } 201 202 virtual ~CG(); 203 204 /* enroll all code generator phases for target machine */ 205 virtual void EnrollTargetPhases(MaplePhaseManager *pm) const = 0; 206 207 virtual PhiOperand &CreatePhiOperand(MemPool &mp, MapleAllocator &mAllocator) = 0; 208 209 virtual CGFunc *CreateCGFunc(MIRModule &mod, MIRFunction &, BECommon &, MemPool &, StackMemPool &, MapleAllocator &, 210 uint32) = 0; 211 212 virtual bool IsExclusiveFunc(MIRFunction &mirFunc) = 0; 213 214 #ifdef ARK_LITECG_DEBUG 215 /* Used for GCTIB pattern merging */ 216 virtual std::string FindGCTIBPatternName(const std::string &name) const = 0; 217 #endif 218 GenerateVerboseAsm()219 bool GenerateVerboseAsm() const 220 { 221 return cgOption.GenerateVerboseAsm(); 222 } 223 GenerateVerboseCG()224 bool GenerateVerboseCG() const 225 { 226 return cgOption.GenerateVerboseCG(); 227 } 228 DoTailCall()229 bool DoTailCall() const 230 { 231 return cgOption.DoTailCall(); 232 } 233 GenerateDebugFriendlyCode()234 bool GenerateDebugFriendlyCode() const 235 { 236 return cgOption.GenerateDebugFriendlyCode(); 237 } 238 GetOptimizeLevel()239 int32 GetOptimizeLevel() const 240 { 241 return cgOption.GetOptimizeLevel(); 242 } 243 UseFastUnwind()244 bool UseFastUnwind() const 245 { 246 return true; 247 } 248 GenYieldPoint()249 bool GenYieldPoint() const 250 { 251 return cgOption.GenYieldPoint(); 252 } 253 GenLocalRC()254 bool GenLocalRC() const 255 { 256 return cgOption.GenLocalRC(); 257 } 258 GenerateExceptionHandlingCode()259 bool GenerateExceptionHandlingCode() const 260 { 261 return cgOption.GenerateExceptionHandlingCode(); 262 } 263 GetMIRModule()264 MIRModule *GetMIRModule() 265 { 266 return mirModule; 267 } 268 SetObjEmitter(Emitter & emitter)269 void SetObjEmitter(Emitter &emitter) 270 { 271 DEBUG_ASSERT(emitters.empty(), "ObjEmitter already exist"); 272 emitters.push_back(&emitter); 273 } 274 SetAsmEmitter(Emitter & emitter)275 void SetAsmEmitter(Emitter &emitter) 276 { 277 DEBUG_ASSERT(emitters.size() == 1U, "AsmEmitter need to be added after objEmmiter"); 278 emitters.push_back(&emitter); 279 } 280 281 enum EmitterType: uint8_t { 282 ObjEmiter = 0, 283 AsmEmitter = 1, 284 All 285 }; 286 287 // NOTE: It's would de better to remove EmmiterType and always use EmitterType::All, 288 // but it's need to unify interfaces. It's better because, it's harder to make a error. 289 template <EmitterType emitType = EmitterType::All> Emit(const std::function<void (Emitter *)> & cb)290 void Emit(const std::function<void(Emitter*)> &cb) const 291 { 292 if constexpr (emitType == EmitterType::All) { 293 EmitAllEmitters(cb); 294 } else if constexpr (emitType == EmitterType::AsmEmitter) { 295 EmitAsmEmitters(cb); 296 } else if constexpr (emitType == EmitterType::ObjEmiter) { 297 EmitObjEmitters(cb); 298 } 299 } 300 GetMIRModule()301 MIRModule *GetMIRModule() const 302 { 303 return mirModule; 304 } 305 SetTargetMachine(TargetMachine & targetMachine)306 void SetTargetMachine(TargetMachine &targetMachine) 307 { 308 this->targetMachine = &targetMachine; 309 } 310 GetTargetMachine()311 TargetMachine *GetTargetMachine() const 312 { 313 return targetMachine; 314 } 315 IncreaseLabelOrderCnt()316 void IncreaseLabelOrderCnt() 317 { 318 labelOrderCnt++; 319 } 320 GetLabelOrderCnt()321 LabelIDOrder GetLabelOrderCnt() const 322 { 323 return labelOrderCnt; 324 } 325 GetCGOptions()326 const CGOptions &GetCGOptions() const 327 { 328 return cgOption; 329 } 330 UpdateCGOptions(const CGOptions & newOption)331 void UpdateCGOptions(const CGOptions &newOption) 332 { 333 cgOption.SetOptionFlag(newOption.GetOptionFlag()); 334 } 335 IsLibcore()336 bool IsLibcore() const 337 { 338 return isLibcore; 339 } 340 IsLmbc()341 bool IsLmbc() const 342 { 343 return isLmbc; 344 } 345 GetDebugTraceEnterFunction()346 MIRSymbol *GetDebugTraceEnterFunction() 347 { 348 return dbgTraceEnter; 349 } 350 GetDebugTraceEnterFunction()351 const MIRSymbol *GetDebugTraceEnterFunction() const 352 { 353 return dbgTraceEnter; 354 } 355 GetProfileFunction()356 MIRSymbol *GetProfileFunction() 357 { 358 return dbgFuncProfile; 359 } 360 GetProfileFunction()361 const MIRSymbol *GetProfileFunction() const 362 { 363 return dbgFuncProfile; 364 } 365 GetDebugTraceExitFunction()366 const MIRSymbol *GetDebugTraceExitFunction() const 367 { 368 return dbgTraceExit; 369 } 370 371 /* Init SubTarget phase */ CreateLiveAnalysis(MemPool & mp,CGFunc & f)372 virtual LiveAnalysis *CreateLiveAnalysis(MemPool &mp, CGFunc &f) const 373 { 374 return nullptr; 375 }; 376 virtual GenProEpilog *CreateGenProEpilog(CGFunc &func, MemPool &mp, MemPool *tempMemPool = nullptr) const = 0; 377 virtual CGPeepHole *CreateCGPeepHole(MemPool &mp, CGFunc &f) const = 0; CreateMoveRegArgs(MemPool & mp,CGFunc & f)378 virtual MoveRegArgs *CreateMoveRegArgs(MemPool &mp, CGFunc &f) const 379 { 380 return nullptr; 381 }; CreateMPIsel(MemPool & mp,MapleAllocator & allocator,CGFunc & f)382 virtual MPISel *CreateMPIsel(MemPool &mp, MapleAllocator &allocator, CGFunc &f) const 383 { 384 return nullptr; 385 } CreateStandardize(MemPool & mp,CGFunc & f)386 virtual Standardize *CreateStandardize(MemPool &mp, CGFunc &f) const 387 { 388 return nullptr; 389 } 390 virtual CFGOptimizer *CreateCFGOptimizer(MemPool &mp, CGFunc &f, LoopAnalysis &loop) const = 0; 391 SetGP(MIRSymbol * sym)392 void SetGP(MIRSymbol *sym) 393 { 394 fileGP = sym; 395 } GetGP()396 MIRSymbol *GetGP() const 397 { 398 return fileGP; 399 } 400 IsInFuncWrapLabels(MIRFunction * func)401 static bool IsInFuncWrapLabels(MIRFunction *func) 402 { 403 return funcWrapLabels.find(func) != funcWrapLabels.end(); 404 } 405 SetFuncWrapLabels(MIRFunction * func,const std::pair<LabelIdx,LabelIdx> labels)406 static void SetFuncWrapLabels(MIRFunction *func, const std::pair<LabelIdx, LabelIdx> labels) 407 { 408 if (!IsInFuncWrapLabels(func)) { 409 funcWrapLabels[func] = labels; 410 } 411 } 412 GetFuncWrapLabels()413 static std::map<MIRFunction *, std::pair<LabelIdx, LabelIdx>> &GetFuncWrapLabels() 414 { 415 return funcWrapLabels; 416 } SetCurCGFunc(CGFunc & cgFunc)417 static void SetCurCGFunc(CGFunc &cgFunc) 418 { 419 currentCGFunction = &cgFunc; 420 } 421 GetCurCGFunc()422 static const CGFunc *GetCurCGFunc() 423 { 424 return currentCGFunction; 425 } 426 GetCurCGFuncNoConst()427 static CGFunc *GetCurCGFuncNoConst() 428 { 429 return currentCGFunction; 430 } 431 432 virtual const InsnDesc &GetTargetMd(MOperator mOp) const = 0; 433 virtual bool IsEffectiveCopy(Insn &insn) const = 0; 434 virtual bool IsTargetInsn(MOperator mOp) const = 0; 435 virtual bool IsClinitInsn(MOperator mOp) const = 0; 436 virtual bool IsPseudoInsn(MOperator mOp) const = 0; 437 virtual void DumpTargetOperand(Operand &opnd, const OpndDesc &opndDesc) const = 0; 438 439 protected: 440 MemPool *memPool; 441 MapleAllocator allocator; 442 443 private: 444 void EmitAllEmitters(const std::function<void(Emitter *)>& cb) const; 445 void EmitAsmEmitters(const std::function<void(Emitter *)>& cb) const; 446 void EmitObjEmitters(const std::function<void(Emitter *)>& cb) const; 447 448 private: 449 MIRModule *mirModule; 450 std::vector<Emitter *> emitters; 451 TargetMachine *targetMachine = nullptr; 452 LabelIDOrder labelOrderCnt = 0; 453 static CGFunc *currentCGFunction; /* current cg function being compiled */ 454 CGOptions cgOption; 455 MIRSymbol *dbgTraceEnter = nullptr; 456 MIRSymbol *dbgTraceExit = nullptr; 457 MIRSymbol *dbgFuncProfile = nullptr; 458 MIRSymbol *fileGP = nullptr; /* for lmbc, one local %GP per file */ 459 static std::map<MIRFunction *, std::pair<LabelIdx, LabelIdx>> funcWrapLabels; 460 bool isLibcore = false; 461 bool isLmbc; 462 }; /* class CG */ 463 } /* namespace maplebe */ 464 465 #endif /* MAPLEBE_INCLUDE_CG_CG_H */ 466