1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===// 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/ADT/STLExtras.h" 11 #include "llvm/ADT/SmallString.h" 12 #include "llvm/ADT/StringExtras.h" 13 #include "llvm/ADT/Twine.h" 14 #include "llvm/MC/MCAsmBackend.h" 15 #include "llvm/MC/MCAsmInfo.h" 16 #include "llvm/MC/MCCodeEmitter.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCFixupKindInfo.h" 20 #include "llvm/MC/MCInst.h" 21 #include "llvm/MC/MCInstPrinter.h" 22 #include "llvm/MC/MCObjectFileInfo.h" 23 #include "llvm/MC/MCRegisterInfo.h" 24 #include "llvm/MC/MCSectionCOFF.h" 25 #include "llvm/MC/MCSectionMachO.h" 26 #include "llvm/MC/MCStreamer.h" 27 #include "llvm/MC/MCSymbolELF.h" 28 #include "llvm/Support/ErrorHandling.h" 29 #include "llvm/Support/Format.h" 30 #include "llvm/Support/FormattedStream.h" 31 #include "llvm/Support/LEB128.h" 32 #include "llvm/Support/MathExtras.h" 33 #include "llvm/Support/Path.h" 34 #include "llvm/Support/SourceMgr.h" 35 #include <cctype> 36 37 using namespace llvm; 38 39 namespace { 40 41 class MCAsmStreamer final : public MCStreamer { 42 std::unique_ptr<formatted_raw_ostream> OSOwner; 43 formatted_raw_ostream &OS; 44 const MCAsmInfo *MAI; 45 std::unique_ptr<MCInstPrinter> InstPrinter; 46 std::unique_ptr<MCCodeEmitter> Emitter; 47 std::unique_ptr<MCAsmBackend> AsmBackend; 48 49 SmallString<128> ExplicitCommentToEmit; 50 SmallString<128> CommentToEmit; 51 raw_svector_ostream CommentStream; 52 53 unsigned IsVerboseAsm : 1; 54 unsigned ShowInst : 1; 55 unsigned UseDwarfDirectory : 1; 56 57 void EmitRegisterName(int64_t Register); 58 void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; 59 void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; 60 61 public: 62 MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os, 63 bool isVerboseAsm, bool useDwarfDirectory, 64 MCInstPrinter *printer, MCCodeEmitter *emitter, 65 MCAsmBackend *asmbackend, bool showInst) 66 : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner), 67 MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter), 68 AsmBackend(asmbackend), CommentStream(CommentToEmit), 69 IsVerboseAsm(isVerboseAsm), ShowInst(showInst), 70 UseDwarfDirectory(useDwarfDirectory) { 71 assert(InstPrinter); 72 if (IsVerboseAsm) 73 InstPrinter->setCommentStream(CommentStream); 74 } 75 76 inline void EmitEOL() { 77 // Dump Explicit Comments here. 78 emitExplicitComments(); 79 // If we don't have any comments, just emit a \n. 80 if (!IsVerboseAsm) { 81 OS << '\n'; 82 return; 83 } 84 EmitCommentsAndEOL(); 85 } 86 87 void EmitSyntaxDirective() override; 88 89 void EmitCommentsAndEOL(); 90 91 /// isVerboseAsm - Return true if this streamer supports verbose assembly at 92 /// all. 93 bool isVerboseAsm() const override { return IsVerboseAsm; } 94 95 /// hasRawTextSupport - We support EmitRawText. 96 bool hasRawTextSupport() const override { return true; } 97 98 /// AddComment - Add a comment that can be emitted to the generated .s 99 /// file if applicable as a QoI issue to make the output of the compiler 100 /// more readable. This only affects the MCAsmStreamer, and only when 101 /// verbose assembly output is enabled. 102 void AddComment(const Twine &T) override; 103 104 /// AddEncodingComment - Add a comment showing the encoding of an instruction. 105 void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); 106 107 /// GetCommentOS - Return a raw_ostream that comments can be written to. 108 /// Unlike AddComment, you are required to terminate comments with \n if you 109 /// use this method. 110 raw_ostream &GetCommentOS() override { 111 if (!IsVerboseAsm) 112 return nulls(); // Discard comments unless in verbose asm mode. 113 return CommentStream; 114 } 115 116 void emitRawComment(const Twine &T, bool TabPrefix = true) override; 117 118 void addExplicitComment(const Twine &T) override; 119 void emitExplicitComments() override; 120 121 /// AddBlankLine - Emit a blank line to a .s file to pretty it up. 122 void AddBlankLine() override { 123 EmitEOL(); 124 } 125 126 /// @name MCStreamer Interface 127 /// @{ 128 129 void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; 130 131 void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; 132 void EmitLabel(MCSymbol *Symbol) override; 133 134 void EmitAssemblerFlag(MCAssemblerFlag Flag) override; 135 void EmitLinkerOptions(ArrayRef<std::string> Options) override; 136 void EmitDataRegion(MCDataRegionType Kind) override; 137 void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, 138 unsigned Update) override; 139 void EmitThumbFunc(MCSymbol *Func) override; 140 141 void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; 142 void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; 143 bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; 144 145 void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; 146 void BeginCOFFSymbolDef(const MCSymbol *Symbol) override; 147 void EmitCOFFSymbolStorageClass(int StorageClass) override; 148 void EmitCOFFSymbolType(int Type) override; 149 void EndCOFFSymbolDef() override; 150 void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; 151 void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; 152 void EmitCOFFSecRel32(MCSymbol const *Symbol) override; 153 void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override; 154 void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 155 unsigned ByteAlignment) override; 156 157 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 158 /// 159 /// @param Symbol - The common symbol to emit. 160 /// @param Size - The size of the common symbol. 161 /// @param ByteAlignment - The alignment of the common symbol in bytes. 162 void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 163 unsigned ByteAlignment) override; 164 165 void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, 166 uint64_t Size = 0, unsigned ByteAlignment = 0) override; 167 168 void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, 169 unsigned ByteAlignment = 0) override; 170 171 void EmitBinaryData(StringRef Data) override; 172 173 void EmitBytes(StringRef Data) override; 174 175 void EmitValueImpl(const MCExpr *Value, unsigned Size, 176 SMLoc Loc = SMLoc()) override; 177 void EmitIntValue(uint64_t Value, unsigned Size) override; 178 179 void EmitULEB128Value(const MCExpr *Value) override; 180 181 void EmitSLEB128Value(const MCExpr *Value) override; 182 183 void EmitGPRel64Value(const MCExpr *Value) override; 184 185 void EmitGPRel32Value(const MCExpr *Value) override; 186 187 188 void emitFill(uint64_t NumBytes, uint8_t FillValue) override; 189 190 void emitFill(const MCExpr &NumBytes, uint64_t FillValue, 191 SMLoc Loc = SMLoc()) override; 192 193 void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) override; 194 195 void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, 196 SMLoc Loc = SMLoc()) override; 197 198 void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, 199 unsigned ValueSize = 1, 200 unsigned MaxBytesToEmit = 0) override; 201 202 void EmitCodeAlignment(unsigned ByteAlignment, 203 unsigned MaxBytesToEmit = 0) override; 204 205 void emitValueToOffset(const MCExpr *Offset, 206 unsigned char Value = 0) override; 207 208 void EmitFileDirective(StringRef Filename) override; 209 unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, 210 StringRef Filename, 211 unsigned CUID = 0) override; 212 void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 213 unsigned Column, unsigned Flags, 214 unsigned Isa, unsigned Discriminator, 215 StringRef FileName) override; 216 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; 217 218 unsigned EmitCVFileDirective(unsigned FileNo, StringRef Filename) override; 219 void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, 220 unsigned Column, bool PrologueEnd, bool IsStmt, 221 StringRef FileName) override; 222 void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, 223 const MCSymbol *FnEnd) override; 224 void EmitCVInlineLinetableDirective( 225 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, 226 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, 227 ArrayRef<unsigned> SecondaryFunctionIds) override; 228 void EmitCVDefRangeDirective( 229 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 230 StringRef FixedSizePortion) override; 231 void EmitCVStringTableDirective() override; 232 void EmitCVFileChecksumsDirective() override; 233 234 void EmitIdent(StringRef IdentString) override; 235 void EmitCFISections(bool EH, bool Debug) override; 236 void EmitCFIDefCfa(int64_t Register, int64_t Offset) override; 237 void EmitCFIDefCfaOffset(int64_t Offset) override; 238 void EmitCFIDefCfaRegister(int64_t Register) override; 239 void EmitCFIOffset(int64_t Register, int64_t Offset) override; 240 void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; 241 void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; 242 void EmitCFIRememberState() override; 243 void EmitCFIRestoreState() override; 244 void EmitCFISameValue(int64_t Register) override; 245 void EmitCFIRelOffset(int64_t Register, int64_t Offset) override; 246 void EmitCFIAdjustCfaOffset(int64_t Adjustment) override; 247 void EmitCFIEscape(StringRef Values) override; 248 void EmitCFIGnuArgsSize(int64_t Size) override; 249 void EmitCFISignalFrame() override; 250 void EmitCFIUndefined(int64_t Register) override; 251 void EmitCFIRegister(int64_t Register1, int64_t Register2) override; 252 void EmitCFIWindowSave() override; 253 254 void EmitWinCFIStartProc(const MCSymbol *Symbol) override; 255 void EmitWinCFIEndProc() override; 256 void EmitWinCFIStartChained() override; 257 void EmitWinCFIEndChained() override; 258 void EmitWinCFIPushReg(unsigned Register) override; 259 void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override; 260 void EmitWinCFIAllocStack(unsigned Size) override; 261 void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override; 262 void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override; 263 void EmitWinCFIPushFrame(bool Code) override; 264 void EmitWinCFIEndProlog() override; 265 266 void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override; 267 void EmitWinEHHandlerData() override; 268 269 void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; 270 271 void EmitBundleAlignMode(unsigned AlignPow2) override; 272 void EmitBundleLock(bool AlignToEnd) override; 273 void EmitBundleUnlock() override; 274 275 bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, 276 const MCExpr *Expr, SMLoc Loc) override; 277 278 /// EmitRawText - If this file is backed by an assembly streamer, this dumps 279 /// the specified string in the output .s file. This capability is 280 /// indicated by the hasRawTextSupport() predicate. 281 void EmitRawTextImpl(StringRef String) override; 282 283 void FinishImpl() override; 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. 292 void MCAsmStreamer::AddComment(const Twine &T) { 293 if (!IsVerboseAsm) return; 294 295 T.toVector(CommentToEmit); 296 // Each comment goes on its own line. 297 CommentToEmit.push_back('\n'); 298 } 299 300 void MCAsmStreamer::EmitCommentsAndEOL() { 301 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { 302 OS << '\n'; 303 return; 304 } 305 306 StringRef Comments = CommentToEmit; 307 308 assert(Comments.back() == '\n' && 309 "Comment array not newline terminated"); 310 do { 311 // Emit a line of comments. 312 OS.PadToColumn(MAI->getCommentColumn()); 313 size_t Position = Comments.find('\n'); 314 OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n'; 315 316 Comments = Comments.substr(Position+1); 317 } while (!Comments.empty()); 318 319 CommentToEmit.clear(); 320 } 321 322 static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 323 assert(Bytes > 0 && Bytes <= 8 && "Invalid size!"); 324 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 325 } 326 327 void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { 328 if (TabPrefix) 329 OS << '\t'; 330 OS << MAI->getCommentString() << T; 331 EmitEOL(); 332 } 333 334 void MCAsmStreamer::addExplicitComment(const Twine &T) { 335 StringRef c = T.getSingleStringRef(); 336 if (c.equals(StringRef(MAI->getSeparatorString()))) 337 return; 338 if (c.startswith(StringRef("//"))) { 339 ExplicitCommentToEmit.append("\t"); 340 ExplicitCommentToEmit.append(MAI->getCommentString()); 341 // drop // 342 ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); 343 } else if (c.startswith(StringRef("/*"))) { 344 size_t p = 2, len = c.size() - 2; 345 // emit each line in comment as separate newline. 346 do { 347 size_t newp = std::min(len, c.find_first_of("\r\n", p)); 348 ExplicitCommentToEmit.append("\t"); 349 ExplicitCommentToEmit.append(MAI->getCommentString()); 350 ExplicitCommentToEmit.append(c.slice(p, newp).str()); 351 // If we have another line in this comment add line 352 if (newp < len) 353 ExplicitCommentToEmit.append("\n"); 354 p = newp + 1; 355 } while (p < len); 356 } else if (c.startswith(StringRef(MAI->getCommentString()))) { 357 ExplicitCommentToEmit.append("\t"); 358 ExplicitCommentToEmit.append(c.str()); 359 } else if (c.front() == '#') { 360 // # are comments for ## commentString. Output extra #. 361 ExplicitCommentToEmit.append("\t#"); 362 ExplicitCommentToEmit.append(c.str()); 363 } else 364 assert(false && "Unexpected Assembly Comment"); 365 // full line comments immediately output 366 if (c.back() == '\n') 367 emitExplicitComments(); 368 } 369 370 void MCAsmStreamer::emitExplicitComments() { 371 StringRef Comments = ExplicitCommentToEmit; 372 if (!Comments.empty()) 373 OS << Comments; 374 ExplicitCommentToEmit.clear(); 375 } 376 377 void MCAsmStreamer::ChangeSection(MCSection *Section, 378 const MCExpr *Subsection) { 379 assert(Section && "Cannot switch to a null section!"); 380 Section->PrintSwitchToSection(*MAI, OS, Subsection); 381 } 382 383 void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) { 384 assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); 385 MCStreamer::EmitLabel(Symbol); 386 387 Symbol->print(OS, MAI); 388 OS << MAI->getLabelSuffix(); 389 390 EmitEOL(); 391 } 392 393 void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { 394 StringRef str = MCLOHIdToName(Kind); 395 396 #ifndef NDEBUG 397 int NbArgs = MCLOHIdToNbArgs(Kind); 398 assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!"); 399 assert(str != "" && "Invalid LOH name"); 400 #endif 401 402 OS << "\t" << MCLOHDirectiveName() << " " << str << "\t"; 403 bool IsFirst = true; 404 for (const MCSymbol *Arg : Args) { 405 if (!IsFirst) 406 OS << ", "; 407 IsFirst = false; 408 Arg->print(OS, MAI); 409 } 410 EmitEOL(); 411 } 412 413 void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { 414 switch (Flag) { 415 case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; 416 case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 417 case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break; 418 case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break; 419 case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break; 420 } 421 EmitEOL(); 422 } 423 424 void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) { 425 assert(!Options.empty() && "At least one option is required!"); 426 OS << "\t.linker_option \"" << Options[0] << '"'; 427 for (ArrayRef<std::string>::iterator it = Options.begin() + 1, 428 ie = Options.end(); it != ie; ++it) { 429 OS << ", " << '"' << *it << '"'; 430 } 431 OS << "\n"; 432 } 433 434 void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) { 435 if (!MAI->doesSupportDataRegionDirectives()) 436 return; 437 switch (Kind) { 438 case MCDR_DataRegion: OS << "\t.data_region"; break; 439 case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break; 440 case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break; 441 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break; 442 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break; 443 } 444 EmitEOL(); 445 } 446 447 void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major, 448 unsigned Minor, unsigned Update) { 449 switch (Kind) { 450 case MCVM_WatchOSVersionMin: OS << "\t.watchos_version_min"; break; 451 case MCVM_TvOSVersionMin: OS << "\t.tvos_version_min"; break; 452 case MCVM_IOSVersionMin: OS << "\t.ios_version_min"; break; 453 case MCVM_OSXVersionMin: OS << "\t.macosx_version_min"; break; 454 } 455 OS << " " << Major << ", " << Minor; 456 if (Update) 457 OS << ", " << Update; 458 EmitEOL(); 459 } 460 461 void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) { 462 // This needs to emit to a temporary string to get properly quoted 463 // MCSymbols when they have spaces in them. 464 OS << "\t.thumb_func"; 465 // Only Mach-O hasSubsectionsViaSymbols() 466 if (MAI->hasSubsectionsViaSymbols()) { 467 OS << '\t'; 468 Func->print(OS, MAI); 469 } 470 EmitEOL(); 471 } 472 473 void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 474 Symbol->print(OS, MAI); 475 OS << " = "; 476 Value->print(OS, MAI); 477 478 EmitEOL(); 479 480 MCStreamer::EmitAssignment(Symbol, Value); 481 } 482 483 void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { 484 OS << ".weakref "; 485 Alias->print(OS, MAI); 486 OS << ", "; 487 Symbol->print(OS, MAI); 488 EmitEOL(); 489 } 490 491 bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, 492 MCSymbolAttr Attribute) { 493 switch (Attribute) { 494 case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute"); 495 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function 496 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC 497 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object 498 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object 499 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common 500 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype 501 case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object 502 if (!MAI->hasDotTypeDotSizeDirective()) 503 return false; // Symbol attribute not supported 504 OS << "\t.type\t"; 505 Symbol->print(OS, MAI); 506 OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%'); 507 switch (Attribute) { 508 default: return false; 509 case MCSA_ELF_TypeFunction: OS << "function"; break; 510 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; 511 case MCSA_ELF_TypeObject: OS << "object"; break; 512 case MCSA_ELF_TypeTLS: OS << "tls_object"; break; 513 case MCSA_ELF_TypeCommon: OS << "common"; break; 514 case MCSA_ELF_TypeNoType: OS << "no_type"; break; 515 case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; 516 } 517 EmitEOL(); 518 return true; 519 case MCSA_Global: // .globl/.global 520 OS << MAI->getGlobalDirective(); 521 break; 522 case MCSA_Hidden: OS << "\t.hidden\t"; break; 523 case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; 524 case MCSA_Internal: OS << "\t.internal\t"; break; 525 case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; 526 case MCSA_Local: OS << "\t.local\t"; break; 527 case MCSA_NoDeadStrip: 528 if (!MAI->hasNoDeadStrip()) 529 return false; 530 OS << "\t.no_dead_strip\t"; 531 break; 532 case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; 533 case MCSA_AltEntry: OS << "\t.alt_entry\t"; break; 534 case MCSA_PrivateExtern: 535 OS << "\t.private_extern\t"; 536 break; 537 case MCSA_Protected: OS << "\t.protected\t"; break; 538 case MCSA_Reference: OS << "\t.reference\t"; break; 539 case MCSA_Weak: OS << MAI->getWeakDirective(); break; 540 case MCSA_WeakDefinition: 541 OS << "\t.weak_definition\t"; 542 break; 543 // .weak_reference 544 case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; 545 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; 546 } 547 548 Symbol->print(OS, MAI); 549 EmitEOL(); 550 551 return true; 552 } 553 554 void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 555 OS << ".desc" << ' '; 556 Symbol->print(OS, MAI); 557 OS << ',' << DescValue; 558 EmitEOL(); 559 } 560 561 void MCAsmStreamer::EmitSyntaxDirective() { 562 if (MAI->getAssemblerDialect() == 1) { 563 OS << "\t.intel_syntax noprefix"; 564 EmitEOL(); 565 } 566 // FIXME: Currently emit unprefix'ed registers. 567 // The intel_syntax directive has one optional argument 568 // with may have a value of prefix or noprefix. 569 } 570 571 void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { 572 OS << "\t.def\t "; 573 Symbol->print(OS, MAI); 574 OS << ';'; 575 EmitEOL(); 576 } 577 578 void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) { 579 OS << "\t.scl\t" << StorageClass << ';'; 580 EmitEOL(); 581 } 582 583 void MCAsmStreamer::EmitCOFFSymbolType (int Type) { 584 OS << "\t.type\t" << Type << ';'; 585 EmitEOL(); 586 } 587 588 void MCAsmStreamer::EndCOFFSymbolDef() { 589 OS << "\t.endef"; 590 EmitEOL(); 591 } 592 593 void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { 594 OS << "\t.safeseh\t"; 595 Symbol->print(OS, MAI); 596 EmitEOL(); 597 } 598 599 void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { 600 OS << "\t.secidx\t"; 601 Symbol->print(OS, MAI); 602 EmitEOL(); 603 } 604 605 void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { 606 OS << "\t.secrel32\t"; 607 Symbol->print(OS, MAI); 608 EmitEOL(); 609 } 610 611 void MCAsmStreamer::emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) { 612 assert(MAI->hasDotTypeDotSizeDirective()); 613 OS << "\t.size\t"; 614 Symbol->print(OS, MAI); 615 OS << ", "; 616 Value->print(OS, MAI); 617 OS << '\n'; 618 } 619 620 void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 621 unsigned ByteAlignment) { 622 OS << "\t.comm\t"; 623 Symbol->print(OS, MAI); 624 OS << ',' << Size; 625 626 if (ByteAlignment != 0) { 627 if (MAI->getCOMMDirectiveAlignmentIsInBytes()) 628 OS << ',' << ByteAlignment; 629 else 630 OS << ',' << Log2_32(ByteAlignment); 631 } 632 EmitEOL(); 633 } 634 635 /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. 636 /// 637 /// @param Symbol - The common symbol to emit. 638 /// @param Size - The size of the common symbol. 639 void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 640 unsigned ByteAlign) { 641 OS << "\t.lcomm\t"; 642 Symbol->print(OS, MAI); 643 OS << ',' << Size; 644 645 if (ByteAlign > 1) { 646 switch (MAI->getLCOMMDirectiveAlignmentType()) { 647 case LCOMM::NoAlignment: 648 llvm_unreachable("alignment not supported on .lcomm!"); 649 case LCOMM::ByteAlignment: 650 OS << ',' << ByteAlign; 651 break; 652 case LCOMM::Log2Alignment: 653 assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2"); 654 OS << ',' << Log2_32(ByteAlign); 655 break; 656 } 657 } 658 EmitEOL(); 659 } 660 661 void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, 662 uint64_t Size, unsigned ByteAlignment) { 663 if (Symbol) 664 AssignFragment(Symbol, &Section->getDummyFragment()); 665 666 // Note: a .zerofill directive does not switch sections. 667 OS << ".zerofill "; 668 669 // This is a mach-o specific directive. 670 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 671 OS << MOSection->getSegmentName() << "," << MOSection->getSectionName(); 672 673 if (Symbol) { 674 OS << ','; 675 Symbol->print(OS, MAI); 676 OS << ',' << Size; 677 if (ByteAlignment != 0) 678 OS << ',' << Log2_32(ByteAlignment); 679 } 680 EmitEOL(); 681 } 682 683 // .tbss sym, size, align 684 // This depends that the symbol has already been mangled from the original, 685 // e.g. _a. 686 void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 687 uint64_t Size, unsigned ByteAlignment) { 688 AssignFragment(Symbol, &Section->getDummyFragment()); 689 690 assert(Symbol && "Symbol shouldn't be NULL!"); 691 // Instead of using the Section we'll just use the shortcut. 692 // This is a mach-o specific directive and section. 693 OS << ".tbss "; 694 Symbol->print(OS, MAI); 695 OS << ", " << Size; 696 697 // Output align if we have it. We default to 1 so don't bother printing 698 // that. 699 if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment); 700 701 EmitEOL(); 702 } 703 704 static inline char toOctal(int X) { return (X&7)+'0'; } 705 706 static void PrintQuotedString(StringRef Data, raw_ostream &OS) { 707 OS << '"'; 708 709 for (unsigned i = 0, e = Data.size(); i != e; ++i) { 710 unsigned char C = Data[i]; 711 if (C == '"' || C == '\\') { 712 OS << '\\' << (char)C; 713 continue; 714 } 715 716 if (isprint((unsigned char)C)) { 717 OS << (char)C; 718 continue; 719 } 720 721 switch (C) { 722 case '\b': OS << "\\b"; break; 723 case '\f': OS << "\\f"; break; 724 case '\n': OS << "\\n"; break; 725 case '\r': OS << "\\r"; break; 726 case '\t': OS << "\\t"; break; 727 default: 728 OS << '\\'; 729 OS << toOctal(C >> 6); 730 OS << toOctal(C >> 3); 731 OS << toOctal(C >> 0); 732 break; 733 } 734 } 735 736 OS << '"'; 737 } 738 739 void MCAsmStreamer::EmitBytes(StringRef Data) { 740 assert(getCurrentSection().first && 741 "Cannot emit contents before setting section!"); 742 if (Data.empty()) return; 743 744 if (Data.size() == 1) { 745 OS << MAI->getData8bitsDirective(); 746 OS << (unsigned)(unsigned char)Data[0]; 747 EmitEOL(); 748 return; 749 } 750 751 // If the data ends with 0 and the target supports .asciz, use it, otherwise 752 // use .ascii 753 if (MAI->getAscizDirective() && Data.back() == 0) { 754 OS << MAI->getAscizDirective(); 755 Data = Data.substr(0, Data.size()-1); 756 } else { 757 OS << MAI->getAsciiDirective(); 758 } 759 760 PrintQuotedString(Data, OS); 761 EmitEOL(); 762 } 763 764 void MCAsmStreamer::EmitBinaryData(StringRef Data) { 765 // This is binary data. Print it in a grid of hex bytes for readability. 766 const size_t Cols = 4; 767 for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) { 768 size_t J = I, EJ = std::min(I + Cols, Data.size()); 769 assert(EJ > 0); 770 OS << MAI->getData8bitsDirective(); 771 for (; J < EJ - 1; ++J) 772 OS << format("0x%02x", uint8_t(Data[J])) << ", "; 773 OS << format("0x%02x", uint8_t(Data[J])); 774 EmitEOL(); 775 } 776 } 777 778 void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) { 779 EmitValue(MCConstantExpr::create(Value, getContext()), Size); 780 } 781 782 void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, 783 SMLoc Loc) { 784 assert(Size <= 8 && "Invalid size"); 785 assert(getCurrentSection().first && 786 "Cannot emit contents before setting section!"); 787 const char *Directive = nullptr; 788 switch (Size) { 789 default: break; 790 case 1: Directive = MAI->getData8bitsDirective(); break; 791 case 2: Directive = MAI->getData16bitsDirective(); break; 792 case 4: Directive = MAI->getData32bitsDirective(); break; 793 case 8: Directive = MAI->getData64bitsDirective(); break; 794 } 795 796 if (!Directive) { 797 int64_t IntValue; 798 if (!Value->evaluateAsAbsolute(IntValue)) 799 report_fatal_error("Don't know how to emit this value."); 800 801 // We couldn't handle the requested integer size so we fallback by breaking 802 // the request down into several, smaller, integers. 803 // Since sizes greater or equal to "Size" are invalid, we use the greatest 804 // power of 2 that is less than "Size" as our largest piece of granularity. 805 bool IsLittleEndian = MAI->isLittleEndian(); 806 for (unsigned Emitted = 0; Emitted != Size;) { 807 unsigned Remaining = Size - Emitted; 808 // The size of our partial emission must be a power of two less than 809 // Size. 810 unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1)); 811 // Calculate the byte offset of our partial emission taking into account 812 // the endianness of the target. 813 unsigned ByteOffset = 814 IsLittleEndian ? Emitted : (Remaining - EmissionSize); 815 uint64_t ValueToEmit = IntValue >> (ByteOffset * 8); 816 // We truncate our partial emission to fit within the bounds of the 817 // emission domain. This produces nicer output and silences potential 818 // truncation warnings when round tripping through another assembler. 819 uint64_t Shift = 64 - EmissionSize * 8; 820 assert(Shift < static_cast<uint64_t>( 821 std::numeric_limits<unsigned long long>::digits) && 822 "undefined behavior"); 823 ValueToEmit &= ~0ULL >> Shift; 824 EmitIntValue(ValueToEmit, EmissionSize); 825 Emitted += EmissionSize; 826 } 827 return; 828 } 829 830 assert(Directive && "Invalid size for machine code value!"); 831 OS << Directive; 832 Value->print(OS, MAI); 833 EmitEOL(); 834 } 835 836 void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { 837 int64_t IntValue; 838 if (Value->evaluateAsAbsolute(IntValue)) { 839 EmitULEB128IntValue(IntValue); 840 return; 841 } 842 OS << ".uleb128 "; 843 Value->print(OS, MAI); 844 EmitEOL(); 845 } 846 847 void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { 848 int64_t IntValue; 849 if (Value->evaluateAsAbsolute(IntValue)) { 850 EmitSLEB128IntValue(IntValue); 851 return; 852 } 853 OS << ".sleb128 "; 854 Value->print(OS, MAI); 855 EmitEOL(); 856 } 857 858 void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) { 859 assert(MAI->getGPRel64Directive() != nullptr); 860 OS << MAI->getGPRel64Directive(); 861 Value->print(OS, MAI); 862 EmitEOL(); 863 } 864 865 void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { 866 assert(MAI->getGPRel32Directive() != nullptr); 867 OS << MAI->getGPRel32Directive(); 868 Value->print(OS, MAI); 869 EmitEOL(); 870 } 871 872 /// emitFill - Emit NumBytes bytes worth of the value specified by 873 /// FillValue. This implements directives such as '.space'. 874 void MCAsmStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { 875 if (NumBytes == 0) return; 876 877 const MCExpr *E = MCConstantExpr::create(NumBytes, getContext()); 878 emitFill(*E, FillValue); 879 } 880 881 void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, 882 SMLoc Loc) { 883 if (const char *ZeroDirective = MAI->getZeroDirective()) { 884 // FIXME: Emit location directives 885 OS << ZeroDirective; 886 NumBytes.print(OS, MAI); 887 if (FillValue != 0) 888 OS << ',' << (int)FillValue; 889 EmitEOL(); 890 return; 891 } 892 893 MCStreamer::emitFill(NumBytes, FillValue); 894 } 895 896 void MCAsmStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) { 897 if (NumValues == 0) 898 return; 899 900 const MCExpr *E = MCConstantExpr::create(NumValues, getContext()); 901 emitFill(*E, Size, Expr); 902 } 903 904 void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size, 905 int64_t Expr, SMLoc Loc) { 906 // FIXME: Emit location directives 907 OS << "\t.fill\t"; 908 NumValues.print(OS, MAI); 909 OS << ", " << Size << ", 0x"; 910 OS.write_hex(truncateToSize(Expr, 4)); 911 EmitEOL(); 912 } 913 914 void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, 915 unsigned ValueSize, 916 unsigned MaxBytesToEmit) { 917 // Some assemblers don't support non-power of two alignments, so we always 918 // emit alignments as a power of two if possible. 919 if (isPowerOf2_32(ByteAlignment)) { 920 switch (ValueSize) { 921 default: 922 llvm_unreachable("Invalid size for machine code value!"); 923 case 1: 924 OS << "\t.p2align\t"; 925 break; 926 case 2: 927 OS << ".p2alignw "; 928 break; 929 case 4: 930 OS << ".p2alignl "; 931 break; 932 case 8: 933 llvm_unreachable("Unsupported alignment size!"); 934 } 935 936 OS << Log2_32(ByteAlignment); 937 938 if (Value || MaxBytesToEmit) { 939 OS << ", 0x"; 940 OS.write_hex(truncateToSize(Value, ValueSize)); 941 942 if (MaxBytesToEmit) 943 OS << ", " << MaxBytesToEmit; 944 } 945 EmitEOL(); 946 return; 947 } 948 949 // Non-power of two alignment. This is not widely supported by assemblers. 950 // FIXME: Parameterize this based on MAI. 951 switch (ValueSize) { 952 default: llvm_unreachable("Invalid size for machine code value!"); 953 case 1: OS << ".balign"; break; 954 case 2: OS << ".balignw"; break; 955 case 4: OS << ".balignl"; break; 956 case 8: llvm_unreachable("Unsupported alignment size!"); 957 } 958 959 OS << ' ' << ByteAlignment; 960 OS << ", " << truncateToSize(Value, ValueSize); 961 if (MaxBytesToEmit) 962 OS << ", " << MaxBytesToEmit; 963 EmitEOL(); 964 } 965 966 void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, 967 unsigned MaxBytesToEmit) { 968 // Emit with a text fill value. 969 EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(), 970 1, MaxBytesToEmit); 971 } 972 973 void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, 974 unsigned char Value) { 975 // FIXME: Verify that Offset is associated with the current section. 976 OS << ".org "; 977 Offset->print(OS, MAI); 978 OS << ", " << (unsigned)Value; 979 EmitEOL(); 980 } 981 982 void MCAsmStreamer::EmitFileDirective(StringRef Filename) { 983 assert(MAI->hasSingleParameterDotFile()); 984 OS << "\t.file\t"; 985 PrintQuotedString(Filename, OS); 986 EmitEOL(); 987 } 988 989 unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo, 990 StringRef Directory, 991 StringRef Filename, 992 unsigned CUID) { 993 assert(CUID == 0); 994 995 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); 996 unsigned NumFiles = Table.getMCDwarfFiles().size(); 997 FileNo = Table.getFile(Directory, Filename, FileNo); 998 if (FileNo == 0) 999 return 0; 1000 if (NumFiles == Table.getMCDwarfFiles().size()) 1001 return FileNo; 1002 1003 SmallString<128> FullPathName; 1004 1005 if (!UseDwarfDirectory && !Directory.empty()) { 1006 if (sys::path::is_absolute(Filename)) 1007 Directory = ""; 1008 else { 1009 FullPathName = Directory; 1010 sys::path::append(FullPathName, Filename); 1011 Directory = ""; 1012 Filename = FullPathName; 1013 } 1014 } 1015 1016 OS << "\t.file\t" << FileNo << ' '; 1017 if (!Directory.empty()) { 1018 PrintQuotedString(Directory, OS); 1019 OS << ' '; 1020 } 1021 PrintQuotedString(Filename, OS); 1022 EmitEOL(); 1023 1024 return FileNo; 1025 } 1026 1027 void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 1028 unsigned Column, unsigned Flags, 1029 unsigned Isa, 1030 unsigned Discriminator, 1031 StringRef FileName) { 1032 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; 1033 if (Flags & DWARF2_FLAG_BASIC_BLOCK) 1034 OS << " basic_block"; 1035 if (Flags & DWARF2_FLAG_PROLOGUE_END) 1036 OS << " prologue_end"; 1037 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) 1038 OS << " epilogue_begin"; 1039 1040 unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); 1041 if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { 1042 OS << " is_stmt "; 1043 1044 if (Flags & DWARF2_FLAG_IS_STMT) 1045 OS << "1"; 1046 else 1047 OS << "0"; 1048 } 1049 1050 if (Isa) 1051 OS << " isa " << Isa; 1052 if (Discriminator) 1053 OS << " discriminator " << Discriminator; 1054 1055 if (IsVerboseAsm) { 1056 OS.PadToColumn(MAI->getCommentColumn()); 1057 OS << MAI->getCommentString() << ' ' << FileName << ':' 1058 << Line << ':' << Column; 1059 } 1060 EmitEOL(); 1061 this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, 1062 Isa, Discriminator, FileName); 1063 } 1064 1065 MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { 1066 // Always use the zeroth line table, since asm syntax only supports one line 1067 // table for now. 1068 return MCStreamer::getDwarfLineTableSymbol(0); 1069 } 1070 1071 unsigned MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, 1072 StringRef Filename) { 1073 if (!getContext().getCVFile(Filename, FileNo)) 1074 return 0; 1075 1076 OS << "\t.cv_file\t" << FileNo << ' '; 1077 1078 PrintQuotedString(Filename, OS); 1079 EmitEOL(); 1080 1081 return FileNo; 1082 } 1083 1084 void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, 1085 unsigned Line, unsigned Column, 1086 bool PrologueEnd, bool IsStmt, 1087 StringRef FileName) { 1088 OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " " 1089 << Column; 1090 if (PrologueEnd) 1091 OS << " prologue_end"; 1092 1093 unsigned OldIsStmt = getContext().getCurrentCVLoc().isStmt(); 1094 if (IsStmt != OldIsStmt) { 1095 OS << " is_stmt "; 1096 1097 if (IsStmt) 1098 OS << "1"; 1099 else 1100 OS << "0"; 1101 } 1102 1103 if (IsVerboseAsm) { 1104 OS.PadToColumn(MAI->getCommentColumn()); 1105 OS << MAI->getCommentString() << ' ' << FileName << ':' 1106 << Line << ':' << Column; 1107 } 1108 EmitEOL(); 1109 this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column, 1110 PrologueEnd, IsStmt, FileName); 1111 } 1112 1113 void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId, 1114 const MCSymbol *FnStart, 1115 const MCSymbol *FnEnd) { 1116 OS << "\t.cv_linetable\t" << FunctionId << ", "; 1117 FnStart->print(OS, MAI); 1118 OS << ", "; 1119 FnEnd->print(OS, MAI); 1120 EmitEOL(); 1121 this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd); 1122 } 1123 1124 void MCAsmStreamer::EmitCVInlineLinetableDirective( 1125 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum, 1126 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym, 1127 ArrayRef<unsigned> SecondaryFunctionIds) { 1128 OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId 1129 << ' ' << SourceLineNum << ' '; 1130 FnStartSym->print(OS, MAI); 1131 OS << ' '; 1132 FnEndSym->print(OS, MAI); 1133 if (!SecondaryFunctionIds.empty()) { 1134 OS << " contains"; 1135 for (unsigned SecondaryFunctionId : SecondaryFunctionIds) 1136 OS << ' ' << SecondaryFunctionId; 1137 } 1138 EmitEOL(); 1139 this->MCStreamer::EmitCVInlineLinetableDirective( 1140 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym, 1141 SecondaryFunctionIds); 1142 } 1143 1144 void MCAsmStreamer::EmitCVDefRangeDirective( 1145 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1146 StringRef FixedSizePortion) { 1147 OS << "\t.cv_def_range\t"; 1148 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) { 1149 OS << ' '; 1150 Range.first->print(OS, MAI); 1151 OS << ' '; 1152 Range.second->print(OS, MAI); 1153 } 1154 OS << ", "; 1155 PrintQuotedString(FixedSizePortion, OS); 1156 EmitEOL(); 1157 this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion); 1158 } 1159 1160 void MCAsmStreamer::EmitCVStringTableDirective() { 1161 OS << "\t.cv_stringtable"; 1162 EmitEOL(); 1163 } 1164 1165 void MCAsmStreamer::EmitCVFileChecksumsDirective() { 1166 OS << "\t.cv_filechecksums"; 1167 EmitEOL(); 1168 } 1169 1170 void MCAsmStreamer::EmitIdent(StringRef IdentString) { 1171 assert(MAI->hasIdentDirective() && ".ident directive not supported"); 1172 OS << "\t.ident\t"; 1173 PrintQuotedString(IdentString, OS); 1174 EmitEOL(); 1175 } 1176 1177 void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) { 1178 MCStreamer::EmitCFISections(EH, Debug); 1179 OS << "\t.cfi_sections "; 1180 if (EH) { 1181 OS << ".eh_frame"; 1182 if (Debug) 1183 OS << ", .debug_frame"; 1184 } else if (Debug) { 1185 OS << ".debug_frame"; 1186 } 1187 1188 EmitEOL(); 1189 } 1190 1191 void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { 1192 OS << "\t.cfi_startproc"; 1193 if (Frame.IsSimple) 1194 OS << " simple"; 1195 EmitEOL(); 1196 } 1197 1198 void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { 1199 MCStreamer::EmitCFIEndProcImpl(Frame); 1200 OS << "\t.cfi_endproc"; 1201 EmitEOL(); 1202 } 1203 1204 void MCAsmStreamer::EmitRegisterName(int64_t Register) { 1205 if (!MAI->useDwarfRegNumForCFI()) { 1206 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 1207 unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true); 1208 InstPrinter->printRegName(OS, LLVMRegister); 1209 } else { 1210 OS << Register; 1211 } 1212 } 1213 1214 void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { 1215 MCStreamer::EmitCFIDefCfa(Register, Offset); 1216 OS << "\t.cfi_def_cfa "; 1217 EmitRegisterName(Register); 1218 OS << ", " << Offset; 1219 EmitEOL(); 1220 } 1221 1222 void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { 1223 MCStreamer::EmitCFIDefCfaOffset(Offset); 1224 OS << "\t.cfi_def_cfa_offset " << Offset; 1225 EmitEOL(); 1226 } 1227 1228 static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) { 1229 OS << "\t.cfi_escape "; 1230 if (!Values.empty()) { 1231 size_t e = Values.size() - 1; 1232 for (size_t i = 0; i < e; ++i) 1233 OS << format("0x%02x", uint8_t(Values[i])) << ", "; 1234 OS << format("0x%02x", uint8_t(Values[e])); 1235 } 1236 } 1237 1238 void MCAsmStreamer::EmitCFIEscape(StringRef Values) { 1239 MCStreamer::EmitCFIEscape(Values); 1240 PrintCFIEscape(OS, Values); 1241 EmitEOL(); 1242 } 1243 1244 void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) { 1245 MCStreamer::EmitCFIGnuArgsSize(Size); 1246 1247 uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size }; 1248 unsigned Len = encodeULEB128(Size, Buffer + 1) + 1; 1249 1250 PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len)); 1251 EmitEOL(); 1252 } 1253 1254 void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { 1255 MCStreamer::EmitCFIDefCfaRegister(Register); 1256 OS << "\t.cfi_def_cfa_register "; 1257 EmitRegisterName(Register); 1258 EmitEOL(); 1259 } 1260 1261 void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { 1262 this->MCStreamer::EmitCFIOffset(Register, Offset); 1263 OS << "\t.cfi_offset "; 1264 EmitRegisterName(Register); 1265 OS << ", " << Offset; 1266 EmitEOL(); 1267 } 1268 1269 void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, 1270 unsigned Encoding) { 1271 MCStreamer::EmitCFIPersonality(Sym, Encoding); 1272 OS << "\t.cfi_personality " << Encoding << ", "; 1273 Sym->print(OS, MAI); 1274 EmitEOL(); 1275 } 1276 1277 void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { 1278 MCStreamer::EmitCFILsda(Sym, Encoding); 1279 OS << "\t.cfi_lsda " << Encoding << ", "; 1280 Sym->print(OS, MAI); 1281 EmitEOL(); 1282 } 1283 1284 void MCAsmStreamer::EmitCFIRememberState() { 1285 MCStreamer::EmitCFIRememberState(); 1286 OS << "\t.cfi_remember_state"; 1287 EmitEOL(); 1288 } 1289 1290 void MCAsmStreamer::EmitCFIRestoreState() { 1291 MCStreamer::EmitCFIRestoreState(); 1292 OS << "\t.cfi_restore_state"; 1293 EmitEOL(); 1294 } 1295 1296 void MCAsmStreamer::EmitCFISameValue(int64_t Register) { 1297 MCStreamer::EmitCFISameValue(Register); 1298 OS << "\t.cfi_same_value "; 1299 EmitRegisterName(Register); 1300 EmitEOL(); 1301 } 1302 1303 void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { 1304 MCStreamer::EmitCFIRelOffset(Register, Offset); 1305 OS << "\t.cfi_rel_offset "; 1306 EmitRegisterName(Register); 1307 OS << ", " << Offset; 1308 EmitEOL(); 1309 } 1310 1311 void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { 1312 MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); 1313 OS << "\t.cfi_adjust_cfa_offset " << Adjustment; 1314 EmitEOL(); 1315 } 1316 1317 void MCAsmStreamer::EmitCFISignalFrame() { 1318 MCStreamer::EmitCFISignalFrame(); 1319 OS << "\t.cfi_signal_frame"; 1320 EmitEOL(); 1321 } 1322 1323 void MCAsmStreamer::EmitCFIUndefined(int64_t Register) { 1324 MCStreamer::EmitCFIUndefined(Register); 1325 OS << "\t.cfi_undefined " << Register; 1326 EmitEOL(); 1327 } 1328 1329 void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) { 1330 MCStreamer::EmitCFIRegister(Register1, Register2); 1331 OS << "\t.cfi_register " << Register1 << ", " << Register2; 1332 EmitEOL(); 1333 } 1334 1335 void MCAsmStreamer::EmitCFIWindowSave() { 1336 MCStreamer::EmitCFIWindowSave(); 1337 OS << "\t.cfi_window_save"; 1338 EmitEOL(); 1339 } 1340 1341 void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { 1342 MCStreamer::EmitWinCFIStartProc(Symbol); 1343 1344 OS << ".seh_proc "; 1345 Symbol->print(OS, MAI); 1346 EmitEOL(); 1347 } 1348 1349 void MCAsmStreamer::EmitWinCFIEndProc() { 1350 MCStreamer::EmitWinCFIEndProc(); 1351 1352 OS << "\t.seh_endproc"; 1353 EmitEOL(); 1354 } 1355 1356 void MCAsmStreamer::EmitWinCFIStartChained() { 1357 MCStreamer::EmitWinCFIStartChained(); 1358 1359 OS << "\t.seh_startchained"; 1360 EmitEOL(); 1361 } 1362 1363 void MCAsmStreamer::EmitWinCFIEndChained() { 1364 MCStreamer::EmitWinCFIEndChained(); 1365 1366 OS << "\t.seh_endchained"; 1367 EmitEOL(); 1368 } 1369 1370 void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, 1371 bool Except) { 1372 MCStreamer::EmitWinEHHandler(Sym, Unwind, Except); 1373 1374 OS << "\t.seh_handler "; 1375 Sym->print(OS, MAI); 1376 if (Unwind) 1377 OS << ", @unwind"; 1378 if (Except) 1379 OS << ", @except"; 1380 EmitEOL(); 1381 } 1382 1383 void MCAsmStreamer::EmitWinEHHandlerData() { 1384 MCStreamer::EmitWinEHHandlerData(); 1385 1386 // Switch sections. Don't call SwitchSection directly, because that will 1387 // cause the section switch to be visible in the emitted assembly. 1388 // We only do this so the section switch that terminates the handler 1389 // data block is visible. 1390 WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); 1391 MCSection *TextSec = &CurFrame->Function->getSection(); 1392 MCSection *XData = getAssociatedXDataSection(TextSec); 1393 SwitchSectionNoChange(XData); 1394 1395 OS << "\t.seh_handlerdata"; 1396 EmitEOL(); 1397 } 1398 1399 void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) { 1400 MCStreamer::EmitWinCFIPushReg(Register); 1401 1402 OS << "\t.seh_pushreg " << Register; 1403 EmitEOL(); 1404 } 1405 1406 void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) { 1407 MCStreamer::EmitWinCFISetFrame(Register, Offset); 1408 1409 OS << "\t.seh_setframe " << Register << ", " << Offset; 1410 EmitEOL(); 1411 } 1412 1413 void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) { 1414 MCStreamer::EmitWinCFIAllocStack(Size); 1415 1416 OS << "\t.seh_stackalloc " << Size; 1417 EmitEOL(); 1418 } 1419 1420 void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) { 1421 MCStreamer::EmitWinCFISaveReg(Register, Offset); 1422 1423 OS << "\t.seh_savereg " << Register << ", " << Offset; 1424 EmitEOL(); 1425 } 1426 1427 void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) { 1428 MCStreamer::EmitWinCFISaveXMM(Register, Offset); 1429 1430 OS << "\t.seh_savexmm " << Register << ", " << Offset; 1431 EmitEOL(); 1432 } 1433 1434 void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) { 1435 MCStreamer::EmitWinCFIPushFrame(Code); 1436 1437 OS << "\t.seh_pushframe"; 1438 if (Code) 1439 OS << " @code"; 1440 EmitEOL(); 1441 } 1442 1443 void MCAsmStreamer::EmitWinCFIEndProlog() { 1444 MCStreamer::EmitWinCFIEndProlog(); 1445 1446 OS << "\t.seh_endprologue"; 1447 EmitEOL(); 1448 } 1449 1450 void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, 1451 const MCSubtargetInfo &STI) { 1452 raw_ostream &OS = GetCommentOS(); 1453 SmallString<256> Code; 1454 SmallVector<MCFixup, 4> Fixups; 1455 raw_svector_ostream VecOS(Code); 1456 Emitter->encodeInstruction(Inst, VecOS, Fixups, STI); 1457 1458 // If we are showing fixups, create symbolic markers in the encoded 1459 // representation. We do this by making a per-bit map to the fixup item index, 1460 // then trying to display it as nicely as possible. 1461 SmallVector<uint8_t, 64> FixupMap; 1462 FixupMap.resize(Code.size() * 8); 1463 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) 1464 FixupMap[i] = 0; 1465 1466 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1467 MCFixup &F = Fixups[i]; 1468 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); 1469 for (unsigned j = 0; j != Info.TargetSize; ++j) { 1470 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; 1471 assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); 1472 FixupMap[Index] = 1 + i; 1473 } 1474 } 1475 1476 // FIXME: Note the fixup comments for Thumb2 are completely bogus since the 1477 // high order halfword of a 32-bit Thumb2 instruction is emitted first. 1478 OS << "encoding: ["; 1479 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 1480 if (i) 1481 OS << ','; 1482 1483 // See if all bits are the same map entry. 1484 uint8_t MapEntry = FixupMap[i * 8 + 0]; 1485 for (unsigned j = 1; j != 8; ++j) { 1486 if (FixupMap[i * 8 + j] == MapEntry) 1487 continue; 1488 1489 MapEntry = uint8_t(~0U); 1490 break; 1491 } 1492 1493 if (MapEntry != uint8_t(~0U)) { 1494 if (MapEntry == 0) { 1495 OS << format("0x%02x", uint8_t(Code[i])); 1496 } else { 1497 if (Code[i]) { 1498 // FIXME: Some of the 8 bits require fix up. 1499 OS << format("0x%02x", uint8_t(Code[i])) << '\'' 1500 << char('A' + MapEntry - 1) << '\''; 1501 } else 1502 OS << char('A' + MapEntry - 1); 1503 } 1504 } else { 1505 // Otherwise, write out in binary. 1506 OS << "0b"; 1507 for (unsigned j = 8; j--;) { 1508 unsigned Bit = (Code[i] >> j) & 1; 1509 1510 unsigned FixupBit; 1511 if (MAI->isLittleEndian()) 1512 FixupBit = i * 8 + j; 1513 else 1514 FixupBit = i * 8 + (7-j); 1515 1516 if (uint8_t MapEntry = FixupMap[FixupBit]) { 1517 assert(Bit == 0 && "Encoder wrote into fixed up bit!"); 1518 OS << char('A' + MapEntry - 1); 1519 } else 1520 OS << Bit; 1521 } 1522 } 1523 } 1524 OS << "]\n"; 1525 1526 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 1527 MCFixup &F = Fixups[i]; 1528 const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind()); 1529 OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() 1530 << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; 1531 } 1532 } 1533 1534 void MCAsmStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { 1535 assert(getCurrentSection().first && 1536 "Cannot emit contents before setting section!"); 1537 1538 // Show the encoding in a comment if we have a code emitter. 1539 if (Emitter) 1540 AddEncodingComment(Inst, STI); 1541 1542 // Show the MCInst if enabled. 1543 if (ShowInst) { 1544 Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n "); 1545 GetCommentOS() << "\n"; 1546 } 1547 1548 if(getTargetStreamer()) 1549 getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI); 1550 else 1551 InstPrinter->printInst(&Inst, OS, "", STI); 1552 1553 EmitEOL(); 1554 } 1555 1556 void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) { 1557 OS << "\t.bundle_align_mode " << AlignPow2; 1558 EmitEOL(); 1559 } 1560 1561 void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) { 1562 OS << "\t.bundle_lock"; 1563 if (AlignToEnd) 1564 OS << " align_to_end"; 1565 EmitEOL(); 1566 } 1567 1568 void MCAsmStreamer::EmitBundleUnlock() { 1569 OS << "\t.bundle_unlock"; 1570 EmitEOL(); 1571 } 1572 1573 bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, 1574 const MCExpr *Expr, SMLoc) { 1575 OS << "\t.reloc "; 1576 Offset.print(OS, MAI); 1577 OS << ", " << Name; 1578 if (Expr) { 1579 OS << ", "; 1580 Expr->print(OS, MAI); 1581 } 1582 EmitEOL(); 1583 return false; 1584 } 1585 1586 /// EmitRawText - If this file is backed by an assembly streamer, this dumps 1587 /// the specified string in the output .s file. This capability is 1588 /// indicated by the hasRawTextSupport() predicate. 1589 void MCAsmStreamer::EmitRawTextImpl(StringRef String) { 1590 if (!String.empty() && String.back() == '\n') 1591 String = String.substr(0, String.size()-1); 1592 OS << String; 1593 EmitEOL(); 1594 } 1595 1596 void MCAsmStreamer::FinishImpl() { 1597 // If we are generating dwarf for assembly source files dump out the sections. 1598 if (getContext().getGenDwarfForAssembly()) 1599 MCGenDwarfInfo::Emit(this); 1600 1601 // Emit the label for the line table, if requested - since the rest of the 1602 // line table will be defined by .loc/.file directives, and not emitted 1603 // directly, the label is the only work required here. 1604 auto &Tables = getContext().getMCDwarfLineTables(); 1605 if (!Tables.empty()) { 1606 assert(Tables.size() == 1 && "asm output only supports one line table"); 1607 if (auto *Label = Tables.begin()->second.getLabel()) { 1608 SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); 1609 EmitLabel(Label); 1610 } 1611 } 1612 } 1613 1614 MCStreamer *llvm::createAsmStreamer(MCContext &Context, 1615 std::unique_ptr<formatted_raw_ostream> OS, 1616 bool isVerboseAsm, bool useDwarfDirectory, 1617 MCInstPrinter *IP, MCCodeEmitter *CE, 1618 MCAsmBackend *MAB, bool ShowInst) { 1619 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, 1620 useDwarfDirectory, IP, CE, MAB, ShowInst); 1621 } 1622