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