• 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_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 &currentBB)
578     {
579         for (BB *exitBB : exitBBVec) {
580             if (exitBB == &currentBB) {
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 &regInfo)
658     {
659         targetRegInfo = &regInfo;
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