• 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_EMIT_H
17 #define MAPLEBE_INCLUDE_CG_EMIT_H
18 
19 /* C++ headers */
20 #include <fstream>
21 #include <functional>
22 #include <map>
23 #include <array>
24 #include "isa.h"
25 #include "lsda.h"
26 #include "asm_info.h"
27 #include "cg.h"
28 
29 /* Maple IR headers */
30 #include "mir_module.h"
31 #include "mir_const.h"
32 #include "mempool_allocator.h"
33 #include "muid_replacement.h"
34 #include "namemangler.h"
35 #include "debug_info.h"
36 #include "alignment.h"
37 
38 namespace maple {
39 const char *GetDwTagName(unsigned n);
40 const char *GetDwFormName(unsigned n);
41 const char *GetDwAtName(unsigned n);
42 } /* namespace maple */
43 
44 #if TARGRISCV64
45 #define CMNT "\t# "
46 #else
47 #define CMNT "\t// "
48 #endif
49 #define TEXT_BEGIN text0
50 #define TEXT_END etext0
51 #define DEBUG_INFO_0 debug_info0
52 #define DEBUG_ABBREV_0 debug_abbrev0
53 #define DEBUG_LINE_0 debug_line0
54 #define DEBUG_STR_LABEL ASF
55 
56 namespace maplebe {
57 constexpr int32 kSizeOfDecoupleStaticStruct = 4;
58 constexpr uint32 kHugeSoInsnCountThreshold = 0x1f00000; /* 124M (4bytes per Insn), leave 4M rooms for 128M */
59 constexpr char kHugeSoPostFix[] = "$$hugeso_";
60 constexpr char kDebugMapleThis[] = "_this";
61 constexpr uint32 kDwarfVersion = 4;
62 constexpr uint32 kSizeOfPTR = 8;
63 class StructEmitInfo {
64 public:
65     /* default ctor */
66     StructEmitInfo() = default;
67 
68     ~StructEmitInfo() = default;
69 
GetNextFieldOffset()70     uint16 GetNextFieldOffset() const
71     {
72         return nextFieldOffset;
73     }
74 
SetNextFieldOffset(uint16 offset)75     void SetNextFieldOffset(uint16 offset)
76     {
77         nextFieldOffset = offset;
78     }
79 
IncreaseNextFieldOffset(uint16 value)80     void IncreaseNextFieldOffset(uint16 value)
81     {
82         nextFieldOffset += value;
83     }
84 
GetCombineBitFieldWidth()85     uint8 GetCombineBitFieldWidth() const
86     {
87         return combineBitFieldWidth;
88     }
89 
SetCombineBitFieldWidth(uint8 offset)90     void SetCombineBitFieldWidth(uint8 offset)
91     {
92         combineBitFieldWidth = offset;
93     }
94 
IncreaseCombineBitFieldWidth(uint8 value)95     void IncreaseCombineBitFieldWidth(uint8 value)
96     {
97         combineBitFieldWidth += value;
98     }
99 
DecreaseCombineBitFieldWidth(uint8 value)100     void DecreaseCombineBitFieldWidth(uint8 value)
101     {
102         combineBitFieldWidth -= value;
103     }
104 
GetCombineBitFieldValue()105     uint64 GetCombineBitFieldValue() const
106     {
107         return combineBitFieldValue;
108     }
109 
SetCombineBitFieldValue(uint64 value)110     void SetCombineBitFieldValue(uint64 value)
111     {
112         combineBitFieldValue = value;
113     }
114 
GetTotalSize()115     uint64 GetTotalSize() const
116     {
117         return totalSize;
118     }
119 
SetTotalSize(uint64 value)120     void SetTotalSize(uint64 value)
121     {
122         totalSize = value;
123     }
124 
IncreaseTotalSize(uint64 value)125     void IncreaseTotalSize(uint64 value)
126     {
127         totalSize += value;
128     }
129 
130 private:
131     /* Next field offset in struct. */
132     uint16 nextFieldOffset = 0;
133     uint8 combineBitFieldWidth = 0;
134     uint64 combineBitFieldValue = 0;
135     /* Total size emitted in current struct. */
136     uint64 totalSize = 0;
137 };
138 
139 class FuncEmitInfo {
140 public:
GetCGFunc()141     CGFunc &GetCGFunc()
142     {
143         return cgFunc;
144     }
145 
GetCGFunc()146     const CGFunc &GetCGFunc() const
147     {
148         return cgFunc;
149     }
150 
151 protected:
FuncEmitInfo(CGFunc & func)152     explicit FuncEmitInfo(CGFunc &func) : cgFunc(func) {}
153     ~FuncEmitInfo() = default;
154 
155 private:
156     CGFunc &cgFunc;
157 };
158 
159 class Emitter {
160 public:
Finish()161     virtual void Finish() {}
162 
CloseOutput()163     virtual void CloseOutput()
164     {
165         if (fileStream.is_open()) {
166             fileStream.close();
167         }
168         rangeIdx2PrefixStr.clear();
169         hugeSoTargets.clear();
170         labdie2labidxTable.clear();
171         fileMap.clear();
172     }
173 
GetCurrentMOP()174     MOperator GetCurrentMOP() const
175     {
176         return currentMop;
177     }
178 
SetCurrentMOP(const MOperator & mOp)179     void SetCurrentMOP(const MOperator &mOp)
180     {
181         currentMop = mOp;
182     }
183 
184     void EmitAsmLabel(AsmLabel label);
185     void EmitAsmLabel(const MIRSymbol &mirSymbol, AsmLabel label);
186     void EmitFileInfo(const std::string &fileName);
187     /* a symbol start/end a block */
188     void EmitBlockMarker(const std::string &markerName, const std::string &sectionName, bool withAddr,
189                          const std::string &addrName = "");
190     void EmitNullConstant(uint64 size);
191     void EmitCombineBfldValue(StructEmitInfo &structEmitInfo);
192     void EmitBitFieldConstant(StructEmitInfo &structEmitInfo, MIRConst &mirConst, const MIRType *nextType,
193                               uint64 fieldOffset);
194     void EmitScalarConstant(MIRConst &mirConst, bool newLine = true, bool flag32 = false, bool isIndirect = false);
195     void EmitStr(const std::string &mplStr, bool emitAscii = false, bool emitNewline = false);
196     void EmitStrConstant(const MIRStrConst &mirStrConst, bool isIndirect = false);
197     void EmitStr16Constant(const MIRStr16Const &mirStr16Const);
198     void EmitIntConst(const MIRSymbol &mirSymbol, MIRAggConst &aggConst, uint32 itabConflictIndex,
199                       const std::map<GStrIdx, MIRType *> &strIdx2Type, size_t idx);
200     void EmitAddrofFuncConst(const MIRSymbol &mirSymbol, MIRConst &elemConst, size_t idx);
201     void EmitAddrofSymbolConst(const MIRSymbol &mirSymbol, MIRConst &elemConst, size_t idx);
202     void EmitConstantTable(const MIRSymbol &mirSymbol, MIRConst &mirConst,
203                            const std::map<GStrIdx, MIRType *> &strIdx2Type);
204     void EmitClassInfoSequential(const MIRSymbol &mirSymbol, const std::map<GStrIdx, MIRType *> &strIdx2Type,
205                                  const std::string &sectionName);
206     void EmitMethodFieldSequential(const MIRSymbol &mirSymbol, const std::map<GStrIdx, MIRType *> &strIdx2Type,
207                                    const std::string &sectionName);
208     void EmitLiterals(std::vector<std::pair<MIRSymbol *, bool>> &literals,
209                       const std::map<GStrIdx, MIRType *> &strIdx2Type);
210     void EmitFuncLayoutInfo(const MIRSymbol &layout);
211     void EmitGlobalVars(std::vector<std::pair<MIRSymbol *, bool>> &globalVars);
212     void EmitGlobalVar(const MIRSymbol &globalVar);
213     void EmitStaticFields(const std::vector<MIRSymbol *> &fields);
214     void EmitLiteral(const MIRSymbol &literal, const std::map<GStrIdx, MIRType *> &strIdx2Type);
215     void EmitStringPointers();
216     void GetHotAndColdMetaSymbolInfo(const std::vector<MIRSymbol *> &mirSymbolVec,
217                                      std::vector<MIRSymbol *> &hotFieldInfoSymbolVec,
218                                      std::vector<MIRSymbol *> &coldFieldInfoSymbolVec, const std::string &prefixStr,
219                                      bool forceCold = false);
220     void EmitMetaDataSymbolWithMarkFlag(const std::vector<MIRSymbol *> &mirSymbolVec,
221                                         const std::map<GStrIdx, MIRType *> &strIdx2Type, const std::string &prefixStr,
222                                         const std::string &sectionName, bool isHotFlag);
223     void EmitMethodDeclaringClass(const MIRSymbol &mirSymbol, const std::string &sectionName);
224     void MarkVtabOrItabEndFlag(const std::vector<MIRSymbol *> &mirSymbolVec);
225     void EmitArrayConstant(MIRConst &mirConst);
226     void EmitStructConstant(MIRConst &mirConst);
227     void EmitStructConstant(MIRConst &mirConst, uint32 &subStructFieldCounts);
228     void EmitVectorConstant(MIRConst &mirConst);
229     void EmitLocalVariable(const CGFunc &cgFunc);
230     void EmitUninitializedSymbolsWithPrefixSection(const MIRSymbol &symbol, const std::string &sectionName);
231     void EmitGlobalVariable();
232     void EmitGlobalRootList(const MIRSymbol &mirSymbol);
233     void EmitMuidTable(const std::vector<MIRSymbol *> &vec, const std::map<GStrIdx, MIRType *> &strIdx2Type,
234                        const std::string &sectionName);
235     MIRAddroffuncConst *GetAddroffuncConst(const MIRSymbol &mirSymbol, MIRAggConst &aggConst);
236     int64 GetFieldOffsetValue(const std::string &className, const MIRIntConst &intConst,
237                               const std::map<GStrIdx, MIRType *> &strIdx2Type);
238 
Emit(int64 val)239     Emitter &Emit(int64 val)
240     {
241         fileStream << val;
242         return *this;
243     }
244 
Emit(const IntVal & val)245     Emitter &Emit(const IntVal &val)
246     {
247         fileStream << val.GetExtValue();
248         return *this;
249     }
250 
Emit(const MapleString & str)251     Emitter &Emit(const MapleString &str)
252     {
253         DEBUG_ASSERT(str.c_str() != nullptr, "nullptr check");
254         fileStream << str;
255         return *this;
256     }
257 
Emit(const std::string & str)258     Emitter &Emit(const std::string &str)
259     {
260         fileStream << str;
261         return *this;
262     }
263 
Emit(const void * data,size_t size)264     Emitter &Emit(const void *data, size_t size)
265     {
266         fileStream.write(reinterpret_cast<const char *>(data), size);
267         return *this;
268     }
269 
SetFileOffset(uint64 offset)270     void SetFileOffset(uint64 offset)
271     {
272         fileStream.seekp(offset);
273     }
274 
275     void EmitLabelRef(LabelIdx labIdx);
276     void EmitStmtLabel(LabelIdx labIdx);
277     void EmitLabelPair(const LabelPair &pairLabel);
278     void EmitLabelForFunc(const MIRFunction *func, LabelIdx labIdx);
279 
280     /* Emit signed/unsigned integer literals in decimal or hexadecimal */
281     void EmitDecSigned(int64 num);
282     void EmitDecUnsigned(uint64 num);
283     void EmitHexUnsigned(uint64 num);
284 
285     /* Dwarf debug info */
286     void FillInClassByteSize(DBGDie *die, DBGDieAttr *byteSizeAttr);
287     void SetupDBGInfo(DebugInfo *mirdi);
288     void ApplyInPrefixOrder(DBGDie *die, const std::function<void(DBGDie *)> &func);
289     void AddLabelDieToLabelIdxMapping(DBGDie *lblDie, LabelIdx lblIdx);
290     LabelIdx GetLabelIdxForLabelDie(DBGDie *lblDie);
291     void EmitDIHeader();
292     void EmitDIFooter();
293     void EmitDIHeaderFileInfo();
294     void EmitDIDebugInfoSection(DebugInfo *mirdi);
295     void EmitDIDebugAbbrevSection(DebugInfo *mirdi);
296     void EmitDIDebugARangesSection();
297     void EmitDIDebugRangesSection();
298     void EmitDIDebugLineSection();
299     void EmitDIDebugStrSection();
300     void EmitDIAttrValue(DBGDie *die, DBGDieAttr *attr, DwAt attrName, DwTag tagName, DebugInfo *di);
301     void EmitDIFormSpecification(unsigned int dwform);
EmitDIFormSpecification(const DBGDieAttr * attr)302     void EmitDIFormSpecification(const DBGDieAttr *attr)
303     {
304         EmitDIFormSpecification(attr->GetDwForm());
305     }
306 
307 #if 1 /* REQUIRE TO SEPERATE TARGAARCH64 TARGARM32 */
308       /* Following code is under TARGAARCH64 condition */
309     void EmitHugeSoRoutines(bool lastRoutine = false);
310     void EmitInlineAsmSection();
311 
GetJavaInsnCount()312     uint64 GetJavaInsnCount() const
313     {
314         return javaInsnCount;
315     }
316 
GetFuncInsnCount()317     uint64 GetFuncInsnCount() const
318     {
319         return funcInsnCount;
320     }
321 
GetFileMap()322     MapleMap<uint32_t, std::string> &GetFileMap()
323     {
324         return fileMap;
325     }
326 
SetFileMapValue(uint32_t n,const std::string & file)327     void SetFileMapValue(uint32_t n, const std::string &file)
328     {
329         fileMap[n] = file;
330     }
331 
GetCG()332     CG *GetCG() const
333     {
334         return cg;
335     }
336 
ClearFuncInsnCount()337     void ClearFuncInsnCount()
338     {
339         funcInsnCount = 0;
340     }
341 
342     void IncreaseJavaInsnCount(uint64 n = 1, bool alignToQuad = false)
343     {
344         if (alignToQuad) {
345             javaInsnCount = (javaInsnCount + 1) & (~0x1UL);
346             funcInsnCount = (funcInsnCount + 1) & (~0x1UL);
347         }
348         javaInsnCount += n;
349         funcInsnCount += n;
350 #ifdef EMIT_INSN_COUNT
351         Emit(" /* InsnCount: ");
352         Emit(javaInsnCount *);
353         Emit("*/ ");
354 #endif
355     }
356 
NeedToDealWithHugeSo()357     bool NeedToDealWithHugeSo() const
358     {
359         return javaInsnCount > kHugeSoInsnCountThreshold;
360     }
361 
HugeSoPostFix()362     std::string HugeSoPostFix() const
363     {
364         return std::string(kHugeSoPostFix) + std::to_string(hugeSoSeqence);
365     }
366 
InsertHugeSoTarget(const std::string & target)367     void InsertHugeSoTarget(const std::string &target)
368     {
369         (void)hugeSoTargets.insert(target);
370     }
371 #endif
372 
InsertLabdie2labidxTable(DBGDie * lbldie,LabelIdx lab)373     void InsertLabdie2labidxTable(DBGDie *lbldie, LabelIdx lab)
374     {
375         if (labdie2labidxTable.find(lbldie) == labdie2labidxTable.end()) {
376             labdie2labidxTable[lbldie] = lab;
377         }
378     }
379 
380 protected:
Emitter(CG & cg,const std::string & fileName)381     Emitter(CG &cg, const std::string &fileName)
382         : cg(&cg),
383           rangeIdx2PrefixStr(cg.GetMIRModule()->GetMPAllocator().Adapter()),
384           arraySize(0),
385           isFlexibleArray(false),
386           stringPtr(cg.GetMIRModule()->GetMPAllocator().Adapter()),
387           localStrPtr(cg.GetMIRModule()->GetMPAllocator().Adapter()),
388           hugeSoTargets(cg.GetMIRModule()->GetMPAllocator().Adapter()),
389           labdie2labidxTable(std::less<DBGDie *>(), cg.GetMIRModule()->GetMPAllocator().Adapter()),
390           fileMap(std::less<uint32_t>(), cg.GetMIRModule()->GetMPAllocator().Adapter())
391     {
392         MIRModule &mirModule = *cg.GetMIRModule();
393         memPool = mirModule.GetMemPool();
394         asmInfo = memPool->New<AsmInfo>(*memPool);
395     }
396 
397     ~Emitter() = default;
398 
399 protected:
400     std::ofstream fileStream;
401     MemPool *memPool;
402     CG *cg;
403 
404 private:
405     AsmLabel GetTypeAsmInfoName(PrimType primType) const;
406     void EmitDWRef(const std::string &name);
407     void InitRangeIdx2PerfixStr();
408     void EmitAddressString(const std::string &address);
409     void EmitAliasAndRef(const MIRSymbol &sym); /* handle function symbol which has alias and weak ref */
410 
411     MOperator currentMop = UINT_MAX;
412     MapleUnorderedMap<int, std::string> rangeIdx2PrefixStr;
413     const AsmInfo *asmInfo;
414     uint32 arraySize;
415     bool isFlexibleArray;
416     MapleSet<UStrIdx> stringPtr;
417     MapleVector<UStrIdx> localStrPtr;
418 #if 1 /* REQUIRE TO SEPERATE TARGAARCH64 TARGARM32 */
419       /* Following code is under TARGAARCH64 condition */
420     uint64 javaInsnCount = 0;
421     uint64 funcInsnCount = 0;
422     MapleSet<std::string> hugeSoTargets;
423     uint32 hugeSoSeqence = 2;
424 #endif
425     MapleMap<DBGDie *, LabelIdx> labdie2labidxTable;
426     MapleMap<uint32_t, std::string> fileMap;
427 };
428 
429 class OpndEmitVisitor : public OperandVisitorBase,
430                         public OperandVisitors<RegOperand, ImmOperand, MemOperand, OfstOperand, ListOperand,
431                                                LabelOperand, FuncNameOperand, StImmOperand, CondOperand,
432                                                BitShiftOperand, ExtendShiftOperand, CommentOperand> {
433 public:
OpndEmitVisitor(Emitter & asmEmitter)434     explicit OpndEmitVisitor(Emitter &asmEmitter) : emitter(asmEmitter) {}
435     virtual ~OpndEmitVisitor() = default;
436 
437 protected:
438     Emitter &emitter;
439 };
440 } /* namespace maplebe */
441 
442 #endif /* MAPLEBE_INCLUDE_CG_EMIT_H */
443