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