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