MCAsmStreamer.cpp revision 5d4918dbd116b0b5e561c431b1ea527ee1b9302a
1//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "llvm/MC/MCStreamer.h" 11#include "llvm/MC/MCAsmInfo.h" 12#include "llvm/MC/MCCodeEmitter.h" 13#include "llvm/MC/MCContext.h" 14#include "llvm/MC/MCExpr.h" 15#include "llvm/MC/MCInst.h" 16#include "llvm/MC/MCInstPrinter.h" 17#include "llvm/MC/MCSectionMachO.h" 18#include "llvm/MC/MCSymbol.h" 19#include "llvm/ADT/OwningPtr.h" 20#include "llvm/ADT/SmallString.h" 21#include "llvm/ADT/Twine.h" 22#include "llvm/Support/ErrorHandling.h" 23#include "llvm/Support/MathExtras.h" 24#include "llvm/Support/Format.h" 25#include "llvm/Support/FormattedStream.h" 26#include "llvm/Target/TargetLoweringObjectFile.h" 27using namespace llvm; 28 29namespace { 30 31class MCAsmStreamer : public MCStreamer { 32 formatted_raw_ostream &OS; 33 const MCAsmInfo &MAI; 34 OwningPtr<MCInstPrinter> InstPrinter; 35 OwningPtr<MCCodeEmitter> Emitter; 36 37 SmallString<128> CommentToEmit; 38 raw_svector_ostream CommentStream; 39 40 const TargetLoweringObjectFile *TLOF; 41 int PointerSize; 42 43 unsigned IsLittleEndian : 1; 44 unsigned IsVerboseAsm : 1; 45 unsigned ShowInst : 1; 46 47 bool needsSet(const MCExpr *Value); 48 49public: 50 MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, 51 bool isLittleEndian, bool isVerboseAsm, 52 const TargetLoweringObjectFile *tlof, int pointerSize, 53 MCInstPrinter *printer, MCCodeEmitter *emitter, bool showInst) 54 : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()), 55 InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit), 56 TLOF(tlof), PointerSize(pointerSize), 57 IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm), 58 ShowInst(showInst) { 59 if (InstPrinter && IsVerboseAsm) 60 InstPrinter->setCommentStream(CommentStream); 61 } 62 ~MCAsmStreamer() {} 63 64 bool isLittleEndian() const { return IsLittleEndian; } 65 66 inline void EmitEOL() { 67 // If we don't have any comments, just emit a \n. 68 if (!IsVerboseAsm) { 69 OS << '\n'; 70 return; 71 } 72 EmitCommentsAndEOL(); 73 } 74 void EmitCommentsAndEOL(); 75 76 /// isVerboseAsm - Return true if this streamer supports verbose assembly at 77 /// all. 78 virtual bool isVerboseAsm() const { return IsVerboseAsm; } 79 80 /// hasRawTextSupport - We support EmitRawText. 81 virtual bool hasRawTextSupport() const { return true; } 82 83 /// AddComment - Add a comment that can be emitted to the generated .s 84 /// file if applicable as a QoI issue to make the output of the compiler 85 /// more readable. This only affects the MCAsmStreamer, and only when 86 /// verbose assembly output is enabled. 87 virtual void AddComment(const Twine &T); 88 89 /// AddEncodingComment - Add a comment showing the encoding of an instruction. 90 virtual void AddEncodingComment(const MCInst &Inst); 91 92 /// GetCommentOS - Return a raw_ostream that comments can be written to. 93 /// Unlike AddComment, you are required to terminate comments with \n if you 94 /// use this method. 95 virtual raw_ostream &GetCommentOS() { 96 if (!IsVerboseAsm) 97 return nulls(); // Discard comments unless in verbose asm mode. 98 return CommentStream; 99 } 100 101 /// AddBlankLine - Emit a blank line to a .s file to pretty it up. 102 virtual void AddBlankLine() { 103 EmitEOL(); 104 } 105 106 /// @name MCStreamer Interface 107 /// @{ 108 109 virtual void SwitchSection(const MCSection *Section); 110 111 virtual void InitSections() { 112 // FIXME, this is MachO specific, but the testsuite 113 // expects this. 114 SwitchSection(getContext().getMachOSection("__TEXT", "__text", 115 MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, 116 0, SectionKind::getText())); 117 } 118 119 virtual void EmitLabel(MCSymbol *Symbol); 120 121 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); 122 virtual void EmitThumbFunc(MCSymbol *Func); 123 124 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); 125 virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); 126 virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, 127 const MCSymbol *LastLabel, 128 const MCSymbol *Label); 129 130 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute); 131 132 virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); 133 virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); 134 virtual void EmitCOFFSymbolStorageClass(int StorageClass); 135 virtual void EmitCOFFSymbolType(int Type); 136 virtual void EndCOFFSymbolDef(); 137 virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); 138 virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 139 unsigned ByteAlignment); 140 141 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 142 /// 143 /// @param Symbol - The common symbol to emit. 144 /// @param Size - The size of the common symbol. 145 virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size); 146 147 virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, 148 unsigned Size = 0, unsigned ByteAlignment = 0); 149 150 virtual void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol, 151 uint64_t Size, unsigned ByteAlignment = 0); 152 153 virtual void EmitBytes(StringRef Data, unsigned AddrSpace); 154 155 virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); 156 virtual void EmitIntValue(uint64_t Value, unsigned Size, 157 unsigned AddrSpace = 0); 158 159 virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); 160 161 virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); 162 163 virtual void EmitGPRel32Value(const MCExpr *Value); 164 165 166 virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, 167 unsigned AddrSpace); 168 169 virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 170 unsigned ValueSize = 1, 171 unsigned MaxBytesToEmit = 0); 172 173 virtual void EmitCodeAlignment(unsigned ByteAlignment, 174 unsigned MaxBytesToEmit = 0); 175 176 virtual void EmitValueToOffset(const MCExpr *Offset, 177 unsigned char Value = 0); 178 179 virtual void EmitFileDirective(StringRef Filename); 180 virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Filename); 181 virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 182 unsigned Column, unsigned Flags, 183 unsigned Isa, unsigned Discriminator); 184 185 virtual bool EmitCFIStartProc(); 186 virtual bool EmitCFIEndProc(); 187 virtual bool EmitCFIDefCfaOffset(int64_t Offset); 188 virtual bool EmitCFIDefCfaRegister(int64_t Register); 189 virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); 190 virtual bool EmitCFIPersonality(const MCSymbol *Sym); 191 virtual bool EmitCFILsda(const MCSymbol *Sym); 192 193 virtual void EmitInstruction(const MCInst &Inst); 194 195 /// EmitRawText - If this file is backed by an assembly streamer, this dumps 196 /// the specified string in the output .s file. This capability is 197 /// indicated by the hasRawTextSupport() predicate. 198 virtual void EmitRawText(StringRef String); 199 200 virtual void Finish(); 201 202 /// @} 203}; 204 205} // end anonymous namespace. 206 207/// AddComment - Add a comment that can be emitted to the generated .s 208/// file if applicable as a QoI issue to make the output of the compiler 209/// more readable. This only affects the MCAsmStreamer, and only when 210/// verbose assembly output is enabled. 211void MCAsmStreamer::AddComment(const Twine &T) { 212 if (!IsVerboseAsm) return; 213 214 // Make sure that CommentStream is flushed. 215 CommentStream.flush(); 216 217 T.toVector(CommentToEmit); 218 // Each comment goes on its own line. 219 CommentToEmit.push_back('\n'); 220 221 // Tell the comment stream that the vector changed underneath it. 222 CommentStream.resync(); 223} 224 225void MCAsmStreamer::EmitCommentsAndEOL() { 226 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { 227 OS << '\n'; 228 return; 229 } 230 231 CommentStream.flush(); 232 StringRef Comments = CommentToEmit.str(); 233 234 assert(Comments.back() == '\n' && 235 "Comment array not newline terminated"); 236 do { 237 // Emit a line of comments. 238 OS.PadToColumn(MAI.getCommentColumn()); 239 size_t Position = Comments.find('\n'); 240 OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n'; 241 242 Comments = Comments.substr(Position+1); 243 } while (!Comments.empty()); 244 245 CommentToEmit.clear(); 246 // Tell the comment stream that the vector changed underneath it. 247 CommentStream.resync(); 248} 249 250static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 251 assert(Bytes && "Invalid size!"); 252 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 253} 254 255void MCAsmStreamer::SwitchSection(const MCSection *Section) { 256 assert(Section && "Cannot switch to a null section!"); 257 if (Section != CurSection) { 258 PrevSection = CurSection; 259 CurSection = Section; 260 Section->PrintSwitchToSection(MAI, OS); 261 } 262} 263 264void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 265 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 266 assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); 267 assert(CurSection && "Cannot emit before setting section!"); 268 269 OS << *Symbol << MAI.getLabelSuffix(); 270 EmitEOL(); 271 Symbol->setSection(*CurSection); 272} 273 274void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 275 switch (Flag) { 276 default: assert(0 && "Invalid flag!"); 277 case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; 278 case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 279 case MCAF_Code16: OS << "\t.code\t16"; break; 280 case MCAF_Code32: OS << "\t.code\t32"; break; 281 } 282 EmitEOL(); 283} 284 285void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { 286 // This needs to emit to a temporary string to get properly quoted 287 // MCSymbols when they have spaces in them. 288 OS << "\t.thumb_func"; 289 if (Func) 290 OS << '\t' << *Func; 291 EmitEOL(); 292} 293 294void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 295 OS << *Symbol << " = " << *Value; 296 EmitEOL(); 297 298 // FIXME: Lift context changes into super class. 299 Symbol->setVariableValue(Value); 300} 301 302void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { 303 OS << ".weakref " << *Alias << ", " << *Symbol; 304 EmitEOL(); 305} 306 307void MCAsmStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, 308 const MCSymbol *LastLabel, 309 const MCSymbol *Label) { 310 EmitDwarfSetLineAddr(LineDelta, Label, PointerSize); 311} 312 313void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 314 MCSymbolAttr Attribute) { 315 switch (Attribute) { 316 case MCSA_Invalid: assert(0 && "Invalid symbol attribute"); 317 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function 318 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC 319 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object 320 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object 321 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common 322 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype 323 case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object 324 assert(MAI.hasDotTypeDotSizeDirective() && "Symbol Attr not supported"); 325 OS << "\t.type\t" << *Symbol << ',' 326 << ((MAI.getCommentString()[0] != '@') ? '@' : '%'); 327 switch (Attribute) { 328 default: assert(0 && "Unknown ELF .type"); 329 case MCSA_ELF_TypeFunction: OS << "function"; break; 330 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; 331 case MCSA_ELF_TypeObject: OS << "object"; break; 332 case MCSA_ELF_TypeTLS: OS << "tls_object"; break; 333 case MCSA_ELF_TypeCommon: OS << "common"; break; 334 case MCSA_ELF_TypeNoType: OS << "no_type"; break; 335 case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; 336 } 337 EmitEOL(); 338 return; 339 case MCSA_Global: // .globl/.global 340 OS << MAI.getGlobalDirective(); 341 break; 342 case MCSA_Hidden: OS << "\t.hidden\t"; break; 343 case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; 344 case MCSA_Internal: OS << "\t.internal\t"; break; 345 case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; 346 case MCSA_Local: OS << "\t.local\t"; break; 347 case MCSA_NoDeadStrip: OS << "\t.no_dead_strip\t"; break; 348 case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; 349 case MCSA_PrivateExtern: OS << "\t.private_extern\t"; break; 350 case MCSA_Protected: OS << "\t.protected\t"; break; 351 case MCSA_Reference: OS << "\t.reference\t"; break; 352 case MCSA_Weak: OS << "\t.weak\t"; break; 353 case MCSA_WeakDefinition: OS << "\t.weak_definition\t"; break; 354 // .weak_reference 355 case MCSA_WeakReference: OS << MAI.getWeakRefDirective(); break; 356 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; 357 } 358 359 OS << *Symbol; 360 EmitEOL(); 361} 362 363void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 364 OS << ".desc" << ' ' << *Symbol << ',' << DescValue; 365 EmitEOL(); 366} 367 368void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { 369 OS << "\t.def\t " << *Symbol << ';'; 370 EmitEOL(); 371} 372 373void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) { 374 OS << "\t.scl\t" << StorageClass << ';'; 375 EmitEOL(); 376} 377 378void MCAsmStreamer::EmitCOFFSymbolType (int Type) { 379 OS << "\t.type\t" << Type << ';'; 380 EmitEOL(); 381} 382 383void MCAsmStreamer::EndCOFFSymbolDef() { 384 OS << "\t.endef"; 385 EmitEOL(); 386} 387 388void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 389 assert(MAI.hasDotTypeDotSizeDirective()); 390 OS << "\t.size\t" << *Symbol << ", " << *Value << '\n'; 391} 392 393void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 394 unsigned ByteAlignment) { 395 OS << "\t.comm\t" << *Symbol << ',' << Size; 396 if (ByteAlignment != 0) { 397 if (MAI.getCOMMDirectiveAlignmentIsInBytes()) 398 OS << ',' << ByteAlignment; 399 else 400 OS << ',' << Log2_32(ByteAlignment); 401 } 402 EmitEOL(); 403} 404 405/// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 406/// 407/// @param Symbol - The common symbol to emit. 408/// @param Size - The size of the common symbol. 409void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) { 410 assert(MAI.hasLCOMMDirective() && "Doesn't have .lcomm, can't emit it!"); 411 OS << "\t.lcomm\t" << *Symbol << ',' << Size; 412 EmitEOL(); 413} 414 415void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, 416 unsigned Size, unsigned ByteAlignment) { 417 // Note: a .zerofill directive does not switch sections. 418 OS << ".zerofill "; 419 420 // This is a mach-o specific directive. 421 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 422 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 423 424 if (Symbol != NULL) { 425 OS << ',' << *Symbol << ',' << Size; 426 if (ByteAlignment != 0) 427 OS << ',' << Log2_32(ByteAlignment); 428 } 429 EmitEOL(); 430} 431 432// .tbss sym, size, align 433// This depends that the symbol has already been mangled from the original, 434// e.g. _a. 435void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, 436 uint64_t Size, unsigned ByteAlignment) { 437 assert(Symbol != NULL && "Symbol shouldn't be NULL!"); 438 // Instead of using the Section we'll just use the shortcut. 439 // This is a mach-o specific directive and section. 440 OS << ".tbss " << *Symbol << ", " << Size; 441 442 // Output align if we have it. We default to 1 so don't bother printing 443 // that. 444 if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment); 445 446 EmitEOL(); 447} 448 449static inline char toOctal(int X) { return (X&7)+'0'; } 450 451static void PrintQuotedString(StringRef Data, raw_ostream &OS) { 452 OS << '"'; 453 454 for (unsigned i = 0, e = Data.size(); i != e; ++i) { 455 unsigned char C = Data[i]; 456 if (C == '"' || C == '\\') { 457 OS << '\\' << (char)C; 458 continue; 459 } 460 461 if (isprint((unsigned char)C)) { 462 OS << (char)C; 463 continue; 464 } 465 466 switch (C) { 467 case '\b': OS << "\\b"; break; 468 case '\f': OS << "\\f"; break; 469 case '\n': OS << "\\n"; break; 470 case '\r': OS << "\\r"; break; 471 case '\t': OS << "\\t"; break; 472 default: 473 OS << '\\'; 474 OS << toOctal(C >> 6); 475 OS << toOctal(C >> 3); 476 OS << toOctal(C >> 0); 477 break; 478 } 479 } 480 481 OS << '"'; 482} 483 484 485void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { 486 assert(CurSection && "Cannot emit contents before setting section!"); 487 if (Data.empty()) return; 488 489 if (Data.size() == 1) { 490 OS << MAI.getData8bitsDirective(AddrSpace); 491 OS << (unsigned)(unsigned char)Data[0]; 492 EmitEOL(); 493 return; 494 } 495 496 // If the data ends with 0 and the target supports .asciz, use it, otherwise 497 // use .ascii 498 if (MAI.getAscizDirective() && Data.back() == 0) { 499 OS << MAI.getAscizDirective(); 500 Data = Data.substr(0, Data.size()-1); 501 } else { 502 OS << MAI.getAsciiDirective(); 503 } 504 505 OS << ' '; 506 PrintQuotedString(Data, OS); 507 EmitEOL(); 508} 509 510void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, 511 unsigned AddrSpace) { 512 EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace); 513} 514 515static bool hasSymbolDifference(const MCExpr *Value) { 516 switch (Value->getKind()) { 517 case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!"); 518 case MCExpr::Constant: 519 case MCExpr::SymbolRef: 520 return false; 521 case MCExpr::Unary: 522 return hasSymbolDifference(cast<MCUnaryExpr>(Value)->getSubExpr()); 523 case MCExpr::Binary: { 524 const MCBinaryExpr *BE = cast<MCBinaryExpr>(Value); 525 if (BE->getOpcode() == MCBinaryExpr::Sub && 526 BE->getLHS()->getKind() == MCExpr::SymbolRef && 527 BE->getRHS()->getKind() == MCExpr::SymbolRef) 528 return true; 529 return hasSymbolDifference(BE->getLHS()) || 530 hasSymbolDifference(BE->getRHS()); 531 } 532 } 533 llvm_unreachable("Switch covers all cases"); 534} 535 536bool MCAsmStreamer::needsSet(const MCExpr *Value) { 537 return getContext().getAsmInfo().needsSetToChangeDiffSize() && 538 hasSymbolDifference(Value); 539} 540 541void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, 542 unsigned AddrSpace) { 543 assert(CurSection && "Cannot emit contents before setting section!"); 544 const char *Directive = 0; 545 switch (Size) { 546 default: break; 547 case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break; 548 case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break; 549 case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break; 550 case 8: 551 Directive = MAI.getData64bitsDirective(AddrSpace); 552 // If the target doesn't support 64-bit data, emit as two 32-bit halves. 553 if (Directive) break; 554 int64_t IntValue; 555 if (!Value->EvaluateAsAbsolute(IntValue)) 556 report_fatal_error("Don't know how to emit this value."); 557 if (isLittleEndian()) { 558 EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); 559 EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); 560 } else { 561 EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace); 562 EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace); 563 } 564 return; 565 } 566 567 assert(Directive && "Invalid size for machine code value!"); 568 if (needsSet(Value)) { 569 MCSymbol *SetLabel = getContext().CreateTempSymbol(); 570 EmitAssignment(SetLabel, Value); 571 OS << Directive << *SetLabel; 572 EmitEOL(); 573 return; 574 } 575 576 OS << Directive << *Value; 577 EmitEOL(); 578} 579 580void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) { 581 int64_t IntValue; 582 if (Value->EvaluateAsAbsolute(IntValue)) { 583 EmitULEB128IntValue(IntValue, AddrSpace); 584 return; 585 } 586 assert(MAI.hasLEB128() && "Cannot print a .uleb"); 587 OS << ".uleb128 " << *Value; 588 EmitEOL(); 589} 590 591void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) { 592 int64_t IntValue; 593 if (Value->EvaluateAsAbsolute(IntValue)) { 594 EmitSLEB128IntValue(IntValue, AddrSpace); 595 return; 596 } 597 assert(MAI.hasLEB128() && "Cannot print a .sleb"); 598 OS << ".sleb128 " << *Value; 599 EmitEOL(); 600} 601 602void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { 603 assert(MAI.getGPRel32Directive() != 0); 604 OS << MAI.getGPRel32Directive() << *Value; 605 EmitEOL(); 606} 607 608 609/// EmitFill - Emit NumBytes bytes worth of the value specified by 610/// FillValue. This implements directives such as '.space'. 611void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, 612 unsigned AddrSpace) { 613 if (NumBytes == 0) return; 614 615 if (AddrSpace == 0) 616 if (const char *ZeroDirective = MAI.getZeroDirective()) { 617 OS << ZeroDirective << NumBytes; 618 if (FillValue != 0) 619 OS << ',' << (int)FillValue; 620 EmitEOL(); 621 return; 622 } 623 624 // Emit a byte at a time. 625 MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace); 626} 627 628void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 629 unsigned ValueSize, 630 unsigned MaxBytesToEmit) { 631 // Some assemblers don't support non-power of two alignments, so we always 632 // emit alignments as a power of two if possible. 633 if (isPowerOf2_32(ByteAlignment)) { 634 switch (ValueSize) { 635 default: llvm_unreachable("Invalid size for machine code value!"); 636 case 1: OS << MAI.getAlignDirective(); break; 637 // FIXME: use MAI for this! 638 case 2: OS << ".p2alignw "; break; 639 case 4: OS << ".p2alignl "; break; 640 case 8: llvm_unreachable("Unsupported alignment size!"); 641 } 642 643 if (MAI.getAlignmentIsInBytes()) 644 OS << ByteAlignment; 645 else 646 OS << Log2_32(ByteAlignment); 647 648 if (Value || MaxBytesToEmit) { 649 OS << ", 0x"; 650 OS.write_hex(truncateToSize(Value, ValueSize)); 651 652 if (MaxBytesToEmit) 653 OS << ", " << MaxBytesToEmit; 654 } 655 EmitEOL(); 656 return; 657 } 658 659 // Non-power of two alignment. This is not widely supported by assemblers. 660 // FIXME: Parameterize this based on MAI. 661 switch (ValueSize) { 662 default: llvm_unreachable("Invalid size for machine code value!"); 663 case 1: OS << ".balign"; break; 664 case 2: OS << ".balignw"; break; 665 case 4: OS << ".balignl"; break; 666 case 8: llvm_unreachable("Unsupported alignment size!"); 667 } 668 669 OS << ' ' << ByteAlignment; 670 OS << ", " << truncateToSize(Value, ValueSize); 671 if (MaxBytesToEmit) 672 OS << ", " << MaxBytesToEmit; 673 EmitEOL(); 674} 675 676void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, 677 unsigned MaxBytesToEmit) { 678 // Emit with a text fill value. 679 EmitValueToAlignment(ByteAlignment, MAI.getTextAlignFillValue(), 680 1, MaxBytesToEmit); 681} 682 683void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, 684 unsigned char Value) { 685 // FIXME: Verify that Offset is associated with the current section. 686 OS << ".org " << *Offset << ", " << (unsigned) Value; 687 EmitEOL(); 688} 689 690 691void MCAsmStreamer::EmitFileDirective(StringRef Filename) { 692 assert(MAI.hasSingleParameterDotFile()); 693 OS << "\t.file\t"; 694 PrintQuotedString(Filename, OS); 695 EmitEOL(); 696} 697 698bool MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, StringRef Filename){ 699 if (!TLOF) { 700 OS << "\t.file\t" << FileNo << ' '; 701 PrintQuotedString(Filename, OS); 702 EmitEOL(); 703 } 704 return this->MCStreamer::EmitDwarfFileDirective(FileNo, Filename); 705} 706 707void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 708 unsigned Column, unsigned Flags, 709 unsigned Isa, 710 unsigned Discriminator) { 711 this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, 712 Isa, Discriminator); 713 if (TLOF) 714 return; 715 716 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; 717 if (Flags & DWARF2_FLAG_BASIC_BLOCK) 718 OS << " basic_block"; 719 if (Flags & DWARF2_FLAG_PROLOGUE_END) 720 OS << " prologue_end"; 721 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) 722 OS << " epilogue_begin"; 723 724 unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); 725 if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { 726 OS << " is_stmt "; 727 728 if (Flags & DWARF2_FLAG_IS_STMT) 729 OS << "1"; 730 else 731 OS << "0"; 732 } 733 734 if (Isa) 735 OS << "isa " << Isa; 736 if (Discriminator) 737 OS << "discriminator " << Discriminator; 738 EmitEOL(); 739} 740 741bool MCAsmStreamer::EmitCFIStartProc() { 742 if (this->MCStreamer::EmitCFIStartProc()) 743 return true; 744 745 OS << ".cfi_startproc"; 746 EmitEOL(); 747 748 return false; 749} 750 751bool MCAsmStreamer::EmitCFIEndProc() { 752 if (this->MCStreamer::EmitCFIEndProc()) 753 return true; 754 755 OS << ".cfi_endproc"; 756 EmitEOL(); 757 758 return false; 759} 760 761bool MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { 762 if (this->MCStreamer::EmitCFIDefCfaOffset(Offset)) 763 return true; 764 765 OS << ".cfi_def_cfa_offset " << Offset; 766 EmitEOL(); 767 768 return false; 769} 770 771bool MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { 772 if (this->MCStreamer::EmitCFIDefCfaRegister(Register)) 773 return true; 774 775 OS << ".cfi_def_cfa_register " << Register; 776 EmitEOL(); 777 778 return false; 779} 780 781bool MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { 782 if (this->MCStreamer::EmitCFIOffset(Register, Offset)) 783 return true; 784 785 OS << ".cfi_offset " << Register << ", " << Offset; 786 EmitEOL(); 787 788 return false; 789} 790 791bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym) { 792 if (this->MCStreamer::EmitCFIPersonality(Sym)) 793 return true; 794 795 OS << ".cfi_personality 0, " << *Sym; 796 EmitEOL(); 797 798 return false; 799} 800 801bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym) { 802 if (this->MCStreamer::EmitCFILsda(Sym)) 803 return true; 804 805 OS << ".cfi_lsda 0, " << *Sym; 806 EmitEOL(); 807 808 return false; 809} 810 811void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { 812 raw_ostream &OS = GetCommentOS(); 813 SmallString<256> Code; 814 SmallVector<MCFixup, 4> Fixups; 815 raw_svector_ostream VecOS(Code); 816 Emitter->EncodeInstruction(Inst, VecOS, Fixups); 817 VecOS.flush(); 818 819 // If we are showing fixups, create symbolic markers in the encoded 820 // representation. We do this by making a per-bit map to the fixup item index, 821 // then trying to display it as nicely as possible. 822 SmallVector<uint8_t, 64> FixupMap; 823 FixupMap.resize(Code.size() * 8); 824 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) 825 FixupMap[i] = 0; 826 827 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 828 MCFixup &F = Fixups[i]; 829 const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); 830 for (unsigned j = 0; j != Info.TargetSize; ++j) { 831 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; 832 assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); 833 FixupMap[Index] = 1 + i; 834 } 835 } 836 837 OS << "encoding: ["; 838 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 839 if (i) 840 OS << ','; 841 842 // See if all bits are the same map entry. 843 uint8_t MapEntry = FixupMap[i * 8 + 0]; 844 for (unsigned j = 1; j != 8; ++j) { 845 if (FixupMap[i * 8 + j] == MapEntry) 846 continue; 847 848 MapEntry = uint8_t(~0U); 849 break; 850 } 851 852 if (MapEntry != uint8_t(~0U)) { 853 if (MapEntry == 0) { 854 OS << format("0x%02x", uint8_t(Code[i])); 855 } else { 856 assert(Code[i] == 0 && "Encoder wrote into fixed up bit!"); 857 OS << char('A' + MapEntry - 1); 858 } 859 } else { 860 // Otherwise, write out in binary. 861 OS << "0b"; 862 for (unsigned j = 8; j--;) { 863 unsigned Bit = (Code[i] >> j) & 1; 864 865 unsigned FixupBit; 866 if (IsLittleEndian) 867 FixupBit = i * 8 + j; 868 else 869 FixupBit = i * 8 + (7-j); 870 871 if (uint8_t MapEntry = FixupMap[FixupBit]) { 872 assert(Bit == 0 && "Encoder wrote into fixed up bit!"); 873 OS << char('A' + MapEntry - 1); 874 } else 875 OS << Bit; 876 } 877 } 878 } 879 OS << "]\n"; 880 881 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 882 MCFixup &F = Fixups[i]; 883 const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); 884 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() 885 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; 886 } 887} 888 889void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { 890 assert(CurSection && "Cannot emit contents before setting section!"); 891 892 if (TLOF) 893 MCLineEntry::Make(this, getCurrentSection()); 894 895 // Show the encoding in a comment if we have a code emitter. 896 if (Emitter) 897 AddEncodingComment(Inst); 898 899 // Show the MCInst if enabled. 900 if (ShowInst) { 901 Inst.dump_pretty(GetCommentOS(), &MAI, InstPrinter.get(), "\n "); 902 GetCommentOS() << "\n"; 903 } 904 905 // If we have an AsmPrinter, use that to print, otherwise print the MCInst. 906 if (InstPrinter) 907 InstPrinter->printInst(&Inst, OS); 908 else 909 Inst.print(OS, &MAI); 910 EmitEOL(); 911} 912 913/// EmitRawText - If this file is backed by an assembly streamer, this dumps 914/// the specified string in the output .s file. This capability is 915/// indicated by the hasRawTextSupport() predicate. 916void MCAsmStreamer::EmitRawText(StringRef String) { 917 if (!String.empty() && String.back() == '\n') 918 String = String.substr(0, String.size()-1); 919 OS << String; 920 EmitEOL(); 921} 922 923void MCAsmStreamer::Finish() { 924 // Dump out the dwarf file & directory tables and line tables. 925 if (getContext().hasDwarfFiles() && TLOF) 926 MCDwarfFileTable::Emit(this, TLOF->getDwarfLineSection()); 927} 928 929MCStreamer *llvm::createAsmStreamer(MCContext &Context, 930 formatted_raw_ostream &OS, 931 bool isLittleEndian, 932 bool isVerboseAsm, MCInstPrinter *IP, 933 MCCodeEmitter *CE, bool ShowInst) { 934 return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, 935 NULL, 0, IP, CE, ShowInst); 936} 937 938 939MCStreamer *llvm::createAsmStreamerNoLoc(MCContext &Context, 940 formatted_raw_ostream &OS, 941 bool isLittleEndian, 942 bool isVerboseAsm, 943 const TargetLoweringObjectFile *TLOF, 944 int PointerSize, 945 MCInstPrinter *IP, 946 MCCodeEmitter *CE, bool ShowInst) { 947 return new MCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm, 948 TLOF, PointerSize, IP, CE, ShowInst); 949} 950