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