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