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