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