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