brintos

brintos / llvm-project-archived public Read only

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