1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ADT/STLExtras.h" 11 #include "llvm/ADT/SmallString.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/ADT/Twine.h" 14 #include "llvm/MC/MCAsmBackend.h" 15 #include "llvm/MC/MCAsmInfo.h" 16 #include "llvm/MC/MCCodeEmitter.h" 17 #include "llvm/MC/MCCodeView.h" 18 #include "llvm/MC/MCContext.h" 19 #include "llvm/MC/MCExpr.h" 20 #include "llvm/MC/MCFixupKindInfo.h" 21 #include "llvm/MC/MCInst.h" 22 #include "llvm/MC/MCInstPrinter.h" 23 #include "llvm/MC/MCObjectFileInfo.h" 24 #include "llvm/MC/MCRegisterInfo.h" 25 #include "llvm/MC/MCSectionCOFF.h" 26 #include "llvm/MC/MCSectionMachO.h" 27 #include "llvm/MC/MCStreamer.h" 28 #include "llvm/MC/MCSymbolELF.h" 29 #include "llvm/Support/ErrorHandling.h" 30 #include "llvm/Support/Format.h" 31 #include "llvm/Support/FormattedStream.h" 32 #include "llvm/Support/LEB128.h" 33 #include "llvm/Support/MathExtras.h" 34 #include "llvm/Support/Path.h" 35 #include "llvm/Support/SourceMgr.h" 36 #include <cctype> 37 38 using namespace llvm; 39 40 namespace { 41 42 class MCAsmStreamer final : public MCStreamer { 43 std::unique_ptr<formatted_raw_ostream> OSOwner; 44 formatted_raw_ostream &OS; 45 const MCAsmInfo *MAI; 46 std::unique_ptr<MCInstPrinter> InstPrinter; 47 std::unique_ptr<MCCodeEmitter> Emitter; 48 std::unique_ptr<MCAsmBackend> AsmBackend; 49 50 SmallString<128> ExplicitCommentToEmit; 51 SmallString<128> CommentToEmit; 52 raw_svector_ostream CommentStream; 53 54 unsigned IsVerboseAsm : 1; 55 unsigned ShowInst : 1; 56 unsigned UseDwarfDirectory : 1; 57 58 void EmitRegisterName(int64_t Register); 59 void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; 60 void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; 61 62 public: 63 MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os, 64 bool isVerboseAsm, bool useDwarfDirectory, 65 MCInstPrinter *printer, MCCodeEmitter *emitter, 66 MCAsmBackend *asmbackend, bool showInst) 67 : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner), 68 MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), 69 AsmBackend(asmbackend), CommentStream(CommentToEmit), 70 IsVerboseAsm(isVerboseAsm), ShowInst(showInst), 71 UseDwarfDirectory(useDwarfDirectory) { 72 assert(InstPrinter); 73 if (IsVerboseAsm) 74 InstPrinter->setCommentStream(CommentStream); 75 } 76 77 inline void EmitEOL() { 78 // Dump Explicit Comments here. 79 emitExplicitComments(); 80 // If we don't have any comments, just emit a \n. 81 if (!IsVerboseAsm) { 82 OS << '\n'; 83 return; 84 } 85 EmitCommentsAndEOL(); 86 } 87 88 void EmitSyntaxDirective() override; 89 90 void EmitCommentsAndEOL(); 91 92 /// isVerboseAsm - Return true if this streamer supports verbose assembly at 93 /// all. 94 bool isVerboseAsm() const override { return IsVerboseAsm; } 95 96 /// hasRawTextSupport - We support EmitRawText. 97 bool hasRawTextSupport() const override { return true; } 98 99 /// AddComment - Add a comment that can be emitted to the generated .s 100 /// file if applicable as a QoI issue to make the output of the compiler 101 /// more readable. This only affects the MCAsmStreamer, and only when 102 /// verbose assembly output is enabled. 103 void AddComment(const Twine &T, bool EOL = true) override; 104 105 /// AddEncodingComment - Add a comment showing the encoding of an instruction. 106 void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); 107 108 /// GetCommentOS - Return a raw_ostream that comments can be written to. 109 /// Unlike AddComment, you are required to terminate comments with \n if you 110 /// use this method. 111 raw_ostream &GetCommentOS() override { 112 if (!IsVerboseAsm) 113 return nulls(); // Discard comments unless in verbose asm mode. 114 return CommentStream; 115 } 116 117 void emitRawComment(const Twine &T, bool TabPrefix = true) override; 118 119 void addExplicitComment(const Twine &T) override; 120 void emitExplicitComments() override; 121 122 /// AddBlankLine - Emit a blank line to a .s file to pretty it up. 123 void AddBlankLine() override { 124 EmitEOL(); 125 } 126 127 /// @name MCStreamer Interface 128 /// @{ 129 130 void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; 131 132 void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; 133 void EmitLabel(MCSymbol *Symbol) override; 134 135 void EmitAssemblerFlag(MCAssemblerFlag Flag) override; 136 void EmitLinkerOptions(ArrayRef<std::string> Options) override; 137 void EmitDataRegion(MCDataRegionType Kind) override; 138 void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, 139 unsigned Update) override; 140 void EmitThumbFunc(MCSymbol *Func) override; 141 142 void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; 143 void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; 144 bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; 145 146 void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; 147 void BeginCOFFSymbolDef(const MCSymbol *Symbol) override; 148 void EmitCOFFSymbolStorageClass(int StorageClass) override; 149 void EmitCOFFSymbolType(int Type) override; 150 void EndCOFFSymbolDef() override; 151 void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; 152 void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; 153 void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; 154 void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; 155 void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 156 unsigned ByteAlignment) override; 157 158 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 159 /// 160 /// @param Symbol - The common symbol to emit. 161 /// @param Size - The size of the common symbol. 162 /// @param ByteAlignment - The alignment of the common symbol in bytes. 163 void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 164 unsigned ByteAlignment) override; 165 166 void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, 167 uint64_t Size = 0, unsigned ByteAlignment = 0) override; 168 169 void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, 170 unsigned ByteAlignment = 0) override; 171 172 void EmitBinaryData(StringRef Data) override; 173 174 void EmitBytes(StringRef Data) override; 175 176 void EmitValueImpl(const MCExpr *Value, unsigned Size, 177 SMLoc Loc = SMLoc()) override; 178 void EmitIntValue(uint64_t Value, unsigned Size) override; 179 180 void EmitULEB128Value(const MCExpr *Value) override; 181 182 void EmitSLEB128Value(const MCExpr *Value) override; 183 184 void EmitDTPRel32Value(const MCExpr *Value) override; 185 void EmitDTPRel64Value(const MCExpr *Value) override; 186 void EmitTPRel32Value(const MCExpr *Value) override; 187 void EmitTPRel64Value(const MCExpr *Value) override; 188 189 void EmitGPRel64Value(const MCExpr *Value) override; 190 191 void EmitGPRel32Value(const MCExpr *Value) override; 192 193 194 void emitFill(uint64_t NumBytes, uint8_t FillValue) override; 195 196 void emitFill(const MCExpr &NumBytes, uint64_t FillValue, 197 SMLoc Loc = SMLoc()) override; 198 199 void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) override; 200 201 void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, 202 SMLoc Loc = SMLoc()) override; 203 204 void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 205 unsigned ValueSize = 1, 206 unsigned MaxBytesToEmit = 0) override; 207 208 void EmitCodeAlignment(unsigned ByteAlignment, 209 unsigned MaxBytesToEmit = 0) override; 210 211 void emitValueToOffset(const MCExpr *Offset, 212 unsigned char Value, 213 SMLoc Loc) override; 214 215 void EmitFileDirective(StringRef Filename) override; 216 unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, 217 StringRef Filename, 218 unsigned CUID = 0) override; 219 void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 220 unsigned Column, unsigned Flags, 221 unsigned Isa, unsigned Discriminator, 222 StringRef FileName) override; 223 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; 224 225 bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override; 226 bool EmitCVFuncIdDirective(unsigned FuncId) override; 227 bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, 228 unsigned IAFile, unsigned IALine, 229 unsigned IACol, SMLoc Loc) override; 230 void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, 231 unsigned Column, bool PrologueEnd, bool IsStmt, 232 StringRef FileName, SMLoc Loc) override; 233 void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, 234 const MCSymbol *FnEnd) override; 235 void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, 236 unsigned SourceFileId, 237 unsigned SourceLineNum, 238 const MCSymbol *FnStartSym, 239 const MCSymbol *FnEndSym) override; 240 void EmitCVDefRangeDirective( 241 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 242 StringRef FixedSizePortion) override; 243 void EmitCVStringTableDirective() override; 244 void EmitCVFileChecksumsDirective() override; 245 246 void EmitIdent(StringRef IdentString) override; 247 void EmitCFISections(bool EH, bool Debug) override; 248 void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; 249 void EmitCFIDefCfaOffset(int64_t Offset) override; 250 void EmitCFIDefCfaRegister(int64_t Register) override; 251 void EmitCFIOffset(int64_t Register, int64_t Offset) override; 252 void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; 253 void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; 254 void EmitCFIRememberState() override; 255 void EmitCFIRestoreState() override; 256 void EmitCFISameValue(int64_t Register) override; 257 void EmitCFIRelOffset(int64_t Register, int64_t Offset) override; 258 void EmitCFIAdjustCfaOffset(int64_t Adjustment) override; 259 void EmitCFIEscape(StringRef Values) override; 260 void EmitCFIGnuArgsSize(int64_t Size) override; 261 void EmitCFISignalFrame() override; 262 void EmitCFIUndefined(int64_t Register) override; 263 void EmitCFIRegister(int64_t Register1, int64_t Register2) override; 264 void EmitCFIWindowSave() override; 265 266 void EmitWinCFIStartProc(const MCSymbol *Symbol) override; 267 void EmitWinCFIEndProc() override; 268 void EmitWinCFIStartChained() override; 269 void EmitWinCFIEndChained() override; 270 void EmitWinCFIPushReg(unsigned Register) override; 271 void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override; 272 void EmitWinCFIAllocStack(unsigned Size) override; 273 void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override; 274 void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override; 275 void EmitWinCFIPushFrame(bool Code) override; 276 void EmitWinCFIEndProlog() override; 277 278 void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override; 279 void EmitWinEHHandlerData() override; 280 281 void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; 282 283 void EmitBundleAlignMode(unsigned AlignPow2) override; 284 void EmitBundleLock(bool AlignToEnd) override; 285 void EmitBundleUnlock() override; 286 287 bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, 288 const MCExpr *Expr, SMLoc Loc) override; 289 290 /// EmitRawText - If this file is backed by an assembly streamer, this dumps 291 /// the specified string in the output .s file. This capability is 292 /// indicated by the hasRawTextSupport() predicate. 293 void EmitRawTextImpl(StringRef String) override; 294 295 void FinishImpl() override; 296 }; 297 298 } // end anonymous namespace. 299 300 /// AddComment - Add a comment that can be emitted to the generated .s 301 /// file if applicable as a QoI issue to make the output of the compiler 302 /// more readable. This only affects the MCAsmStreamer, and only when 303 /// verbose assembly output is enabled. 304 /// By deafult EOL is set to true so that each comment goes on its own line. 305 void MCAsmStreamer::AddComment(const Twine &T, bool EOL) { 306 if (!IsVerboseAsm) return; 307 308 T.toVector(CommentToEmit); 309 310 if (EOL) 311 CommentToEmit.push_back('\n'); // Place comment in a new line. 312 } 313 314 void MCAsmStreamer::EmitCommentsAndEOL() { 315 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { 316 OS << '\n'; 317 return; 318 } 319 320 StringRef Comments = CommentToEmit; 321 322 assert(Comments.back() == '\n' && 323 "Comment array not newline terminated"); 324 do { 325 // Emit a line of comments. 326 OS.PadToColumn(MAI->getCommentColumn()); 327 size_t Position = Comments.find('\n'); 328 OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n'; 329 330 Comments = Comments.substr(Position+1); 331 } while (!Comments.empty()); 332 333 CommentToEmit.clear(); 334 } 335 336 static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 337 assert(Bytes > 0 && Bytes <= 8 && "Invalid size!"); 338 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 339 } 340 341 void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { 342 if (TabPrefix) 343 OS << '\t'; 344 OS << MAI->getCommentString() << T; 345 EmitEOL(); 346 } 347 348 void MCAsmStreamer::addExplicitComment(const Twine &T) { 349 StringRef c = T.getSingleStringRef(); 350 if (c.equals(StringRef(MAI->getSeparatorString()))) 351 return; 352 if (c.startswith(StringRef("//"))) { 353 ExplicitCommentToEmit.append("\t"); 354 ExplicitCommentToEmit.append(MAI->getCommentString()); 355 // drop // 356 ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); 357 } else if (c.startswith(StringRef("/*"))) { 358 size_t p = 2, len = c.size() - 2; 359 // emit each line in comment as separate newline. 360 do { 361 size_t newp = std::min(len, c.find_first_of("\r\n", p)); 362 ExplicitCommentToEmit.append("\t"); 363 ExplicitCommentToEmit.append(MAI->getCommentString()); 364 ExplicitCommentToEmit.append(c.slice(p, newp).str()); 365 // If we have another line in this comment add line 366 if (newp < len) 367 ExplicitCommentToEmit.append("\n"); 368 p = newp + 1; 369 } while (p < len); 370 } else if (c.startswith(StringRef(MAI->getCommentString()))) { 371 ExplicitCommentToEmit.append("\t"); 372 ExplicitCommentToEmit.append(c.str()); 373 } else if (c.front() == '#') { 374 375 ExplicitCommentToEmit.append("\t"); 376 ExplicitCommentToEmit.append(MAI->getCommentString()); 377 ExplicitCommentToEmit.append(c.slice(1, c.size()).str()); 378 } else 379 assert(false && "Unexpected Assembly Comment"); 380 // full line comments immediately output 381 if (c.back() == '\n') 382 emitExplicitComments(); 383 } 384 385 void MCAsmStreamer::emitExplicitComments() { 386 StringRef Comments = ExplicitCommentToEmit; 387 if (!Comments.empty()) 388 OS << Comments; 389 ExplicitCommentToEmit.clear(); 390 } 391 392 void MCAsmStreamer::ChangeSection(MCSection *Section, 393 const MCExpr *Subsection) { 394 assert(Section && "Cannot switch to a null section!"); 395 Section->PrintSwitchToSection(*MAI, OS, Subsection); 396 } 397 398 void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 399 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 400 MCStreamer::EmitLabel(Symbol); 401 402 Symbol->print(OS, MAI); 403 OS << MAI->getLabelSuffix(); 404 405 EmitEOL(); 406 } 407 408 void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { 409 StringRef str = MCLOHIdToName(Kind); 410 411 #ifndef NDEBUG 412 int NbArgs = MCLOHIdToNbArgs(Kind); 413 assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!"); 414 assert(str != "" && "Invalid LOH name"); 415 #endif 416 417 OS << "\t" << MCLOHDirectiveName() << " " << str << "\t"; 418 bool IsFirst = true; 419 for (const MCSymbol *Arg : Args) { 420 if (!IsFirst) 421 OS << ", "; 422 IsFirst = false; 423 Arg->print(OS, MAI); 424 } 425 EmitEOL(); 426 } 427 428 void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 429 switch (Flag) { 430 case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; 431 case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 432 case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break; 433 case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break; 434 case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break; 435 } 436 EmitEOL(); 437 } 438 439 void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { 440 assert(!Options.empty() && "At least one option is required!"); 441 OS << "\t.linker_option \"" << Options[0] << '"'; 442 for (ArrayRef<std::string>::iterator it = Options.begin() + 1, 443 ie = Options.end(); it != ie; ++it) { 444 OS << ", " << '"' << *it << '"'; 445 } 446 EmitEOL(); 447 } 448 449 void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { 450 if (!MAI->doesSupportDataRegionDirectives()) 451 return; 452 switch (Kind) { 453 case MCDR_DataRegion: OS << "\t.data_region"; break; 454 case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break; 455 case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break; 456 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break; 457 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break; 458 } 459 EmitEOL(); 460 } 461 462 void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, 463 unsigned Minor, unsigned Update) { 464 switch (Kind) { 465 case MCVM_WatchOSVersionMin: OS << "\t.watchos_version_min"; break; 466 case MCVM_TvOSVersionMin: OS << "\t.tvos_version_min"; break; 467 case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break; 468 case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break; 469 } 470 OS << " " << Major << ", " << Minor; 471 if (Update) 472 OS << ", " << Update; 473 EmitEOL(); 474 } 475 476 void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { 477 // This needs to emit to a temporary string to get properly quoted 478 // MCSymbols when they have spaces in them. 479 OS << "\t.thumb_func"; 480 // Only Mach-O hasSubsectionsViaSymbols() 481 if (MAI->hasSubsectionsViaSymbols()) { 482 OS << '\t'; 483 Func->print(OS, MAI); 484 } 485 EmitEOL(); 486 } 487 488 void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 489 Symbol->print(OS, MAI); 490 OS << " = "; 491 Value->print(OS, MAI); 492 493 EmitEOL(); 494 495 MCStreamer::EmitAssignment(Symbol, Value); 496 } 497 498 void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { 499 OS << ".weakref "; 500 Alias->print(OS, MAI); 501 OS << ", "; 502 Symbol->print(OS, MAI); 503 EmitEOL(); 504 } 505 506 bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 507 MCSymbolAttr Attribute) { 508 switch (Attribute) { 509 case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute"); 510 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function 511 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC 512 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object 513 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object 514 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common 515 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype 516 case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object 517 if (!MAI->hasDotTypeDotSizeDirective()) 518 return false; // Symbol attribute not supported 519 OS << "\t.type\t"; 520 Symbol->print(OS, MAI); 521 OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%'); 522 switch (Attribute) { 523 default: return false; 524 case MCSA_ELF_TypeFunction: OS << "function"; break; 525 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; 526 case MCSA_ELF_TypeObject: OS << "object"; break; 527 case MCSA_ELF_TypeTLS: OS << "tls_object"; break; 528 case MCSA_ELF_TypeCommon: OS << "common"; break; 529 case MCSA_ELF_TypeNoType: OS << "no_type"; break; 530 case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; 531 } 532 EmitEOL(); 533 return true; 534 case MCSA_Global: // .globl/.global 535 OS << MAI->getGlobalDirective(); 536 break; 537 case MCSA_Hidden: OS << "\t.hidden\t"; break; 538 case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; 539 case MCSA_Internal: OS << "\t.internal\t"; break; 540 case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; 541 case MCSA_Local: OS << "\t.local\t"; break; 542 case MCSA_NoDeadStrip: 543 if (!MAI->hasNoDeadStrip()) 544 return false; 545 OS << "\t.no_dead_strip\t"; 546 break; 547 case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; 548 case MCSA_AltEntry: OS << "\t.alt_entry\t"; break; 549 case MCSA_PrivateExtern: 550 OS << "\t.private_extern\t"; 551 break; 552 case MCSA_Protected: OS << "\t.protected\t"; break; 553 case MCSA_Reference: OS << "\t.reference\t"; break; 554 case MCSA_Weak: OS << MAI->getWeakDirective(); break; 555 case MCSA_WeakDefinition: 556 OS << "\t.weak_definition\t"; 557 break; 558 // .weak_reference 559 case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; 560 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; 561 } 562 563 Symbol->print(OS, MAI); 564 EmitEOL(); 565 566 return true; 567 } 568 569 void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 570 OS << ".desc" << ' '; 571 Symbol->print(OS, MAI); 572 OS << ',' << DescValue; 573 EmitEOL(); 574 } 575 576 void MCAsmStreamer::EmitSyntaxDirective() { 577 if (MAI->getAssemblerDialect() == 1) { 578 OS << "\t.intel_syntax noprefix"; 579 EmitEOL(); 580 } 581 // FIXME: Currently emit unprefix'ed registers. 582 // The intel_syntax directive has one optional argument 583 // with may have a value of prefix or noprefix. 584 } 585 586 void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { 587 OS << "\t.def\t "; 588 Symbol->print(OS, MAI); 589 OS << ';'; 590 EmitEOL(); 591 } 592 593 void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) { 594 OS << "\t.scl\t" << StorageClass << ';'; 595 EmitEOL(); 596 } 597 598 void MCAsmStreamer::EmitCOFFSymbolType (int Type) { 599 OS << "\t.type\t" << Type << ';'; 600 EmitEOL(); 601 } 602 603 void MCAsmStreamer::EndCOFFSymbolDef() { 604 OS << "\t.endef"; 605 EmitEOL(); 606 } 607 608 void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { 609 OS << "\t.safeseh\t"; 610 Symbol->print(OS, MAI); 611 EmitEOL(); 612 } 613 614 void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { 615 OS << "\t.secidx\t"; 616 Symbol->print(OS, MAI); 617 EmitEOL(); 618 } 619 620 void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) { 621 OS << "\t.secrel32\t"; 622 Symbol->print(OS, MAI); 623 if (Offset != 0) 624 OS << '+' << Offset; 625 EmitEOL(); 626 } 627 628 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 629 assert(MAI->hasDotTypeDotSizeDirective()); 630 OS << "\t.size\t"; 631 Symbol->print(OS, MAI); 632 OS << ", "; 633 Value->print(OS, MAI); 634 EmitEOL(); 635 } 636 637 void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 638 unsigned ByteAlignment) { 639 OS << "\t.comm\t"; 640 Symbol->print(OS, MAI); 641 OS << ',' << Size; 642 643 if (ByteAlignment != 0) { 644 if (MAI->getCOMMDirectiveAlignmentIsInBytes()) 645 OS << ',' << ByteAlignment; 646 else 647 OS << ',' << Log2_32(ByteAlignment); 648 } 649 EmitEOL(); 650 } 651 652 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 653 /// 654 /// @param Symbol - The common symbol to emit. 655 /// @param Size - The size of the common symbol. 656 void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 657 unsigned ByteAlign) { 658 OS << "\t.lcomm\t"; 659 Symbol->print(OS, MAI); 660 OS << ',' << Size; 661 662 if (ByteAlign > 1) { 663 switch (MAI->getLCOMMDirectiveAlignmentType()) { 664 case LCOMM::NoAlignment: 665 llvm_unreachable("alignment not supported on .lcomm!"); 666 case LCOMM::ByteAlignment: 667 OS << ',' << ByteAlign; 668 break; 669 case LCOMM::Log2Alignment: 670 assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2"); 671 OS << ',' << Log2_32(ByteAlign); 672 break; 673 } 674 } 675 EmitEOL(); 676 } 677 678 void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 679 uint64_t Size, unsigned ByteAlignment) { 680 if (Symbol) 681 AssignFragment(Symbol, &Section->getDummyFragment()); 682 683 // Note: a .zerofill directive does not switch sections. 684 OS << ".zerofill "; 685 686 // This is a mach-o specific directive. 687 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 688 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 689 690 if (Symbol) { 691 OS << ','; 692 Symbol->print(OS, MAI); 693 OS << ',' << Size; 694 if (ByteAlignment != 0) 695 OS << ',' << Log2_32(ByteAlignment); 696 } 697 EmitEOL(); 698 } 699 700 // .tbss sym, size, align 701 // This depends that the symbol has already been mangled from the original, 702 // e.g. _a. 703 void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 704 uint64_t Size, unsigned ByteAlignment) { 705 AssignFragment(Symbol, &Section->getDummyFragment()); 706 707 assert(Symbol && "Symbol shouldn't be NULL!"); 708 // Instead of using the Section we'll just use the shortcut. 709 // This is a mach-o specific directive and section. 710 OS << ".tbss "; 711 Symbol->print(OS, MAI); 712 OS << ", " << Size; 713 714 // Output align if we have it. We default to 1 so don't bother printing 715 // that. 716 if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment); 717 718 EmitEOL(); 719 } 720 721 static inline char toOctal(int X) { return (X&7)+'0'; } 722 723 static void PrintQuotedString(StringRef Data, raw_ostream &OS) { 724 OS << '"'; 725 726 for (unsigned i = 0, e = Data.size(); i != e; ++i) { 727 unsigned char C = Data[i]; 728 if (C == '"' || C == '\\') { 729 OS << '\\' << (char)C; 730 continue; 731 } 732 733 if (isprint((unsigned char)C)) { 734 OS << (char)C; 735 continue; 736 } 737 738 switch (C) { 739 case '\b': OS << "\\b"; break; 740 case '\f': OS << "\\f"; break; 741 case '\n': OS << "\\n"; break; 742 case '\r': OS << "\\r"; break; 743 case '\t': OS << "\\t"; break; 744 default: 745 OS << '\\'; 746 OS << toOctal(C >> 6); 747 OS << toOctal(C >> 3); 748 OS << toOctal(C >> 0); 749 break; 750 } 751 } 752 753 OS << '"'; 754 } 755 756 void MCAsmStreamer::EmitBytes(StringRef Data) { 757 assert(getCurrentSectionOnly() && 758 "Cannot emit contents before setting section!"); 759 if (Data.empty()) return; 760 761 if (Data.size() == 1) { 762 OS << MAI->getData8bitsDirective(); 763 OS << (unsigned)(unsigned char)Data[0]; 764 EmitEOL(); 765 return; 766 } 767 768 // If the data ends with 0 and the target supports .asciz, use it, otherwise 769 // use .ascii 770 if (MAI->getAscizDirective() && Data.back() == 0) { 771 OS << MAI->getAscizDirective(); 772 Data = Data.substr(0, Data.size()-1); 773 } else { 774 OS << MAI->getAsciiDirective(); 775 } 776 777 PrintQuotedString(Data, OS); 778 EmitEOL(); 779 } 780 781 void MCAsmStreamer::EmitBinaryData(StringRef Data) { 782 // This is binary data. Print it in a grid of hex bytes for readability. 783 const size_t Cols = 4; 784 for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) { 785 size_t J = I, EJ = std::min(I + Cols, Data.size()); 786 assert(EJ > 0); 787 OS << MAI->getData8bitsDirective(); 788 for (; J < EJ - 1; ++J) 789 OS << format("0x%02x", uint8_t(Data[J])) << ", "; 790 OS << format("0x%02x", uint8_t(Data[J])); 791 EmitEOL(); 792 } 793 } 794 795 void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { 796 EmitValue(MCConstantExpr::create(Value, getContext()), Size); 797 } 798 799 void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, 800 SMLoc Loc) { 801 assert(Size <= 8 && "Invalid size"); 802 assert(getCurrentSectionOnly() && 803 "Cannot emit contents before setting section!"); 804 const char *Directive = nullptr; 805 switch (Size) { 806 default: break; 807 case 1: Directive = MAI->getData8bitsDirective(); break; 808 case 2: Directive = MAI->getData16bitsDirective(); break; 809 case 4: Directive = MAI->getData32bitsDirective(); break; 810 case 8: Directive = MAI->getData64bitsDirective(); break; 811 } 812 813 if (!Directive) { 814 int64_t IntValue; 815 if (!Value->evaluateAsAbsolute(IntValue)) 816 report_fatal_error("Don't know how to emit this value."); 817 818 // We couldn't handle the requested integer size so we fallback by breaking 819 // the request down into several, smaller, integers. 820 // Since sizes greater or equal to "Size" are invalid, we use the greatest 821 // power of 2 that is less than "Size" as our largest piece of granularity. 822 bool IsLittleEndian = MAI->isLittleEndian(); 823 for (unsigned Emitted = 0; Emitted != Size;) { 824 unsigned Remaining = Size - Emitted; 825 // The size of our partial emission must be a power of two less than 826 // Size. 827 unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1)); 828 // Calculate the byte offset of our partial emission taking into account 829 // the endianness of the target. 830 unsigned ByteOffset = 831 IsLittleEndian ? Emitted : (Remaining - EmissionSize); 832 uint64_t ValueToEmit = IntValue >> (ByteOffset * 8); 833 // We truncate our partial emission to fit within the bounds of the 834 // emission domain. This produces nicer output and silences potential 835 // truncation warnings when round tripping through another assembler. 836 uint64_t Shift = 64 - EmissionSize * 8; 837 assert(Shift < static_cast<uint64_t>( 838 std::numeric_limits<unsigned long long>::digits) && 839 "undefined behavior"); 840 ValueToEmit &= ~0ULL >> Shift; 841 EmitIntValue(ValueToEmit, EmissionSize); 842 Emitted += EmissionSize; 843 } 844 return; 845 } 846 847 assert(Directive && "Invalid size for machine code value!"); 848 OS << Directive; 849 Value->print(OS, MAI); 850 EmitEOL(); 851 } 852 853 void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { 854 int64_t IntValue; 855 if (Value->evaluateAsAbsolute(IntValue)) { 856 EmitULEB128IntValue(IntValue); 857 return; 858 } 859 OS << ".uleb128 "; 860 Value->print(OS, MAI); 861 EmitEOL(); 862 } 863 864 void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { 865 int64_t IntValue; 866 if (Value->evaluateAsAbsolute(IntValue)) { 867 EmitSLEB128IntValue(IntValue); 868 return; 869 } 870 OS << ".sleb128 "; 871 Value->print(OS, MAI); 872 EmitEOL(); 873 } 874 875 void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) { 876 assert(MAI->getDTPRel64Directive() != nullptr); 877 OS << MAI->getDTPRel64Directive(); 878 Value->print(OS, MAI); 879 EmitEOL(); 880 } 881 882 void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) { 883 assert(MAI->getDTPRel32Directive() != nullptr); 884 OS << MAI->getDTPRel32Directive(); 885 Value->print(OS, MAI); 886 EmitEOL(); 887 } 888 889 void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) { 890 assert(MAI->getTPRel64Directive() != nullptr); 891 OS << MAI->getTPRel64Directive(); 892 Value->print(OS, MAI); 893 EmitEOL(); 894 } 895 896 void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) { 897 assert(MAI->getTPRel32Directive() != nullptr); 898 OS << MAI->getTPRel32Directive(); 899 Value->print(OS, MAI); 900 EmitEOL(); 901 } 902 903 void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) { 904 assert(MAI->getGPRel64Directive() != nullptr); 905 OS << MAI->getGPRel64Directive(); 906 Value->print(OS, MAI); 907 EmitEOL(); 908 } 909 910 void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { 911 assert(MAI->getGPRel32Directive() != nullptr); 912 OS << MAI->getGPRel32Directive(); 913 Value->print(OS, MAI); 914 EmitEOL(); 915 } 916 917 /// emitFill - Emit NumBytes bytes worth of the value specified by 918 /// FillValue. This implements directives such as '.space'. 919 void MCAsmStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { 920 if (NumBytes == 0) return; 921 922 const MCExpr *E = MCConstantExpr::create(NumBytes, getContext()); 923 emitFill(*E, FillValue); 924 } 925 926 void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, 927 SMLoc Loc) { 928 if (const char *ZeroDirective = MAI->getZeroDirective()) { 929 // FIXME: Emit location directives 930 OS << ZeroDirective; 931 NumBytes.print(OS, MAI); 932 if (FillValue != 0) 933 OS << ',' << (int)FillValue; 934 EmitEOL(); 935 return; 936 } 937 938 MCStreamer::emitFill(NumBytes, FillValue); 939 } 940 941 void MCAsmStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) { 942 if (NumValues == 0) 943 return; 944 945 const MCExpr *E = MCConstantExpr::create(NumValues, getContext()); 946 emitFill(*E, Size, Expr); 947 } 948 949 void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size, 950 int64_t Expr, SMLoc Loc) { 951 // FIXME: Emit location directives 952 OS << "\t.fill\t"; 953 NumValues.print(OS, MAI); 954 OS << ", " << Size << ", 0x"; 955 OS.write_hex(truncateToSize(Expr, 4)); 956 EmitEOL(); 957 } 958 959 void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 960 unsigned ValueSize, 961 unsigned MaxBytesToEmit) { 962 // Some assemblers don't support non-power of two alignments, so we always 963 // emit alignments as a power of two if possible. 964 if (isPowerOf2_32(ByteAlignment)) { 965 switch (ValueSize) { 966 default: 967 llvm_unreachable("Invalid size for machine code value!"); 968 case 1: 969 OS << "\t.p2align\t"; 970 break; 971 case 2: 972 OS << ".p2alignw "; 973 break; 974 case 4: 975 OS << ".p2alignl "; 976 break; 977 case 8: 978 llvm_unreachable("Unsupported alignment size!"); 979 } 980 981 OS << Log2_32(ByteAlignment); 982 983 if (Value || MaxBytesToEmit) { 984 OS << ", 0x"; 985 OS.write_hex(truncateToSize(Value, ValueSize)); 986 987 if (MaxBytesToEmit) 988 OS << ", " << MaxBytesToEmit; 989 } 990 EmitEOL(); 991 return; 992 } 993 994 // Non-power of two alignment. This is not widely supported by assemblers. 995 // FIXME: Parameterize this based on MAI. 996 switch (ValueSize) { 997 default: llvm_unreachable("Invalid size for machine code value!"); 998 case 1: OS << ".balign"; break; 999 case 2: OS << ".balignw"; break; 1000 case 4: OS << ".balignl"; break; 1001 case 8: llvm_unreachable("Unsupported alignment size!"); 1002 } 1003 1004 OS << ' ' << ByteAlignment; 1005 OS << ", " << truncateToSize(Value, ValueSize); 1006 if (MaxBytesToEmit) 1007 OS << ", " << MaxBytesToEmit; 1008 EmitEOL(); 1009 } 1010 1011 void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, 1012 unsigned MaxBytesToEmit) { 1013 // Emit with a text fill value. 1014 EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(), 1015 1, MaxBytesToEmit); 1016 } 1017 1018 void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, 1019 unsigned char Value, 1020 SMLoc Loc) { 1021 // FIXME: Verify that Offset is associated with the current section. 1022 OS << ".org "; 1023 Offset->print(OS, MAI); 1024 OS << ", " << (unsigned)Value; 1025 EmitEOL(); 1026 } 1027 1028 void MCAsmStreamer::EmitFileDirective(StringRef Filename) { 1029 assert(MAI->hasSingleParameterDotFile()); 1030 OS << "\t.file\t"; 1031 PrintQuotedString(Filename, OS); 1032 EmitEOL(); 1033 } 1034 1035 unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, 1036 StringRef Directory, 1037 StringRef Filename, 1038 unsigned CUID) { 1039 assert(CUID == 0); 1040 1041 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); 1042 unsigned NumFiles = Table.getMCDwarfFiles().size(); 1043 FileNo = Table.getFile(Directory, Filename, FileNo); 1044 if (FileNo == 0) 1045 return 0; 1046 if (NumFiles == Table.getMCDwarfFiles().size()) 1047 return FileNo; 1048 1049 SmallString<128> FullPathName; 1050 1051 if (!UseDwarfDirectory && !Directory.empty()) { 1052 if (sys::path::is_absolute(Filename)) 1053 Directory = ""; 1054 else { 1055 FullPathName = Directory; 1056 sys::path::append(FullPathName, Filename); 1057 Directory = ""; 1058 Filename = FullPathName; 1059 } 1060 } 1061 1062 OS << "\t.file\t" << FileNo << ' '; 1063 if (!Directory.empty()) { 1064 PrintQuotedString(Directory, OS); 1065 OS << ' '; 1066 } 1067 PrintQuotedString(Filename, OS); 1068 EmitEOL(); 1069 1070 return FileNo; 1071 } 1072 1073 void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 1074 unsigned Column, unsigned Flags, 1075 unsigned Isa, 1076 unsigned Discriminator, 1077 StringRef FileName) { 1078 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; 1079 if (Flags & DWARF2_FLAG_BASIC_BLOCK) 1080 OS << " basic_block"; 1081 if (Flags & DWARF2_FLAG_PROLOGUE_END) 1082 OS << " prologue_end"; 1083 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) 1084 OS << " epilogue_begin"; 1085 1086 unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); 1087 if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { 1088 OS << " is_stmt "; 1089 1090 if (Flags & DWARF2_FLAG_IS_STMT) 1091 OS << "1"; 1092 else 1093 OS << "0"; 1094 } 1095 1096 if (Isa) 1097 OS << " isa " << Isa; 1098 if (Discriminator) 1099 OS << " discriminator " << Discriminator; 1100 1101 if (IsVerboseAsm) { 1102 OS.PadToColumn(MAI->getCommentColumn()); 1103 OS << MAI->getCommentString() << ' ' << FileName << ':' 1104 << Line << ':' << Column; 1105 } 1106 EmitEOL(); 1107 this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, 1108 Isa, Discriminator, FileName); 1109 } 1110 1111 MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { 1112 // Always use the zeroth line table, since asm syntax only supports one line 1113 // table for now. 1114 return MCStreamer::getDwarfLineTableSymbol(0); 1115 } 1116 1117 bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) { 1118 if (!getContext().getCVContext().addFile(FileNo, Filename)) 1119 return false; 1120 1121 OS << "\t.cv_file\t" << FileNo << ' '; 1122 1123 PrintQuotedString(Filename, OS); 1124 EmitEOL(); 1125 return true; 1126 } 1127 1128 bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) { 1129 OS << "\t.cv_func_id " << FuncId << '\n'; 1130 return MCStreamer::EmitCVFuncIdDirective(FuncId); 1131 } 1132 1133 bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId, 1134 unsigned IAFunc, 1135 unsigned IAFile, 1136 unsigned IALine, unsigned IACol, 1137 SMLoc Loc) { 1138 OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc 1139 << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n'; 1140 return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, 1141 IALine, IACol, Loc); 1142 } 1143 1144 void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, 1145 unsigned Line, unsigned Column, 1146 bool PrologueEnd, bool IsStmt, 1147 StringRef FileName, SMLoc Loc) { 1148 OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " " 1149 << Column; 1150 if (PrologueEnd) 1151 OS << " prologue_end"; 1152 1153 unsigned OldIsStmt = getContext().getCVContext().getCurrentCVLoc().isStmt(); 1154 if (IsStmt != OldIsStmt) { 1155 OS << " is_stmt "; 1156 1157 if (IsStmt) 1158 OS << "1"; 1159 else 1160 OS << "0"; 1161 } 1162 1163 if (IsVerboseAsm) { 1164 OS.PadToColumn(MAI->getCommentColumn()); 1165 OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':' 1166 << Column; 1167 } 1168 EmitEOL(); 1169 this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column, 1170 PrologueEnd, IsStmt, FileName, Loc); 1171 } 1172 1173 void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId, 1174 const MCSymbol *FnStart, 1175 const MCSymbol *FnEnd) { 1176 OS << "\t.cv_linetable\t" << FunctionId << ", "; 1177 FnStart->print(OS, MAI); 1178 OS << ", "; 1179 FnEnd->print(OS, MAI); 1180 EmitEOL(); 1181 this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd); 1182 } 1183 1184 void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId, 1185 unsigned SourceFileId, 1186 unsigned SourceLineNum, 1187 const MCSymbol *FnStartSym, 1188 const MCSymbol *FnEndSym) { 1189 OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId 1190 << ' ' << SourceLineNum << ' '; 1191 FnStartSym->print(OS, MAI); 1192 OS << ' '; 1193 FnEndSym->print(OS, MAI); 1194 EmitEOL(); 1195 this->MCStreamer::EmitCVInlineLinetableDirective( 1196 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym); 1197 } 1198 1199 void MCAsmStreamer::EmitCVDefRangeDirective( 1200 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1201 StringRef FixedSizePortion) { 1202 OS << "\t.cv_def_range\t"; 1203 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) { 1204 OS << ' '; 1205 Range.first->print(OS, MAI); 1206 OS << ' '; 1207 Range.second->print(OS, MAI); 1208 } 1209 OS << ", "; 1210 PrintQuotedString(FixedSizePortion, OS); 1211 EmitEOL(); 1212 this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); 1213 } 1214 1215 void MCAsmStreamer::EmitCVStringTableDirective() { 1216 OS << "\t.cv_stringtable"; 1217 EmitEOL(); 1218 } 1219 1220 void MCAsmStreamer::EmitCVFileChecksumsDirective() { 1221 OS << "\t.cv_filechecksums"; 1222 EmitEOL(); 1223 } 1224 1225 void MCAsmStreamer::EmitIdent(StringRef IdentString) { 1226 assert(MAI->hasIdentDirective() && ".ident directive not supported"); 1227 OS << "\t.ident\t"; 1228 PrintQuotedString(IdentString, OS); 1229 EmitEOL(); 1230 } 1231 1232 void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { 1233 MCStreamer::EmitCFISections(EH, Debug); 1234 OS << "\t.cfi_sections "; 1235 if (EH) { 1236 OS << ".eh_frame"; 1237 if (Debug) 1238 OS << ", .debug_frame"; 1239 } else if (Debug) { 1240 OS << ".debug_frame"; 1241 } 1242 1243 EmitEOL(); 1244 } 1245 1246 void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { 1247 OS << "\t.cfi_startproc"; 1248 if (Frame.IsSimple) 1249 OS << " simple"; 1250 EmitEOL(); 1251 } 1252 1253 void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { 1254 MCStreamer::EmitCFIEndProcImpl(Frame); 1255 OS << "\t.cfi_endproc"; 1256 EmitEOL(); 1257 } 1258 1259 void MCAsmStreamer::EmitRegisterName(int64_t Register) { 1260 if (!MAI->useDwarfRegNumForCFI()) { 1261 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 1262 unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true); 1263 InstPrinter->printRegName(OS, LLVMRegister); 1264 } else { 1265 OS << Register; 1266 } 1267 } 1268 1269 void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { 1270 MCStreamer::EmitCFIDefCfa(Register, Offset); 1271 OS << "\t.cfi_def_cfa "; 1272 EmitRegisterName(Register); 1273 OS << ", " << Offset; 1274 EmitEOL(); 1275 } 1276 1277 void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { 1278 MCStreamer::EmitCFIDefCfaOffset(Offset); 1279 OS << "\t.cfi_def_cfa_offset " << Offset; 1280 EmitEOL(); 1281 } 1282 1283 static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) { 1284 OS << "\t.cfi_escape "; 1285 if (!Values.empty()) { 1286 size_t e = Values.size() - 1; 1287 for (size_t i = 0; i < e; ++i) 1288 OS << format("0x%02x", uint8_t(Values[i])) << ", "; 1289 OS << format("0x%02x", uint8_t(Values[e])); 1290 } 1291 } 1292 1293 void MCAsmStreamer::EmitCFIEscape(StringRef Values) { 1294 MCStreamer::EmitCFIEscape(Values); 1295 PrintCFIEscape(OS, Values); 1296 EmitEOL(); 1297 } 1298 1299 void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) { 1300 MCStreamer::EmitCFIGnuArgsSize(Size); 1301 1302 uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size }; 1303 unsigned Len = encodeULEB128(Size, Buffer + 1) + 1; 1304 1305 PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len)); 1306 EmitEOL(); 1307 } 1308 1309 void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { 1310 MCStreamer::EmitCFIDefCfaRegister(Register); 1311 OS << "\t.cfi_def_cfa_register "; 1312 EmitRegisterName(Register); 1313 EmitEOL(); 1314 } 1315 1316 void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { 1317 this->MCStreamer::EmitCFIOffset(Register, Offset); 1318 OS << "\t.cfi_offset "; 1319 EmitRegisterName(Register); 1320 OS << ", " << Offset; 1321 EmitEOL(); 1322 } 1323 1324 void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, 1325 unsigned Encoding) { 1326 MCStreamer::EmitCFIPersonality(Sym, Encoding); 1327 OS << "\t.cfi_personality " << Encoding << ", "; 1328 Sym->print(OS, MAI); 1329 EmitEOL(); 1330 } 1331 1332 void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { 1333 MCStreamer::EmitCFILsda(Sym, Encoding); 1334 OS << "\t.cfi_lsda " << Encoding << ", "; 1335 Sym->print(OS, MAI); 1336 EmitEOL(); 1337 } 1338 1339 void MCAsmStreamer::EmitCFIRememberState() { 1340 MCStreamer::EmitCFIRememberState(); 1341 OS << "\t.cfi_remember_state"; 1342 EmitEOL(); 1343 } 1344 1345 void MCAsmStreamer::EmitCFIRestoreState() { 1346 MCStreamer::EmitCFIRestoreState(); 1347 OS << "\t.cfi_restore_state"; 1348 EmitEOL(); 1349 } 1350 1351 void MCAsmStreamer::EmitCFISameValue(int64_t Register) { 1352 MCStreamer::EmitCFISameValue(Register); 1353 OS << "\t.cfi_same_value "; 1354 EmitRegisterName(Register); 1355 EmitEOL(); 1356 } 1357 1358 void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { 1359 MCStreamer::EmitCFIRelOffset(Register, Offset); 1360 OS << "\t.cfi_rel_offset "; 1361 EmitRegisterName(Register); 1362 OS << ", " << Offset; 1363 EmitEOL(); 1364 } 1365 1366 void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { 1367 MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); 1368 OS << "\t.cfi_adjust_cfa_offset " << Adjustment; 1369 EmitEOL(); 1370 } 1371 1372 void MCAsmStreamer::EmitCFISignalFrame() { 1373 MCStreamer::EmitCFISignalFrame(); 1374 OS << "\t.cfi_signal_frame"; 1375 EmitEOL(); 1376 } 1377 1378 void MCAsmStreamer::EmitCFIUndefined(int64_t Register) { 1379 MCStreamer::EmitCFIUndefined(Register); 1380 OS << "\t.cfi_undefined " << Register; 1381 EmitEOL(); 1382 } 1383 1384 void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { 1385 MCStreamer::EmitCFIRegister(Register1, Register2); 1386 OS << "\t.cfi_register " << Register1 << ", " << Register2; 1387 EmitEOL(); 1388 } 1389 1390 void MCAsmStreamer::EmitCFIWindowSave() { 1391 MCStreamer::EmitCFIWindowSave(); 1392 OS << "\t.cfi_window_save"; 1393 EmitEOL(); 1394 } 1395 1396 void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { 1397 MCStreamer::EmitWinCFIStartProc(Symbol); 1398 1399 OS << ".seh_proc "; 1400 Symbol->print(OS, MAI); 1401 EmitEOL(); 1402 } 1403 1404 void MCAsmStreamer::EmitWinCFIEndProc() { 1405 MCStreamer::EmitWinCFIEndProc(); 1406 1407 OS << "\t.seh_endproc"; 1408 EmitEOL(); 1409 } 1410 1411 void MCAsmStreamer::EmitWinCFIStartChained() { 1412 MCStreamer::EmitWinCFIStartChained(); 1413 1414 OS << "\t.seh_startchained"; 1415 EmitEOL(); 1416 } 1417 1418 void MCAsmStreamer::EmitWinCFIEndChained() { 1419 MCStreamer::EmitWinCFIEndChained(); 1420 1421 OS << "\t.seh_endchained"; 1422 EmitEOL(); 1423 } 1424 1425 void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, 1426 bool Except) { 1427 MCStreamer::EmitWinEHHandler(Sym, Unwind, Except); 1428 1429 OS << "\t.seh_handler "; 1430 Sym->print(OS, MAI); 1431 if (Unwind) 1432 OS << ", @unwind"; 1433 if (Except) 1434 OS << ", @except"; 1435 EmitEOL(); 1436 } 1437 1438 void MCAsmStreamer::EmitWinEHHandlerData() { 1439 MCStreamer::EmitWinEHHandlerData(); 1440 1441 // Switch sections. Don't call SwitchSection directly, because that will 1442 // cause the section switch to be visible in the emitted assembly. 1443 // We only do this so the section switch that terminates the handler 1444 // data block is visible. 1445 WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); 1446 MCSection *TextSec = &CurFrame->Function->getSection(); 1447 MCSection *XData = getAssociatedXDataSection(TextSec); 1448 SwitchSectionNoChange(XData); 1449 1450 OS << "\t.seh_handlerdata"; 1451 EmitEOL(); 1452 } 1453 1454 void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) { 1455 MCStreamer::EmitWinCFIPushReg(Register); 1456 1457 OS << "\t.seh_pushreg " << Register; 1458 EmitEOL(); 1459 } 1460 1461 void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { 1462 MCStreamer::EmitWinCFISetFrame(Register, Offset); 1463 1464 OS << "\t.seh_setframe " << Register << ", " << Offset; 1465 EmitEOL(); 1466 } 1467 1468 void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) { 1469 MCStreamer::EmitWinCFIAllocStack(Size); 1470 1471 OS << "\t.seh_stackalloc " << Size; 1472 EmitEOL(); 1473 } 1474 1475 void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { 1476 MCStreamer::EmitWinCFISaveReg(Register, Offset); 1477 1478 OS << "\t.seh_savereg " << Register << ", " << Offset; 1479 EmitEOL(); 1480 } 1481 1482 void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { 1483 MCStreamer::EmitWinCFISaveXMM(Register, Offset); 1484 1485 OS << "\t.seh_savexmm " << Register << ", " << Offset; 1486 EmitEOL(); 1487 } 1488 1489 void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) { 1490 MCStreamer::EmitWinCFIPushFrame(Code); 1491 1492 OS << "\t.seh_pushframe"; 1493 if (Code) 1494 OS << " @code"; 1495 EmitEOL(); 1496 } 1497 1498 void MCAsmStreamer::EmitWinCFIEndProlog() { 1499 MCStreamer::EmitWinCFIEndProlog(); 1500 1501 OS << "\t.seh_endprologue"; 1502 EmitEOL(); 1503 } 1504 1505 void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, 1506 const MCSubtargetInfo &STI) { 1507 raw_ostream &OS = GetCommentOS(); 1508 SmallString<256> Code; 1509 SmallVector<MCFixup, 4> Fixups; 1510 raw_svector_ostream VecOS(Code); 1511 Emitter->encodeInstruction(Inst, VecOS, Fixups, STI); 1512 1513 // If we are showing fixups, create symbolic markers in the encoded 1514 // representation. We do this by making a per-bit map to the fixup item index, 1515 // then trying to display it as nicely as possible. 1516 SmallVector<uint8_t, 64> FixupMap; 1517 FixupMap.resize(Code.size() * 8); 1518 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) 1519 FixupMap[i] = 0; 1520 1521 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1522 MCFixup &F = Fixups[i]; 1523 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); 1524 for (unsigned j = 0; j != Info.TargetSize; ++j) { 1525 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; 1526 assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); 1527 FixupMap[Index] = 1 + i; 1528 } 1529 } 1530 1531 // FIXME: Note the fixup comments for Thumb2 are completely bogus since the 1532 // high order halfword of a 32-bit Thumb2 instruction is emitted first. 1533 OS << "encoding: ["; 1534 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 1535 if (i) 1536 OS << ','; 1537 1538 // See if all bits are the same map entry. 1539 uint8_t MapEntry = FixupMap[i * 8 + 0]; 1540 for (unsigned j = 1; j != 8; ++j) { 1541 if (FixupMap[i * 8 + j] == MapEntry) 1542 continue; 1543 1544 MapEntry = uint8_t(~0U); 1545 break; 1546 } 1547 1548 if (MapEntry != uint8_t(~0U)) { 1549 if (MapEntry == 0) { 1550 OS << format("0x%02x", uint8_t(Code[i])); 1551 } else { 1552 if (Code[i]) { 1553 // FIXME: Some of the 8 bits require fix up. 1554 OS << format("0x%02x", uint8_t(Code[i])) << '\'' 1555 << char('A' + MapEntry - 1) << '\''; 1556 } else 1557 OS << char('A' + MapEntry - 1); 1558 } 1559 } else { 1560 // Otherwise, write out in binary. 1561 OS << "0b"; 1562 for (unsigned j = 8; j--;) { 1563 unsigned Bit = (Code[i] >> j) & 1; 1564 1565 unsigned FixupBit; 1566 if (MAI->isLittleEndian()) 1567 FixupBit = i * 8 + j; 1568 else 1569 FixupBit = i * 8 + (7-j); 1570 1571 if (uint8_t MapEntry = FixupMap[FixupBit]) { 1572 assert(Bit == 0 && "Encoder wrote into fixed up bit!"); 1573 OS << char('A' + MapEntry - 1); 1574 } else 1575 OS << Bit; 1576 } 1577 } 1578 } 1579 OS << "]\n"; 1580 1581 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1582 MCFixup &F = Fixups[i]; 1583 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); 1584 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() 1585 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; 1586 } 1587 } 1588 1589 void MCAsmStreamer::EmitInstruction(const MCInst &Inst, 1590 const MCSubtargetInfo &STI) { 1591 assert(getCurrentSectionOnly() && 1592 "Cannot emit contents before setting section!"); 1593 1594 // Show the encoding in a comment if we have a code emitter. 1595 if (Emitter) 1596 AddEncodingComment(Inst, STI); 1597 1598 // Show the MCInst if enabled. 1599 if (ShowInst) { 1600 Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); 1601 GetCommentOS() << "\n"; 1602 } 1603 1604 if(getTargetStreamer()) 1605 getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI); 1606 else 1607 InstPrinter->printInst(&Inst, OS, "", STI); 1608 1609 EmitEOL(); 1610 } 1611 1612 void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) { 1613 OS << "\t.bundle_align_mode " << AlignPow2; 1614 EmitEOL(); 1615 } 1616 1617 void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) { 1618 OS << "\t.bundle_lock"; 1619 if (AlignToEnd) 1620 OS << " align_to_end"; 1621 EmitEOL(); 1622 } 1623 1624 void MCAsmStreamer::EmitBundleUnlock() { 1625 OS << "\t.bundle_unlock"; 1626 EmitEOL(); 1627 } 1628 1629 bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, 1630 const MCExpr *Expr, SMLoc) { 1631 OS << "\t.reloc "; 1632 Offset.print(OS, MAI); 1633 OS << ", " << Name; 1634 if (Expr) { 1635 OS << ", "; 1636 Expr->print(OS, MAI); 1637 } 1638 EmitEOL(); 1639 return false; 1640 } 1641 1642 /// EmitRawText - If this file is backed by an assembly streamer, this dumps 1643 /// the specified string in the output .s file. This capability is 1644 /// indicated by the hasRawTextSupport() predicate. 1645 void MCAsmStreamer::EmitRawTextImpl(StringRef String) { 1646 if (!String.empty() && String.back() == '\n') 1647 String = String.substr(0, String.size()-1); 1648 OS << String; 1649 EmitEOL(); 1650 } 1651 1652 void MCAsmStreamer::FinishImpl() { 1653 // If we are generating dwarf for assembly source files dump out the sections. 1654 if (getContext().getGenDwarfForAssembly()) 1655 MCGenDwarfInfo::Emit(this); 1656 1657 // Emit the label for the line table, if requested - since the rest of the 1658 // line table will be defined by .loc/.file directives, and not emitted 1659 // directly, the label is the only work required here. 1660 auto &Tables = getContext().getMCDwarfLineTables(); 1661 if (!Tables.empty()) { 1662 assert(Tables.size() == 1 && "asm output only supports one line table"); 1663 if (auto *Label = Tables.begin()->second.getLabel()) { 1664 SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); 1665 EmitLabel(Label); 1666 } 1667 } 1668 } 1669 1670 MCStreamer *llvm::createAsmStreamer(MCContext &Context, 1671 std::unique_ptr<formatted_raw_ostream> OS, 1672 bool isVerboseAsm, bool useDwarfDirectory, 1673 MCInstPrinter *IP, MCCodeEmitter *CE, 1674 MCAsmBackend *MAB, bool ShowInst) { 1675 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, 1676 useDwarfDirectory, IP, CE, MAB, ShowInst); 1677 } 1678