MCAsmStreamer.cpp revision 206083
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/MC/MCAsmInfo.h" 12#include "llvm/MC/MCCodeEmitter.h" 13#include "llvm/MC/MCContext.h" 14#include "llvm/MC/MCExpr.h" 15#include "llvm/MC/MCInst.h" 16#include "llvm/MC/MCInstPrinter.h" 17#include "llvm/MC/MCSectionMachO.h" 18#include "llvm/MC/MCSymbol.h" 19#include "llvm/ADT/OwningPtr.h" 20#include "llvm/ADT/SmallString.h" 21#include "llvm/ADT/Twine.h" 22#include "llvm/Support/ErrorHandling.h" 23#include "llvm/Support/MathExtras.h" 24#include "llvm/Support/Format.h" 25#include "llvm/Support/FormattedStream.h" 26using namespace llvm; 27 28namespace { 29 30class MCAsmStreamer : public MCStreamer { 31 formatted_raw_ostream &OS; 32 const MCAsmInfo &MAI; 33 OwningPtr<MCInstPrinter> InstPrinter; 34 MCCodeEmitter *Emitter; 35 36 SmallString<128> CommentToEmit; 37 raw_svector_ostream CommentStream; 38 39 unsigned IsLittleEndian : 1; 40 unsigned IsVerboseAsm : 1; 41 unsigned ShowInst : 1; 42 43public: 44 MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, 45 bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer, 46 MCCodeEmitter *emitter, bool showInst) 47 : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), 48 InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), 49 IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), 50 ShowInst(showInst) { 51 if (InstPrinter && IsVerboseAsm) 52 InstPrinter->setCommentStream(CommentStream); 53 } 54 ~MCAsmStreamer() {} 55 56 bool isLittleEndian() const { return IsLittleEndian; } 57 58 inline void EmitEOL() { 59 // If we don't have any comments, just emit a \n. 60 if (!IsVerboseAsm) { 61 OS << '\n'; 62 return; 63 } 64 EmitCommentsAndEOL(); 65 } 66 void EmitCommentsAndEOL(); 67 68 /// isVerboseAsm - Return true if this streamer supports verbose assembly at 69 /// all. 70 virtual bool isVerboseAsm() const { return IsVerboseAsm; } 71 72 /// AddComment - Add a comment that can be emitted to the generated .s 73 /// file if applicable as a QoI issue to make the output of the compiler 74 /// more readable. This only affects the MCAsmStreamer, and only when 75 /// verbose assembly output is enabled. 76 virtual void AddComment(const Twine &T); 77 78 /// AddEncodingComment - Add a comment showing the encoding of an instruction. 79 virtual void AddEncodingComment(const MCInst &Inst); 80 81 /// GetCommentOS - Return a raw_ostream that comments can be written to. 82 /// Unlike AddComment, you are required to terminate comments with \n if you 83 /// use this method. 84 virtual raw_ostream &GetCommentOS() { 85 if (!IsVerboseAsm) 86 return nulls(); // Discard comments unless in verbose asm mode. 87 return CommentStream; 88 } 89 90 /// AddBlankLine - Emit a blank line to a .s file to pretty it up. 91 virtual void AddBlankLine() { 92 EmitEOL(); 93 } 94 95 /// @name MCStreamer Interface 96 /// @{ 97 98 virtual void SwitchSection(const MCSection *Section); 99 100 virtual void EmitLabel(MCSymbol *Symbol); 101 102 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); 103 104 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); 105 106 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); 107 108 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 109 110 virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); 111 virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 112 unsigned ByteAlignment); 113 114 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 115 /// 116 /// @param Symbol - The common symbol to emit. 117 /// @param Size - The size of the common symbol. 118 virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); 119 120 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, 121 unsigned Size = 0, unsigned ByteAlignment = 0); 122 123 virtual void EmitBytes(StringRef Data, unsigned AddrSpace); 124 125 virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); 126 virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace); 127 virtual void EmitGPRel32Value(const MCExpr *Value); 128 129 130 virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, 131 unsigned AddrSpace); 132 133 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 134 unsigned ValueSize = 1, 135 unsigned MaxBytesToEmit = 0); 136 137 virtual void EmitCodeAlignment(unsigned ByteAlignment, 138 unsigned MaxBytesToEmit = 0); 139 140 virtual void EmitValueToOffset(const MCExpr *Offset, 141 unsigned char Value = 0); 142 143 virtual void EmitFileDirective(StringRef Filename); 144 virtual void EmitDwarfFileDirective(unsigned FileNo, StringRef Filename); 145 146 virtual void EmitInstruction(const MCInst &Inst); 147 148 virtual void Finish(); 149 150 /// @} 151}; 152 153} // end anonymous namespace. 154 155/// AddComment - Add a comment that can be emitted to the generated .s 156/// file if applicable as a QoI issue to make the output of the compiler 157/// more readable. This only affects the MCAsmStreamer, and only when 158/// verbose assembly output is enabled. 159void MCAsmStreamer::AddComment(const Twine &T) { 160 if (!IsVerboseAsm) return; 161 162 // Make sure that CommentStream is flushed. 163 CommentStream.flush(); 164 165 T.toVector(CommentToEmit); 166 // Each comment goes on its own line. 167 CommentToEmit.push_back('\n'); 168 169 // Tell the comment stream that the vector changed underneath it. 170 CommentStream.resync(); 171} 172 173void MCAsmStreamer::EmitCommentsAndEOL() { 174 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { 175 OS << '\n'; 176 return; 177 } 178 179 CommentStream.flush(); 180 StringRef Comments = CommentToEmit.str(); 181 182 assert(Comments.back() == '\n' && 183 "Comment array not newline terminated"); 184 do { 185 // Emit a line of comments. 186 OS.PadToColumn(MAI.getCommentColumn()); 187 size_t Position = Comments.find('\n'); 188 OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n'; 189 190 Comments = Comments.substr(Position+1); 191 } while (!Comments.empty()); 192 193 CommentToEmit.clear(); 194 // Tell the comment stream that the vector changed underneath it. 195 CommentStream.resync(); 196} 197 198 199static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 200 assert(Bytes && "Invalid size!"); 201 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 202} 203 204void MCAsmStreamer::SwitchSection(const MCSection *Section) { 205 assert(Section && "Cannot switch to a null section!"); 206 if (Section != CurSection) { 207 CurSection = Section; 208 Section->PrintSwitchToSection(MAI, OS); 209 } 210} 211 212void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 213 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 214 assert(CurSection && "Cannot emit before setting section!"); 215 216 OS << *Symbol << ":"; 217 EmitEOL(); 218 Symbol->setSection(*CurSection); 219} 220 221void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 222 switch (Flag) { 223 default: assert(0 && "Invalid flag!"); 224 case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 225 } 226 EmitEOL(); 227} 228 229void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 230 // Only absolute symbols can be redefined. 231 assert((Symbol->isUndefined() || Symbol->isAbsolute()) && 232 "Cannot define a symbol twice!"); 233 234 OS << *Symbol << " = " << *Value; 235 EmitEOL(); 236 237 // FIXME: Lift context changes into super class. 238 // FIXME: Set associated section. 239 Symbol->setValue(Value); 240} 241 242void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 243 MCSymbolAttr Attribute) { 244 switch (Attribute) { 245 case MCSA_Invalid: assert(0 && "Invalid symbol attribute"); 246 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function 247 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC 248 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object 249 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object 250 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common 251 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype 252 assert(MAI.hasDotTypeDotSizeDirective() && "Symbol Attr not supported"); 253 OS << "\t.type\t" << *Symbol << ',' 254 << ((MAI.getCommentString()[0] != '@') ? '@' : '%'); 255 switch (Attribute) { 256 default: assert(0 && "Unknown ELF .type"); 257 case MCSA_ELF_TypeFunction: OS << "function"; break; 258 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; 259 case MCSA_ELF_TypeObject: OS << "object"; break; 260 case MCSA_ELF_TypeTLS: OS << "tls_object"; break; 261 case MCSA_ELF_TypeCommon: OS << "common"; break; 262 case MCSA_ELF_TypeNoType: OS << "no_type"; break; 263 } 264 EmitEOL(); 265 return; 266 case MCSA_Global: // .globl/.global 267 OS << MAI.getGlobalDirective(); 268 break; 269 case MCSA_Hidden: OS << ".hidden "; break; 270 case MCSA_IndirectSymbol: OS << ".indirect_symbol "; break; 271 case MCSA_Internal: OS << ".internal "; break; 272 case MCSA_LazyReference: OS << ".lazy_reference "; break; 273 case MCSA_Local: OS << ".local "; break; 274 case MCSA_NoDeadStrip: OS << ".no_dead_strip "; break; 275 case MCSA_PrivateExtern: OS << ".private_extern "; break; 276 case MCSA_Protected: OS << ".protected "; break; 277 case MCSA_Reference: OS << ".reference "; break; 278 case MCSA_Weak: OS << ".weak "; break; 279 case MCSA_WeakDefinition: OS << ".weak_definition "; break; 280 // .weak_reference 281 case MCSA_WeakReference: OS << MAI.getWeakRefDirective(); break; 282 } 283 284 OS << *Symbol; 285 EmitEOL(); 286} 287 288void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 289 OS << ".desc" << ' ' << *Symbol << ',' << DescValue; 290 EmitEOL(); 291} 292 293void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 294 assert(MAI.hasDotTypeDotSizeDirective()); 295 OS << "\t.size\t" << *Symbol << ", " << *Value << '\n'; 296} 297 298void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 299 unsigned ByteAlignment) { 300 OS << "\t.comm\t" << *Symbol << ',' << Size; 301 if (ByteAlignment != 0) { 302 if (MAI.getCOMMDirectiveAlignmentIsInBytes()) 303 OS << ',' << ByteAlignment; 304 else 305 OS << ',' << Log2_32(ByteAlignment); 306 } 307 EmitEOL(); 308} 309 310/// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 311/// 312/// @param Symbol - The common symbol to emit. 313/// @param Size - The size of the common symbol. 314void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { 315 assert(MAI.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!"); 316 OS << "\t.lcomm\t" << *Symbol << ',' << Size; 317 EmitEOL(); 318} 319 320void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 321 unsigned Size, unsigned ByteAlignment) { 322 // Note: a .zerofill directive does not switch sections. 323 OS << ".zerofill "; 324 325 // This is a mach-o specific directive. 326 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 327 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 328 329 if (Symbol != NULL) { 330 OS << ',' << *Symbol << ',' << Size; 331 if (ByteAlignment != 0) 332 OS << ',' << Log2_32(ByteAlignment); 333 } 334 EmitEOL(); 335} 336 337static inline char toOctal(int X) { return (X&7)+'0'; } 338 339static void PrintQuotedString(StringRef Data, raw_ostream &OS) { 340 OS << '"'; 341 342 for (unsigned i = 0, e = Data.size(); i != e; ++i) { 343 unsigned char C = Data[i]; 344 if (C == '"' || C == '\\') { 345 OS << '\\' << (char)C; 346 continue; 347 } 348 349 if (isprint((unsigned char)C)) { 350 OS << (char)C; 351 continue; 352 } 353 354 switch (C) { 355 case '\b': OS << "\\b"; break; 356 case '\f': OS << "\\f"; break; 357 case '\n': OS << "\\n"; break; 358 case '\r': OS << "\\r"; break; 359 case '\t': OS << "\\t"; break; 360 default: 361 OS << '\\'; 362 OS << toOctal(C >> 6); 363 OS << toOctal(C >> 3); 364 OS << toOctal(C >> 0); 365 break; 366 } 367 } 368 369 OS << '"'; 370} 371 372 373void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { 374 assert(CurSection && "Cannot emit contents before setting section!"); 375 if (Data.empty()) return; 376 377 if (Data.size() == 1) { 378 OS << MAI.getData8bitsDirective(AddrSpace); 379 OS << (unsigned)(unsigned char)Data[0]; 380 EmitEOL(); 381 return; 382 } 383 384 // If the data ends with 0 and the target supports .asciz, use it, otherwise 385 // use .ascii 386 if (MAI.getAscizDirective() && Data.back() == 0) { 387 OS << MAI.getAscizDirective(); 388 Data = Data.substr(0, Data.size()-1); 389 } else { 390 OS << MAI.getAsciiDirective(); 391 } 392 393 OS << ' '; 394 PrintQuotedString(Data, OS); 395 EmitEOL(); 396} 397 398/// EmitIntValue - Special case of EmitValue that avoids the client having 399/// to pass in a MCExpr for constant integers. 400void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, 401 unsigned AddrSpace) { 402 assert(CurSection && "Cannot emit contents before setting section!"); 403 const char *Directive = 0; 404 switch (Size) { 405 default: break; 406 case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; 407 case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; 408 case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; 409 case 8: 410 Directive = MAI.getData64bitsDirective(AddrSpace); 411 // If the target doesn't support 64-bit data, emit as two 32-bit halves. 412 if (Directive) break; 413 if (isLittleEndian()) { 414 EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); 415 EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); 416 } else { 417 EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace); 418 EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace); 419 } 420 return; 421 } 422 423 assert(Directive && "Invalid size for machine code value!"); 424 OS << Directive << truncateToSize(Value, Size); 425 EmitEOL(); 426} 427 428void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, 429 unsigned AddrSpace) { 430 assert(CurSection && "Cannot emit contents before setting section!"); 431 const char *Directive = 0; 432 switch (Size) { 433 default: break; 434 case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; 435 case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; 436 case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; 437 case 8: Directive = MAI.getData64bitsDirective(AddrSpace); break; 438 } 439 440 assert(Directive && "Invalid size for machine code value!"); 441 OS << Directive << *Value; 442 EmitEOL(); 443} 444 445void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { 446 assert(MAI.getGPRel32Directive() != 0); 447 OS << MAI.getGPRel32Directive() << *Value; 448 EmitEOL(); 449} 450 451 452/// EmitFill - Emit NumBytes bytes worth of the value specified by 453/// FillValue. This implements directives such as '.space'. 454void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, 455 unsigned AddrSpace) { 456 if (NumBytes == 0) return; 457 458 if (AddrSpace == 0) 459 if (const char *ZeroDirective = MAI.getZeroDirective()) { 460 OS << ZeroDirective << NumBytes; 461 if (FillValue != 0) 462 OS << ',' << (int)FillValue; 463 EmitEOL(); 464 return; 465 } 466 467 // Emit a byte at a time. 468 MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace); 469} 470 471void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 472 unsigned ValueSize, 473 unsigned MaxBytesToEmit) { 474 // Some assemblers don't support non-power of two alignments, so we always 475 // emit alignments as a power of two if possible. 476 if (isPowerOf2_32(ByteAlignment)) { 477 switch (ValueSize) { 478 default: llvm_unreachable("Invalid size for machine code value!"); 479 case 1: OS << MAI.getAlignDirective(); break; 480 // FIXME: use MAI for this! 481 case 2: OS << ".p2alignw "; break; 482 case 4: OS << ".p2alignl "; break; 483 case 8: llvm_unreachable("Unsupported alignment size!"); 484 } 485 486 if (MAI.getAlignmentIsInBytes()) 487 OS << ByteAlignment; 488 else 489 OS << Log2_32(ByteAlignment); 490 491 if (Value || MaxBytesToEmit) { 492 OS << ", 0x"; 493 OS.write_hex(truncateToSize(Value, ValueSize)); 494 495 if (MaxBytesToEmit) 496 OS << ", " << MaxBytesToEmit; 497 } 498 EmitEOL(); 499 return; 500 } 501 502 // Non-power of two alignment. This is not widely supported by assemblers. 503 // FIXME: Parameterize this based on MAI. 504 switch (ValueSize) { 505 default: llvm_unreachable("Invalid size for machine code value!"); 506 case 1: OS << ".balign"; break; 507 case 2: OS << ".balignw"; break; 508 case 4: OS << ".balignl"; break; 509 case 8: llvm_unreachable("Unsupported alignment size!"); 510 } 511 512 OS << ' ' << ByteAlignment; 513 OS << ", " << truncateToSize(Value, ValueSize); 514 if (MaxBytesToEmit) 515 OS << ", " << MaxBytesToEmit; 516 EmitEOL(); 517} 518 519void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, 520 unsigned MaxBytesToEmit) { 521 // Emit with a text fill value. 522 EmitValueToAlignment(ByteAlignment, MAI.getTextAlignFillValue(), 523 1, MaxBytesToEmit); 524} 525 526void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, 527 unsigned char Value) { 528 // FIXME: Verify that Offset is associated with the current section. 529 OS << ".org " << *Offset << ", " << (unsigned) Value; 530 EmitEOL(); 531} 532 533 534void MCAsmStreamer::EmitFileDirective(StringRef Filename) { 535 assert(MAI.hasSingleParameterDotFile()); 536 OS << "\t.file\t"; 537 PrintQuotedString(Filename, OS); 538 EmitEOL(); 539} 540 541void MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ 542 OS << "\t.file\t" << FileNo << ' '; 543 PrintQuotedString(Filename, OS); 544 EmitEOL(); 545} 546 547void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { 548 raw_ostream &OS = GetCommentOS(); 549 SmallString<256> Code; 550 SmallVector<MCFixup, 4> Fixups; 551 raw_svector_ostream VecOS(Code); 552 Emitter->EncodeInstruction(Inst, VecOS, Fixups); 553 VecOS.flush(); 554 555 // If we are showing fixups, create symbolic markers in the encoded 556 // representation. We do this by making a per-bit map to the fixup item index, 557 // then trying to display it as nicely as possible. 558 SmallVector<uint8_t, 64> FixupMap; 559 FixupMap.resize(Code.size() * 8); 560 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) 561 FixupMap[i] = 0; 562 563 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 564 MCFixup &F = Fixups[i]; 565 const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); 566 for (unsigned j = 0; j != Info.TargetSize; ++j) { 567 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; 568 assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); 569 FixupMap[Index] = 1 + i; 570 } 571 } 572 573 OS << "encoding: ["; 574 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 575 if (i) 576 OS << ','; 577 578 // See if all bits are the same map entry. 579 uint8_t MapEntry = FixupMap[i * 8 + 0]; 580 for (unsigned j = 1; j != 8; ++j) { 581 if (FixupMap[i * 8 + j] == MapEntry) 582 continue; 583 584 MapEntry = uint8_t(~0U); 585 break; 586 } 587 588 if (MapEntry != uint8_t(~0U)) { 589 if (MapEntry == 0) { 590 OS << format("0x%02x", uint8_t(Code[i])); 591 } else { 592 assert(Code[i] == 0 && "Encoder wrote into fixed up bit!"); 593 OS << char('A' + MapEntry - 1); 594 } 595 } else { 596 // Otherwise, write out in binary. 597 OS << "0b"; 598 for (unsigned j = 8; j--;) { 599 unsigned Bit = (Code[i] >> j) & 1; 600 if (uint8_t MapEntry = FixupMap[i * 8 + j]) { 601 assert(Bit == 0 && "Encoder wrote into fixed up bit!"); 602 OS << char('A' + MapEntry - 1); 603 } else 604 OS << Bit; 605 } 606 } 607 } 608 OS << "]\n"; 609 610 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 611 MCFixup &F = Fixups[i]; 612 const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); 613 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() 614 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; 615 } 616} 617 618void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { 619 assert(CurSection && "Cannot emit contents before setting section!"); 620 621 // Show the encoding in a comment if we have a code emitter. 622 if (Emitter) 623 AddEncodingComment(Inst); 624 625 // Show the MCInst if enabled. 626 if (ShowInst) 627 Inst.dump_pretty(GetCommentOS(), &MAI, InstPrinter.get(), "\n "); 628 629 // If we have an AsmPrinter, use that to print, otherwise print the MCInst. 630 if (InstPrinter) 631 InstPrinter->printInst(&Inst); 632 else 633 Inst.print(OS, &MAI); 634 EmitEOL(); 635} 636 637void MCAsmStreamer::Finish() { 638 OS.flush(); 639} 640 641MCStreamer *llvm::createAsmStreamer(MCContext &Context, 642 formatted_raw_ostream &OS, 643 bool isLittleEndian, 644 bool isVerboseAsm, MCInstPrinter *IP, 645 MCCodeEmitter *CE, bool ShowInst) { 646 return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, 647 IP, CE, ShowInst); 648} 649