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_PrivateExtern: 476 OS << "\t.private_extern\t"; 477 break; 478 case MCSA_Protected: OS << "\t.protected\t"; break; 479 case MCSA_Reference: OS << "\t.reference\t"; break; 480 case MCSA_Weak: OS << MAI->getWeakDirective(); break; 481 case MCSA_WeakDefinition: 482 OS << "\t.weak_definition\t"; 483 break; 484 // .weak_reference 485 case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; 486 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; 487 } 488 489 Symbol->print(OS, MAI); 490 EmitEOL(); 491 492 return true; 493 } 494 495 void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 496 OS << ".desc" << ' '; 497 Symbol->print(OS, MAI); 498 OS << ',' << DescValue; 499 EmitEOL(); 500 } 501 502 void MCAsmStreamer::EmitSyntaxDirective() { 503 if (MAI->getAssemblerDialect() == 1) 504 OS << "\t.intel_syntax noprefix\n"; 505 // FIXME: Currently emit unprefix'ed registers. 506 // The intel_syntax directive has one optional argument 507 // with may have a value of prefix or noprefix. 508 } 509 510 void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { 511 OS << "\t.def\t "; 512 Symbol->print(OS, MAI); 513 OS << ';'; 514 EmitEOL(); 515 } 516 517 void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) { 518 OS << "\t.scl\t" << StorageClass << ';'; 519 EmitEOL(); 520 } 521 522 void MCAsmStreamer::EmitCOFFSymbolType (int Type) { 523 OS << "\t.type\t" << Type << ';'; 524 EmitEOL(); 525 } 526 527 void MCAsmStreamer::EndCOFFSymbolDef() { 528 OS << "\t.endef"; 529 EmitEOL(); 530 } 531 532 void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { 533 OS << "\t.safeseh\t"; 534 Symbol->print(OS, MAI); 535 EmitEOL(); 536 } 537 538 void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { 539 OS << "\t.secidx\t"; 540 Symbol->print(OS, MAI); 541 EmitEOL(); 542 } 543 544 void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { 545 OS << "\t.secrel32\t"; 546 Symbol->print(OS, MAI); 547 EmitEOL(); 548 } 549 550 void MCAsmStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) { 551 assert(MAI->hasDotTypeDotSizeDirective()); 552 OS << "\t.size\t"; 553 Symbol->print(OS, MAI); 554 OS << ", "; 555 Value->print(OS, MAI); 556 OS << '\n'; 557 } 558 559 void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 560 unsigned ByteAlignment) { 561 OS << "\t.comm\t"; 562 Symbol->print(OS, MAI); 563 OS << ',' << Size; 564 565 if (ByteAlignment != 0) { 566 if (MAI->getCOMMDirectiveAlignmentIsInBytes()) 567 OS << ',' << ByteAlignment; 568 else 569 OS << ',' << Log2_32(ByteAlignment); 570 } 571 EmitEOL(); 572 } 573 574 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 575 /// 576 /// @param Symbol - The common symbol to emit. 577 /// @param Size - The size of the common symbol. 578 void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 579 unsigned ByteAlign) { 580 OS << "\t.lcomm\t"; 581 Symbol->print(OS, MAI); 582 OS << ',' << Size; 583 584 if (ByteAlign > 1) { 585 switch (MAI->getLCOMMDirectiveAlignmentType()) { 586 case LCOMM::NoAlignment: 587 llvm_unreachable("alignment not supported on .lcomm!"); 588 case LCOMM::ByteAlignment: 589 OS << ',' << ByteAlign; 590 break; 591 case LCOMM::Log2Alignment: 592 assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2"); 593 OS << ',' << Log2_32(ByteAlign); 594 break; 595 } 596 } 597 EmitEOL(); 598 } 599 600 void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 601 uint64_t Size, unsigned ByteAlignment) { 602 if (Symbol) 603 AssignFragment(Symbol, &Section->getDummyFragment()); 604 605 // Note: a .zerofill directive does not switch sections. 606 OS << ".zerofill "; 607 608 // This is a mach-o specific directive. 609 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 610 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 611 612 if (Symbol) { 613 OS << ','; 614 Symbol->print(OS, MAI); 615 OS << ',' << Size; 616 if (ByteAlignment != 0) 617 OS << ',' << Log2_32(ByteAlignment); 618 } 619 EmitEOL(); 620 } 621 622 // .tbss sym, size, align 623 // This depends that the symbol has already been mangled from the original, 624 // e.g. _a. 625 void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 626 uint64_t Size, unsigned ByteAlignment) { 627 AssignFragment(Symbol, &Section->getDummyFragment()); 628 629 assert(Symbol && "Symbol shouldn't be NULL!"); 630 // Instead of using the Section we'll just use the shortcut. 631 // This is a mach-o specific directive and section. 632 OS << ".tbss "; 633 Symbol->print(OS, MAI); 634 OS << ", " << Size; 635 636 // Output align if we have it. We default to 1 so don't bother printing 637 // that. 638 if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment); 639 640 EmitEOL(); 641 } 642 643 static inline char toOctal(int X) { return (X&7)+'0'; } 644 645 static void PrintQuotedString(StringRef Data, raw_ostream &OS) { 646 OS << '"'; 647 648 for (unsigned i = 0, e = Data.size(); i != e; ++i) { 649 unsigned char C = Data[i]; 650 if (C == '"' || C == '\\') { 651 OS << '\\' << (char)C; 652 continue; 653 } 654 655 if (isprint((unsigned char)C)) { 656 OS << (char)C; 657 continue; 658 } 659 660 switch (C) { 661 case '\b': OS << "\\b"; break; 662 case '\f': OS << "\\f"; break; 663 case '\n': OS << "\\n"; break; 664 case '\r': OS << "\\r"; break; 665 case '\t': OS << "\\t"; break; 666 default: 667 OS << '\\'; 668 OS << toOctal(C >> 6); 669 OS << toOctal(C >> 3); 670 OS << toOctal(C >> 0); 671 break; 672 } 673 } 674 675 OS << '"'; 676 } 677 678 void MCAsmStreamer::EmitBytes(StringRef Data) { 679 assert(getCurrentSection().first && 680 "Cannot emit contents before setting section!"); 681 if (Data.empty()) return; 682 683 if (Data.size() == 1) { 684 OS << MAI->getData8bitsDirective(); 685 OS << (unsigned)(unsigned char)Data[0]; 686 EmitEOL(); 687 return; 688 } 689 690 // If the data ends with 0 and the target supports .asciz, use it, otherwise 691 // use .ascii 692 if (MAI->getAscizDirective() && Data.back() == 0) { 693 OS << MAI->getAscizDirective(); 694 Data = Data.substr(0, Data.size()-1); 695 } else { 696 OS << MAI->getAsciiDirective(); 697 } 698 699 PrintQuotedString(Data, OS); 700 EmitEOL(); 701 } 702 703 void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { 704 EmitValue(MCConstantExpr::create(Value, getContext()), Size); 705 } 706 707 void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, 708 SMLoc Loc) { 709 assert(Size <= 8 && "Invalid size"); 710 assert(getCurrentSection().first && 711 "Cannot emit contents before setting section!"); 712 const char *Directive = nullptr; 713 switch (Size) { 714 default: break; 715 case 1: Directive = MAI->getData8bitsDirective(); break; 716 case 2: Directive = MAI->getData16bitsDirective(); break; 717 case 4: Directive = MAI->getData32bitsDirective(); break; 718 case 8: Directive = MAI->getData64bitsDirective(); break; 719 } 720 721 if (!Directive) { 722 int64_t IntValue; 723 if (!Value->evaluateAsAbsolute(IntValue)) 724 report_fatal_error("Don't know how to emit this value."); 725 726 // We couldn't handle the requested integer size so we fallback by breaking 727 // the request down into several, smaller, integers. 728 // Since sizes greater or equal to "Size" are invalid, we use the greatest 729 // power of 2 that is less than "Size" as our largest piece of granularity. 730 bool IsLittleEndian = MAI->isLittleEndian(); 731 for (unsigned Emitted = 0; Emitted != Size;) { 732 unsigned Remaining = Size - Emitted; 733 // The size of our partial emission must be a power of two less than 734 // Size. 735 unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1)); 736 // Calculate the byte offset of our partial emission taking into account 737 // the endianness of the target. 738 unsigned ByteOffset = 739 IsLittleEndian ? Emitted : (Remaining - EmissionSize); 740 uint64_t ValueToEmit = IntValue >> (ByteOffset * 8); 741 // We truncate our partial emission to fit within the bounds of the 742 // emission domain. This produces nicer output and silences potential 743 // truncation warnings when round tripping through another assembler. 744 uint64_t Shift = 64 - EmissionSize * 8; 745 assert(Shift < static_cast<uint64_t>( 746 std::numeric_limits<unsigned long long>::digits) && 747 "undefined behavior"); 748 ValueToEmit &= ~0ULL >> Shift; 749 EmitIntValue(ValueToEmit, EmissionSize); 750 Emitted += EmissionSize; 751 } 752 return; 753 } 754 755 assert(Directive && "Invalid size for machine code value!"); 756 OS << Directive; 757 Value->print(OS, MAI); 758 EmitEOL(); 759 } 760 761 void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { 762 int64_t IntValue; 763 if (Value->evaluateAsAbsolute(IntValue)) { 764 EmitULEB128IntValue(IntValue); 765 return; 766 } 767 OS << ".uleb128 "; 768 Value->print(OS, MAI); 769 EmitEOL(); 770 } 771 772 void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { 773 int64_t IntValue; 774 if (Value->evaluateAsAbsolute(IntValue)) { 775 EmitSLEB128IntValue(IntValue); 776 return; 777 } 778 OS << ".sleb128 "; 779 Value->print(OS, MAI); 780 EmitEOL(); 781 } 782 783 void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) { 784 assert(MAI->getGPRel64Directive() != nullptr); 785 OS << MAI->getGPRel64Directive(); 786 Value->print(OS, MAI); 787 EmitEOL(); 788 } 789 790 void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { 791 assert(MAI->getGPRel32Directive() != nullptr); 792 OS << MAI->getGPRel32Directive(); 793 Value->print(OS, MAI); 794 EmitEOL(); 795 } 796 797 /// EmitFill - Emit NumBytes bytes worth of the value specified by 798 /// FillValue. This implements directives such as '.space'. 799 void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { 800 if (NumBytes == 0) return; 801 802 if (const char *ZeroDirective = MAI->getZeroDirective()) { 803 OS << ZeroDirective << NumBytes; 804 if (FillValue != 0) 805 OS << ',' << (int)FillValue; 806 EmitEOL(); 807 return; 808 } 809 810 // Emit a byte at a time. 811 MCStreamer::EmitFill(NumBytes, FillValue); 812 } 813 814 void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 815 unsigned ValueSize, 816 unsigned MaxBytesToEmit) { 817 // Some assemblers don't support non-power of two alignments, so we always 818 // emit alignments as a power of two if possible. 819 if (isPowerOf2_32(ByteAlignment)) { 820 switch (ValueSize) { 821 default: 822 llvm_unreachable("Invalid size for machine code value!"); 823 case 1: 824 OS << "\t.p2align\t"; 825 break; 826 case 2: 827 OS << ".p2alignw "; 828 break; 829 case 4: 830 OS << ".p2alignl "; 831 break; 832 case 8: 833 llvm_unreachable("Unsupported alignment size!"); 834 } 835 836 OS << Log2_32(ByteAlignment); 837 838 if (Value || MaxBytesToEmit) { 839 OS << ", 0x"; 840 OS.write_hex(truncateToSize(Value, ValueSize)); 841 842 if (MaxBytesToEmit) 843 OS << ", " << MaxBytesToEmit; 844 } 845 EmitEOL(); 846 return; 847 } 848 849 // Non-power of two alignment. This is not widely supported by assemblers. 850 // FIXME: Parameterize this based on MAI. 851 switch (ValueSize) { 852 default: llvm_unreachable("Invalid size for machine code value!"); 853 case 1: OS << ".balign"; break; 854 case 2: OS << ".balignw"; break; 855 case 4: OS << ".balignl"; break; 856 case 8: llvm_unreachable("Unsupported alignment size!"); 857 } 858 859 OS << ' ' << ByteAlignment; 860 OS << ", " << truncateToSize(Value, ValueSize); 861 if (MaxBytesToEmit) 862 OS << ", " << MaxBytesToEmit; 863 EmitEOL(); 864 } 865 866 void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, 867 unsigned MaxBytesToEmit) { 868 // Emit with a text fill value. 869 EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(), 870 1, MaxBytesToEmit); 871 } 872 873 void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, 874 unsigned char Value) { 875 // FIXME: Verify that Offset is associated with the current section. 876 OS << ".org "; 877 Offset->print(OS, MAI); 878 OS << ", " << (unsigned)Value; 879 EmitEOL(); 880 } 881 882 void MCAsmStreamer::EmitFileDirective(StringRef Filename) { 883 assert(MAI->hasSingleParameterDotFile()); 884 OS << "\t.file\t"; 885 PrintQuotedString(Filename, OS); 886 EmitEOL(); 887 } 888 889 unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, 890 StringRef Directory, 891 StringRef Filename, 892 unsigned CUID) { 893 assert(CUID == 0); 894 895 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); 896 unsigned NumFiles = Table.getMCDwarfFiles().size(); 897 FileNo = Table.getFile(Directory, Filename, FileNo); 898 if (FileNo == 0) 899 return 0; 900 if (NumFiles == Table.getMCDwarfFiles().size()) 901 return FileNo; 902 903 SmallString<128> FullPathName; 904 905 if (!UseDwarfDirectory && !Directory.empty()) { 906 if (sys::path::is_absolute(Filename)) 907 Directory = ""; 908 else { 909 FullPathName = Directory; 910 sys::path::append(FullPathName, Filename); 911 Directory = ""; 912 Filename = FullPathName; 913 } 914 } 915 916 OS << "\t.file\t" << FileNo << ' '; 917 if (!Directory.empty()) { 918 PrintQuotedString(Directory, OS); 919 OS << ' '; 920 } 921 PrintQuotedString(Filename, OS); 922 EmitEOL(); 923 924 return FileNo; 925 } 926 927 void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 928 unsigned Column, unsigned Flags, 929 unsigned Isa, 930 unsigned Discriminator, 931 StringRef FileName) { 932 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; 933 if (Flags & DWARF2_FLAG_BASIC_BLOCK) 934 OS << " basic_block"; 935 if (Flags & DWARF2_FLAG_PROLOGUE_END) 936 OS << " prologue_end"; 937 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) 938 OS << " epilogue_begin"; 939 940 unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); 941 if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { 942 OS << " is_stmt "; 943 944 if (Flags & DWARF2_FLAG_IS_STMT) 945 OS << "1"; 946 else 947 OS << "0"; 948 } 949 950 if (Isa) 951 OS << " isa " << Isa; 952 if (Discriminator) 953 OS << " discriminator " << Discriminator; 954 955 if (IsVerboseAsm) { 956 OS.PadToColumn(MAI->getCommentColumn()); 957 OS << MAI->getCommentString() << ' ' << FileName << ':' 958 << Line << ':' << Column; 959 } 960 EmitEOL(); 961 this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, 962 Isa, Discriminator, FileName); 963 } 964 965 MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { 966 // Always use the zeroth line table, since asm syntax only supports one line 967 // table for now. 968 return MCStreamer::getDwarfLineTableSymbol(0); 969 } 970 971 unsigned MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, 972 StringRef Filename) { 973 if (!getContext().getCVFile(Filename, FileNo)) 974 return 0; 975 976 OS << "\t.cv_file\t" << FileNo << ' '; 977 978 PrintQuotedString(Filename, OS); 979 EmitEOL(); 980 981 return FileNo; 982 } 983 984 void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, 985 unsigned Line, unsigned Column, 986 bool PrologueEnd, bool IsStmt, 987 StringRef FileName) { 988 OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " " 989 << Column; 990 if (PrologueEnd) 991 OS << " prologue_end"; 992 993 unsigned OldIsStmt = getContext().getCurrentCVLoc().isStmt(); 994 if (IsStmt != OldIsStmt) { 995 OS << " is_stmt "; 996 997 if (IsStmt) 998 OS << "1"; 999 else 1000 OS << "0"; 1001 } 1002 1003 if (IsVerboseAsm) { 1004 OS.PadToColumn(MAI->getCommentColumn()); 1005 OS << MAI->getCommentString() << ' ' << FileName << ':' 1006 << Line << ':' << Column; 1007 } 1008 EmitEOL(); 1009 this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column, 1010 PrologueEnd, IsStmt, FileName); 1011 } 1012 1013 void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId, 1014 const MCSymbol *FnStart, 1015 const MCSymbol *FnEnd) { 1016 OS << "\t.cv_linetable\t" << FunctionId << ", "; 1017 FnStart->print(OS, MAI); 1018 OS << ", "; 1019 FnEnd->print(OS, MAI); 1020 EmitEOL(); 1021 this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd); 1022 } 1023 1024 void MCAsmStreamer::EmitCVInlineLinetableDirective( 1025 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, 1026 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, 1027 ArrayRef<unsigned> SecondaryFunctionIds) { 1028 OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId 1029 << ' ' << SourceLineNum << ' '; 1030 FnStartSym->print(OS, MAI); 1031 OS << ' '; 1032 FnEndSym->print(OS, MAI); 1033 if (!SecondaryFunctionIds.empty()) { 1034 OS << " contains"; 1035 for (unsigned SecondaryFunctionId : SecondaryFunctionIds) 1036 OS << ' ' << SecondaryFunctionId; 1037 } 1038 EmitEOL(); 1039 this->MCStreamer::EmitCVInlineLinetableDirective( 1040 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym, 1041 SecondaryFunctionIds); 1042 } 1043 1044 void MCAsmStreamer::EmitCVDefRangeDirective( 1045 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1046 StringRef FixedSizePortion) { 1047 OS << "\t.cv_def_range\t"; 1048 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) { 1049 OS << ' '; 1050 Range.first->print(OS, MAI); 1051 OS << ' '; 1052 Range.second->print(OS, MAI); 1053 } 1054 OS << ", "; 1055 PrintQuotedString(FixedSizePortion, OS); 1056 EmitEOL(); 1057 this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); 1058 } 1059 1060 void MCAsmStreamer::EmitCVStringTableDirective() { 1061 OS << "\t.cv_stringtable"; 1062 EmitEOL(); 1063 } 1064 1065 void MCAsmStreamer::EmitCVFileChecksumsDirective() { 1066 OS << "\t.cv_filechecksums"; 1067 EmitEOL(); 1068 } 1069 1070 void MCAsmStreamer::EmitIdent(StringRef IdentString) { 1071 assert(MAI->hasIdentDirective() && ".ident directive not supported"); 1072 OS << "\t.ident\t"; 1073 PrintQuotedString(IdentString, OS); 1074 EmitEOL(); 1075 } 1076 1077 void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { 1078 MCStreamer::EmitCFISections(EH, Debug); 1079 OS << "\t.cfi_sections "; 1080 if (EH) { 1081 OS << ".eh_frame"; 1082 if (Debug) 1083 OS << ", .debug_frame"; 1084 } else if (Debug) { 1085 OS << ".debug_frame"; 1086 } 1087 1088 EmitEOL(); 1089 } 1090 1091 void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { 1092 OS << "\t.cfi_startproc"; 1093 if (Frame.IsSimple) 1094 OS << " simple"; 1095 EmitEOL(); 1096 } 1097 1098 void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { 1099 MCStreamer::EmitCFIEndProcImpl(Frame); 1100 OS << "\t.cfi_endproc"; 1101 EmitEOL(); 1102 } 1103 1104 void MCAsmStreamer::EmitRegisterName(int64_t Register) { 1105 if (!MAI->useDwarfRegNumForCFI()) { 1106 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 1107 unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true); 1108 InstPrinter->printRegName(OS, LLVMRegister); 1109 } else { 1110 OS << Register; 1111 } 1112 } 1113 1114 void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { 1115 MCStreamer::EmitCFIDefCfa(Register, Offset); 1116 OS << "\t.cfi_def_cfa "; 1117 EmitRegisterName(Register); 1118 OS << ", " << Offset; 1119 EmitEOL(); 1120 } 1121 1122 void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { 1123 MCStreamer::EmitCFIDefCfaOffset(Offset); 1124 OS << "\t.cfi_def_cfa_offset " << Offset; 1125 EmitEOL(); 1126 } 1127 1128 static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) { 1129 OS << "\t.cfi_escape "; 1130 if (!Values.empty()) { 1131 size_t e = Values.size() - 1; 1132 for (size_t i = 0; i < e; ++i) 1133 OS << format("0x%02x", uint8_t(Values[i])) << ", "; 1134 OS << format("0x%02x", uint8_t(Values[e])); 1135 } 1136 } 1137 1138 void MCAsmStreamer::EmitCFIEscape(StringRef Values) { 1139 MCStreamer::EmitCFIEscape(Values); 1140 PrintCFIEscape(OS, Values); 1141 EmitEOL(); 1142 } 1143 1144 void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) { 1145 MCStreamer::EmitCFIGnuArgsSize(Size); 1146 1147 uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size }; 1148 unsigned Len = encodeULEB128(Size, Buffer + 1) + 1; 1149 1150 PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len)); 1151 EmitEOL(); 1152 } 1153 1154 void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { 1155 MCStreamer::EmitCFIDefCfaRegister(Register); 1156 OS << "\t.cfi_def_cfa_register "; 1157 EmitRegisterName(Register); 1158 EmitEOL(); 1159 } 1160 1161 void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { 1162 this->MCStreamer::EmitCFIOffset(Register, Offset); 1163 OS << "\t.cfi_offset "; 1164 EmitRegisterName(Register); 1165 OS << ", " << Offset; 1166 EmitEOL(); 1167 } 1168 1169 void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, 1170 unsigned Encoding) { 1171 MCStreamer::EmitCFIPersonality(Sym, Encoding); 1172 OS << "\t.cfi_personality " << Encoding << ", "; 1173 Sym->print(OS, MAI); 1174 EmitEOL(); 1175 } 1176 1177 void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { 1178 MCStreamer::EmitCFILsda(Sym, Encoding); 1179 OS << "\t.cfi_lsda " << Encoding << ", "; 1180 Sym->print(OS, MAI); 1181 EmitEOL(); 1182 } 1183 1184 void MCAsmStreamer::EmitCFIRememberState() { 1185 MCStreamer::EmitCFIRememberState(); 1186 OS << "\t.cfi_remember_state"; 1187 EmitEOL(); 1188 } 1189 1190 void MCAsmStreamer::EmitCFIRestoreState() { 1191 MCStreamer::EmitCFIRestoreState(); 1192 OS << "\t.cfi_restore_state"; 1193 EmitEOL(); 1194 } 1195 1196 void MCAsmStreamer::EmitCFISameValue(int64_t Register) { 1197 MCStreamer::EmitCFISameValue(Register); 1198 OS << "\t.cfi_same_value "; 1199 EmitRegisterName(Register); 1200 EmitEOL(); 1201 } 1202 1203 void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { 1204 MCStreamer::EmitCFIRelOffset(Register, Offset); 1205 OS << "\t.cfi_rel_offset "; 1206 EmitRegisterName(Register); 1207 OS << ", " << Offset; 1208 EmitEOL(); 1209 } 1210 1211 void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { 1212 MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); 1213 OS << "\t.cfi_adjust_cfa_offset " << Adjustment; 1214 EmitEOL(); 1215 } 1216 1217 void MCAsmStreamer::EmitCFISignalFrame() { 1218 MCStreamer::EmitCFISignalFrame(); 1219 OS << "\t.cfi_signal_frame"; 1220 EmitEOL(); 1221 } 1222 1223 void MCAsmStreamer::EmitCFIUndefined(int64_t Register) { 1224 MCStreamer::EmitCFIUndefined(Register); 1225 OS << "\t.cfi_undefined " << Register; 1226 EmitEOL(); 1227 } 1228 1229 void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { 1230 MCStreamer::EmitCFIRegister(Register1, Register2); 1231 OS << "\t.cfi_register " << Register1 << ", " << Register2; 1232 EmitEOL(); 1233 } 1234 1235 void MCAsmStreamer::EmitCFIWindowSave() { 1236 MCStreamer::EmitCFIWindowSave(); 1237 OS << "\t.cfi_window_save"; 1238 EmitEOL(); 1239 } 1240 1241 void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { 1242 MCStreamer::EmitWinCFIStartProc(Symbol); 1243 1244 OS << ".seh_proc "; 1245 Symbol->print(OS, MAI); 1246 EmitEOL(); 1247 } 1248 1249 void MCAsmStreamer::EmitWinCFIEndProc() { 1250 MCStreamer::EmitWinCFIEndProc(); 1251 1252 OS << "\t.seh_endproc"; 1253 EmitEOL(); 1254 } 1255 1256 void MCAsmStreamer::EmitWinCFIStartChained() { 1257 MCStreamer::EmitWinCFIStartChained(); 1258 1259 OS << "\t.seh_startchained"; 1260 EmitEOL(); 1261 } 1262 1263 void MCAsmStreamer::EmitWinCFIEndChained() { 1264 MCStreamer::EmitWinCFIEndChained(); 1265 1266 OS << "\t.seh_endchained"; 1267 EmitEOL(); 1268 } 1269 1270 void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, 1271 bool Except) { 1272 MCStreamer::EmitWinEHHandler(Sym, Unwind, Except); 1273 1274 OS << "\t.seh_handler "; 1275 Sym->print(OS, MAI); 1276 if (Unwind) 1277 OS << ", @unwind"; 1278 if (Except) 1279 OS << ", @except"; 1280 EmitEOL(); 1281 } 1282 1283 void MCAsmStreamer::EmitWinEHHandlerData() { 1284 MCStreamer::EmitWinEHHandlerData(); 1285 1286 // Switch sections. Don't call SwitchSection directly, because that will 1287 // cause the section switch to be visible in the emitted assembly. 1288 // We only do this so the section switch that terminates the handler 1289 // data block is visible. 1290 WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); 1291 MCSection *XData = 1292 WinEH::UnwindEmitter::getXDataSection(CurFrame->Function, getContext()); 1293 SwitchSectionNoChange(XData); 1294 1295 OS << "\t.seh_handlerdata"; 1296 EmitEOL(); 1297 } 1298 1299 void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) { 1300 MCStreamer::EmitWinCFIPushReg(Register); 1301 1302 OS << "\t.seh_pushreg " << Register; 1303 EmitEOL(); 1304 } 1305 1306 void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { 1307 MCStreamer::EmitWinCFISetFrame(Register, Offset); 1308 1309 OS << "\t.seh_setframe " << Register << ", " << Offset; 1310 EmitEOL(); 1311 } 1312 1313 void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) { 1314 MCStreamer::EmitWinCFIAllocStack(Size); 1315 1316 OS << "\t.seh_stackalloc " << Size; 1317 EmitEOL(); 1318 } 1319 1320 void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { 1321 MCStreamer::EmitWinCFISaveReg(Register, Offset); 1322 1323 OS << "\t.seh_savereg " << Register << ", " << Offset; 1324 EmitEOL(); 1325 } 1326 1327 void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { 1328 MCStreamer::EmitWinCFISaveXMM(Register, Offset); 1329 1330 OS << "\t.seh_savexmm " << Register << ", " << Offset; 1331 EmitEOL(); 1332 } 1333 1334 void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) { 1335 MCStreamer::EmitWinCFIPushFrame(Code); 1336 1337 OS << "\t.seh_pushframe"; 1338 if (Code) 1339 OS << " @code"; 1340 EmitEOL(); 1341 } 1342 1343 void MCAsmStreamer::EmitWinCFIEndProlog() { 1344 MCStreamer::EmitWinCFIEndProlog(); 1345 1346 OS << "\t.seh_endprologue"; 1347 EmitEOL(); 1348 } 1349 1350 void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, 1351 const MCSubtargetInfo &STI) { 1352 raw_ostream &OS = GetCommentOS(); 1353 SmallString<256> Code; 1354 SmallVector<MCFixup, 4> Fixups; 1355 raw_svector_ostream VecOS(Code); 1356 Emitter->encodeInstruction(Inst, VecOS, Fixups, STI); 1357 1358 // If we are showing fixups, create symbolic markers in the encoded 1359 // representation. We do this by making a per-bit map to the fixup item index, 1360 // then trying to display it as nicely as possible. 1361 SmallVector<uint8_t, 64> FixupMap; 1362 FixupMap.resize(Code.size() * 8); 1363 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) 1364 FixupMap[i] = 0; 1365 1366 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1367 MCFixup &F = Fixups[i]; 1368 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); 1369 for (unsigned j = 0; j != Info.TargetSize; ++j) { 1370 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; 1371 assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); 1372 FixupMap[Index] = 1 + i; 1373 } 1374 } 1375 1376 // FIXME: Note the fixup comments for Thumb2 are completely bogus since the 1377 // high order halfword of a 32-bit Thumb2 instruction is emitted first. 1378 OS << "encoding: ["; 1379 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 1380 if (i) 1381 OS << ','; 1382 1383 // See if all bits are the same map entry. 1384 uint8_t MapEntry = FixupMap[i * 8 + 0]; 1385 for (unsigned j = 1; j != 8; ++j) { 1386 if (FixupMap[i * 8 + j] == MapEntry) 1387 continue; 1388 1389 MapEntry = uint8_t(~0U); 1390 break; 1391 } 1392 1393 if (MapEntry != uint8_t(~0U)) { 1394 if (MapEntry == 0) { 1395 OS << format("0x%02x", uint8_t(Code[i])); 1396 } else { 1397 if (Code[i]) { 1398 // FIXME: Some of the 8 bits require fix up. 1399 OS << format("0x%02x", uint8_t(Code[i])) << '\'' 1400 << char('A' + MapEntry - 1) << '\''; 1401 } else 1402 OS << char('A' + MapEntry - 1); 1403 } 1404 } else { 1405 // Otherwise, write out in binary. 1406 OS << "0b"; 1407 for (unsigned j = 8; j--;) { 1408 unsigned Bit = (Code[i] >> j) & 1; 1409 1410 unsigned FixupBit; 1411 if (MAI->isLittleEndian()) 1412 FixupBit = i * 8 + j; 1413 else 1414 FixupBit = i * 8 + (7-j); 1415 1416 if (uint8_t MapEntry = FixupMap[FixupBit]) { 1417 assert(Bit == 0 && "Encoder wrote into fixed up bit!"); 1418 OS << char('A' + MapEntry - 1); 1419 } else 1420 OS << Bit; 1421 } 1422 } 1423 } 1424 OS << "]\n"; 1425 1426 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1427 MCFixup &F = Fixups[i]; 1428 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); 1429 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() 1430 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; 1431 } 1432 } 1433 1434 void MCAsmStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { 1435 assert(getCurrentSection().first && 1436 "Cannot emit contents before setting section!"); 1437 1438 // Show the encoding in a comment if we have a code emitter. 1439 if (Emitter) 1440 AddEncodingComment(Inst, STI); 1441 1442 // Show the MCInst if enabled. 1443 if (ShowInst) { 1444 Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); 1445 GetCommentOS() << "\n"; 1446 } 1447 1448 if(getTargetStreamer()) 1449 getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI); 1450 else 1451 InstPrinter->printInst(&Inst, OS, "", STI); 1452 1453 EmitEOL(); 1454 } 1455 1456 void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) { 1457 OS << "\t.bundle_align_mode " << AlignPow2; 1458 EmitEOL(); 1459 } 1460 1461 void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) { 1462 OS << "\t.bundle_lock"; 1463 if (AlignToEnd) 1464 OS << " align_to_end"; 1465 EmitEOL(); 1466 } 1467 1468 void MCAsmStreamer::EmitBundleUnlock() { 1469 OS << "\t.bundle_unlock"; 1470 EmitEOL(); 1471 } 1472 1473 bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, 1474 const MCExpr *Expr, SMLoc) { 1475 OS << "\t.reloc "; 1476 Offset.print(OS, MAI); 1477 OS << ", " << Name; 1478 if (Expr) { 1479 OS << ", "; 1480 Expr->print(OS, MAI); 1481 } 1482 EmitEOL(); 1483 return false; 1484 } 1485 1486 /// EmitRawText - If this file is backed by an assembly streamer, this dumps 1487 /// the specified string in the output .s file. This capability is 1488 /// indicated by the hasRawTextSupport() predicate. 1489 void MCAsmStreamer::EmitRawTextImpl(StringRef String) { 1490 if (!String.empty() && String.back() == '\n') 1491 String = String.substr(0, String.size()-1); 1492 OS << String; 1493 EmitEOL(); 1494 } 1495 1496 void MCAsmStreamer::FinishImpl() { 1497 // If we are generating dwarf for assembly source files dump out the sections. 1498 if (getContext().getGenDwarfForAssembly()) 1499 MCGenDwarfInfo::Emit(this); 1500 1501 // Emit the label for the line table, if requested - since the rest of the 1502 // line table will be defined by .loc/.file directives, and not emitted 1503 // directly, the label is the only work required here. 1504 auto &Tables = getContext().getMCDwarfLineTables(); 1505 if (!Tables.empty()) { 1506 assert(Tables.size() == 1 && "asm output only supports one line table"); 1507 if (auto *Label = Tables.begin()->second.getLabel()) { 1508 SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); 1509 EmitLabel(Label); 1510 } 1511 } 1512 } 1513 1514 MCStreamer *llvm::createAsmStreamer(MCContext &Context, 1515 std::unique_ptr<formatted_raw_ostream> OS, 1516 bool isVerboseAsm, bool useDwarfDirectory, 1517 MCInstPrinter *IP, MCCodeEmitter *CE, 1518 MCAsmBackend *MAB, bool ShowInst) { 1519 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, 1520 useDwarfDirectory, IP, CE, MAB, ShowInst); 1521 } 1522