• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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