1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/SmallString.h" 10 #include "llvm/ADT/StringExtras.h" 11 #include "llvm/ADT/Twine.h" 12 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 13 #include "llvm/MC/MCAsmBackend.h" 14 #include "llvm/MC/MCAsmInfo.h" 15 #include "llvm/MC/MCAssembler.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/MCObjectWriter.h" 25 #include "llvm/MC/MCPseudoProbe.h" 26 #include "llvm/MC/MCRegister.h" 27 #include "llvm/MC/MCRegisterInfo.h" 28 #include "llvm/MC/MCSectionMachO.h" 29 #include "llvm/MC/MCStreamer.h" 30 #include "llvm/MC/MCSymbolXCOFF.h" 31 #include "llvm/MC/TargetRegistry.h" 32 #include "llvm/Support/Casting.h" 33 #include "llvm/Support/ErrorHandling.h" 34 #include "llvm/Support/Format.h" 35 #include "llvm/Support/FormattedStream.h" 36 #include "llvm/Support/LEB128.h" 37 #include "llvm/Support/MathExtras.h" 38 #include "llvm/Support/Path.h" 39 #include <optional> 40 41 using namespace llvm; 42 43 namespace { 44 45 class MCAsmStreamer final : public MCStreamer { 46 std::unique_ptr<formatted_raw_ostream> OSOwner; 47 formatted_raw_ostream &OS; 48 const MCAsmInfo *MAI; 49 std::unique_ptr<MCInstPrinter> InstPrinter; 50 std::unique_ptr<MCAssembler> Assembler; 51 52 SmallString<128> ExplicitCommentToEmit; 53 SmallString<128> CommentToEmit; 54 raw_svector_ostream CommentStream; 55 raw_null_ostream NullStream; 56 57 unsigned IsVerboseAsm : 1; 58 unsigned ShowInst : 1; 59 unsigned UseDwarfDirectory : 1; 60 61 void EmitRegisterName(int64_t Register); 62 void PrintQuotedString(StringRef Data, raw_ostream &OS) const; 63 void printDwarfFileDirective(unsigned FileNo, StringRef Directory, 64 StringRef Filename, 65 std::optional<MD5::MD5Result> Checksum, 66 std::optional<StringRef> Source, 67 bool UseDwarfDirectory, 68 raw_svector_ostream &OS) const; 69 void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; 70 void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; 71 72 public: 73 MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os, 74 bool isVerboseAsm, bool useDwarfDirectory, 75 MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter, 76 std::unique_ptr<MCAsmBackend> asmbackend, bool showInst) 77 : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner), 78 MAI(Context.getAsmInfo()), InstPrinter(printer), 79 Assembler(std::make_unique<MCAssembler>( 80 Context, std::move(asmbackend), std::move(emitter), 81 (asmbackend) ? asmbackend->createObjectWriter(NullStream) 82 : nullptr)), 83 CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm), 84 ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) { 85 assert(InstPrinter); 86 if (IsVerboseAsm) 87 InstPrinter->setCommentStream(CommentStream); 88 if (Assembler->getBackendPtr()) 89 setAllowAutoPadding(Assembler->getBackend().allowAutoPadding()); 90 91 Context.setUseNamesOnTempLabels(true); 92 } 93 94 MCAssembler &getAssembler() { return *Assembler; } 95 MCAssembler *getAssemblerPtr() override { return nullptr; } 96 97 inline void EmitEOL() { 98 // Dump Explicit Comments here. 99 emitExplicitComments(); 100 // If we don't have any comments, just emit a \n. 101 if (!IsVerboseAsm) { 102 OS << '\n'; 103 return; 104 } 105 EmitCommentsAndEOL(); 106 } 107 108 void emitSyntaxDirective() override; 109 110 void EmitCommentsAndEOL(); 111 112 /// Return true if this streamer supports verbose assembly at all. 113 bool isVerboseAsm() const override { return IsVerboseAsm; } 114 115 /// Do we support EmitRawText? 116 bool hasRawTextSupport() const override { return true; } 117 118 /// Add a comment that can be emitted to the generated .s file to make the 119 /// output of the compiler more readable. This only affects the MCAsmStreamer 120 /// and only when verbose assembly output is enabled. 121 void AddComment(const Twine &T, bool EOL = true) override; 122 123 /// Add a comment showing the encoding of an instruction. 124 void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &); 125 126 /// Return a raw_ostream that comments can be written to. 127 /// Unlike AddComment, you are required to terminate comments with \n if you 128 /// use this method. 129 raw_ostream &getCommentOS() override { 130 if (!IsVerboseAsm) 131 return nulls(); // Discard comments unless in verbose asm mode. 132 return CommentStream; 133 } 134 135 void emitRawComment(const Twine &T, bool TabPrefix = true) override; 136 137 void addExplicitComment(const Twine &T) override; 138 void emitExplicitComments() override; 139 140 /// Emit a blank line to a .s file to pretty it up. 141 void addBlankLine() override { EmitEOL(); } 142 143 /// @name MCStreamer Interface 144 /// @{ 145 146 void changeSection(MCSection *Section, const MCExpr *Subsection) override; 147 148 void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name, 149 bool KeepOriginalSym) override; 150 151 void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override; 152 153 void emitGNUAttribute(unsigned Tag, unsigned Value) override; 154 155 StringRef getMnemonic(MCInst &MI) override { 156 return InstPrinter->getMnemonic(&MI).first; 157 } 158 159 void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; 160 161 void emitAssemblerFlag(MCAssemblerFlag Flag) override; 162 void emitLinkerOptions(ArrayRef<std::string> Options) override; 163 void emitDataRegion(MCDataRegionType Kind) override; 164 void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor, 165 unsigned Update, VersionTuple SDKVersion) override; 166 void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor, 167 unsigned Update, VersionTuple SDKVersion) override; 168 void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major, 169 unsigned Minor, unsigned Update, 170 VersionTuple SDKVersion) override; 171 void emitThumbFunc(MCSymbol *Func) override; 172 173 void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; 174 void emitConditionalAssignment(MCSymbol *Symbol, 175 const MCExpr *Value) override; 176 void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; 177 bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override; 178 179 void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override; 180 void beginCOFFSymbolDef(const MCSymbol *Symbol) override; 181 void emitCOFFSymbolStorageClass(int StorageClass) override; 182 void emitCOFFSymbolType(int Type) override; 183 void endCOFFSymbolDef() override; 184 void emitCOFFSafeSEH(MCSymbol const *Symbol) override; 185 void emitCOFFSymbolIndex(MCSymbol const *Symbol) override; 186 void emitCOFFSectionIndex(MCSymbol const *Symbol) override; 187 void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; 188 void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override; 189 void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size, 190 MCSymbol *CsectSym, Align Alignment) override; 191 void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol, 192 MCSymbolAttr Linakge, 193 MCSymbolAttr Visibility) override; 194 void emitXCOFFRenameDirective(const MCSymbol *Name, 195 StringRef Rename) override; 196 197 void emitXCOFFRefDirective(StringRef Name) override; 198 199 void emitXCOFFExceptDirective(const MCSymbol *Symbol, 200 const MCSymbol *Trap, 201 unsigned Lang, unsigned Reason, 202 unsigned FunctionSize, bool hasDebug) override; 203 204 void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; 205 void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 206 Align ByteAlignment) override; 207 208 /// Emit a local common (.lcomm) symbol. 209 /// 210 /// @param Symbol - The common symbol to emit. 211 /// @param Size - The size of the common symbol. 212 /// @param ByteAlignment - The alignment of the common symbol in bytes. 213 void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 214 Align ByteAlignment) override; 215 216 void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, 217 uint64_t Size = 0, Align ByteAlignment = Align(1), 218 SMLoc Loc = SMLoc()) override; 219 220 void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, 221 Align ByteAlignment = Align(1)) override; 222 223 void emitBinaryData(StringRef Data) override; 224 225 void emitBytes(StringRef Data) override; 226 227 void emitValueImpl(const MCExpr *Value, unsigned Size, 228 SMLoc Loc = SMLoc()) override; 229 void emitIntValue(uint64_t Value, unsigned Size) override; 230 void emitIntValueInHex(uint64_t Value, unsigned Size) override; 231 void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override; 232 233 void emitULEB128Value(const MCExpr *Value) override; 234 235 void emitSLEB128Value(const MCExpr *Value) override; 236 237 void emitDTPRel32Value(const MCExpr *Value) override; 238 void emitDTPRel64Value(const MCExpr *Value) override; 239 void emitTPRel32Value(const MCExpr *Value) override; 240 void emitTPRel64Value(const MCExpr *Value) override; 241 242 void emitGPRel64Value(const MCExpr *Value) override; 243 244 void emitGPRel32Value(const MCExpr *Value) override; 245 246 void emitFill(const MCExpr &NumBytes, uint64_t FillValue, 247 SMLoc Loc = SMLoc()) override; 248 249 void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, 250 SMLoc Loc = SMLoc()) override; 251 252 void emitAlignmentDirective(unsigned ByteAlignment, 253 std::optional<int64_t> Value, unsigned ValueSize, 254 unsigned MaxBytesToEmit); 255 256 void emitValueToAlignment(Align Alignment, int64_t Value = 0, 257 unsigned ValueSize = 1, 258 unsigned MaxBytesToEmit = 0) override; 259 260 void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, 261 unsigned MaxBytesToEmit = 0) override; 262 263 void emitValueToOffset(const MCExpr *Offset, 264 unsigned char Value, 265 SMLoc Loc) override; 266 267 void emitFileDirective(StringRef Filename) override; 268 void emitFileDirective(StringRef Filename, StringRef CompilerVerion, 269 StringRef TimeStamp, StringRef Description) override; 270 Expected<unsigned> tryEmitDwarfFileDirective( 271 unsigned FileNo, StringRef Directory, StringRef Filename, 272 std::optional<MD5::MD5Result> Checksum = std::nullopt, 273 std::optional<StringRef> Source = std::nullopt, 274 unsigned CUID = 0) override; 275 void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, 276 std::optional<MD5::MD5Result> Checksum, 277 std::optional<StringRef> Source, 278 unsigned CUID = 0) override; 279 void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, 280 unsigned Flags, unsigned Isa, 281 unsigned Discriminator, 282 StringRef FileName) override; 283 MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; 284 285 bool emitCVFileDirective(unsigned FileNo, StringRef Filename, 286 ArrayRef<uint8_t> Checksum, 287 unsigned ChecksumKind) override; 288 bool emitCVFuncIdDirective(unsigned FuncId) override; 289 bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc, 290 unsigned IAFile, unsigned IALine, 291 unsigned IACol, SMLoc Loc) override; 292 void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line, 293 unsigned Column, bool PrologueEnd, bool IsStmt, 294 StringRef FileName, SMLoc Loc) override; 295 void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart, 296 const MCSymbol *FnEnd) override; 297 void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, 298 unsigned SourceFileId, 299 unsigned SourceLineNum, 300 const MCSymbol *FnStartSym, 301 const MCSymbol *FnEndSym) override; 302 303 void PrintCVDefRangePrefix( 304 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges); 305 306 void emitCVDefRangeDirective( 307 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 308 codeview::DefRangeRegisterRelHeader DRHdr) override; 309 310 void emitCVDefRangeDirective( 311 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 312 codeview::DefRangeSubfieldRegisterHeader DRHdr) override; 313 314 void emitCVDefRangeDirective( 315 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 316 codeview::DefRangeRegisterHeader DRHdr) override; 317 318 void emitCVDefRangeDirective( 319 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 320 codeview::DefRangeFramePointerRelHeader DRHdr) override; 321 322 void emitCVStringTableDirective() override; 323 void emitCVFileChecksumsDirective() override; 324 void emitCVFileChecksumOffsetDirective(unsigned FileNo) override; 325 void emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override; 326 327 void emitIdent(StringRef IdentString) override; 328 void emitCFIBKeyFrame() override; 329 void emitCFIMTETaggedFrame() override; 330 void emitCFISections(bool EH, bool Debug) override; 331 void emitCFIDefCfa(int64_t Register, int64_t Offset) override; 332 void emitCFIDefCfaOffset(int64_t Offset) override; 333 void emitCFIDefCfaRegister(int64_t Register) override; 334 void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, 335 int64_t AddressSpace) override; 336 void emitCFIOffset(int64_t Register, int64_t Offset) override; 337 void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override; 338 void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override; 339 void emitCFIRememberState() override; 340 void emitCFIRestoreState() override; 341 void emitCFIRestore(int64_t Register) override; 342 void emitCFISameValue(int64_t Register) override; 343 void emitCFIRelOffset(int64_t Register, int64_t Offset) override; 344 void emitCFIAdjustCfaOffset(int64_t Adjustment) override; 345 void emitCFIEscape(StringRef Values) override; 346 void emitCFIGnuArgsSize(int64_t Size) override; 347 void emitCFISignalFrame() override; 348 void emitCFIUndefined(int64_t Register) override; 349 void emitCFIRegister(int64_t Register1, int64_t Register2) override; 350 void emitCFIWindowSave() override; 351 void emitCFINegateRAState() override; 352 void emitCFIReturnColumn(int64_t Register) override; 353 354 void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override; 355 void emitWinCFIEndProc(SMLoc Loc) override; 356 void emitWinCFIFuncletOrFuncEnd(SMLoc Loc) override; 357 void emitWinCFIStartChained(SMLoc Loc) override; 358 void emitWinCFIEndChained(SMLoc Loc) override; 359 void emitWinCFIPushReg(MCRegister Register, SMLoc Loc) override; 360 void emitWinCFISetFrame(MCRegister Register, unsigned Offset, 361 SMLoc Loc) override; 362 void emitWinCFIAllocStack(unsigned Size, SMLoc Loc) override; 363 void emitWinCFISaveReg(MCRegister Register, unsigned Offset, 364 SMLoc Loc) override; 365 void emitWinCFISaveXMM(MCRegister Register, unsigned Offset, 366 SMLoc Loc) override; 367 void emitWinCFIPushFrame(bool Code, SMLoc Loc) override; 368 void emitWinCFIEndProlog(SMLoc Loc) override; 369 370 void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except, 371 SMLoc Loc) override; 372 void emitWinEHHandlerData(SMLoc Loc) override; 373 374 void emitCGProfileEntry(const MCSymbolRefExpr *From, 375 const MCSymbolRefExpr *To, uint64_t Count) override; 376 377 void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override; 378 379 void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type, 380 uint64_t Attr, 381 const MCPseudoProbeInlineStack &InlineStack, MCSymbol *FnSym) override; 382 383 void emitBundleAlignMode(Align Alignment) override; 384 void emitBundleLock(bool AlignToEnd) override; 385 void emitBundleUnlock() override; 386 387 std::optional<std::pair<bool, std::string>> 388 emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, 389 SMLoc Loc, const MCSubtargetInfo &STI) override; 390 391 void emitAddrsig() override; 392 void emitAddrsigSym(const MCSymbol *Sym) override; 393 394 /// If this file is backed by an assembly streamer, this dumps the specified 395 /// string in the output .s file. This capability is indicated by the 396 /// hasRawTextSupport() predicate. 397 void emitRawTextImpl(StringRef String) override; 398 399 void finishImpl() override; 400 401 void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override; 402 403 MCSymbol *emitDwarfUnitLength(const Twine &Prefix, 404 const Twine &Comment) override; 405 406 void emitDwarfLineStartLabel(MCSymbol *StartSym) override; 407 408 void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override; 409 410 void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, 411 const MCSymbol *Label, 412 unsigned PointerSize) override; 413 414 void doFinalizationAtSectionEnd(MCSection *Section) override; 415 }; 416 417 } // end anonymous namespace. 418 419 void MCAsmStreamer::AddComment(const Twine &T, bool EOL) { 420 if (!IsVerboseAsm) return; 421 422 T.toVector(CommentToEmit); 423 424 if (EOL) 425 CommentToEmit.push_back('\n'); // Place comment in a new line. 426 } 427 428 void MCAsmStreamer::EmitCommentsAndEOL() { 429 if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) { 430 OS << '\n'; 431 return; 432 } 433 434 StringRef Comments = CommentToEmit; 435 436 assert(Comments.back() == '\n' && 437 "Comment array not newline terminated"); 438 do { 439 // Emit a line of comments. 440 OS.PadToColumn(MAI->getCommentColumn()); 441 size_t Position = Comments.find('\n'); 442 OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n'; 443 444 Comments = Comments.substr(Position+1); 445 } while (!Comments.empty()); 446 447 CommentToEmit.clear(); 448 } 449 450 static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) { 451 assert(Bytes > 0 && Bytes <= 8 && "Invalid size!"); 452 return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8)); 453 } 454 455 void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) { 456 if (TabPrefix) 457 OS << '\t'; 458 OS << MAI->getCommentString() << T; 459 EmitEOL(); 460 } 461 462 void MCAsmStreamer::addExplicitComment(const Twine &T) { 463 StringRef c = T.getSingleStringRef(); 464 if (c.equals(StringRef(MAI->getSeparatorString()))) 465 return; 466 if (c.startswith(StringRef("//"))) { 467 ExplicitCommentToEmit.append("\t"); 468 ExplicitCommentToEmit.append(MAI->getCommentString()); 469 // drop // 470 ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); 471 } else if (c.startswith(StringRef("/*"))) { 472 size_t p = 2, len = c.size() - 2; 473 // emit each line in comment as separate newline. 474 do { 475 size_t newp = std::min(len, c.find_first_of("\r\n", p)); 476 ExplicitCommentToEmit.append("\t"); 477 ExplicitCommentToEmit.append(MAI->getCommentString()); 478 ExplicitCommentToEmit.append(c.slice(p, newp).str()); 479 // If we have another line in this comment add line 480 if (newp < len) 481 ExplicitCommentToEmit.append("\n"); 482 p = newp + 1; 483 } while (p < len); 484 } else if (c.startswith(StringRef(MAI->getCommentString()))) { 485 ExplicitCommentToEmit.append("\t"); 486 ExplicitCommentToEmit.append(c.str()); 487 } else if (c.front() == '#') { 488 489 ExplicitCommentToEmit.append("\t"); 490 ExplicitCommentToEmit.append(MAI->getCommentString()); 491 ExplicitCommentToEmit.append(c.slice(1, c.size()).str()); 492 } else 493 assert(false && "Unexpected Assembly Comment"); 494 // full line comments immediately output 495 if (c.back() == '\n') 496 emitExplicitComments(); 497 } 498 499 void MCAsmStreamer::emitExplicitComments() { 500 StringRef Comments = ExplicitCommentToEmit; 501 if (!Comments.empty()) 502 OS << Comments; 503 ExplicitCommentToEmit.clear(); 504 } 505 506 void MCAsmStreamer::changeSection(MCSection *Section, 507 const MCExpr *Subsection) { 508 assert(Section && "Cannot switch to a null section!"); 509 if (MCTargetStreamer *TS = getTargetStreamer()) { 510 TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS); 511 } else { 512 Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS, 513 Subsection); 514 } 515 } 516 517 void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym, 518 StringRef Name, 519 bool KeepOriginalSym) { 520 OS << ".symver "; 521 OriginalSym->print(OS, MAI); 522 OS << ", " << Name; 523 if (!KeepOriginalSym && !Name.contains("@@@")) 524 OS << ", remove"; 525 EmitEOL(); 526 } 527 528 void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { 529 MCStreamer::emitLabel(Symbol, Loc); 530 531 Symbol->print(OS, MAI); 532 OS << MAI->getLabelSuffix(); 533 534 EmitEOL(); 535 } 536 537 void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) { 538 StringRef str = MCLOHIdToName(Kind); 539 540 #ifndef NDEBUG 541 int NbArgs = MCLOHIdToNbArgs(Kind); 542 assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!"); 543 assert(str != "" && "Invalid LOH name"); 544 #endif 545 546 OS << "\t" << MCLOHDirectiveName() << " " << str << "\t"; 547 bool IsFirst = true; 548 for (const MCSymbol *Arg : Args) { 549 if (!IsFirst) 550 OS << ", "; 551 IsFirst = false; 552 Arg->print(OS, MAI); 553 } 554 EmitEOL(); 555 } 556 557 void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) { 558 OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n"; 559 } 560 561 void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) { 562 switch (Flag) { 563 case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break; 564 case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break; 565 case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break; 566 case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break; 567 case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break; 568 } 569 EmitEOL(); 570 } 571 572 void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) { 573 assert(!Options.empty() && "At least one option is required!"); 574 OS << "\t.linker_option \"" << Options[0] << '"'; 575 for (const std::string &Opt : llvm::drop_begin(Options)) 576 OS << ", " << '"' << Opt << '"'; 577 EmitEOL(); 578 } 579 580 void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) { 581 if (!MAI->doesSupportDataRegionDirectives()) 582 return; 583 switch (Kind) { 584 case MCDR_DataRegion: OS << "\t.data_region"; break; 585 case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break; 586 case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break; 587 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break; 588 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break; 589 } 590 EmitEOL(); 591 } 592 593 static const char *getVersionMinDirective(MCVersionMinType Type) { 594 switch (Type) { 595 case MCVM_WatchOSVersionMin: return ".watchos_version_min"; 596 case MCVM_TvOSVersionMin: return ".tvos_version_min"; 597 case MCVM_IOSVersionMin: return ".ios_version_min"; 598 case MCVM_OSXVersionMin: return ".macosx_version_min"; 599 } 600 llvm_unreachable("Invalid MC version min type"); 601 } 602 603 static void EmitSDKVersionSuffix(raw_ostream &OS, 604 const VersionTuple &SDKVersion) { 605 if (SDKVersion.empty()) 606 return; 607 OS << '\t' << "sdk_version " << SDKVersion.getMajor(); 608 if (auto Minor = SDKVersion.getMinor()) { 609 OS << ", " << *Minor; 610 if (auto Subminor = SDKVersion.getSubminor()) { 611 OS << ", " << *Subminor; 612 } 613 } 614 } 615 616 void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major, 617 unsigned Minor, unsigned Update, 618 VersionTuple SDKVersion) { 619 OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor; 620 if (Update) 621 OS << ", " << Update; 622 EmitSDKVersionSuffix(OS, SDKVersion); 623 EmitEOL(); 624 } 625 626 static const char *getPlatformName(MachO::PlatformType Type) { 627 switch (Type) { 628 case MachO::PLATFORM_UNKNOWN: /* silence warning*/ 629 break; 630 case MachO::PLATFORM_MACOS: return "macos"; 631 case MachO::PLATFORM_IOS: return "ios"; 632 case MachO::PLATFORM_TVOS: return "tvos"; 633 case MachO::PLATFORM_WATCHOS: return "watchos"; 634 case MachO::PLATFORM_BRIDGEOS: return "bridgeos"; 635 case MachO::PLATFORM_MACCATALYST: return "macCatalyst"; 636 case MachO::PLATFORM_IOSSIMULATOR: return "iossimulator"; 637 case MachO::PLATFORM_TVOSSIMULATOR: return "tvossimulator"; 638 case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator"; 639 case MachO::PLATFORM_DRIVERKIT: return "driverkit"; 640 } 641 llvm_unreachable("Invalid Mach-O platform type"); 642 } 643 644 void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major, 645 unsigned Minor, unsigned Update, 646 VersionTuple SDKVersion) { 647 const char *PlatformName = getPlatformName((MachO::PlatformType)Platform); 648 OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor; 649 if (Update) 650 OS << ", " << Update; 651 EmitSDKVersionSuffix(OS, SDKVersion); 652 EmitEOL(); 653 } 654 655 void MCAsmStreamer::emitDarwinTargetVariantBuildVersion( 656 unsigned Platform, unsigned Major, unsigned Minor, unsigned Update, 657 VersionTuple SDKVersion) { 658 emitBuildVersion(Platform, Major, Minor, Update, SDKVersion); 659 } 660 661 void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) { 662 // This needs to emit to a temporary string to get properly quoted 663 // MCSymbols when they have spaces in them. 664 OS << "\t.thumb_func"; 665 // Only Mach-O hasSubsectionsViaSymbols() 666 if (MAI->hasSubsectionsViaSymbols()) { 667 OS << '\t'; 668 Func->print(OS, MAI); 669 } 670 EmitEOL(); 671 } 672 673 void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) { 674 // Do not emit a .set on inlined target assignments. 675 bool EmitSet = true; 676 if (auto *E = dyn_cast<MCTargetExpr>(Value)) 677 if (E->inlineAssignedExpr()) 678 EmitSet = false; 679 if (EmitSet) { 680 OS << ".set "; 681 Symbol->print(OS, MAI); 682 OS << ", "; 683 Value->print(OS, MAI); 684 685 EmitEOL(); 686 } 687 688 MCStreamer::emitAssignment(Symbol, Value); 689 } 690 691 void MCAsmStreamer::emitConditionalAssignment(MCSymbol *Symbol, 692 const MCExpr *Value) { 693 OS << ".lto_set_conditional "; 694 Symbol->print(OS, MAI); 695 OS << ", "; 696 Value->print(OS, MAI); 697 EmitEOL(); 698 } 699 700 void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { 701 OS << ".weakref "; 702 Alias->print(OS, MAI); 703 OS << ", "; 704 Symbol->print(OS, MAI); 705 EmitEOL(); 706 } 707 708 bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol, 709 MCSymbolAttr Attribute) { 710 switch (Attribute) { 711 case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute"); 712 case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function 713 case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC 714 case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object 715 case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object 716 case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common 717 case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype 718 case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object 719 if (!MAI->hasDotTypeDotSizeDirective()) 720 return false; // Symbol attribute not supported 721 OS << "\t.type\t"; 722 Symbol->print(OS, MAI); 723 OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%'); 724 switch (Attribute) { 725 default: return false; 726 case MCSA_ELF_TypeFunction: OS << "function"; break; 727 case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break; 728 case MCSA_ELF_TypeObject: OS << "object"; break; 729 case MCSA_ELF_TypeTLS: OS << "tls_object"; break; 730 case MCSA_ELF_TypeCommon: OS << "common"; break; 731 case MCSA_ELF_TypeNoType: OS << "notype"; break; 732 case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break; 733 } 734 EmitEOL(); 735 return true; 736 case MCSA_Global: // .globl/.global 737 OS << MAI->getGlobalDirective(); 738 break; 739 case MCSA_LGlobal: OS << "\t.lglobl\t"; break; 740 case MCSA_Hidden: OS << "\t.hidden\t"; break; 741 case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break; 742 case MCSA_Internal: OS << "\t.internal\t"; break; 743 case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; 744 case MCSA_Local: OS << "\t.local\t"; break; 745 case MCSA_NoDeadStrip: 746 if (!MAI->hasNoDeadStrip()) 747 return false; 748 OS << "\t.no_dead_strip\t"; 749 break; 750 case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; 751 case MCSA_AltEntry: OS << "\t.alt_entry\t"; break; 752 case MCSA_PrivateExtern: 753 OS << "\t.private_extern\t"; 754 break; 755 case MCSA_Protected: OS << "\t.protected\t"; break; 756 case MCSA_Reference: OS << "\t.reference\t"; break; 757 case MCSA_Extern: 758 OS << "\t.extern\t"; 759 break; 760 case MCSA_Weak: OS << MAI->getWeakDirective(); break; 761 case MCSA_WeakDefinition: 762 OS << "\t.weak_definition\t"; 763 break; 764 // .weak_reference 765 case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break; 766 case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break; 767 case MCSA_Cold: 768 // Assemblers currently do not support a .cold directive. 769 case MCSA_Exported: 770 // Non-AIX assemblers currently do not support exported visibility. 771 return false; 772 case MCSA_Memtag: 773 OS << "\t.memtag\t"; 774 break; 775 } 776 777 Symbol->print(OS, MAI); 778 EmitEOL(); 779 780 return true; 781 } 782 783 void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { 784 OS << ".desc" << ' '; 785 Symbol->print(OS, MAI); 786 OS << ',' << DescValue; 787 EmitEOL(); 788 } 789 790 void MCAsmStreamer::emitSyntaxDirective() { 791 if (MAI->getAssemblerDialect() == 1) { 792 OS << "\t.intel_syntax noprefix"; 793 EmitEOL(); 794 } 795 // FIXME: Currently emit unprefix'ed registers. 796 // The intel_syntax directive has one optional argument 797 // with may have a value of prefix or noprefix. 798 } 799 800 void MCAsmStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) { 801 OS << "\t.def\t"; 802 Symbol->print(OS, MAI); 803 OS << ';'; 804 EmitEOL(); 805 } 806 807 void MCAsmStreamer::emitCOFFSymbolStorageClass(int StorageClass) { 808 OS << "\t.scl\t" << StorageClass << ';'; 809 EmitEOL(); 810 } 811 812 void MCAsmStreamer::emitCOFFSymbolType(int Type) { 813 OS << "\t.type\t" << Type << ';'; 814 EmitEOL(); 815 } 816 817 void MCAsmStreamer::endCOFFSymbolDef() { 818 OS << "\t.endef"; 819 EmitEOL(); 820 } 821 822 void MCAsmStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) { 823 OS << "\t.safeseh\t"; 824 Symbol->print(OS, MAI); 825 EmitEOL(); 826 } 827 828 void MCAsmStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) { 829 OS << "\t.symidx\t"; 830 Symbol->print(OS, MAI); 831 EmitEOL(); 832 } 833 834 void MCAsmStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) { 835 OS << "\t.secidx\t"; 836 Symbol->print(OS, MAI); 837 EmitEOL(); 838 } 839 840 void MCAsmStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) { 841 OS << "\t.secrel32\t"; 842 Symbol->print(OS, MAI); 843 if (Offset != 0) 844 OS << '+' << Offset; 845 EmitEOL(); 846 } 847 848 void MCAsmStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) { 849 OS << "\t.rva\t"; 850 Symbol->print(OS, MAI); 851 if (Offset > 0) 852 OS << '+' << Offset; 853 else if (Offset < 0) 854 OS << '-' << -Offset; 855 EmitEOL(); 856 } 857 858 // We need an XCOFF-specific version of this directive as the AIX syntax 859 // requires a QualName argument identifying the csect name and storage mapping 860 // class to appear before the alignment if we are specifying it. 861 void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, 862 uint64_t Size, 863 MCSymbol *CsectSym, 864 Align Alignment) { 865 assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment && 866 "We only support writing log base-2 alignment format with XCOFF."); 867 868 OS << "\t.lcomm\t"; 869 LabelSym->print(OS, MAI); 870 OS << ',' << Size << ','; 871 CsectSym->print(OS, MAI); 872 OS << ',' << Log2(Alignment); 873 874 EmitEOL(); 875 876 // Print symbol's rename (original name contains invalid character(s)) if 877 // there is one. 878 MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym); 879 if (XSym->hasRename()) 880 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName()); 881 } 882 883 void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility( 884 MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) { 885 886 switch (Linkage) { 887 case MCSA_Global: 888 OS << MAI->getGlobalDirective(); 889 break; 890 case MCSA_Weak: 891 OS << MAI->getWeakDirective(); 892 break; 893 case MCSA_Extern: 894 OS << "\t.extern\t"; 895 break; 896 case MCSA_LGlobal: 897 OS << "\t.lglobl\t"; 898 break; 899 default: 900 report_fatal_error("unhandled linkage type"); 901 } 902 903 Symbol->print(OS, MAI); 904 905 switch (Visibility) { 906 case MCSA_Invalid: 907 // Nothing to do. 908 break; 909 case MCSA_Hidden: 910 OS << ",hidden"; 911 break; 912 case MCSA_Protected: 913 OS << ",protected"; 914 break; 915 case MCSA_Exported: 916 OS << ",exported"; 917 break; 918 default: 919 report_fatal_error("unexpected value for Visibility type"); 920 } 921 EmitEOL(); 922 923 // Print symbol's rename (original name contains invalid character(s)) if 924 // there is one. 925 if (cast<MCSymbolXCOFF>(Symbol)->hasRename()) 926 emitXCOFFRenameDirective(Symbol, 927 cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName()); 928 } 929 930 void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name, 931 StringRef Rename) { 932 OS << "\t.rename\t"; 933 Name->print(OS, MAI); 934 const char DQ = '"'; 935 OS << ',' << DQ; 936 for (char C : Rename) { 937 // To escape a double quote character, the character should be doubled. 938 if (C == DQ) 939 OS << DQ; 940 OS << C; 941 } 942 OS << DQ; 943 EmitEOL(); 944 } 945 946 void MCAsmStreamer::emitXCOFFRefDirective(StringRef Name) { 947 OS << "\t.ref " << Name; 948 EmitEOL(); 949 } 950 951 void MCAsmStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol, 952 const MCSymbol *Trap, 953 unsigned Lang, 954 unsigned Reason, 955 unsigned FunctionSize, 956 bool hasDebug) { 957 OS << "\t.except\t"; 958 Symbol->print(OS, MAI); 959 OS << ", " << Lang << ", " << Reason; 960 EmitEOL(); 961 } 962 963 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { 964 assert(MAI->hasDotTypeDotSizeDirective()); 965 OS << "\t.size\t"; 966 Symbol->print(OS, MAI); 967 OS << ", "; 968 Value->print(OS, MAI); 969 EmitEOL(); 970 } 971 972 void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, 973 Align ByteAlignment) { 974 OS << "\t.comm\t"; 975 Symbol->print(OS, MAI); 976 OS << ',' << Size; 977 978 if (MAI->getCOMMDirectiveAlignmentIsInBytes()) 979 OS << ',' << ByteAlignment.value(); 980 else 981 OS << ',' << Log2(ByteAlignment); 982 EmitEOL(); 983 984 // Print symbol's rename (original name contains invalid character(s)) if 985 // there is one. 986 MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol); 987 if (XSym && XSym->hasRename()) 988 emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName()); 989 } 990 991 void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, 992 Align ByteAlign) { 993 OS << "\t.lcomm\t"; 994 Symbol->print(OS, MAI); 995 OS << ',' << Size; 996 997 if (ByteAlign > 1) { 998 switch (MAI->getLCOMMDirectiveAlignmentType()) { 999 case LCOMM::NoAlignment: 1000 llvm_unreachable("alignment not supported on .lcomm!"); 1001 case LCOMM::ByteAlignment: 1002 OS << ',' << ByteAlign.value(); 1003 break; 1004 case LCOMM::Log2Alignment: 1005 OS << ',' << Log2(ByteAlign); 1006 break; 1007 } 1008 } 1009 EmitEOL(); 1010 } 1011 1012 void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol, 1013 uint64_t Size, Align ByteAlignment, 1014 SMLoc Loc) { 1015 if (Symbol) 1016 assignFragment(Symbol, &Section->getDummyFragment()); 1017 1018 // Note: a .zerofill directive does not switch sections. 1019 OS << ".zerofill "; 1020 1021 assert(Section->getVariant() == MCSection::SV_MachO && 1022 ".zerofill is a Mach-O specific directive"); 1023 // This is a mach-o specific directive. 1024 1025 const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section); 1026 OS << MOSection->getSegmentName() << "," << MOSection->getName(); 1027 1028 if (Symbol) { 1029 OS << ','; 1030 Symbol->print(OS, MAI); 1031 OS << ',' << Size; 1032 OS << ',' << Log2(ByteAlignment); 1033 } 1034 EmitEOL(); 1035 } 1036 1037 // .tbss sym, size, align 1038 // This depends that the symbol has already been mangled from the original, 1039 // e.g. _a. 1040 void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, 1041 uint64_t Size, Align ByteAlignment) { 1042 assignFragment(Symbol, &Section->getDummyFragment()); 1043 1044 assert(Symbol && "Symbol shouldn't be NULL!"); 1045 // Instead of using the Section we'll just use the shortcut. 1046 1047 assert(Section->getVariant() == MCSection::SV_MachO && 1048 ".zerofill is a Mach-O specific directive"); 1049 // This is a mach-o specific directive and section. 1050 1051 OS << ".tbss "; 1052 Symbol->print(OS, MAI); 1053 OS << ", " << Size; 1054 1055 // Output align if we have it. We default to 1 so don't bother printing 1056 // that. 1057 if (ByteAlignment > 1) 1058 OS << ", " << Log2(ByteAlignment); 1059 1060 EmitEOL(); 1061 } 1062 1063 static inline bool isPrintableString(StringRef Data) { 1064 const auto BeginPtr = Data.begin(), EndPtr = Data.end(); 1065 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) { 1066 if (!isPrint(C)) 1067 return false; 1068 } 1069 return isPrint(Data.back()) || Data.back() == 0; 1070 } 1071 1072 static inline char toOctal(int X) { return (X&7)+'0'; } 1073 1074 static void PrintByteList(StringRef Data, raw_ostream &OS, 1075 MCAsmInfo::AsmCharLiteralSyntax ACLS) { 1076 assert(!Data.empty() && "Cannot generate an empty list."); 1077 const auto printCharacterInOctal = [&OS](unsigned char C) { 1078 OS << '0'; 1079 OS << toOctal(C >> 6); 1080 OS << toOctal(C >> 3); 1081 OS << toOctal(C >> 0); 1082 }; 1083 const auto printOneCharacterFor = [printCharacterInOctal]( 1084 auto printOnePrintingCharacter) { 1085 return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) { 1086 if (isPrint(C)) { 1087 printOnePrintingCharacter(static_cast<char>(C)); 1088 return; 1089 } 1090 printCharacterInOctal(C); 1091 }; 1092 }; 1093 const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) { 1094 const auto BeginPtr = Data.begin(), EndPtr = Data.end(); 1095 for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) { 1096 printOneCharacter(C); 1097 OS << ','; 1098 } 1099 printOneCharacter(*(EndPtr - 1)); 1100 }; 1101 switch (ACLS) { 1102 case MCAsmInfo::ACLS_Unknown: 1103 printCharacterList(printCharacterInOctal); 1104 return; 1105 case MCAsmInfo::ACLS_SingleQuotePrefix: 1106 printCharacterList(printOneCharacterFor([&OS](char C) { 1107 const char AsmCharLitBuf[2] = {'\'', C}; 1108 OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf)); 1109 })); 1110 return; 1111 } 1112 llvm_unreachable("Invalid AsmCharLiteralSyntax value!"); 1113 } 1114 1115 void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const { 1116 OS << '"'; 1117 1118 if (MAI->hasPairedDoubleQuoteStringConstants()) { 1119 for (unsigned char C : Data) { 1120 if (C == '"') 1121 OS << "\"\""; 1122 else 1123 OS << (char)C; 1124 } 1125 } else { 1126 for (unsigned char C : Data) { 1127 if (C == '"' || C == '\\') { 1128 OS << '\\' << (char)C; 1129 continue; 1130 } 1131 1132 if (isPrint((unsigned char)C)) { 1133 OS << (char)C; 1134 continue; 1135 } 1136 1137 switch (C) { 1138 case '\b': 1139 OS << "\\b"; 1140 break; 1141 case '\f': 1142 OS << "\\f"; 1143 break; 1144 case '\n': 1145 OS << "\\n"; 1146 break; 1147 case '\r': 1148 OS << "\\r"; 1149 break; 1150 case '\t': 1151 OS << "\\t"; 1152 break; 1153 default: 1154 OS << '\\'; 1155 OS << toOctal(C >> 6); 1156 OS << toOctal(C >> 3); 1157 OS << toOctal(C >> 0); 1158 break; 1159 } 1160 } 1161 } 1162 1163 OS << '"'; 1164 } 1165 1166 void MCAsmStreamer::emitBytes(StringRef Data) { 1167 assert(getCurrentSectionOnly() && 1168 "Cannot emit contents before setting section!"); 1169 if (Data.empty()) return; 1170 1171 const auto emitAsString = [this](StringRef Data) { 1172 // If the data ends with 0 and the target supports .asciz, use it, otherwise 1173 // use .ascii or a byte-list directive 1174 if (MAI->getAscizDirective() && Data.back() == 0) { 1175 OS << MAI->getAscizDirective(); 1176 Data = Data.substr(0, Data.size() - 1); 1177 } else if (LLVM_LIKELY(MAI->getAsciiDirective())) { 1178 OS << MAI->getAsciiDirective(); 1179 } else if (MAI->hasPairedDoubleQuoteStringConstants() && 1180 isPrintableString(Data)) { 1181 // For target with DoubleQuoteString constants, .string and .byte are used 1182 // as replacement of .asciz and .ascii. 1183 assert(MAI->getPlainStringDirective() && 1184 "hasPairedDoubleQuoteStringConstants target must support " 1185 "PlainString Directive"); 1186 assert(MAI->getByteListDirective() && 1187 "hasPairedDoubleQuoteStringConstants target must support ByteList " 1188 "Directive"); 1189 if (Data.back() == 0) { 1190 OS << MAI->getPlainStringDirective(); 1191 Data = Data.substr(0, Data.size() - 1); 1192 } else { 1193 OS << MAI->getByteListDirective(); 1194 } 1195 } else if (MAI->getByteListDirective()) { 1196 OS << MAI->getByteListDirective(); 1197 PrintByteList(Data, OS, MAI->characterLiteralSyntax()); 1198 EmitEOL(); 1199 return true; 1200 } else { 1201 return false; 1202 } 1203 1204 PrintQuotedString(Data, OS); 1205 EmitEOL(); 1206 return true; 1207 }; 1208 1209 if (Data.size() != 1 && emitAsString(Data)) 1210 return; 1211 1212 // Only single byte is provided or no ascii, asciz, or byte-list directives 1213 // are applicable. Emit as vector of individual 8bits data elements. 1214 if (MCTargetStreamer *TS = getTargetStreamer()) { 1215 TS->emitRawBytes(Data); 1216 return; 1217 } 1218 const char *Directive = MAI->getData8bitsDirective(); 1219 for (const unsigned char C : Data.bytes()) { 1220 OS << Directive << (unsigned)C; 1221 EmitEOL(); 1222 } 1223 } 1224 1225 void MCAsmStreamer::emitBinaryData(StringRef Data) { 1226 // This is binary data. Print it in a grid of hex bytes for readability. 1227 const size_t Cols = 4; 1228 for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) { 1229 size_t J = I, EJ = std::min(I + Cols, Data.size()); 1230 assert(EJ > 0); 1231 OS << MAI->getData8bitsDirective(); 1232 for (; J < EJ - 1; ++J) 1233 OS << format("0x%02x", uint8_t(Data[J])) << ", "; 1234 OS << format("0x%02x", uint8_t(Data[J])); 1235 EmitEOL(); 1236 } 1237 } 1238 1239 void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) { 1240 emitValue(MCConstantExpr::create(Value, getContext()), Size); 1241 } 1242 1243 void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) { 1244 emitValue(MCConstantExpr::create(Value, getContext(), true), Size); 1245 } 1246 1247 void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value, 1248 unsigned Size) { 1249 emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size); 1250 } 1251 1252 void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size, 1253 SMLoc Loc) { 1254 assert(Size <= 8 && "Invalid size"); 1255 assert(getCurrentSectionOnly() && 1256 "Cannot emit contents before setting section!"); 1257 const char *Directive = nullptr; 1258 switch (Size) { 1259 default: break; 1260 case 1: Directive = MAI->getData8bitsDirective(); break; 1261 case 2: Directive = MAI->getData16bitsDirective(); break; 1262 case 4: Directive = MAI->getData32bitsDirective(); break; 1263 case 8: Directive = MAI->getData64bitsDirective(); break; 1264 } 1265 1266 if (!Directive) { 1267 int64_t IntValue; 1268 if (!Value->evaluateAsAbsolute(IntValue)) 1269 report_fatal_error("Don't know how to emit this value."); 1270 1271 // We couldn't handle the requested integer size so we fallback by breaking 1272 // the request down into several, smaller, integers. 1273 // Since sizes greater or equal to "Size" are invalid, we use the greatest 1274 // power of 2 that is less than "Size" as our largest piece of granularity. 1275 bool IsLittleEndian = MAI->isLittleEndian(); 1276 for (unsigned Emitted = 0; Emitted != Size;) { 1277 unsigned Remaining = Size - Emitted; 1278 // The size of our partial emission must be a power of two less than 1279 // Size. 1280 unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1)); 1281 // Calculate the byte offset of our partial emission taking into account 1282 // the endianness of the target. 1283 unsigned ByteOffset = 1284 IsLittleEndian ? Emitted : (Remaining - EmissionSize); 1285 uint64_t ValueToEmit = IntValue >> (ByteOffset * 8); 1286 // We truncate our partial emission to fit within the bounds of the 1287 // emission domain. This produces nicer output and silences potential 1288 // truncation warnings when round tripping through another assembler. 1289 uint64_t Shift = 64 - EmissionSize * 8; 1290 assert(Shift < static_cast<uint64_t>( 1291 std::numeric_limits<unsigned long long>::digits) && 1292 "undefined behavior"); 1293 ValueToEmit &= ~0ULL >> Shift; 1294 emitIntValue(ValueToEmit, EmissionSize); 1295 Emitted += EmissionSize; 1296 } 1297 return; 1298 } 1299 1300 assert(Directive && "Invalid size for machine code value!"); 1301 OS << Directive; 1302 if (MCTargetStreamer *TS = getTargetStreamer()) { 1303 TS->emitValue(Value); 1304 } else { 1305 Value->print(OS, MAI); 1306 EmitEOL(); 1307 } 1308 } 1309 1310 void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) { 1311 int64_t IntValue; 1312 if (Value->evaluateAsAbsolute(IntValue)) { 1313 emitULEB128IntValue(IntValue); 1314 return; 1315 } 1316 OS << "\t.uleb128 "; 1317 Value->print(OS, MAI); 1318 EmitEOL(); 1319 } 1320 1321 void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) { 1322 int64_t IntValue; 1323 if (Value->evaluateAsAbsolute(IntValue)) { 1324 emitSLEB128IntValue(IntValue); 1325 return; 1326 } 1327 OS << "\t.sleb128 "; 1328 Value->print(OS, MAI); 1329 EmitEOL(); 1330 } 1331 1332 void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) { 1333 assert(MAI->getDTPRel64Directive() != nullptr); 1334 OS << MAI->getDTPRel64Directive(); 1335 Value->print(OS, MAI); 1336 EmitEOL(); 1337 } 1338 1339 void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) { 1340 assert(MAI->getDTPRel32Directive() != nullptr); 1341 OS << MAI->getDTPRel32Directive(); 1342 Value->print(OS, MAI); 1343 EmitEOL(); 1344 } 1345 1346 void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) { 1347 assert(MAI->getTPRel64Directive() != nullptr); 1348 OS << MAI->getTPRel64Directive(); 1349 Value->print(OS, MAI); 1350 EmitEOL(); 1351 } 1352 1353 void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) { 1354 assert(MAI->getTPRel32Directive() != nullptr); 1355 OS << MAI->getTPRel32Directive(); 1356 Value->print(OS, MAI); 1357 EmitEOL(); 1358 } 1359 1360 void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) { 1361 assert(MAI->getGPRel64Directive() != nullptr); 1362 OS << MAI->getGPRel64Directive(); 1363 Value->print(OS, MAI); 1364 EmitEOL(); 1365 } 1366 1367 void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) { 1368 assert(MAI->getGPRel32Directive() != nullptr); 1369 OS << MAI->getGPRel32Directive(); 1370 Value->print(OS, MAI); 1371 EmitEOL(); 1372 } 1373 1374 void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, 1375 SMLoc Loc) { 1376 int64_t IntNumBytes; 1377 const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes); 1378 if (IsAbsolute && IntNumBytes == 0) 1379 return; 1380 1381 if (const char *ZeroDirective = MAI->getZeroDirective()) { 1382 if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) { 1383 // FIXME: Emit location directives 1384 OS << ZeroDirective; 1385 NumBytes.print(OS, MAI); 1386 if (FillValue != 0) 1387 OS << ',' << (int)FillValue; 1388 EmitEOL(); 1389 } else { 1390 if (!IsAbsolute) 1391 report_fatal_error( 1392 "Cannot emit non-absolute expression lengths of fill."); 1393 for (int i = 0; i < IntNumBytes; ++i) { 1394 OS << MAI->getData8bitsDirective() << (int)FillValue; 1395 EmitEOL(); 1396 } 1397 } 1398 return; 1399 } 1400 1401 MCStreamer::emitFill(NumBytes, FillValue); 1402 } 1403 1404 void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size, 1405 int64_t Expr, SMLoc Loc) { 1406 // FIXME: Emit location directives 1407 OS << "\t.fill\t"; 1408 NumValues.print(OS, MAI); 1409 OS << ", " << Size << ", 0x"; 1410 OS.write_hex(truncateToSize(Expr, 4)); 1411 EmitEOL(); 1412 } 1413 1414 void MCAsmStreamer::emitAlignmentDirective(unsigned ByteAlignment, 1415 std::optional<int64_t> Value, 1416 unsigned ValueSize, 1417 unsigned MaxBytesToEmit) { 1418 if (MAI->useDotAlignForAlignment()) { 1419 if (!isPowerOf2_32(ByteAlignment)) 1420 report_fatal_error("Only power-of-two alignments are supported " 1421 "with .align."); 1422 OS << "\t.align\t"; 1423 OS << Log2_32(ByteAlignment); 1424 EmitEOL(); 1425 return; 1426 } 1427 1428 // Some assemblers don't support non-power of two alignments, so we always 1429 // emit alignments as a power of two if possible. 1430 if (isPowerOf2_32(ByteAlignment)) { 1431 switch (ValueSize) { 1432 default: 1433 llvm_unreachable("Invalid size for machine code value!"); 1434 case 1: 1435 OS << "\t.p2align\t"; 1436 break; 1437 case 2: 1438 OS << ".p2alignw "; 1439 break; 1440 case 4: 1441 OS << ".p2alignl "; 1442 break; 1443 case 8: 1444 llvm_unreachable("Unsupported alignment size!"); 1445 } 1446 1447 OS << Log2_32(ByteAlignment); 1448 1449 if (Value.has_value() || MaxBytesToEmit) { 1450 if (Value.has_value()) { 1451 OS << ", 0x"; 1452 OS.write_hex(truncateToSize(*Value, ValueSize)); 1453 } else { 1454 OS << ", "; 1455 } 1456 1457 if (MaxBytesToEmit) 1458 OS << ", " << MaxBytesToEmit; 1459 } 1460 EmitEOL(); 1461 return; 1462 } 1463 1464 // Non-power of two alignment. This is not widely supported by assemblers. 1465 // FIXME: Parameterize this based on MAI. 1466 switch (ValueSize) { 1467 default: llvm_unreachable("Invalid size for machine code value!"); 1468 case 1: OS << ".balign"; break; 1469 case 2: OS << ".balignw"; break; 1470 case 4: OS << ".balignl"; break; 1471 case 8: llvm_unreachable("Unsupported alignment size!"); 1472 } 1473 1474 OS << ' ' << ByteAlignment; 1475 if (Value.has_value()) 1476 OS << ", " << truncateToSize(*Value, ValueSize); 1477 else if (MaxBytesToEmit) 1478 OS << ", "; 1479 if (MaxBytesToEmit) 1480 OS << ", " << MaxBytesToEmit; 1481 EmitEOL(); 1482 } 1483 1484 void MCAsmStreamer::emitValueToAlignment(Align Alignment, int64_t Value, 1485 unsigned ValueSize, 1486 unsigned MaxBytesToEmit) { 1487 emitAlignmentDirective(Alignment.value(), Value, ValueSize, MaxBytesToEmit); 1488 } 1489 1490 void MCAsmStreamer::emitCodeAlignment(Align Alignment, 1491 const MCSubtargetInfo *STI, 1492 unsigned MaxBytesToEmit) { 1493 // Emit with a text fill value. 1494 if (MAI->getTextAlignFillValue()) 1495 emitAlignmentDirective(Alignment.value(), MAI->getTextAlignFillValue(), 1, 1496 MaxBytesToEmit); 1497 else 1498 emitAlignmentDirective(Alignment.value(), std::nullopt, 1, MaxBytesToEmit); 1499 } 1500 1501 void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, 1502 unsigned char Value, 1503 SMLoc Loc) { 1504 // FIXME: Verify that Offset is associated with the current section. 1505 OS << ".org "; 1506 Offset->print(OS, MAI); 1507 OS << ", " << (unsigned)Value; 1508 EmitEOL(); 1509 } 1510 1511 void MCAsmStreamer::emitFileDirective(StringRef Filename) { 1512 assert(MAI->hasSingleParameterDotFile()); 1513 OS << "\t.file\t"; 1514 PrintQuotedString(Filename, OS); 1515 EmitEOL(); 1516 } 1517 1518 void MCAsmStreamer::emitFileDirective(StringRef Filename, 1519 StringRef CompilerVerion, 1520 StringRef TimeStamp, 1521 StringRef Description) { 1522 assert(MAI->hasFourStringsDotFile()); 1523 OS << "\t.file\t"; 1524 PrintQuotedString(Filename, OS); 1525 OS << ","; 1526 if (!CompilerVerion.empty()) { 1527 PrintQuotedString(CompilerVerion, OS); 1528 } 1529 if (!TimeStamp.empty()) { 1530 OS << ","; 1531 PrintQuotedString(TimeStamp, OS); 1532 } 1533 if (!Description.empty()) { 1534 OS << ","; 1535 PrintQuotedString(Description, OS); 1536 } 1537 EmitEOL(); 1538 } 1539 1540 void MCAsmStreamer::printDwarfFileDirective( 1541 unsigned FileNo, StringRef Directory, StringRef Filename, 1542 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source, 1543 bool UseDwarfDirectory, raw_svector_ostream &OS) const { 1544 SmallString<128> FullPathName; 1545 1546 if (!UseDwarfDirectory && !Directory.empty()) { 1547 if (sys::path::is_absolute(Filename)) 1548 Directory = ""; 1549 else { 1550 FullPathName = Directory; 1551 sys::path::append(FullPathName, Filename); 1552 Directory = ""; 1553 Filename = FullPathName; 1554 } 1555 } 1556 1557 OS << "\t.file\t" << FileNo << ' '; 1558 if (!Directory.empty()) { 1559 PrintQuotedString(Directory, OS); 1560 OS << ' '; 1561 } 1562 PrintQuotedString(Filename, OS); 1563 if (Checksum) 1564 OS << " md5 0x" << Checksum->digest(); 1565 if (Source) { 1566 OS << " source "; 1567 PrintQuotedString(*Source, OS); 1568 } 1569 } 1570 1571 Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective( 1572 unsigned FileNo, StringRef Directory, StringRef Filename, 1573 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source, 1574 unsigned CUID) { 1575 assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer"); 1576 1577 MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); 1578 unsigned NumFiles = Table.getMCDwarfFiles().size(); 1579 Expected<unsigned> FileNoOrErr = 1580 Table.tryGetFile(Directory, Filename, Checksum, Source, 1581 getContext().getDwarfVersion(), FileNo); 1582 if (!FileNoOrErr) 1583 return FileNoOrErr.takeError(); 1584 FileNo = FileNoOrErr.get(); 1585 1586 // Return early if this file is already emitted before or if target doesn't 1587 // support .file directive. 1588 if (NumFiles == Table.getMCDwarfFiles().size() || 1589 !MAI->usesDwarfFileAndLocDirectives()) 1590 return FileNo; 1591 1592 SmallString<128> Str; 1593 raw_svector_ostream OS1(Str); 1594 printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source, 1595 UseDwarfDirectory, OS1); 1596 1597 if (MCTargetStreamer *TS = getTargetStreamer()) 1598 TS->emitDwarfFileDirective(OS1.str()); 1599 else 1600 emitRawText(OS1.str()); 1601 1602 return FileNo; 1603 } 1604 1605 void MCAsmStreamer::emitDwarfFile0Directive( 1606 StringRef Directory, StringRef Filename, 1607 std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source, 1608 unsigned CUID) { 1609 assert(CUID == 0); 1610 // .file 0 is new for DWARF v5. 1611 if (getContext().getDwarfVersion() < 5) 1612 return; 1613 // Inform MCDwarf about the root file. 1614 getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum, 1615 Source); 1616 1617 // Target doesn't support .loc/.file directives, return early. 1618 if (!MAI->usesDwarfFileAndLocDirectives()) 1619 return; 1620 1621 SmallString<128> Str; 1622 raw_svector_ostream OS1(Str); 1623 printDwarfFileDirective(0, Directory, Filename, Checksum, Source, 1624 UseDwarfDirectory, OS1); 1625 1626 if (MCTargetStreamer *TS = getTargetStreamer()) 1627 TS->emitDwarfFileDirective(OS1.str()); 1628 else 1629 emitRawText(OS1.str()); 1630 } 1631 1632 void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, 1633 unsigned Column, unsigned Flags, 1634 unsigned Isa, unsigned Discriminator, 1635 StringRef FileName) { 1636 // If target doesn't support .loc/.file directive, we need to record the lines 1637 // same way like we do in object mode. 1638 if (!MAI->usesDwarfFileAndLocDirectives()) { 1639 // In case we see two .loc directives in a row, make sure the 1640 // first one gets a line entry. 1641 MCDwarfLineEntry::make(this, getCurrentSectionOnly()); 1642 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa, 1643 Discriminator, FileName); 1644 return; 1645 } 1646 1647 OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; 1648 if (MAI->supportsExtendedDwarfLocDirective()) { 1649 if (Flags & DWARF2_FLAG_BASIC_BLOCK) 1650 OS << " basic_block"; 1651 if (Flags & DWARF2_FLAG_PROLOGUE_END) 1652 OS << " prologue_end"; 1653 if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN) 1654 OS << " epilogue_begin"; 1655 1656 unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags(); 1657 if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) { 1658 OS << " is_stmt "; 1659 1660 if (Flags & DWARF2_FLAG_IS_STMT) 1661 OS << "1"; 1662 else 1663 OS << "0"; 1664 } 1665 1666 if (Isa) 1667 OS << " isa " << Isa; 1668 if (Discriminator) 1669 OS << " discriminator " << Discriminator; 1670 } 1671 1672 if (IsVerboseAsm) { 1673 OS.PadToColumn(MAI->getCommentColumn()); 1674 OS << MAI->getCommentString() << ' ' << FileName << ':' 1675 << Line << ':' << Column; 1676 } 1677 EmitEOL(); 1678 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa, 1679 Discriminator, FileName); 1680 } 1681 1682 MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { 1683 // Always use the zeroth line table, since asm syntax only supports one line 1684 // table for now. 1685 return MCStreamer::getDwarfLineTableSymbol(0); 1686 } 1687 1688 bool MCAsmStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename, 1689 ArrayRef<uint8_t> Checksum, 1690 unsigned ChecksumKind) { 1691 if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum, 1692 ChecksumKind)) 1693 return false; 1694 1695 OS << "\t.cv_file\t" << FileNo << ' '; 1696 PrintQuotedString(Filename, OS); 1697 1698 if (!ChecksumKind) { 1699 EmitEOL(); 1700 return true; 1701 } 1702 1703 OS << ' '; 1704 PrintQuotedString(toHex(Checksum), OS); 1705 OS << ' ' << ChecksumKind; 1706 1707 EmitEOL(); 1708 return true; 1709 } 1710 1711 bool MCAsmStreamer::emitCVFuncIdDirective(unsigned FuncId) { 1712 OS << "\t.cv_func_id " << FuncId << '\n'; 1713 return MCStreamer::emitCVFuncIdDirective(FuncId); 1714 } 1715 1716 bool MCAsmStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId, 1717 unsigned IAFunc, 1718 unsigned IAFile, 1719 unsigned IALine, unsigned IACol, 1720 SMLoc Loc) { 1721 OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc 1722 << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n'; 1723 return MCStreamer::emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile, 1724 IALine, IACol, Loc); 1725 } 1726 1727 void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo, 1728 unsigned Line, unsigned Column, 1729 bool PrologueEnd, bool IsStmt, 1730 StringRef FileName, SMLoc Loc) { 1731 // Validate the directive. 1732 if (!checkCVLocSection(FunctionId, FileNo, Loc)) 1733 return; 1734 1735 OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " " 1736 << Column; 1737 if (PrologueEnd) 1738 OS << " prologue_end"; 1739 1740 if (IsStmt) 1741 OS << " is_stmt 1"; 1742 1743 if (IsVerboseAsm) { 1744 OS.PadToColumn(MAI->getCommentColumn()); 1745 OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':' 1746 << Column; 1747 } 1748 EmitEOL(); 1749 } 1750 1751 void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId, 1752 const MCSymbol *FnStart, 1753 const MCSymbol *FnEnd) { 1754 OS << "\t.cv_linetable\t" << FunctionId << ", "; 1755 FnStart->print(OS, MAI); 1756 OS << ", "; 1757 FnEnd->print(OS, MAI); 1758 EmitEOL(); 1759 this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd); 1760 } 1761 1762 void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId, 1763 unsigned SourceFileId, 1764 unsigned SourceLineNum, 1765 const MCSymbol *FnStartSym, 1766 const MCSymbol *FnEndSym) { 1767 OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId 1768 << ' ' << SourceLineNum << ' '; 1769 FnStartSym->print(OS, MAI); 1770 OS << ' '; 1771 FnEndSym->print(OS, MAI); 1772 EmitEOL(); 1773 this->MCStreamer::emitCVInlineLinetableDirective( 1774 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym); 1775 } 1776 1777 void MCAsmStreamer::PrintCVDefRangePrefix( 1778 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) { 1779 OS << "\t.cv_def_range\t"; 1780 for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) { 1781 OS << ' '; 1782 Range.first->print(OS, MAI); 1783 OS << ' '; 1784 Range.second->print(OS, MAI); 1785 } 1786 } 1787 1788 void MCAsmStreamer::emitCVDefRangeDirective( 1789 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1790 codeview::DefRangeRegisterRelHeader DRHdr) { 1791 PrintCVDefRangePrefix(Ranges); 1792 OS << ", reg_rel, "; 1793 OS << DRHdr.Register << ", " << DRHdr.Flags << ", " 1794 << DRHdr.BasePointerOffset; 1795 EmitEOL(); 1796 } 1797 1798 void MCAsmStreamer::emitCVDefRangeDirective( 1799 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1800 codeview::DefRangeSubfieldRegisterHeader DRHdr) { 1801 PrintCVDefRangePrefix(Ranges); 1802 OS << ", subfield_reg, "; 1803 OS << DRHdr.Register << ", " << DRHdr.OffsetInParent; 1804 EmitEOL(); 1805 } 1806 1807 void MCAsmStreamer::emitCVDefRangeDirective( 1808 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1809 codeview::DefRangeRegisterHeader DRHdr) { 1810 PrintCVDefRangePrefix(Ranges); 1811 OS << ", reg, "; 1812 OS << DRHdr.Register; 1813 EmitEOL(); 1814 } 1815 1816 void MCAsmStreamer::emitCVDefRangeDirective( 1817 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges, 1818 codeview::DefRangeFramePointerRelHeader DRHdr) { 1819 PrintCVDefRangePrefix(Ranges); 1820 OS << ", frame_ptr_rel, "; 1821 OS << DRHdr.Offset; 1822 EmitEOL(); 1823 } 1824 1825 void MCAsmStreamer::emitCVStringTableDirective() { 1826 OS << "\t.cv_stringtable"; 1827 EmitEOL(); 1828 } 1829 1830 void MCAsmStreamer::emitCVFileChecksumsDirective() { 1831 OS << "\t.cv_filechecksums"; 1832 EmitEOL(); 1833 } 1834 1835 void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) { 1836 OS << "\t.cv_filechecksumoffset\t" << FileNo; 1837 EmitEOL(); 1838 } 1839 1840 void MCAsmStreamer::emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) { 1841 OS << "\t.cv_fpo_data\t"; 1842 ProcSym->print(OS, MAI); 1843 EmitEOL(); 1844 } 1845 1846 void MCAsmStreamer::emitIdent(StringRef IdentString) { 1847 assert(MAI->hasIdentDirective() && ".ident directive not supported"); 1848 OS << "\t.ident\t"; 1849 PrintQuotedString(IdentString, OS); 1850 EmitEOL(); 1851 } 1852 1853 void MCAsmStreamer::emitCFISections(bool EH, bool Debug) { 1854 MCStreamer::emitCFISections(EH, Debug); 1855 OS << "\t.cfi_sections "; 1856 if (EH) { 1857 OS << ".eh_frame"; 1858 if (Debug) 1859 OS << ", .debug_frame"; 1860 } else if (Debug) { 1861 OS << ".debug_frame"; 1862 } 1863 1864 EmitEOL(); 1865 } 1866 1867 void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) { 1868 OS << "\t.cfi_startproc"; 1869 if (Frame.IsSimple) 1870 OS << " simple"; 1871 EmitEOL(); 1872 } 1873 1874 void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) { 1875 MCStreamer::emitCFIEndProcImpl(Frame); 1876 OS << "\t.cfi_endproc"; 1877 EmitEOL(); 1878 } 1879 1880 void MCAsmStreamer::EmitRegisterName(int64_t Register) { 1881 if (!MAI->useDwarfRegNumForCFI()) { 1882 // User .cfi_* directives can use arbitrary DWARF register numbers, not 1883 // just ones that map to LLVM register numbers and have known names. 1884 // Fall back to using the original number directly if no name is known. 1885 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 1886 if (std::optional<unsigned> LLVMRegister = 1887 MRI->getLLVMRegNum(Register, true)) { 1888 InstPrinter->printRegName(OS, *LLVMRegister); 1889 return; 1890 } 1891 } 1892 OS << Register; 1893 } 1894 1895 void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) { 1896 MCStreamer::emitCFIDefCfa(Register, Offset); 1897 OS << "\t.cfi_def_cfa "; 1898 EmitRegisterName(Register); 1899 OS << ", " << Offset; 1900 EmitEOL(); 1901 } 1902 1903 void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset) { 1904 MCStreamer::emitCFIDefCfaOffset(Offset); 1905 OS << "\t.cfi_def_cfa_offset " << Offset; 1906 EmitEOL(); 1907 } 1908 1909 void MCAsmStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset, 1910 int64_t AddressSpace) { 1911 MCStreamer::emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace); 1912 OS << "\t.cfi_llvm_def_aspace_cfa "; 1913 EmitRegisterName(Register); 1914 OS << ", " << Offset; 1915 OS << ", " << AddressSpace; 1916 EmitEOL(); 1917 } 1918 1919 static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) { 1920 OS << "\t.cfi_escape "; 1921 if (!Values.empty()) { 1922 size_t e = Values.size() - 1; 1923 for (size_t i = 0; i < e; ++i) 1924 OS << format("0x%02x", uint8_t(Values[i])) << ", "; 1925 OS << format("0x%02x", uint8_t(Values[e])); 1926 } 1927 } 1928 1929 void MCAsmStreamer::emitCFIEscape(StringRef Values) { 1930 MCStreamer::emitCFIEscape(Values); 1931 PrintCFIEscape(OS, Values); 1932 EmitEOL(); 1933 } 1934 1935 void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size) { 1936 MCStreamer::emitCFIGnuArgsSize(Size); 1937 1938 uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size }; 1939 unsigned Len = encodeULEB128(Size, Buffer + 1) + 1; 1940 1941 PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len)); 1942 EmitEOL(); 1943 } 1944 1945 void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register) { 1946 MCStreamer::emitCFIDefCfaRegister(Register); 1947 OS << "\t.cfi_def_cfa_register "; 1948 EmitRegisterName(Register); 1949 EmitEOL(); 1950 } 1951 1952 void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset) { 1953 this->MCStreamer::emitCFIOffset(Register, Offset); 1954 OS << "\t.cfi_offset "; 1955 EmitRegisterName(Register); 1956 OS << ", " << Offset; 1957 EmitEOL(); 1958 } 1959 1960 void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym, 1961 unsigned Encoding) { 1962 MCStreamer::emitCFIPersonality(Sym, Encoding); 1963 OS << "\t.cfi_personality " << Encoding << ", "; 1964 Sym->print(OS, MAI); 1965 EmitEOL(); 1966 } 1967 1968 void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) { 1969 MCStreamer::emitCFILsda(Sym, Encoding); 1970 OS << "\t.cfi_lsda " << Encoding << ", "; 1971 Sym->print(OS, MAI); 1972 EmitEOL(); 1973 } 1974 1975 void MCAsmStreamer::emitCFIRememberState() { 1976 MCStreamer::emitCFIRememberState(); 1977 OS << "\t.cfi_remember_state"; 1978 EmitEOL(); 1979 } 1980 1981 void MCAsmStreamer::emitCFIRestoreState() { 1982 MCStreamer::emitCFIRestoreState(); 1983 OS << "\t.cfi_restore_state"; 1984 EmitEOL(); 1985 } 1986 1987 void MCAsmStreamer::emitCFIRestore(int64_t Register) { 1988 MCStreamer::emitCFIRestore(Register); 1989 OS << "\t.cfi_restore "; 1990 EmitRegisterName(Register); 1991 EmitEOL(); 1992 } 1993 1994 void MCAsmStreamer::emitCFISameValue(int64_t Register) { 1995 MCStreamer::emitCFISameValue(Register); 1996 OS << "\t.cfi_same_value "; 1997 EmitRegisterName(Register); 1998 EmitEOL(); 1999 } 2000 2001 void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) { 2002 MCStreamer::emitCFIRelOffset(Register, Offset); 2003 OS << "\t.cfi_rel_offset "; 2004 EmitRegisterName(Register); 2005 OS << ", " << Offset; 2006 EmitEOL(); 2007 } 2008 2009 void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) { 2010 MCStreamer::emitCFIAdjustCfaOffset(Adjustment); 2011 OS << "\t.cfi_adjust_cfa_offset " << Adjustment; 2012 EmitEOL(); 2013 } 2014 2015 void MCAsmStreamer::emitCFISignalFrame() { 2016 MCStreamer::emitCFISignalFrame(); 2017 OS << "\t.cfi_signal_frame"; 2018 EmitEOL(); 2019 } 2020 2021 void MCAsmStreamer::emitCFIUndefined(int64_t Register) { 2022 MCStreamer::emitCFIUndefined(Register); 2023 OS << "\t.cfi_undefined "; 2024 EmitRegisterName(Register); 2025 EmitEOL(); 2026 } 2027 2028 void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) { 2029 MCStreamer::emitCFIRegister(Register1, Register2); 2030 OS << "\t.cfi_register "; 2031 EmitRegisterName(Register1); 2032 OS << ", "; 2033 EmitRegisterName(Register2); 2034 EmitEOL(); 2035 } 2036 2037 void MCAsmStreamer::emitCFIWindowSave() { 2038 MCStreamer::emitCFIWindowSave(); 2039 OS << "\t.cfi_window_save"; 2040 EmitEOL(); 2041 } 2042 2043 void MCAsmStreamer::emitCFINegateRAState() { 2044 MCStreamer::emitCFINegateRAState(); 2045 OS << "\t.cfi_negate_ra_state"; 2046 EmitEOL(); 2047 } 2048 2049 void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) { 2050 MCStreamer::emitCFIReturnColumn(Register); 2051 OS << "\t.cfi_return_column "; 2052 EmitRegisterName(Register); 2053 EmitEOL(); 2054 } 2055 2056 void MCAsmStreamer::emitCFIBKeyFrame() { 2057 MCStreamer::emitCFIBKeyFrame(); 2058 OS << "\t.cfi_b_key_frame"; 2059 EmitEOL(); 2060 } 2061 2062 void MCAsmStreamer::emitCFIMTETaggedFrame() { 2063 MCStreamer::emitCFIMTETaggedFrame(); 2064 OS << "\t.cfi_mte_tagged_frame"; 2065 EmitEOL(); 2066 } 2067 2068 void MCAsmStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { 2069 MCStreamer::emitWinCFIStartProc(Symbol, Loc); 2070 2071 OS << ".seh_proc "; 2072 Symbol->print(OS, MAI); 2073 EmitEOL(); 2074 } 2075 2076 void MCAsmStreamer::emitWinCFIEndProc(SMLoc Loc) { 2077 MCStreamer::emitWinCFIEndProc(Loc); 2078 2079 OS << "\t.seh_endproc"; 2080 EmitEOL(); 2081 } 2082 2083 void MCAsmStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) { 2084 MCStreamer::emitWinCFIFuncletOrFuncEnd(Loc); 2085 2086 OS << "\t.seh_endfunclet"; 2087 EmitEOL(); 2088 } 2089 2090 void MCAsmStreamer::emitWinCFIStartChained(SMLoc Loc) { 2091 MCStreamer::emitWinCFIStartChained(Loc); 2092 2093 OS << "\t.seh_startchained"; 2094 EmitEOL(); 2095 } 2096 2097 void MCAsmStreamer::emitWinCFIEndChained(SMLoc Loc) { 2098 MCStreamer::emitWinCFIEndChained(Loc); 2099 2100 OS << "\t.seh_endchained"; 2101 EmitEOL(); 2102 } 2103 2104 void MCAsmStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind, 2105 bool Except, SMLoc Loc) { 2106 MCStreamer::emitWinEHHandler(Sym, Unwind, Except, Loc); 2107 2108 OS << "\t.seh_handler "; 2109 Sym->print(OS, MAI); 2110 char Marker = '@'; 2111 const Triple &T = getContext().getTargetTriple(); 2112 if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb) 2113 Marker = '%'; 2114 if (Unwind) 2115 OS << ", " << Marker << "unwind"; 2116 if (Except) 2117 OS << ", " << Marker << "except"; 2118 EmitEOL(); 2119 } 2120 2121 void MCAsmStreamer::emitWinEHHandlerData(SMLoc Loc) { 2122 MCStreamer::emitWinEHHandlerData(Loc); 2123 2124 // Switch sections. Don't call switchSection directly, because that will 2125 // cause the section switch to be visible in the emitted assembly. 2126 // We only do this so the section switch that terminates the handler 2127 // data block is visible. 2128 WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); 2129 2130 // Do nothing if no frame is open. MCStreamer should've already reported an 2131 // error. 2132 if (!CurFrame) 2133 return; 2134 2135 MCSection *TextSec = &CurFrame->Function->getSection(); 2136 MCSection *XData = getAssociatedXDataSection(TextSec); 2137 switchSectionNoChange(XData); 2138 2139 OS << "\t.seh_handlerdata"; 2140 EmitEOL(); 2141 } 2142 2143 void MCAsmStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) { 2144 MCStreamer::emitWinCFIPushReg(Register, Loc); 2145 2146 OS << "\t.seh_pushreg "; 2147 InstPrinter->printRegName(OS, Register); 2148 EmitEOL(); 2149 } 2150 2151 void MCAsmStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset, 2152 SMLoc Loc) { 2153 MCStreamer::emitWinCFISetFrame(Register, Offset, Loc); 2154 2155 OS << "\t.seh_setframe "; 2156 InstPrinter->printRegName(OS, Register); 2157 OS << ", " << Offset; 2158 EmitEOL(); 2159 } 2160 2161 void MCAsmStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) { 2162 MCStreamer::emitWinCFIAllocStack(Size, Loc); 2163 2164 OS << "\t.seh_stackalloc " << Size; 2165 EmitEOL(); 2166 } 2167 2168 void MCAsmStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset, 2169 SMLoc Loc) { 2170 MCStreamer::emitWinCFISaveReg(Register, Offset, Loc); 2171 2172 OS << "\t.seh_savereg "; 2173 InstPrinter->printRegName(OS, Register); 2174 OS << ", " << Offset; 2175 EmitEOL(); 2176 } 2177 2178 void MCAsmStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset, 2179 SMLoc Loc) { 2180 MCStreamer::emitWinCFISaveXMM(Register, Offset, Loc); 2181 2182 OS << "\t.seh_savexmm "; 2183 InstPrinter->printRegName(OS, Register); 2184 OS << ", " << Offset; 2185 EmitEOL(); 2186 } 2187 2188 void MCAsmStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) { 2189 MCStreamer::emitWinCFIPushFrame(Code, Loc); 2190 2191 OS << "\t.seh_pushframe"; 2192 if (Code) 2193 OS << " @code"; 2194 EmitEOL(); 2195 } 2196 2197 void MCAsmStreamer::emitWinCFIEndProlog(SMLoc Loc) { 2198 MCStreamer::emitWinCFIEndProlog(Loc); 2199 2200 OS << "\t.seh_endprologue"; 2201 EmitEOL(); 2202 } 2203 2204 void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From, 2205 const MCSymbolRefExpr *To, 2206 uint64_t Count) { 2207 OS << "\t.cg_profile "; 2208 From->getSymbol().print(OS, MAI); 2209 OS << ", "; 2210 To->getSymbol().print(OS, MAI); 2211 OS << ", " << Count; 2212 EmitEOL(); 2213 } 2214 2215 void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, 2216 const MCSubtargetInfo &STI) { 2217 raw_ostream &OS = getCommentOS(); 2218 SmallString<256> Code; 2219 SmallVector<MCFixup, 4> Fixups; 2220 raw_svector_ostream VecOS(Code); 2221 2222 // If we have no code emitter, don't emit code. 2223 if (!getAssembler().getEmitterPtr()) 2224 return; 2225 2226 getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); 2227 2228 // If we are showing fixups, create symbolic markers in the encoded 2229 // representation. We do this by making a per-bit map to the fixup item index, 2230 // then trying to display it as nicely as possible. 2231 SmallVector<uint8_t, 64> FixupMap; 2232 FixupMap.resize(Code.size() * 8); 2233 for (unsigned i = 0, e = Code.size() * 8; i != e; ++i) 2234 FixupMap[i] = 0; 2235 2236 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 2237 MCFixup &F = Fixups[i]; 2238 const MCFixupKindInfo &Info = 2239 getAssembler().getBackend().getFixupKindInfo(F.getKind()); 2240 for (unsigned j = 0; j != Info.TargetSize; ++j) { 2241 unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; 2242 assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); 2243 FixupMap[Index] = 1 + i; 2244 } 2245 } 2246 2247 // FIXME: Note the fixup comments for Thumb2 are completely bogus since the 2248 // high order halfword of a 32-bit Thumb2 instruction is emitted first. 2249 OS << "encoding: ["; 2250 for (unsigned i = 0, e = Code.size(); i != e; ++i) { 2251 if (i) 2252 OS << ','; 2253 2254 // See if all bits are the same map entry. 2255 uint8_t MapEntry = FixupMap[i * 8 + 0]; 2256 for (unsigned j = 1; j != 8; ++j) { 2257 if (FixupMap[i * 8 + j] == MapEntry) 2258 continue; 2259 2260 MapEntry = uint8_t(~0U); 2261 break; 2262 } 2263 2264 if (MapEntry != uint8_t(~0U)) { 2265 if (MapEntry == 0) { 2266 OS << format("0x%02x", uint8_t(Code[i])); 2267 } else { 2268 if (Code[i]) { 2269 // FIXME: Some of the 8 bits require fix up. 2270 OS << format("0x%02x", uint8_t(Code[i])) << '\'' 2271 << char('A' + MapEntry - 1) << '\''; 2272 } else 2273 OS << char('A' + MapEntry - 1); 2274 } 2275 } else { 2276 // Otherwise, write out in binary. 2277 OS << "0b"; 2278 for (unsigned j = 8; j--;) { 2279 unsigned Bit = (Code[i] >> j) & 1; 2280 2281 unsigned FixupBit; 2282 if (MAI->isLittleEndian()) 2283 FixupBit = i * 8 + j; 2284 else 2285 FixupBit = i * 8 + (7-j); 2286 2287 if (uint8_t MapEntry = FixupMap[FixupBit]) { 2288 assert(Bit == 0 && "Encoder wrote into fixed up bit!"); 2289 OS << char('A' + MapEntry - 1); 2290 } else 2291 OS << Bit; 2292 } 2293 } 2294 } 2295 OS << "]\n"; 2296 2297 for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { 2298 MCFixup &F = Fixups[i]; 2299 const MCFixupKindInfo &Info = 2300 getAssembler().getBackend().getFixupKindInfo(F.getKind()); 2301 OS << " fixup " << char('A' + i) << " - " 2302 << "offset: " << F.getOffset() << ", value: "; 2303 F.getValue()->print(OS, MAI); 2304 OS << ", kind: " << Info.Name << "\n"; 2305 } 2306 } 2307 2308 void MCAsmStreamer::emitInstruction(const MCInst &Inst, 2309 const MCSubtargetInfo &STI) { 2310 assert(getCurrentSectionOnly() && 2311 "Cannot emit contents before setting section!"); 2312 2313 if (!MAI->usesDwarfFileAndLocDirectives()) 2314 // Now that a machine instruction has been assembled into this section, make 2315 // a line entry for any .loc directive that has been seen. 2316 MCDwarfLineEntry::make(this, getCurrentSectionOnly()); 2317 2318 // Show the encoding in a comment if we have a code emitter. 2319 AddEncodingComment(Inst, STI); 2320 2321 // Show the MCInst if enabled. 2322 if (ShowInst) { 2323 Inst.dump_pretty(getCommentOS(), InstPrinter.get(), "\n "); 2324 getCommentOS() << "\n"; 2325 } 2326 2327 if(getTargetStreamer()) 2328 getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS); 2329 else 2330 InstPrinter->printInst(&Inst, 0, "", STI, OS); 2331 2332 StringRef Comments = CommentToEmit; 2333 if (Comments.size() && Comments.back() != '\n') 2334 getCommentOS() << "\n"; 2335 2336 EmitEOL(); 2337 } 2338 2339 void MCAsmStreamer::emitPseudoProbe( 2340 uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attr, 2341 const MCPseudoProbeInlineStack &InlineStack, MCSymbol *FnSym) { 2342 OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " " 2343 << Attr; 2344 // Emit inline stack like 2345 // @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:11 2346 for (const auto &Site : InlineStack) 2347 OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site); 2348 2349 OS << " " << FnSym->getName(); 2350 2351 EmitEOL(); 2352 } 2353 2354 void MCAsmStreamer::emitBundleAlignMode(Align Alignment) { 2355 OS << "\t.bundle_align_mode " << Log2(Alignment); 2356 EmitEOL(); 2357 } 2358 2359 void MCAsmStreamer::emitBundleLock(bool AlignToEnd) { 2360 OS << "\t.bundle_lock"; 2361 if (AlignToEnd) 2362 OS << " align_to_end"; 2363 EmitEOL(); 2364 } 2365 2366 void MCAsmStreamer::emitBundleUnlock() { 2367 OS << "\t.bundle_unlock"; 2368 EmitEOL(); 2369 } 2370 2371 std::optional<std::pair<bool, std::string>> 2372 MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name, 2373 const MCExpr *Expr, SMLoc, 2374 const MCSubtargetInfo &STI) { 2375 OS << "\t.reloc "; 2376 Offset.print(OS, MAI); 2377 OS << ", " << Name; 2378 if (Expr) { 2379 OS << ", "; 2380 Expr->print(OS, MAI); 2381 } 2382 EmitEOL(); 2383 return std::nullopt; 2384 } 2385 2386 void MCAsmStreamer::emitAddrsig() { 2387 OS << "\t.addrsig"; 2388 EmitEOL(); 2389 } 2390 2391 void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) { 2392 OS << "\t.addrsig_sym "; 2393 Sym->print(OS, MAI); 2394 EmitEOL(); 2395 } 2396 2397 /// EmitRawText - If this file is backed by an assembly streamer, this dumps 2398 /// the specified string in the output .s file. This capability is 2399 /// indicated by the hasRawTextSupport() predicate. 2400 void MCAsmStreamer::emitRawTextImpl(StringRef String) { 2401 if (!String.empty() && String.back() == '\n') 2402 String = String.substr(0, String.size()-1); 2403 OS << String; 2404 EmitEOL(); 2405 } 2406 2407 void MCAsmStreamer::finishImpl() { 2408 // If we are generating dwarf for assembly source files dump out the sections. 2409 if (getContext().getGenDwarfForAssembly()) 2410 MCGenDwarfInfo::Emit(this); 2411 2412 // Now it is time to emit debug line sections if target doesn't support .loc 2413 // and .line directives. 2414 if (!MAI->usesDwarfFileAndLocDirectives()) { 2415 MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams()); 2416 return; 2417 } 2418 2419 // Emit the label for the line table, if requested - since the rest of the 2420 // line table will be defined by .loc/.file directives, and not emitted 2421 // directly, the label is the only work required here. 2422 const auto &Tables = getContext().getMCDwarfLineTables(); 2423 if (!Tables.empty()) { 2424 assert(Tables.size() == 1 && "asm output only supports one line table"); 2425 if (auto *Label = Tables.begin()->second.getLabel()) { 2426 switchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); 2427 emitLabel(Label); 2428 } 2429 } 2430 } 2431 2432 void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) { 2433 // If the assembler on some target fills in the DWARF unit length, we 2434 // don't want to emit the length in the compiler. For example, the AIX 2435 // assembler requires the assembly file with the unit length omitted from 2436 // the debug section headers. In such cases, any label we placed occurs 2437 // after the implied length field. We need to adjust the reference here 2438 // to account for the offset introduced by the inserted length field. 2439 if (!MAI->needsDwarfSectionSizeInHeader()) 2440 return; 2441 MCStreamer::emitDwarfUnitLength(Length, Comment); 2442 } 2443 2444 MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix, 2445 const Twine &Comment) { 2446 // If the assembler on some target fills in the DWARF unit length, we 2447 // don't want to emit the length in the compiler. For example, the AIX 2448 // assembler requires the assembly file with the unit length omitted from 2449 // the debug section headers. In such cases, any label we placed occurs 2450 // after the implied length field. We need to adjust the reference here 2451 // to account for the offset introduced by the inserted length field. 2452 if (!MAI->needsDwarfSectionSizeInHeader()) 2453 return getContext().createTempSymbol(Prefix + "_end"); 2454 return MCStreamer::emitDwarfUnitLength(Prefix, Comment); 2455 } 2456 2457 void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) { 2458 // If the assembler on some target fills in the DWARF unit length, we 2459 // don't want to emit the length in the compiler. For example, the AIX 2460 // assembler requires the assembly file with the unit length omitted from 2461 // the debug section headers. In such cases, any label we placed occurs 2462 // after the implied length field. We need to adjust the reference here 2463 // to account for the offset introduced by the inserted length field. 2464 MCContext &Ctx = getContext(); 2465 if (!MAI->needsDwarfSectionSizeInHeader()) { 2466 MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_"); 2467 // Emit the symbol which does not contain the unit length field. 2468 emitLabel(DebugLineSymTmp); 2469 2470 // Adjust the outer reference to account for the offset introduced by the 2471 // inserted length field. 2472 unsigned LengthFieldSize = 2473 dwarf::getUnitLengthFieldByteSize(Ctx.getDwarfFormat()); 2474 const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx); 2475 const MCExpr *OuterSym = MCBinaryExpr::createSub( 2476 MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx); 2477 2478 emitAssignment(StartSym, OuterSym); 2479 return; 2480 } 2481 MCStreamer::emitDwarfLineStartLabel(StartSym); 2482 } 2483 2484 void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section, 2485 MCSymbol *LastLabel) { 2486 // If the targets write the raw debug line data for assembly output (We can 2487 // not switch to Section and add the end symbol there for assembly output) 2488 // we currently use the .text end label as any section end. This will not 2489 // impact the debugability as we will jump to the caller of the last function 2490 // in the section before we come into the .text end address. 2491 assert(!MAI->usesDwarfFileAndLocDirectives() && 2492 ".loc should not be generated together with raw data!"); 2493 2494 MCContext &Ctx = getContext(); 2495 2496 // FIXME: use section end symbol as end of the Section. We need to consider 2497 // the explicit sections and -ffunction-sections when we try to generate or 2498 // find section end symbol for the Section. 2499 MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection(); 2500 assert(TextSection->hasEnded() && ".text section is not end!"); 2501 2502 MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx); 2503 const MCAsmInfo *AsmInfo = Ctx.getAsmInfo(); 2504 emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, 2505 AsmInfo->getCodePointerSize()); 2506 } 2507 2508 // Generate DWARF line sections for assembly mode without .loc/.file 2509 void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, 2510 const MCSymbol *LastLabel, 2511 const MCSymbol *Label, 2512 unsigned PointerSize) { 2513 assert(!MAI->usesDwarfFileAndLocDirectives() && 2514 ".loc/.file don't need raw data in debug line section!"); 2515 2516 // Set to new address. 2517 AddComment("Set address to " + Label->getName()); 2518 emitIntValue(dwarf::DW_LNS_extended_op, 1); 2519 emitULEB128IntValue(PointerSize + 1); 2520 emitIntValue(dwarf::DW_LNE_set_address, 1); 2521 emitSymbolValue(Label, PointerSize); 2522 2523 if (!LastLabel) { 2524 // Emit the sequence for the LineDelta (from 1) and a zero address delta. 2525 AddComment("Start sequence"); 2526 MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0); 2527 return; 2528 } 2529 2530 // INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence 2531 // for the end of the section. 2532 if (LineDelta == INT64_MAX) { 2533 AddComment("End sequence"); 2534 emitIntValue(dwarf::DW_LNS_extended_op, 1); 2535 emitULEB128IntValue(1); 2536 emitIntValue(dwarf::DW_LNE_end_sequence, 1); 2537 return; 2538 } 2539 2540 // Advance line. 2541 AddComment("Advance line " + Twine(LineDelta)); 2542 emitIntValue(dwarf::DW_LNS_advance_line, 1); 2543 emitSLEB128IntValue(LineDelta); 2544 emitIntValue(dwarf::DW_LNS_copy, 1); 2545 } 2546 2547 void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) { 2548 // Emit section end. This is used to tell the debug line section where the end 2549 // is for a text section if we don't use .loc to represent the debug line. 2550 if (MAI->usesDwarfFileAndLocDirectives()) 2551 return; 2552 2553 switchSectionNoChange(Section); 2554 2555 MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext()); 2556 2557 if (!Sym->isInSection()) 2558 emitLabel(Sym); 2559 } 2560 2561 MCStreamer *llvm::createAsmStreamer(MCContext &Context, 2562 std::unique_ptr<formatted_raw_ostream> OS, 2563 bool isVerboseAsm, bool useDwarfDirectory, 2564 MCInstPrinter *IP, 2565 std::unique_ptr<MCCodeEmitter> &&CE, 2566 std::unique_ptr<MCAsmBackend> &&MAB, 2567 bool ShowInst) { 2568 return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm, 2569 useDwarfDirectory, IP, std::move(CE), std::move(MAB), 2570 ShowInst); 2571 } 2572