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