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