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