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