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 §ionName, 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 §ionName); 203 void EmitMethodFieldSequential(const MIRSymbol &mirSymbol, const std::map<GStrIdx, MIRType *> &strIdx2Type, 204 const std::string §ionName); 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 §ionName, bool isHotFlag); 221 void EmitMethodDeclaringClass(const MIRSymbol &mirSymbol, const std::string §ionName); 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 §ionName); 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 §ionName); 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