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