xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
100b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
110b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
128bcb0991SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCCodeView.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCInstPrinter.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
25e8d8bef9SDimitry Andric #include "llvm/MC/MCPseudoProbe.h"
268bcb0991SDimitry Andric #include "llvm/MC/MCRegister.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCSectionMachO.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
305ffd83dbSDimitry Andric #include "llvm/MC/MCSymbolXCOFF.h"
31349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
3281ad6265SDimitry Andric #include "llvm/Support/Casting.h"
330b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
340b57cec5SDimitry Andric #include "llvm/Support/Format.h"
350b57cec5SDimitry Andric #include "llvm/Support/FormattedStream.h"
360b57cec5SDimitry Andric #include "llvm/Support/LEB128.h"
370b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
380b57cec5SDimitry Andric #include "llvm/Support/Path.h"
3906c3fb27SDimitry Andric #include <algorithm>
40bdd1243dSDimitry Andric #include <optional>
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric using namespace llvm;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric namespace {
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric class MCAsmStreamer final : public MCStreamer {
470b57cec5SDimitry Andric   std::unique_ptr<formatted_raw_ostream> OSOwner;
480b57cec5SDimitry Andric   formatted_raw_ostream &OS;
490b57cec5SDimitry Andric   const MCAsmInfo *MAI;
500b57cec5SDimitry Andric   std::unique_ptr<MCInstPrinter> InstPrinter;
510b57cec5SDimitry Andric   std::unique_ptr<MCAssembler> Assembler;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   SmallString<128> ExplicitCommentToEmit;
540b57cec5SDimitry Andric   SmallString<128> CommentToEmit;
550b57cec5SDimitry Andric   raw_svector_ostream CommentStream;
560b57cec5SDimitry Andric   raw_null_ostream NullStream;
570b57cec5SDimitry Andric 
58*0fca6ea1SDimitry Andric   bool IsVerboseAsm = false;
59*0fca6ea1SDimitry Andric   bool ShowInst = false;
60*0fca6ea1SDimitry Andric   bool UseDwarfDirectory = false;
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   void EmitRegisterName(int64_t Register);
63fe6060f1SDimitry Andric   void PrintQuotedString(StringRef Data, raw_ostream &OS) const;
64fe6060f1SDimitry Andric   void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
65fe6060f1SDimitry Andric                                StringRef Filename,
66bdd1243dSDimitry Andric                                std::optional<MD5::MD5Result> Checksum,
67bdd1243dSDimitry Andric                                std::optional<StringRef> Source,
68fe6060f1SDimitry Andric                                bool UseDwarfDirectory,
69fe6060f1SDimitry Andric                                raw_svector_ostream &OS) const;
705ffd83dbSDimitry Andric   void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
715ffd83dbSDimitry Andric   void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric public:
740b57cec5SDimitry Andric   MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
750b57cec5SDimitry Andric                 MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
76*0fca6ea1SDimitry Andric                 std::unique_ptr<MCAsmBackend> asmbackend)
770b57cec5SDimitry Andric       : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
780b57cec5SDimitry Andric         MAI(Context.getAsmInfo()), InstPrinter(printer),
798bcb0991SDimitry Andric         Assembler(std::make_unique<MCAssembler>(
800b57cec5SDimitry Andric             Context, std::move(asmbackend), std::move(emitter),
810b57cec5SDimitry Andric             (asmbackend) ? asmbackend->createObjectWriter(NullStream)
820b57cec5SDimitry Andric                          : nullptr)),
83*0fca6ea1SDimitry Andric         CommentStream(CommentToEmit) {
840b57cec5SDimitry Andric     assert(InstPrinter);
85480093f4SDimitry Andric     if (Assembler->getBackendPtr())
86480093f4SDimitry Andric       setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric     Context.setUseNamesOnTempLabels(true);
89*0fca6ea1SDimitry Andric 
90*0fca6ea1SDimitry Andric     auto *TO = Context.getTargetOptions();
91*0fca6ea1SDimitry Andric     if (!TO)
92*0fca6ea1SDimitry Andric       return;
93*0fca6ea1SDimitry Andric     IsVerboseAsm = TO->AsmVerbose;
94*0fca6ea1SDimitry Andric     if (IsVerboseAsm)
95*0fca6ea1SDimitry Andric       InstPrinter->setCommentStream(CommentStream);
96*0fca6ea1SDimitry Andric     ShowInst = TO->ShowMCInst;
97*0fca6ea1SDimitry Andric     switch (TO->MCUseDwarfDirectory) {
98*0fca6ea1SDimitry Andric     case MCTargetOptions::DisableDwarfDirectory:
99*0fca6ea1SDimitry Andric       UseDwarfDirectory = false;
100*0fca6ea1SDimitry Andric       break;
101*0fca6ea1SDimitry Andric     case MCTargetOptions::EnableDwarfDirectory:
102*0fca6ea1SDimitry Andric       UseDwarfDirectory = true;
103*0fca6ea1SDimitry Andric       break;
104*0fca6ea1SDimitry Andric     case MCTargetOptions::DefaultDwarfDirectory:
105*0fca6ea1SDimitry Andric       UseDwarfDirectory =
106*0fca6ea1SDimitry Andric           Context.getAsmInfo()->enableDwarfFileDirectoryDefault();
107*0fca6ea1SDimitry Andric       break;
108*0fca6ea1SDimitry Andric     }
1090b57cec5SDimitry Andric   }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   MCAssembler &getAssembler() { return *Assembler; }
1120b57cec5SDimitry Andric   MCAssembler *getAssemblerPtr() override { return nullptr; }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   inline void EmitEOL() {
1150b57cec5SDimitry Andric     // Dump Explicit Comments here.
1160b57cec5SDimitry Andric     emitExplicitComments();
1170b57cec5SDimitry Andric     // If we don't have any comments, just emit a \n.
1180b57cec5SDimitry Andric     if (!IsVerboseAsm) {
1190b57cec5SDimitry Andric       OS << '\n';
1200b57cec5SDimitry Andric       return;
1210b57cec5SDimitry Andric     }
1220b57cec5SDimitry Andric     EmitCommentsAndEOL();
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
1255ffd83dbSDimitry Andric   void emitSyntaxDirective() override;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   void EmitCommentsAndEOL();
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   /// Return true if this streamer supports verbose assembly at all.
1300b57cec5SDimitry Andric   bool isVerboseAsm() const override { return IsVerboseAsm; }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   /// Do we support EmitRawText?
1330b57cec5SDimitry Andric   bool hasRawTextSupport() const override { return true; }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   /// Add a comment that can be emitted to the generated .s file to make the
1360b57cec5SDimitry Andric   /// output of the compiler more readable. This only affects the MCAsmStreamer
1370b57cec5SDimitry Andric   /// and only when verbose assembly output is enabled.
1380b57cec5SDimitry Andric   void AddComment(const Twine &T, bool EOL = true) override;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   /// Add a comment showing the encoding of an instruction.
1410b57cec5SDimitry Andric   void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   /// Return a raw_ostream that comments can be written to.
1440b57cec5SDimitry Andric   /// Unlike AddComment, you are required to terminate comments with \n if you
1450b57cec5SDimitry Andric   /// use this method.
14681ad6265SDimitry Andric   raw_ostream &getCommentOS() override {
1470b57cec5SDimitry Andric     if (!IsVerboseAsm)
1480b57cec5SDimitry Andric       return nulls();  // Discard comments unless in verbose asm mode.
1490b57cec5SDimitry Andric     return CommentStream;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   void emitRawComment(const Twine &T, bool TabPrefix = true) override;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   void addExplicitComment(const Twine &T) override;
1550b57cec5SDimitry Andric   void emitExplicitComments() override;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric   /// Emit a blank line to a .s file to pretty it up.
15881ad6265SDimitry Andric   void addBlankLine() override { EmitEOL(); }
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   /// @name MCStreamer Interface
1610b57cec5SDimitry Andric   /// @{
1620b57cec5SDimitry Andric 
163*0fca6ea1SDimitry Andric   void changeSection(MCSection *Section, uint32_t Subsection) override;
1640b57cec5SDimitry Andric 
165fe6060f1SDimitry Andric   void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
166fe6060f1SDimitry Andric                               bool KeepOriginalSym) override;
1670b57cec5SDimitry Andric 
1685ffd83dbSDimitry Andric   void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
169e8d8bef9SDimitry Andric 
170fe6060f1SDimitry Andric   void emitGNUAttribute(unsigned Tag, unsigned Value) override;
171fe6060f1SDimitry Andric 
172e8d8bef9SDimitry Andric   StringRef getMnemonic(MCInst &MI) override {
173cb14a3feSDimitry Andric     auto [Ptr, Bits] = InstPrinter->getMnemonic(&MI);
174cb14a3feSDimitry Andric     assert((Bits != 0 || Ptr == nullptr) &&
175cb14a3feSDimitry Andric            "Invalid char pointer for instruction with no mnemonic");
176cb14a3feSDimitry Andric     return Ptr;
177e8d8bef9SDimitry Andric   }
178e8d8bef9SDimitry Andric 
1795ffd83dbSDimitry Andric   void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
1800b57cec5SDimitry Andric 
1815ffd83dbSDimitry Andric   void emitAssemblerFlag(MCAssemblerFlag Flag) override;
1825ffd83dbSDimitry Andric   void emitLinkerOptions(ArrayRef<std::string> Options) override;
1835ffd83dbSDimitry Andric   void emitDataRegion(MCDataRegionType Kind) override;
1845ffd83dbSDimitry Andric   void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
1850b57cec5SDimitry Andric                       unsigned Update, VersionTuple SDKVersion) override;
1865ffd83dbSDimitry Andric   void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
1870b57cec5SDimitry Andric                         unsigned Update, VersionTuple SDKVersion) override;
1880eae32dcSDimitry Andric   void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,
1890eae32dcSDimitry Andric                                            unsigned Minor, unsigned Update,
1900eae32dcSDimitry Andric                                            VersionTuple SDKVersion) override;
1915ffd83dbSDimitry Andric   void emitThumbFunc(MCSymbol *Func) override;
1920b57cec5SDimitry Andric 
1935ffd83dbSDimitry Andric   void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
1940eae32dcSDimitry Andric   void emitConditionalAssignment(MCSymbol *Symbol,
1950eae32dcSDimitry Andric                                  const MCExpr *Value) override;
1965ffd83dbSDimitry Andric   void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
1975ffd83dbSDimitry Andric   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
1980b57cec5SDimitry Andric 
1995ffd83dbSDimitry Andric   void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
20081ad6265SDimitry Andric   void beginCOFFSymbolDef(const MCSymbol *Symbol) override;
20181ad6265SDimitry Andric   void emitCOFFSymbolStorageClass(int StorageClass) override;
20281ad6265SDimitry Andric   void emitCOFFSymbolType(int Type) override;
20381ad6265SDimitry Andric   void endCOFFSymbolDef() override;
20481ad6265SDimitry Andric   void emitCOFFSafeSEH(MCSymbol const *Symbol) override;
20581ad6265SDimitry Andric   void emitCOFFSymbolIndex(MCSymbol const *Symbol) override;
20681ad6265SDimitry Andric   void emitCOFFSectionIndex(MCSymbol const *Symbol) override;
20781ad6265SDimitry Andric   void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
20881ad6265SDimitry Andric   void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
2095ffd83dbSDimitry Andric   void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
210bdd1243dSDimitry Andric                                   MCSymbol *CsectSym, Align Alignment) override;
2115ffd83dbSDimitry Andric   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
2125f757f3fSDimitry Andric                                             MCSymbolAttr Linkage,
2135ffd83dbSDimitry Andric                                             MCSymbolAttr Visibility) override;
2145ffd83dbSDimitry Andric   void emitXCOFFRenameDirective(const MCSymbol *Name,
2155ffd83dbSDimitry Andric                                 StringRef Rename) override;
2165ffd83dbSDimitry Andric 
21706c3fb27SDimitry Andric   void emitXCOFFRefDirective(const MCSymbol *Symbol) override;
21881ad6265SDimitry Andric 
219bdd1243dSDimitry Andric   void emitXCOFFExceptDirective(const MCSymbol *Symbol,
220bdd1243dSDimitry Andric                                 const MCSymbol *Trap,
221bdd1243dSDimitry Andric                                 unsigned Lang, unsigned Reason,
222bdd1243dSDimitry Andric                                 unsigned FunctionSize, bool hasDebug) override;
22306c3fb27SDimitry Andric   void emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) override;
224bdd1243dSDimitry Andric 
2250b57cec5SDimitry Andric   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
2265ffd83dbSDimitry Andric   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
227bdd1243dSDimitry Andric                         Align ByteAlignment) override;
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   /// Emit a local common (.lcomm) symbol.
2300b57cec5SDimitry Andric   ///
2310b57cec5SDimitry Andric   /// @param Symbol - The common symbol to emit.
2320b57cec5SDimitry Andric   /// @param Size - The size of the common symbol.
2330b57cec5SDimitry Andric   /// @param ByteAlignment - The alignment of the common symbol in bytes.
2345ffd83dbSDimitry Andric   void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
235bdd1243dSDimitry Andric                              Align ByteAlignment) override;
2360b57cec5SDimitry Andric 
2375ffd83dbSDimitry Andric   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
238bdd1243dSDimitry Andric                     uint64_t Size = 0, Align ByteAlignment = Align(1),
2390b57cec5SDimitry Andric                     SMLoc Loc = SMLoc()) override;
2400b57cec5SDimitry Andric 
2415ffd83dbSDimitry Andric   void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
242bdd1243dSDimitry Andric                       Align ByteAlignment = Align(1)) override;
2430b57cec5SDimitry Andric 
2445ffd83dbSDimitry Andric   void emitBinaryData(StringRef Data) override;
2450b57cec5SDimitry Andric 
2465ffd83dbSDimitry Andric   void emitBytes(StringRef Data) override;
2470b57cec5SDimitry Andric 
2485ffd83dbSDimitry Andric   void emitValueImpl(const MCExpr *Value, unsigned Size,
2490b57cec5SDimitry Andric                      SMLoc Loc = SMLoc()) override;
2505ffd83dbSDimitry Andric   void emitIntValue(uint64_t Value, unsigned Size) override;
2515ffd83dbSDimitry Andric   void emitIntValueInHex(uint64_t Value, unsigned Size) override;
2525ffd83dbSDimitry Andric   void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
2530b57cec5SDimitry Andric 
2545ffd83dbSDimitry Andric   void emitULEB128Value(const MCExpr *Value) override;
2550b57cec5SDimitry Andric 
2565ffd83dbSDimitry Andric   void emitSLEB128Value(const MCExpr *Value) override;
2570b57cec5SDimitry Andric 
2585ffd83dbSDimitry Andric   void emitDTPRel32Value(const MCExpr *Value) override;
2595ffd83dbSDimitry Andric   void emitDTPRel64Value(const MCExpr *Value) override;
2605ffd83dbSDimitry Andric   void emitTPRel32Value(const MCExpr *Value) override;
2615ffd83dbSDimitry Andric   void emitTPRel64Value(const MCExpr *Value) override;
2620b57cec5SDimitry Andric 
2635ffd83dbSDimitry Andric   void emitGPRel64Value(const MCExpr *Value) override;
2640b57cec5SDimitry Andric 
2655ffd83dbSDimitry Andric   void emitGPRel32Value(const MCExpr *Value) override;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
2680b57cec5SDimitry Andric                 SMLoc Loc = SMLoc()) override;
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
2710b57cec5SDimitry Andric                 SMLoc Loc = SMLoc()) override;
2720b57cec5SDimitry Andric 
273*0fca6ea1SDimitry Andric   void emitAlignmentDirective(uint64_t ByteAlignment,
274bdd1243dSDimitry Andric                               std::optional<int64_t> Value, unsigned ValueSize,
275bdd1243dSDimitry Andric                               unsigned MaxBytesToEmit);
276bdd1243dSDimitry Andric 
277bdd1243dSDimitry Andric   void emitValueToAlignment(Align Alignment, int64_t Value = 0,
2780b57cec5SDimitry Andric                             unsigned ValueSize = 1,
2790b57cec5SDimitry Andric                             unsigned MaxBytesToEmit = 0) override;
2800b57cec5SDimitry Andric 
281bdd1243dSDimitry Andric   void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI,
2820b57cec5SDimitry Andric                          unsigned MaxBytesToEmit = 0) override;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   void emitValueToOffset(const MCExpr *Offset,
2850b57cec5SDimitry Andric                          unsigned char Value,
2860b57cec5SDimitry Andric                          SMLoc Loc) override;
2870b57cec5SDimitry Andric 
2885ffd83dbSDimitry Andric   void emitFileDirective(StringRef Filename) override;
289*0fca6ea1SDimitry Andric   void emitFileDirective(StringRef Filename, StringRef CompilerVersion,
290fe6060f1SDimitry Andric                          StringRef TimeStamp, StringRef Description) override;
291bdd1243dSDimitry Andric   Expected<unsigned> tryEmitDwarfFileDirective(
292bdd1243dSDimitry Andric       unsigned FileNo, StringRef Directory, StringRef Filename,
293bdd1243dSDimitry Andric       std::optional<MD5::MD5Result> Checksum = std::nullopt,
294bdd1243dSDimitry Andric       std::optional<StringRef> Source = std::nullopt,
2950b57cec5SDimitry Andric       unsigned CUID = 0) override;
2960b57cec5SDimitry Andric   void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
297bdd1243dSDimitry Andric                                std::optional<MD5::MD5Result> Checksum,
298bdd1243dSDimitry Andric                                std::optional<StringRef> Source,
2990b57cec5SDimitry Andric                                unsigned CUID = 0) override;
3005ffd83dbSDimitry Andric   void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
3015ffd83dbSDimitry Andric                              unsigned Flags, unsigned Isa,
3025ffd83dbSDimitry Andric                              unsigned Discriminator,
3030b57cec5SDimitry Andric                              StringRef FileName) override;
3040b57cec5SDimitry Andric   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
3050b57cec5SDimitry Andric 
30681ad6265SDimitry Andric   bool emitCVFileDirective(unsigned FileNo, StringRef Filename,
3070b57cec5SDimitry Andric                            ArrayRef<uint8_t> Checksum,
3080b57cec5SDimitry Andric                            unsigned ChecksumKind) override;
30981ad6265SDimitry Andric   bool emitCVFuncIdDirective(unsigned FuncId) override;
31081ad6265SDimitry Andric   bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
3110b57cec5SDimitry Andric                                    unsigned IAFile, unsigned IALine,
3120b57cec5SDimitry Andric                                    unsigned IACol, SMLoc Loc) override;
3135ffd83dbSDimitry Andric   void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
3140b57cec5SDimitry Andric                           unsigned Column, bool PrologueEnd, bool IsStmt,
3150b57cec5SDimitry Andric                           StringRef FileName, SMLoc Loc) override;
3165ffd83dbSDimitry Andric   void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
3170b57cec5SDimitry Andric                                 const MCSymbol *FnEnd) override;
3185ffd83dbSDimitry Andric   void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
3190b57cec5SDimitry Andric                                       unsigned SourceFileId,
3200b57cec5SDimitry Andric                                       unsigned SourceLineNum,
3210b57cec5SDimitry Andric                                       const MCSymbol *FnStartSym,
3220b57cec5SDimitry Andric                                       const MCSymbol *FnEndSym) override;
3238bcb0991SDimitry Andric 
3248bcb0991SDimitry Andric   void PrintCVDefRangePrefix(
3258bcb0991SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
3268bcb0991SDimitry Andric 
3275ffd83dbSDimitry Andric   void emitCVDefRangeDirective(
3280b57cec5SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
3298bcb0991SDimitry Andric       codeview::DefRangeRegisterRelHeader DRHdr) override;
3308bcb0991SDimitry Andric 
3315ffd83dbSDimitry Andric   void emitCVDefRangeDirective(
3328bcb0991SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
3338bcb0991SDimitry Andric       codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
3348bcb0991SDimitry Andric 
3355ffd83dbSDimitry Andric   void emitCVDefRangeDirective(
3368bcb0991SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
3378bcb0991SDimitry Andric       codeview::DefRangeRegisterHeader DRHdr) override;
3388bcb0991SDimitry Andric 
3395ffd83dbSDimitry Andric   void emitCVDefRangeDirective(
3408bcb0991SDimitry Andric       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
3418bcb0991SDimitry Andric       codeview::DefRangeFramePointerRelHeader DRHdr) override;
3428bcb0991SDimitry Andric 
3435ffd83dbSDimitry Andric   void emitCVStringTableDirective() override;
3445ffd83dbSDimitry Andric   void emitCVFileChecksumsDirective() override;
3455ffd83dbSDimitry Andric   void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
34681ad6265SDimitry Andric   void emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
3470b57cec5SDimitry Andric 
3485ffd83dbSDimitry Andric   void emitIdent(StringRef IdentString) override;
3495ffd83dbSDimitry Andric   void emitCFIBKeyFrame() override;
35081ad6265SDimitry Andric   void emitCFIMTETaggedFrame() override;
3515ffd83dbSDimitry Andric   void emitCFISections(bool EH, bool Debug) override;
35206c3fb27SDimitry Andric   void emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) override;
35306c3fb27SDimitry Andric   void emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) override;
35406c3fb27SDimitry Andric   void emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) override;
355fe6060f1SDimitry Andric   void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
35606c3fb27SDimitry Andric                                int64_t AddressSpace, SMLoc Loc) override;
35706c3fb27SDimitry Andric   void emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) override;
3585ffd83dbSDimitry Andric   void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
3595ffd83dbSDimitry Andric   void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
36006c3fb27SDimitry Andric   void emitCFIRememberState(SMLoc Loc) override;
36106c3fb27SDimitry Andric   void emitCFIRestoreState(SMLoc Loc) override;
36206c3fb27SDimitry Andric   void emitCFIRestore(int64_t Register, SMLoc Loc) override;
36306c3fb27SDimitry Andric   void emitCFISameValue(int64_t Register, SMLoc Loc) override;
36406c3fb27SDimitry Andric   void emitCFIRelOffset(int64_t Register, int64_t Offset, SMLoc Loc) override;
36506c3fb27SDimitry Andric   void emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) override;
36606c3fb27SDimitry Andric   void emitCFIEscape(StringRef Values, SMLoc Loc) override;
36706c3fb27SDimitry Andric   void emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) override;
3685ffd83dbSDimitry Andric   void emitCFISignalFrame() override;
36906c3fb27SDimitry Andric   void emitCFIUndefined(int64_t Register, SMLoc Loc) override;
37006c3fb27SDimitry Andric   void emitCFIRegister(int64_t Register1, int64_t Register2,
37106c3fb27SDimitry Andric                        SMLoc Loc) override;
37206c3fb27SDimitry Andric   void emitCFIWindowSave(SMLoc Loc) override;
37306c3fb27SDimitry Andric   void emitCFINegateRAState(SMLoc Loc) override;
3745ffd83dbSDimitry Andric   void emitCFIReturnColumn(int64_t Register) override;
375*0fca6ea1SDimitry Andric   void emitCFILabelDirective(SMLoc Loc, StringRef Name) override;
3760b57cec5SDimitry Andric 
37781ad6265SDimitry Andric   void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
37881ad6265SDimitry Andric   void emitWinCFIEndProc(SMLoc Loc) override;
37981ad6265SDimitry Andric   void emitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
38081ad6265SDimitry Andric   void emitWinCFIStartChained(SMLoc Loc) override;
38181ad6265SDimitry Andric   void emitWinCFIEndChained(SMLoc Loc) override;
38281ad6265SDimitry Andric   void emitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
38381ad6265SDimitry Andric   void emitWinCFISetFrame(MCRegister Register, unsigned Offset,
3840b57cec5SDimitry Andric                           SMLoc Loc) override;
38581ad6265SDimitry Andric   void emitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
38681ad6265SDimitry Andric   void emitWinCFISaveReg(MCRegister Register, unsigned Offset,
3870b57cec5SDimitry Andric                          SMLoc Loc) override;
38881ad6265SDimitry Andric   void emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
3890b57cec5SDimitry Andric                          SMLoc Loc) override;
39081ad6265SDimitry Andric   void emitWinCFIPushFrame(bool Code, SMLoc Loc) override;
39181ad6265SDimitry Andric   void emitWinCFIEndProlog(SMLoc Loc) override;
3920b57cec5SDimitry Andric 
39381ad6265SDimitry Andric   void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
3940b57cec5SDimitry Andric                         SMLoc Loc) override;
39581ad6265SDimitry Andric   void emitWinEHHandlerData(SMLoc Loc) override;
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric   void emitCGProfileEntry(const MCSymbolRefExpr *From,
3980b57cec5SDimitry Andric                           const MCSymbolRefExpr *To, uint64_t Count) override;
3990b57cec5SDimitry Andric 
4005ffd83dbSDimitry Andric   void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
4010b57cec5SDimitry Andric 
402e8d8bef9SDimitry Andric   void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
40306c3fb27SDimitry Andric                        uint64_t Attr, uint64_t Discriminator,
40406c3fb27SDimitry Andric                        const MCPseudoProbeInlineStack &InlineStack,
40506c3fb27SDimitry Andric                        MCSymbol *FnSym) override;
406e8d8bef9SDimitry Andric 
407bdd1243dSDimitry Andric   void emitBundleAlignMode(Align Alignment) override;
4085ffd83dbSDimitry Andric   void emitBundleLock(bool AlignToEnd) override;
4095ffd83dbSDimitry Andric   void emitBundleUnlock() override;
4100b57cec5SDimitry Andric 
411bdd1243dSDimitry Andric   std::optional<std::pair<bool, std::string>>
4125ffd83dbSDimitry Andric   emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
4135ffd83dbSDimitry Andric                      SMLoc Loc, const MCSubtargetInfo &STI) override;
4140b57cec5SDimitry Andric 
4155ffd83dbSDimitry Andric   void emitAddrsig() override;
4165ffd83dbSDimitry Andric   void emitAddrsigSym(const MCSymbol *Sym) override;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   /// If this file is backed by an assembly streamer, this dumps the specified
4190b57cec5SDimitry Andric   /// string in the output .s file. This capability is indicated by the
4200b57cec5SDimitry Andric   /// hasRawTextSupport() predicate.
4215ffd83dbSDimitry Andric   void emitRawTextImpl(StringRef String) override;
4220b57cec5SDimitry Andric 
4235ffd83dbSDimitry Andric   void finishImpl() override;
424fe6060f1SDimitry Andric 
425fe6060f1SDimitry Andric   void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override;
426fe6060f1SDimitry Andric 
427fe6060f1SDimitry Andric   MCSymbol *emitDwarfUnitLength(const Twine &Prefix,
428fe6060f1SDimitry Andric                                 const Twine &Comment) override;
429fe6060f1SDimitry Andric 
430fe6060f1SDimitry Andric   void emitDwarfLineStartLabel(MCSymbol *StartSym) override;
431fe6060f1SDimitry Andric 
432fe6060f1SDimitry Andric   void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override;
433fe6060f1SDimitry Andric 
434fe6060f1SDimitry Andric   void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
435fe6060f1SDimitry Andric                                 const MCSymbol *Label,
436fe6060f1SDimitry Andric                                 unsigned PointerSize) override;
437fe6060f1SDimitry Andric 
438fe6060f1SDimitry Andric   void doFinalizationAtSectionEnd(MCSection *Section) override;
4390b57cec5SDimitry Andric };
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric } // end anonymous namespace.
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
4440b57cec5SDimitry Andric   if (!IsVerboseAsm) return;
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   T.toVector(CommentToEmit);
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   if (EOL)
4490b57cec5SDimitry Andric     CommentToEmit.push_back('\n'); // Place comment in a new line.
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric void MCAsmStreamer::EmitCommentsAndEOL() {
4530b57cec5SDimitry Andric   if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
4540b57cec5SDimitry Andric     OS << '\n';
4550b57cec5SDimitry Andric     return;
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   StringRef Comments = CommentToEmit;
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   assert(Comments.back() == '\n' &&
4610b57cec5SDimitry Andric          "Comment array not newline terminated");
4620b57cec5SDimitry Andric   do {
4630b57cec5SDimitry Andric     // Emit a line of comments.
4640b57cec5SDimitry Andric     OS.PadToColumn(MAI->getCommentColumn());
4650b57cec5SDimitry Andric     size_t Position = Comments.find('\n');
4660b57cec5SDimitry Andric     OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric     Comments = Comments.substr(Position+1);
4690b57cec5SDimitry Andric   } while (!Comments.empty());
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   CommentToEmit.clear();
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
4750b57cec5SDimitry Andric   assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
4760b57cec5SDimitry Andric   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
4800b57cec5SDimitry Andric   if (TabPrefix)
4810b57cec5SDimitry Andric     OS << '\t';
4820b57cec5SDimitry Andric   OS << MAI->getCommentString() << T;
4830b57cec5SDimitry Andric   EmitEOL();
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric void MCAsmStreamer::addExplicitComment(const Twine &T) {
4870b57cec5SDimitry Andric   StringRef c = T.getSingleStringRef();
488*0fca6ea1SDimitry Andric   if (c == MAI->getSeparatorString())
4890b57cec5SDimitry Andric     return;
4905f757f3fSDimitry Andric   if (c.starts_with(StringRef("//"))) {
4910b57cec5SDimitry Andric     ExplicitCommentToEmit.append("\t");
4920b57cec5SDimitry Andric     ExplicitCommentToEmit.append(MAI->getCommentString());
4930b57cec5SDimitry Andric     // drop //
4940b57cec5SDimitry Andric     ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
4955f757f3fSDimitry Andric   } else if (c.starts_with(StringRef("/*"))) {
4960b57cec5SDimitry Andric     size_t p = 2, len = c.size() - 2;
4970b57cec5SDimitry Andric     // emit each line in comment as separate newline.
4980b57cec5SDimitry Andric     do {
4990b57cec5SDimitry Andric       size_t newp = std::min(len, c.find_first_of("\r\n", p));
5000b57cec5SDimitry Andric       ExplicitCommentToEmit.append("\t");
5010b57cec5SDimitry Andric       ExplicitCommentToEmit.append(MAI->getCommentString());
5020b57cec5SDimitry Andric       ExplicitCommentToEmit.append(c.slice(p, newp).str());
5030b57cec5SDimitry Andric       // If we have another line in this comment add line
5040b57cec5SDimitry Andric       if (newp < len)
5050b57cec5SDimitry Andric         ExplicitCommentToEmit.append("\n");
5060b57cec5SDimitry Andric       p = newp + 1;
5070b57cec5SDimitry Andric     } while (p < len);
5085f757f3fSDimitry Andric   } else if (c.starts_with(StringRef(MAI->getCommentString()))) {
5090b57cec5SDimitry Andric     ExplicitCommentToEmit.append("\t");
5100b57cec5SDimitry Andric     ExplicitCommentToEmit.append(c.str());
5110b57cec5SDimitry Andric   } else if (c.front() == '#') {
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric     ExplicitCommentToEmit.append("\t");
5140b57cec5SDimitry Andric     ExplicitCommentToEmit.append(MAI->getCommentString());
5150b57cec5SDimitry Andric     ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
5160b57cec5SDimitry Andric   } else
5170b57cec5SDimitry Andric     assert(false && "Unexpected Assembly Comment");
5180b57cec5SDimitry Andric   // full line comments immediately output
5190b57cec5SDimitry Andric   if (c.back() == '\n')
5200b57cec5SDimitry Andric     emitExplicitComments();
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric void MCAsmStreamer::emitExplicitComments() {
5240b57cec5SDimitry Andric   StringRef Comments = ExplicitCommentToEmit;
5250b57cec5SDimitry Andric   if (!Comments.empty())
5260b57cec5SDimitry Andric     OS << Comments;
5270b57cec5SDimitry Andric   ExplicitCommentToEmit.clear();
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric 
530*0fca6ea1SDimitry Andric void MCAsmStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
5310b57cec5SDimitry Andric   if (MCTargetStreamer *TS = getTargetStreamer()) {
532*0fca6ea1SDimitry Andric     TS->changeSection(getCurrentSection().first, Section, Subsection, OS);
5330b57cec5SDimitry Andric   } else {
53481ad6265SDimitry Andric     Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS,
5350b57cec5SDimitry Andric                                   Subsection);
5360b57cec5SDimitry Andric   }
537*0fca6ea1SDimitry Andric   MCStreamer::changeSection(Section, Subsection);
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric 
540fe6060f1SDimitry Andric void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
541fe6060f1SDimitry Andric                                            StringRef Name,
542fe6060f1SDimitry Andric                                            bool KeepOriginalSym) {
5430b57cec5SDimitry Andric   OS << ".symver ";
544fe6060f1SDimitry Andric   OriginalSym->print(OS, MAI);
545fe6060f1SDimitry Andric   OS << ", " << Name;
546fe6060f1SDimitry Andric   if (!KeepOriginalSym && !Name.contains("@@@"))
547fe6060f1SDimitry Andric     OS << ", remove";
5480b57cec5SDimitry Andric   EmitEOL();
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric 
5515ffd83dbSDimitry Andric void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
5525ffd83dbSDimitry Andric   MCStreamer::emitLabel(Symbol, Loc);
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   Symbol->print(OS, MAI);
5550b57cec5SDimitry Andric   OS << MAI->getLabelSuffix();
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   EmitEOL();
5580b57cec5SDimitry Andric }
5590b57cec5SDimitry Andric 
5605ffd83dbSDimitry Andric void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
5610b57cec5SDimitry Andric   StringRef str = MCLOHIdToName(Kind);
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric #ifndef NDEBUG
5640b57cec5SDimitry Andric   int NbArgs = MCLOHIdToNbArgs(Kind);
5650b57cec5SDimitry Andric   assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
5660b57cec5SDimitry Andric   assert(str != "" && "Invalid LOH name");
5670b57cec5SDimitry Andric #endif
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
5700b57cec5SDimitry Andric   bool IsFirst = true;
5710b57cec5SDimitry Andric   for (const MCSymbol *Arg : Args) {
5720b57cec5SDimitry Andric     if (!IsFirst)
5730b57cec5SDimitry Andric       OS << ", ";
5740b57cec5SDimitry Andric     IsFirst = false;
5750b57cec5SDimitry Andric     Arg->print(OS, MAI);
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric   EmitEOL();
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric 
580fe6060f1SDimitry Andric void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {
581fe6060f1SDimitry Andric   OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";
582fe6060f1SDimitry Andric }
583fe6060f1SDimitry Andric 
5845ffd83dbSDimitry Andric void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
5850b57cec5SDimitry Andric   switch (Flag) {
5860b57cec5SDimitry Andric   case MCAF_SyntaxUnified:         OS << "\t.syntax unified"; break;
5870b57cec5SDimitry Andric   case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
5880b57cec5SDimitry Andric   case MCAF_Code16:                OS << '\t'<< MAI->getCode16Directive();break;
5890b57cec5SDimitry Andric   case MCAF_Code32:                OS << '\t'<< MAI->getCode32Directive();break;
5900b57cec5SDimitry Andric   case MCAF_Code64:                OS << '\t'<< MAI->getCode64Directive();break;
5910b57cec5SDimitry Andric   }
5920b57cec5SDimitry Andric   EmitEOL();
5930b57cec5SDimitry Andric }
5940b57cec5SDimitry Andric 
5955ffd83dbSDimitry Andric void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
5960b57cec5SDimitry Andric   assert(!Options.empty() && "At least one option is required!");
5970b57cec5SDimitry Andric   OS << "\t.linker_option \"" << Options[0] << '"';
598bdd1243dSDimitry Andric   for (const std::string &Opt : llvm::drop_begin(Options))
599bdd1243dSDimitry Andric     OS << ", " << '"' << Opt << '"';
6000b57cec5SDimitry Andric   EmitEOL();
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric 
6035ffd83dbSDimitry Andric void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
6040b57cec5SDimitry Andric   if (!MAI->doesSupportDataRegionDirectives())
6050b57cec5SDimitry Andric     return;
6060b57cec5SDimitry Andric   switch (Kind) {
6070b57cec5SDimitry Andric   case MCDR_DataRegion:            OS << "\t.data_region"; break;
6080b57cec5SDimitry Andric   case MCDR_DataRegionJT8:         OS << "\t.data_region jt8"; break;
6090b57cec5SDimitry Andric   case MCDR_DataRegionJT16:        OS << "\t.data_region jt16"; break;
6100b57cec5SDimitry Andric   case MCDR_DataRegionJT32:        OS << "\t.data_region jt32"; break;
6110b57cec5SDimitry Andric   case MCDR_DataRegionEnd:         OS << "\t.end_data_region"; break;
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric   EmitEOL();
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric static const char *getVersionMinDirective(MCVersionMinType Type) {
6170b57cec5SDimitry Andric   switch (Type) {
6180b57cec5SDimitry Andric   case MCVM_WatchOSVersionMin: return ".watchos_version_min";
6190b57cec5SDimitry Andric   case MCVM_TvOSVersionMin:    return ".tvos_version_min";
6200b57cec5SDimitry Andric   case MCVM_IOSVersionMin:     return ".ios_version_min";
6210b57cec5SDimitry Andric   case MCVM_OSXVersionMin:     return ".macosx_version_min";
6220b57cec5SDimitry Andric   }
6230b57cec5SDimitry Andric   llvm_unreachable("Invalid MC version min type");
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric static void EmitSDKVersionSuffix(raw_ostream &OS,
6270b57cec5SDimitry Andric                                  const VersionTuple &SDKVersion) {
6280b57cec5SDimitry Andric   if (SDKVersion.empty())
6290b57cec5SDimitry Andric     return;
6300b57cec5SDimitry Andric   OS << '\t' << "sdk_version " << SDKVersion.getMajor();
6310b57cec5SDimitry Andric   if (auto Minor = SDKVersion.getMinor()) {
6320b57cec5SDimitry Andric     OS << ", " << *Minor;
6330b57cec5SDimitry Andric     if (auto Subminor = SDKVersion.getSubminor()) {
6340b57cec5SDimitry Andric       OS << ", " << *Subminor;
6350b57cec5SDimitry Andric     }
6360b57cec5SDimitry Andric   }
6370b57cec5SDimitry Andric }
6380b57cec5SDimitry Andric 
6395ffd83dbSDimitry Andric void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
6400b57cec5SDimitry Andric                                    unsigned Minor, unsigned Update,
6410b57cec5SDimitry Andric                                    VersionTuple SDKVersion) {
6420b57cec5SDimitry Andric   OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
6430b57cec5SDimitry Andric   if (Update)
6440b57cec5SDimitry Andric     OS << ", " << Update;
6450b57cec5SDimitry Andric   EmitSDKVersionSuffix(OS, SDKVersion);
6460b57cec5SDimitry Andric   EmitEOL();
6470b57cec5SDimitry Andric }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric static const char *getPlatformName(MachO::PlatformType Type) {
6500b57cec5SDimitry Andric   switch (Type) {
6515f757f3fSDimitry Andric #define PLATFORM(platform, id, name, build_name, target, tapi_target,          \
6525f757f3fSDimitry Andric                  marketing)                                                    \
6535f757f3fSDimitry Andric   case MachO::PLATFORM_##platform:                                             \
6545f757f3fSDimitry Andric     return #build_name;
6555f757f3fSDimitry Andric #include "llvm/BinaryFormat/MachO.def"
6560b57cec5SDimitry Andric   }
6570b57cec5SDimitry Andric   llvm_unreachable("Invalid Mach-O platform type");
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6605ffd83dbSDimitry Andric void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
6610b57cec5SDimitry Andric                                      unsigned Minor, unsigned Update,
6620b57cec5SDimitry Andric                                      VersionTuple SDKVersion) {
6630b57cec5SDimitry Andric   const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
6640b57cec5SDimitry Andric   OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
6650b57cec5SDimitry Andric   if (Update)
6660b57cec5SDimitry Andric     OS << ", " << Update;
6670b57cec5SDimitry Andric   EmitSDKVersionSuffix(OS, SDKVersion);
6680b57cec5SDimitry Andric   EmitEOL();
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
6710eae32dcSDimitry Andric void MCAsmStreamer::emitDarwinTargetVariantBuildVersion(
6720eae32dcSDimitry Andric     unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,
6730eae32dcSDimitry Andric     VersionTuple SDKVersion) {
6740eae32dcSDimitry Andric   emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);
6750eae32dcSDimitry Andric }
6760eae32dcSDimitry Andric 
6775ffd83dbSDimitry Andric void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {
6780b57cec5SDimitry Andric   // This needs to emit to a temporary string to get properly quoted
6790b57cec5SDimitry Andric   // MCSymbols when they have spaces in them.
6800b57cec5SDimitry Andric   OS << "\t.thumb_func";
6810b57cec5SDimitry Andric   // Only Mach-O hasSubsectionsViaSymbols()
6820b57cec5SDimitry Andric   if (MAI->hasSubsectionsViaSymbols()) {
6830b57cec5SDimitry Andric     OS << '\t';
6840b57cec5SDimitry Andric     Func->print(OS, MAI);
6850b57cec5SDimitry Andric   }
6860b57cec5SDimitry Andric   EmitEOL();
6870b57cec5SDimitry Andric }
6880b57cec5SDimitry Andric 
6895ffd83dbSDimitry Andric void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
6900b57cec5SDimitry Andric   // Do not emit a .set on inlined target assignments.
6910b57cec5SDimitry Andric   bool EmitSet = true;
6920b57cec5SDimitry Andric   if (auto *E = dyn_cast<MCTargetExpr>(Value))
6930b57cec5SDimitry Andric     if (E->inlineAssignedExpr())
6940b57cec5SDimitry Andric       EmitSet = false;
6950b57cec5SDimitry Andric   if (EmitSet) {
6960b57cec5SDimitry Andric     OS << ".set ";
6970b57cec5SDimitry Andric     Symbol->print(OS, MAI);
6980b57cec5SDimitry Andric     OS << ", ";
6990b57cec5SDimitry Andric     Value->print(OS, MAI);
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric     EmitEOL();
7020b57cec5SDimitry Andric   }
7030b57cec5SDimitry Andric 
7045ffd83dbSDimitry Andric   MCStreamer::emitAssignment(Symbol, Value);
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric 
7070eae32dcSDimitry Andric void MCAsmStreamer::emitConditionalAssignment(MCSymbol *Symbol,
7080eae32dcSDimitry Andric                                               const MCExpr *Value) {
7090eae32dcSDimitry Andric   OS << ".lto_set_conditional ";
7100eae32dcSDimitry Andric   Symbol->print(OS, MAI);
7110eae32dcSDimitry Andric   OS << ", ";
7120eae32dcSDimitry Andric   Value->print(OS, MAI);
7130eae32dcSDimitry Andric   EmitEOL();
7140eae32dcSDimitry Andric }
7150eae32dcSDimitry Andric 
7165ffd83dbSDimitry Andric void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
7170b57cec5SDimitry Andric   OS << ".weakref ";
7180b57cec5SDimitry Andric   Alias->print(OS, MAI);
7190b57cec5SDimitry Andric   OS << ", ";
7200b57cec5SDimitry Andric   Symbol->print(OS, MAI);
7210b57cec5SDimitry Andric   EmitEOL();
7220b57cec5SDimitry Andric }
7230b57cec5SDimitry Andric 
7245ffd83dbSDimitry Andric bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
7250b57cec5SDimitry Andric                                         MCSymbolAttr Attribute) {
7260b57cec5SDimitry Andric   switch (Attribute) {
7270b57cec5SDimitry Andric   case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
7280b57cec5SDimitry Andric   case MCSA_ELF_TypeFunction:    /// .type _foo, STT_FUNC  # aka @function
7290b57cec5SDimitry Andric   case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
7300b57cec5SDimitry Andric   case MCSA_ELF_TypeObject:      /// .type _foo, STT_OBJECT  # aka @object
7310b57cec5SDimitry Andric   case MCSA_ELF_TypeTLS:         /// .type _foo, STT_TLS     # aka @tls_object
7320b57cec5SDimitry Andric   case MCSA_ELF_TypeCommon:      /// .type _foo, STT_COMMON  # aka @common
7330b57cec5SDimitry Andric   case MCSA_ELF_TypeNoType:      /// .type _foo, STT_NOTYPE  # aka @notype
7340b57cec5SDimitry Andric   case MCSA_ELF_TypeGnuUniqueObject:  /// .type _foo, @gnu_unique_object
7350b57cec5SDimitry Andric     if (!MAI->hasDotTypeDotSizeDirective())
7360b57cec5SDimitry Andric       return false; // Symbol attribute not supported
7370b57cec5SDimitry Andric     OS << "\t.type\t";
7380b57cec5SDimitry Andric     Symbol->print(OS, MAI);
7390b57cec5SDimitry Andric     OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
7400b57cec5SDimitry Andric     switch (Attribute) {
7410b57cec5SDimitry Andric     default: return false;
7420b57cec5SDimitry Andric     case MCSA_ELF_TypeFunction:    OS << "function"; break;
7430b57cec5SDimitry Andric     case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
7440b57cec5SDimitry Andric     case MCSA_ELF_TypeObject:      OS << "object"; break;
7450b57cec5SDimitry Andric     case MCSA_ELF_TypeTLS:         OS << "tls_object"; break;
7460b57cec5SDimitry Andric     case MCSA_ELF_TypeCommon:      OS << "common"; break;
7470b57cec5SDimitry Andric     case MCSA_ELF_TypeNoType:      OS << "notype"; break;
7480b57cec5SDimitry Andric     case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
7490b57cec5SDimitry Andric     }
7500b57cec5SDimitry Andric     EmitEOL();
7510b57cec5SDimitry Andric     return true;
7520b57cec5SDimitry Andric   case MCSA_Global: // .globl/.global
7530b57cec5SDimitry Andric     OS << MAI->getGlobalDirective();
7540b57cec5SDimitry Andric     break;
7558bcb0991SDimitry Andric   case MCSA_LGlobal:        OS << "\t.lglobl\t";          break;
7560b57cec5SDimitry Andric   case MCSA_Hidden:         OS << "\t.hidden\t";          break;
7570b57cec5SDimitry Andric   case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
7580b57cec5SDimitry Andric   case MCSA_Internal:       OS << "\t.internal\t";        break;
7590b57cec5SDimitry Andric   case MCSA_LazyReference:  OS << "\t.lazy_reference\t";  break;
7600b57cec5SDimitry Andric   case MCSA_Local:          OS << "\t.local\t";           break;
7610b57cec5SDimitry Andric   case MCSA_NoDeadStrip:
7620b57cec5SDimitry Andric     if (!MAI->hasNoDeadStrip())
7630b57cec5SDimitry Andric       return false;
7640b57cec5SDimitry Andric     OS << "\t.no_dead_strip\t";
7650b57cec5SDimitry Andric     break;
7660b57cec5SDimitry Andric   case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
7670b57cec5SDimitry Andric   case MCSA_AltEntry:       OS << "\t.alt_entry\t";       break;
7680b57cec5SDimitry Andric   case MCSA_PrivateExtern:
7690b57cec5SDimitry Andric     OS << "\t.private_extern\t";
7700b57cec5SDimitry Andric     break;
7710b57cec5SDimitry Andric   case MCSA_Protected:      OS << "\t.protected\t";       break;
7720b57cec5SDimitry Andric   case MCSA_Reference:      OS << "\t.reference\t";       break;
7735ffd83dbSDimitry Andric   case MCSA_Extern:
7745ffd83dbSDimitry Andric     OS << "\t.extern\t";
7755ffd83dbSDimitry Andric     break;
7760b57cec5SDimitry Andric   case MCSA_Weak:           OS << MAI->getWeakDirective(); break;
7770b57cec5SDimitry Andric   case MCSA_WeakDefinition:
7780b57cec5SDimitry Andric     OS << "\t.weak_definition\t";
7790b57cec5SDimitry Andric     break;
7800b57cec5SDimitry Andric       // .weak_reference
7810b57cec5SDimitry Andric   case MCSA_WeakReference:  OS << MAI->getWeakRefDirective(); break;
7820b57cec5SDimitry Andric   case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
7830b57cec5SDimitry Andric   case MCSA_Cold:
7840b57cec5SDimitry Andric     // Assemblers currently do not support a .cold directive.
78581ad6265SDimitry Andric   case MCSA_Exported:
78681ad6265SDimitry Andric     // Non-AIX assemblers currently do not support exported visibility.
7870b57cec5SDimitry Andric     return false;
788bdd1243dSDimitry Andric   case MCSA_Memtag:
789bdd1243dSDimitry Andric     OS << "\t.memtag\t";
790bdd1243dSDimitry Andric     break;
79106c3fb27SDimitry Andric   case MCSA_WeakAntiDep:
79206c3fb27SDimitry Andric     OS << "\t.weak_anti_dep\t";
79306c3fb27SDimitry Andric     break;
7940b57cec5SDimitry Andric   }
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric   Symbol->print(OS, MAI);
7970b57cec5SDimitry Andric   EmitEOL();
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   return true;
8000b57cec5SDimitry Andric }
8010b57cec5SDimitry Andric 
8025ffd83dbSDimitry Andric void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
8030b57cec5SDimitry Andric   OS << ".desc" << ' ';
8040b57cec5SDimitry Andric   Symbol->print(OS, MAI);
8050b57cec5SDimitry Andric   OS << ',' << DescValue;
8060b57cec5SDimitry Andric   EmitEOL();
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric 
8095ffd83dbSDimitry Andric void MCAsmStreamer::emitSyntaxDirective() {
8100b57cec5SDimitry Andric   if (MAI->getAssemblerDialect() == 1) {
8110b57cec5SDimitry Andric     OS << "\t.intel_syntax noprefix";
8120b57cec5SDimitry Andric     EmitEOL();
8130b57cec5SDimitry Andric   }
8140b57cec5SDimitry Andric   // FIXME: Currently emit unprefix'ed registers.
8150b57cec5SDimitry Andric   // The intel_syntax directive has one optional argument
8160b57cec5SDimitry Andric   // with may have a value of prefix or noprefix.
8170b57cec5SDimitry Andric }
8180b57cec5SDimitry Andric 
81981ad6265SDimitry Andric void MCAsmStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {
8200b57cec5SDimitry Andric   OS << "\t.def\t";
8210b57cec5SDimitry Andric   Symbol->print(OS, MAI);
8220b57cec5SDimitry Andric   OS << ';';
8230b57cec5SDimitry Andric   EmitEOL();
8240b57cec5SDimitry Andric }
8250b57cec5SDimitry Andric 
82681ad6265SDimitry Andric void MCAsmStreamer::emitCOFFSymbolStorageClass(int StorageClass) {
8270b57cec5SDimitry Andric   OS << "\t.scl\t" << StorageClass << ';';
8280b57cec5SDimitry Andric   EmitEOL();
8290b57cec5SDimitry Andric }
8300b57cec5SDimitry Andric 
83181ad6265SDimitry Andric void MCAsmStreamer::emitCOFFSymbolType(int Type) {
8320b57cec5SDimitry Andric   OS << "\t.type\t" << Type << ';';
8330b57cec5SDimitry Andric   EmitEOL();
8340b57cec5SDimitry Andric }
8350b57cec5SDimitry Andric 
83681ad6265SDimitry Andric void MCAsmStreamer::endCOFFSymbolDef() {
8370b57cec5SDimitry Andric   OS << "\t.endef";
8380b57cec5SDimitry Andric   EmitEOL();
8390b57cec5SDimitry Andric }
8400b57cec5SDimitry Andric 
84181ad6265SDimitry Andric void MCAsmStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {
8420b57cec5SDimitry Andric   OS << "\t.safeseh\t";
8430b57cec5SDimitry Andric   Symbol->print(OS, MAI);
8440b57cec5SDimitry Andric   EmitEOL();
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
84781ad6265SDimitry Andric void MCAsmStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
8480b57cec5SDimitry Andric   OS << "\t.symidx\t";
8490b57cec5SDimitry Andric   Symbol->print(OS, MAI);
8500b57cec5SDimitry Andric   EmitEOL();
8510b57cec5SDimitry Andric }
8520b57cec5SDimitry Andric 
85381ad6265SDimitry Andric void MCAsmStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {
8540b57cec5SDimitry Andric   OS << "\t.secidx\t";
8550b57cec5SDimitry Andric   Symbol->print(OS, MAI);
8560b57cec5SDimitry Andric   EmitEOL();
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric 
85981ad6265SDimitry Andric void MCAsmStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
8600b57cec5SDimitry Andric   OS << "\t.secrel32\t";
8610b57cec5SDimitry Andric   Symbol->print(OS, MAI);
8620b57cec5SDimitry Andric   if (Offset != 0)
8630b57cec5SDimitry Andric     OS << '+' << Offset;
8640b57cec5SDimitry Andric   EmitEOL();
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric 
86781ad6265SDimitry Andric void MCAsmStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
8680b57cec5SDimitry Andric   OS << "\t.rva\t";
8690b57cec5SDimitry Andric   Symbol->print(OS, MAI);
8700b57cec5SDimitry Andric   if (Offset > 0)
8710b57cec5SDimitry Andric     OS << '+' << Offset;
8720b57cec5SDimitry Andric   else if (Offset < 0)
8730b57cec5SDimitry Andric     OS << '-' << -Offset;
8740b57cec5SDimitry Andric   EmitEOL();
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
8778bcb0991SDimitry Andric // We need an XCOFF-specific version of this directive as the AIX syntax
8788bcb0991SDimitry Andric // requires a QualName argument identifying the csect name and storage mapping
8798bcb0991SDimitry Andric // class to appear before the alignment if we are specifying it.
8805ffd83dbSDimitry Andric void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
881480093f4SDimitry Andric                                                uint64_t Size,
882480093f4SDimitry Andric                                                MCSymbol *CsectSym,
883bdd1243dSDimitry Andric                                                Align Alignment) {
8848bcb0991SDimitry Andric   assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
8858bcb0991SDimitry Andric          "We only support writing log base-2 alignment format with XCOFF.");
8868bcb0991SDimitry Andric 
8878bcb0991SDimitry Andric   OS << "\t.lcomm\t";
888480093f4SDimitry Andric   LabelSym->print(OS, MAI);
889480093f4SDimitry Andric   OS << ',' << Size << ',';
890480093f4SDimitry Andric   CsectSym->print(OS, MAI);
891bdd1243dSDimitry Andric   OS << ',' << Log2(Alignment);
8928bcb0991SDimitry Andric 
8938bcb0991SDimitry Andric   EmitEOL();
894e8d8bef9SDimitry Andric 
895e8d8bef9SDimitry Andric   // Print symbol's rename (original name contains invalid character(s)) if
896e8d8bef9SDimitry Andric   // there is one.
897e8d8bef9SDimitry Andric   MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym);
898e8d8bef9SDimitry Andric   if (XSym->hasRename())
899e8d8bef9SDimitry Andric     emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
9008bcb0991SDimitry Andric }
9018bcb0991SDimitry Andric 
9025ffd83dbSDimitry Andric void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
9035ffd83dbSDimitry Andric     MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
9045ffd83dbSDimitry Andric 
9055ffd83dbSDimitry Andric   switch (Linkage) {
9065ffd83dbSDimitry Andric   case MCSA_Global:
9075ffd83dbSDimitry Andric     OS << MAI->getGlobalDirective();
9085ffd83dbSDimitry Andric     break;
9095ffd83dbSDimitry Andric   case MCSA_Weak:
9105ffd83dbSDimitry Andric     OS << MAI->getWeakDirective();
9115ffd83dbSDimitry Andric     break;
9125ffd83dbSDimitry Andric   case MCSA_Extern:
9135ffd83dbSDimitry Andric     OS << "\t.extern\t";
9145ffd83dbSDimitry Andric     break;
9155ffd83dbSDimitry Andric   case MCSA_LGlobal:
9165ffd83dbSDimitry Andric     OS << "\t.lglobl\t";
9175ffd83dbSDimitry Andric     break;
9185ffd83dbSDimitry Andric   default:
9195ffd83dbSDimitry Andric     report_fatal_error("unhandled linkage type");
9205ffd83dbSDimitry Andric   }
9215ffd83dbSDimitry Andric 
9225ffd83dbSDimitry Andric   Symbol->print(OS, MAI);
9235ffd83dbSDimitry Andric 
9245ffd83dbSDimitry Andric   switch (Visibility) {
9255ffd83dbSDimitry Andric   case MCSA_Invalid:
9265ffd83dbSDimitry Andric     // Nothing to do.
9275ffd83dbSDimitry Andric     break;
9285ffd83dbSDimitry Andric   case MCSA_Hidden:
9295ffd83dbSDimitry Andric     OS << ",hidden";
9305ffd83dbSDimitry Andric     break;
9315ffd83dbSDimitry Andric   case MCSA_Protected:
9325ffd83dbSDimitry Andric     OS << ",protected";
9335ffd83dbSDimitry Andric     break;
93481ad6265SDimitry Andric   case MCSA_Exported:
93581ad6265SDimitry Andric     OS << ",exported";
93681ad6265SDimitry Andric     break;
9375ffd83dbSDimitry Andric   default:
9385ffd83dbSDimitry Andric     report_fatal_error("unexpected value for Visibility type");
9395ffd83dbSDimitry Andric   }
9405ffd83dbSDimitry Andric   EmitEOL();
941e8d8bef9SDimitry Andric 
942e8d8bef9SDimitry Andric   // Print symbol's rename (original name contains invalid character(s)) if
943e8d8bef9SDimitry Andric   // there is one.
944e8d8bef9SDimitry Andric   if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
945e8d8bef9SDimitry Andric     emitXCOFFRenameDirective(Symbol,
946e8d8bef9SDimitry Andric                              cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
9475ffd83dbSDimitry Andric }
9485ffd83dbSDimitry Andric 
9495ffd83dbSDimitry Andric void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
9505ffd83dbSDimitry Andric                                              StringRef Rename) {
9515ffd83dbSDimitry Andric   OS << "\t.rename\t";
9525ffd83dbSDimitry Andric   Name->print(OS, MAI);
9535ffd83dbSDimitry Andric   const char DQ = '"';
9545ffd83dbSDimitry Andric   OS << ',' << DQ;
9555ffd83dbSDimitry Andric   for (char C : Rename) {
9565ffd83dbSDimitry Andric     // To escape a double quote character, the character should be doubled.
9575ffd83dbSDimitry Andric     if (C == DQ)
9585ffd83dbSDimitry Andric       OS << DQ;
9595ffd83dbSDimitry Andric     OS << C;
9605ffd83dbSDimitry Andric   }
9615ffd83dbSDimitry Andric   OS << DQ;
9625ffd83dbSDimitry Andric   EmitEOL();
9635ffd83dbSDimitry Andric }
9645ffd83dbSDimitry Andric 
96506c3fb27SDimitry Andric void MCAsmStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {
96606c3fb27SDimitry Andric   OS << "\t.ref ";
96706c3fb27SDimitry Andric   Symbol->print(OS, MAI);
96881ad6265SDimitry Andric   EmitEOL();
96981ad6265SDimitry Andric }
97081ad6265SDimitry Andric 
971bdd1243dSDimitry Andric void MCAsmStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,
972bdd1243dSDimitry Andric                                              const MCSymbol *Trap,
973bdd1243dSDimitry Andric                                              unsigned Lang,
974bdd1243dSDimitry Andric                                              unsigned Reason,
975bdd1243dSDimitry Andric                                              unsigned FunctionSize,
976bdd1243dSDimitry Andric                                              bool hasDebug) {
977bdd1243dSDimitry Andric   OS << "\t.except\t";
978bdd1243dSDimitry Andric   Symbol->print(OS, MAI);
979bdd1243dSDimitry Andric   OS << ", " << Lang << ", " << Reason;
980bdd1243dSDimitry Andric   EmitEOL();
981bdd1243dSDimitry Andric }
982bdd1243dSDimitry Andric 
98306c3fb27SDimitry Andric void MCAsmStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {
98406c3fb27SDimitry Andric   const char InfoDirective[] = "\t.info ";
98506c3fb27SDimitry Andric   const char *Separator = ", ";
98606c3fb27SDimitry Andric   constexpr int WordSize = sizeof(uint32_t);
98706c3fb27SDimitry Andric 
98806c3fb27SDimitry Andric   // Start by emitting the .info pseudo-op and C_INFO symbol name.
98906c3fb27SDimitry Andric   OS << InfoDirective;
99006c3fb27SDimitry Andric   PrintQuotedString(Name, OS);
99106c3fb27SDimitry Andric   OS << Separator;
99206c3fb27SDimitry Andric 
99306c3fb27SDimitry Andric   size_t MetadataSize = Metadata.size();
99406c3fb27SDimitry Andric 
99506c3fb27SDimitry Andric   // Emit the 4-byte length of the metadata.
99606c3fb27SDimitry Andric   OS << format_hex(MetadataSize, 10) << Separator;
99706c3fb27SDimitry Andric 
99806c3fb27SDimitry Andric   // Nothing left to do if there's no metadata.
99906c3fb27SDimitry Andric   if (MetadataSize == 0) {
100006c3fb27SDimitry Andric     EmitEOL();
100106c3fb27SDimitry Andric     return;
100206c3fb27SDimitry Andric   }
100306c3fb27SDimitry Andric 
100406c3fb27SDimitry Andric   // Metadata needs to be padded out to an even word size when generating
100506c3fb27SDimitry Andric   // assembly because the .info pseudo-op can only generate words of data. We
100606c3fb27SDimitry Andric   // apply the same restriction to the object case for consistency, however the
100706c3fb27SDimitry Andric   // linker doesn't require padding, so it will only save bytes specified by the
100806c3fb27SDimitry Andric   // length and discard any padding.
100906c3fb27SDimitry Andric   uint32_t PaddedSize = alignTo(MetadataSize, WordSize);
101006c3fb27SDimitry Andric   uint32_t PaddingSize = PaddedSize - MetadataSize;
101106c3fb27SDimitry Andric 
101206c3fb27SDimitry Andric   // Write out the payload a word at a time.
101306c3fb27SDimitry Andric   //
101406c3fb27SDimitry Andric   // The assembler has a limit on the number of operands in an expression,
101506c3fb27SDimitry Andric   // so we need multiple .info pseudo-ops. We choose a small number of words
101606c3fb27SDimitry Andric   // per pseudo-op to keep the assembly readable.
101706c3fb27SDimitry Andric   constexpr int WordsPerDirective = 5;
101806c3fb27SDimitry Andric   // Force emitting a new directive to keep the first directive purely about the
101906c3fb27SDimitry Andric   // name and size of the note.
102006c3fb27SDimitry Andric   int WordsBeforeNextDirective = 0;
102106c3fb27SDimitry Andric   auto PrintWord = [&](const uint8_t *WordPtr) {
102206c3fb27SDimitry Andric     if (WordsBeforeNextDirective-- == 0) {
102306c3fb27SDimitry Andric       EmitEOL();
102406c3fb27SDimitry Andric       OS << InfoDirective;
102506c3fb27SDimitry Andric       WordsBeforeNextDirective = WordsPerDirective;
102606c3fb27SDimitry Andric     }
102706c3fb27SDimitry Andric     OS << Separator;
102806c3fb27SDimitry Andric     uint32_t Word = llvm::support::endian::read32be(WordPtr);
102906c3fb27SDimitry Andric     OS << format_hex(Word, 10);
103006c3fb27SDimitry Andric   };
103106c3fb27SDimitry Andric 
103206c3fb27SDimitry Andric   size_t Index = 0;
103306c3fb27SDimitry Andric   for (; Index + WordSize <= MetadataSize; Index += WordSize)
103406c3fb27SDimitry Andric     PrintWord(reinterpret_cast<const uint8_t *>(Metadata.data()) + Index);
103506c3fb27SDimitry Andric 
103606c3fb27SDimitry Andric   // If there is padding, then we have at least one byte of payload left
103706c3fb27SDimitry Andric   // to emit.
103806c3fb27SDimitry Andric   if (PaddingSize) {
103906c3fb27SDimitry Andric     assert(PaddedSize - Index == WordSize);
104006c3fb27SDimitry Andric     std::array<uint8_t, WordSize> LastWord = {0};
104106c3fb27SDimitry Andric     ::memcpy(LastWord.data(), Metadata.data() + Index, MetadataSize - Index);
104206c3fb27SDimitry Andric     PrintWord(LastWord.data());
104306c3fb27SDimitry Andric   }
104406c3fb27SDimitry Andric   EmitEOL();
104506c3fb27SDimitry Andric }
104606c3fb27SDimitry Andric 
10470b57cec5SDimitry Andric void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
10480b57cec5SDimitry Andric   assert(MAI->hasDotTypeDotSizeDirective());
10490b57cec5SDimitry Andric   OS << "\t.size\t";
10500b57cec5SDimitry Andric   Symbol->print(OS, MAI);
10510b57cec5SDimitry Andric   OS << ", ";
10520b57cec5SDimitry Andric   Value->print(OS, MAI);
10530b57cec5SDimitry Andric   EmitEOL();
10540b57cec5SDimitry Andric }
10550b57cec5SDimitry Andric 
10565ffd83dbSDimitry Andric void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1057bdd1243dSDimitry Andric                                      Align ByteAlignment) {
10580b57cec5SDimitry Andric   OS << "\t.comm\t";
10590b57cec5SDimitry Andric   Symbol->print(OS, MAI);
10600b57cec5SDimitry Andric   OS << ',' << Size;
10610b57cec5SDimitry Andric 
10620b57cec5SDimitry Andric   if (MAI->getCOMMDirectiveAlignmentIsInBytes())
1063bdd1243dSDimitry Andric     OS << ',' << ByteAlignment.value();
10640b57cec5SDimitry Andric   else
1065bdd1243dSDimitry Andric     OS << ',' << Log2(ByteAlignment);
10660b57cec5SDimitry Andric   EmitEOL();
1067e8d8bef9SDimitry Andric 
1068e8d8bef9SDimitry Andric   // Print symbol's rename (original name contains invalid character(s)) if
1069e8d8bef9SDimitry Andric   // there is one.
1070e8d8bef9SDimitry Andric   MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
1071e8d8bef9SDimitry Andric   if (XSym && XSym->hasRename())
1072e8d8bef9SDimitry Andric     emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
10730b57cec5SDimitry Andric }
10740b57cec5SDimitry Andric 
10755ffd83dbSDimitry Andric void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
1076bdd1243dSDimitry Andric                                           Align ByteAlign) {
10770b57cec5SDimitry Andric   OS << "\t.lcomm\t";
10780b57cec5SDimitry Andric   Symbol->print(OS, MAI);
10790b57cec5SDimitry Andric   OS << ',' << Size;
10800b57cec5SDimitry Andric 
10810b57cec5SDimitry Andric   if (ByteAlign > 1) {
10820b57cec5SDimitry Andric     switch (MAI->getLCOMMDirectiveAlignmentType()) {
10830b57cec5SDimitry Andric     case LCOMM::NoAlignment:
10840b57cec5SDimitry Andric       llvm_unreachable("alignment not supported on .lcomm!");
10850b57cec5SDimitry Andric     case LCOMM::ByteAlignment:
1086bdd1243dSDimitry Andric       OS << ',' << ByteAlign.value();
10870b57cec5SDimitry Andric       break;
10880b57cec5SDimitry Andric     case LCOMM::Log2Alignment:
1089bdd1243dSDimitry Andric       OS << ',' << Log2(ByteAlign);
10900b57cec5SDimitry Andric       break;
10910b57cec5SDimitry Andric     }
10920b57cec5SDimitry Andric   }
10930b57cec5SDimitry Andric   EmitEOL();
10940b57cec5SDimitry Andric }
10950b57cec5SDimitry Andric 
10965ffd83dbSDimitry Andric void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
1097bdd1243dSDimitry Andric                                  uint64_t Size, Align ByteAlignment,
10980b57cec5SDimitry Andric                                  SMLoc Loc) {
10990b57cec5SDimitry Andric   if (Symbol)
1100*0fca6ea1SDimitry Andric     Symbol->setFragment(&Section->getDummyFragment());
11010b57cec5SDimitry Andric 
11020b57cec5SDimitry Andric   // Note: a .zerofill directive does not switch sections.
11030b57cec5SDimitry Andric   OS << ".zerofill ";
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   assert(Section->getVariant() == MCSection::SV_MachO &&
11060b57cec5SDimitry Andric          ".zerofill is a Mach-O specific directive");
11070b57cec5SDimitry Andric   // This is a mach-o specific directive.
11080b57cec5SDimitry Andric 
11090b57cec5SDimitry Andric   const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
11105ffd83dbSDimitry Andric   OS << MOSection->getSegmentName() << "," << MOSection->getName();
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   if (Symbol) {
11130b57cec5SDimitry Andric     OS << ',';
11140b57cec5SDimitry Andric     Symbol->print(OS, MAI);
11150b57cec5SDimitry Andric     OS << ',' << Size;
1116bdd1243dSDimitry Andric     OS << ',' << Log2(ByteAlignment);
11170b57cec5SDimitry Andric   }
11180b57cec5SDimitry Andric   EmitEOL();
11190b57cec5SDimitry Andric }
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric // .tbss sym, size, align
11220b57cec5SDimitry Andric // This depends that the symbol has already been mangled from the original,
11230b57cec5SDimitry Andric // e.g. _a.
11245ffd83dbSDimitry Andric void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
1125bdd1243dSDimitry Andric                                    uint64_t Size, Align ByteAlignment) {
1126*0fca6ea1SDimitry Andric   Symbol->setFragment(&Section->getDummyFragment());
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric   // Instead of using the Section we'll just use the shortcut.
11290b57cec5SDimitry Andric 
11300b57cec5SDimitry Andric   assert(Section->getVariant() == MCSection::SV_MachO &&
11310b57cec5SDimitry Andric          ".zerofill is a Mach-O specific directive");
11320b57cec5SDimitry Andric   // This is a mach-o specific directive and section.
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric   OS << ".tbss ";
11350b57cec5SDimitry Andric   Symbol->print(OS, MAI);
11360b57cec5SDimitry Andric   OS << ", " << Size;
11370b57cec5SDimitry Andric 
11380b57cec5SDimitry Andric   // Output align if we have it.  We default to 1 so don't bother printing
11390b57cec5SDimitry Andric   // that.
1140bdd1243dSDimitry Andric   if (ByteAlignment > 1)
1141bdd1243dSDimitry Andric     OS << ", " << Log2(ByteAlignment);
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric   EmitEOL();
11440b57cec5SDimitry Andric }
11450b57cec5SDimitry Andric 
1146fe6060f1SDimitry Andric static inline bool isPrintableString(StringRef Data) {
1147fe6060f1SDimitry Andric   const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1148fe6060f1SDimitry Andric   for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1149fe6060f1SDimitry Andric     if (!isPrint(C))
1150fe6060f1SDimitry Andric       return false;
1151fe6060f1SDimitry Andric   }
1152fe6060f1SDimitry Andric   return isPrint(Data.back()) || Data.back() == 0;
1153fe6060f1SDimitry Andric }
1154fe6060f1SDimitry Andric 
11550b57cec5SDimitry Andric static inline char toOctal(int X) { return (X&7)+'0'; }
11560b57cec5SDimitry Andric 
1157e8d8bef9SDimitry Andric static void PrintByteList(StringRef Data, raw_ostream &OS,
1158e8d8bef9SDimitry Andric                           MCAsmInfo::AsmCharLiteralSyntax ACLS) {
1159e8d8bef9SDimitry Andric   assert(!Data.empty() && "Cannot generate an empty list.");
1160e8d8bef9SDimitry Andric   const auto printCharacterInOctal = [&OS](unsigned char C) {
1161e8d8bef9SDimitry Andric     OS << '0';
1162e8d8bef9SDimitry Andric     OS << toOctal(C >> 6);
1163e8d8bef9SDimitry Andric     OS << toOctal(C >> 3);
1164e8d8bef9SDimitry Andric     OS << toOctal(C >> 0);
1165e8d8bef9SDimitry Andric   };
1166e8d8bef9SDimitry Andric   const auto printOneCharacterFor = [printCharacterInOctal](
1167e8d8bef9SDimitry Andric                                         auto printOnePrintingCharacter) {
1168e8d8bef9SDimitry Andric     return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {
1169e8d8bef9SDimitry Andric       if (isPrint(C)) {
1170e8d8bef9SDimitry Andric         printOnePrintingCharacter(static_cast<char>(C));
1171e8d8bef9SDimitry Andric         return;
1172e8d8bef9SDimitry Andric       }
1173e8d8bef9SDimitry Andric       printCharacterInOctal(C);
1174e8d8bef9SDimitry Andric     };
1175e8d8bef9SDimitry Andric   };
1176e8d8bef9SDimitry Andric   const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {
1177e8d8bef9SDimitry Andric     const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1178e8d8bef9SDimitry Andric     for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1179e8d8bef9SDimitry Andric       printOneCharacter(C);
1180e8d8bef9SDimitry Andric       OS << ',';
1181e8d8bef9SDimitry Andric     }
1182e8d8bef9SDimitry Andric     printOneCharacter(*(EndPtr - 1));
1183e8d8bef9SDimitry Andric   };
1184e8d8bef9SDimitry Andric   switch (ACLS) {
1185e8d8bef9SDimitry Andric   case MCAsmInfo::ACLS_Unknown:
1186e8d8bef9SDimitry Andric     printCharacterList(printCharacterInOctal);
1187e8d8bef9SDimitry Andric     return;
1188e8d8bef9SDimitry Andric   case MCAsmInfo::ACLS_SingleQuotePrefix:
1189e8d8bef9SDimitry Andric     printCharacterList(printOneCharacterFor([&OS](char C) {
1190e8d8bef9SDimitry Andric       const char AsmCharLitBuf[2] = {'\'', C};
1191e8d8bef9SDimitry Andric       OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));
1192e8d8bef9SDimitry Andric     }));
1193e8d8bef9SDimitry Andric     return;
1194e8d8bef9SDimitry Andric   }
1195e8d8bef9SDimitry Andric   llvm_unreachable("Invalid AsmCharLiteralSyntax value!");
1196e8d8bef9SDimitry Andric }
1197e8d8bef9SDimitry Andric 
1198fe6060f1SDimitry Andric void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const {
11990b57cec5SDimitry Andric   OS << '"';
12000b57cec5SDimitry Andric 
1201fe6060f1SDimitry Andric   if (MAI->hasPairedDoubleQuoteStringConstants()) {
12024824e7fdSDimitry Andric     for (unsigned char C : Data) {
1203fe6060f1SDimitry Andric       if (C == '"')
1204fe6060f1SDimitry Andric         OS << "\"\"";
1205fe6060f1SDimitry Andric       else
1206fe6060f1SDimitry Andric         OS << (char)C;
1207fe6060f1SDimitry Andric     }
1208fe6060f1SDimitry Andric   } else {
12094824e7fdSDimitry Andric     for (unsigned char C : Data) {
12100b57cec5SDimitry Andric       if (C == '"' || C == '\\') {
12110b57cec5SDimitry Andric         OS << '\\' << (char)C;
12120b57cec5SDimitry Andric         continue;
12130b57cec5SDimitry Andric       }
12140b57cec5SDimitry Andric 
12150b57cec5SDimitry Andric       if (isPrint((unsigned char)C)) {
12160b57cec5SDimitry Andric         OS << (char)C;
12170b57cec5SDimitry Andric         continue;
12180b57cec5SDimitry Andric       }
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric       switch (C) {
1221fe6060f1SDimitry Andric       case '\b':
1222fe6060f1SDimitry Andric         OS << "\\b";
1223fe6060f1SDimitry Andric         break;
1224fe6060f1SDimitry Andric       case '\f':
1225fe6060f1SDimitry Andric         OS << "\\f";
1226fe6060f1SDimitry Andric         break;
1227fe6060f1SDimitry Andric       case '\n':
1228fe6060f1SDimitry Andric         OS << "\\n";
1229fe6060f1SDimitry Andric         break;
1230fe6060f1SDimitry Andric       case '\r':
1231fe6060f1SDimitry Andric         OS << "\\r";
1232fe6060f1SDimitry Andric         break;
1233fe6060f1SDimitry Andric       case '\t':
1234fe6060f1SDimitry Andric         OS << "\\t";
1235fe6060f1SDimitry Andric         break;
12360b57cec5SDimitry Andric       default:
12370b57cec5SDimitry Andric         OS << '\\';
12380b57cec5SDimitry Andric         OS << toOctal(C >> 6);
12390b57cec5SDimitry Andric         OS << toOctal(C >> 3);
12400b57cec5SDimitry Andric         OS << toOctal(C >> 0);
12410b57cec5SDimitry Andric         break;
12420b57cec5SDimitry Andric       }
12430b57cec5SDimitry Andric     }
1244fe6060f1SDimitry Andric   }
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric   OS << '"';
12470b57cec5SDimitry Andric }
12480b57cec5SDimitry Andric 
12495ffd83dbSDimitry Andric void MCAsmStreamer::emitBytes(StringRef Data) {
12500b57cec5SDimitry Andric   assert(getCurrentSectionOnly() &&
12510b57cec5SDimitry Andric          "Cannot emit contents before setting section!");
12520b57cec5SDimitry Andric   if (Data.empty()) return;
12530b57cec5SDimitry Andric 
1254e8d8bef9SDimitry Andric   const auto emitAsString = [this](StringRef Data) {
1255e8d8bef9SDimitry Andric     // If the data ends with 0 and the target supports .asciz, use it, otherwise
1256e8d8bef9SDimitry Andric     // use .ascii or a byte-list directive
1257e8d8bef9SDimitry Andric     if (MAI->getAscizDirective() && Data.back() == 0) {
1258e8d8bef9SDimitry Andric       OS << MAI->getAscizDirective();
1259e8d8bef9SDimitry Andric       Data = Data.substr(0, Data.size() - 1);
1260e8d8bef9SDimitry Andric     } else if (LLVM_LIKELY(MAI->getAsciiDirective())) {
1261e8d8bef9SDimitry Andric       OS << MAI->getAsciiDirective();
1262fe6060f1SDimitry Andric     } else if (MAI->hasPairedDoubleQuoteStringConstants() &&
1263fe6060f1SDimitry Andric                isPrintableString(Data)) {
1264fe6060f1SDimitry Andric       // For target with DoubleQuoteString constants, .string and .byte are used
1265fe6060f1SDimitry Andric       // as replacement of .asciz and .ascii.
1266fe6060f1SDimitry Andric       assert(MAI->getPlainStringDirective() &&
1267fe6060f1SDimitry Andric              "hasPairedDoubleQuoteStringConstants target must support "
1268fe6060f1SDimitry Andric              "PlainString Directive");
1269fe6060f1SDimitry Andric       assert(MAI->getByteListDirective() &&
1270fe6060f1SDimitry Andric              "hasPairedDoubleQuoteStringConstants target must support ByteList "
1271fe6060f1SDimitry Andric              "Directive");
1272fe6060f1SDimitry Andric       if (Data.back() == 0) {
1273fe6060f1SDimitry Andric         OS << MAI->getPlainStringDirective();
1274fe6060f1SDimitry Andric         Data = Data.substr(0, Data.size() - 1);
1275fe6060f1SDimitry Andric       } else {
1276fe6060f1SDimitry Andric         OS << MAI->getByteListDirective();
1277fe6060f1SDimitry Andric       }
1278e8d8bef9SDimitry Andric     } else if (MAI->getByteListDirective()) {
1279e8d8bef9SDimitry Andric       OS << MAI->getByteListDirective();
1280e8d8bef9SDimitry Andric       PrintByteList(Data, OS, MAI->characterLiteralSyntax());
1281e8d8bef9SDimitry Andric       EmitEOL();
1282e8d8bef9SDimitry Andric       return true;
1283e8d8bef9SDimitry Andric     } else {
1284e8d8bef9SDimitry Andric       return false;
1285e8d8bef9SDimitry Andric     }
1286e8d8bef9SDimitry Andric 
1287e8d8bef9SDimitry Andric     PrintQuotedString(Data, OS);
1288e8d8bef9SDimitry Andric     EmitEOL();
1289e8d8bef9SDimitry Andric     return true;
1290e8d8bef9SDimitry Andric   };
1291e8d8bef9SDimitry Andric 
1292e8d8bef9SDimitry Andric   if (Data.size() != 1 && emitAsString(Data))
1293e8d8bef9SDimitry Andric     return;
1294e8d8bef9SDimitry Andric 
1295e8d8bef9SDimitry Andric   // Only single byte is provided or no ascii, asciz, or byte-list directives
1296e8d8bef9SDimitry Andric   // are applicable. Emit as vector of individual 8bits data elements.
12970b57cec5SDimitry Andric   if (MCTargetStreamer *TS = getTargetStreamer()) {
12980b57cec5SDimitry Andric     TS->emitRawBytes(Data);
1299e8d8bef9SDimitry Andric     return;
1300e8d8bef9SDimitry Andric   }
13010b57cec5SDimitry Andric   const char *Directive = MAI->getData8bitsDirective();
13020b57cec5SDimitry Andric   for (const unsigned char C : Data.bytes()) {
13030b57cec5SDimitry Andric     OS << Directive << (unsigned)C;
13040b57cec5SDimitry Andric     EmitEOL();
13050b57cec5SDimitry Andric   }
13060b57cec5SDimitry Andric }
13070b57cec5SDimitry Andric 
13085ffd83dbSDimitry Andric void MCAsmStreamer::emitBinaryData(StringRef Data) {
13090b57cec5SDimitry Andric   // This is binary data. Print it in a grid of hex bytes for readability.
13100b57cec5SDimitry Andric   const size_t Cols = 4;
13110b57cec5SDimitry Andric   for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
13120b57cec5SDimitry Andric     size_t J = I, EJ = std::min(I + Cols, Data.size());
13130b57cec5SDimitry Andric     assert(EJ > 0);
13140b57cec5SDimitry Andric     OS << MAI->getData8bitsDirective();
13150b57cec5SDimitry Andric     for (; J < EJ - 1; ++J)
13160b57cec5SDimitry Andric       OS << format("0x%02x", uint8_t(Data[J])) << ", ";
13170b57cec5SDimitry Andric     OS << format("0x%02x", uint8_t(Data[J]));
13180b57cec5SDimitry Andric     EmitEOL();
13190b57cec5SDimitry Andric   }
13200b57cec5SDimitry Andric }
13210b57cec5SDimitry Andric 
13225ffd83dbSDimitry Andric void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
13235ffd83dbSDimitry Andric   emitValue(MCConstantExpr::create(Value, getContext()), Size);
13240b57cec5SDimitry Andric }
13250b57cec5SDimitry Andric 
13265ffd83dbSDimitry Andric void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
13275ffd83dbSDimitry Andric   emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
13280b57cec5SDimitry Andric }
13290b57cec5SDimitry Andric 
13305ffd83dbSDimitry Andric void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
13315ffd83dbSDimitry Andric                                                  unsigned Size) {
13325ffd83dbSDimitry Andric   emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
13335ffd83dbSDimitry Andric }
13345ffd83dbSDimitry Andric 
13355ffd83dbSDimitry Andric void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
13360b57cec5SDimitry Andric                                   SMLoc Loc) {
13370b57cec5SDimitry Andric   assert(Size <= 8 && "Invalid size");
13380b57cec5SDimitry Andric   assert(getCurrentSectionOnly() &&
13390b57cec5SDimitry Andric          "Cannot emit contents before setting section!");
13400b57cec5SDimitry Andric   const char *Directive = nullptr;
13410b57cec5SDimitry Andric   switch (Size) {
13420b57cec5SDimitry Andric   default: break;
13430b57cec5SDimitry Andric   case 1: Directive = MAI->getData8bitsDirective();  break;
13440b57cec5SDimitry Andric   case 2: Directive = MAI->getData16bitsDirective(); break;
13450b57cec5SDimitry Andric   case 4: Directive = MAI->getData32bitsDirective(); break;
13460b57cec5SDimitry Andric   case 8: Directive = MAI->getData64bitsDirective(); break;
13470b57cec5SDimitry Andric   }
13480b57cec5SDimitry Andric 
13490b57cec5SDimitry Andric   if (!Directive) {
13500b57cec5SDimitry Andric     int64_t IntValue;
13510b57cec5SDimitry Andric     if (!Value->evaluateAsAbsolute(IntValue))
13520b57cec5SDimitry Andric       report_fatal_error("Don't know how to emit this value.");
13530b57cec5SDimitry Andric 
13540b57cec5SDimitry Andric     // We couldn't handle the requested integer size so we fallback by breaking
13550b57cec5SDimitry Andric     // the request down into several, smaller, integers.
13560b57cec5SDimitry Andric     // Since sizes greater or equal to "Size" are invalid, we use the greatest
13570b57cec5SDimitry Andric     // power of 2 that is less than "Size" as our largest piece of granularity.
13580b57cec5SDimitry Andric     bool IsLittleEndian = MAI->isLittleEndian();
13590b57cec5SDimitry Andric     for (unsigned Emitted = 0; Emitted != Size;) {
13600b57cec5SDimitry Andric       unsigned Remaining = Size - Emitted;
13610b57cec5SDimitry Andric       // The size of our partial emission must be a power of two less than
13620b57cec5SDimitry Andric       // Size.
136306c3fb27SDimitry Andric       unsigned EmissionSize = llvm::bit_floor(std::min(Remaining, Size - 1));
13640b57cec5SDimitry Andric       // Calculate the byte offset of our partial emission taking into account
13650b57cec5SDimitry Andric       // the endianness of the target.
13660b57cec5SDimitry Andric       unsigned ByteOffset =
13670b57cec5SDimitry Andric           IsLittleEndian ? Emitted : (Remaining - EmissionSize);
13680b57cec5SDimitry Andric       uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
13690b57cec5SDimitry Andric       // We truncate our partial emission to fit within the bounds of the
13700b57cec5SDimitry Andric       // emission domain.  This produces nicer output and silences potential
13710b57cec5SDimitry Andric       // truncation warnings when round tripping through another assembler.
13720b57cec5SDimitry Andric       uint64_t Shift = 64 - EmissionSize * 8;
13730b57cec5SDimitry Andric       assert(Shift < static_cast<uint64_t>(
13740b57cec5SDimitry Andric                          std::numeric_limits<unsigned long long>::digits) &&
13750b57cec5SDimitry Andric              "undefined behavior");
13760b57cec5SDimitry Andric       ValueToEmit &= ~0ULL >> Shift;
13775ffd83dbSDimitry Andric       emitIntValue(ValueToEmit, EmissionSize);
13780b57cec5SDimitry Andric       Emitted += EmissionSize;
13790b57cec5SDimitry Andric     }
13800b57cec5SDimitry Andric     return;
13810b57cec5SDimitry Andric   }
13820b57cec5SDimitry Andric 
13830b57cec5SDimitry Andric   assert(Directive && "Invalid size for machine code value!");
13840b57cec5SDimitry Andric   OS << Directive;
13850b57cec5SDimitry Andric   if (MCTargetStreamer *TS = getTargetStreamer()) {
13860b57cec5SDimitry Andric     TS->emitValue(Value);
13870b57cec5SDimitry Andric   } else {
13880b57cec5SDimitry Andric     Value->print(OS, MAI);
13890b57cec5SDimitry Andric     EmitEOL();
13900b57cec5SDimitry Andric   }
13910b57cec5SDimitry Andric }
13920b57cec5SDimitry Andric 
13935ffd83dbSDimitry Andric void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
13940b57cec5SDimitry Andric   int64_t IntValue;
13950b57cec5SDimitry Andric   if (Value->evaluateAsAbsolute(IntValue)) {
13965ffd83dbSDimitry Andric     emitULEB128IntValue(IntValue);
13970b57cec5SDimitry Andric     return;
13980b57cec5SDimitry Andric   }
13990b57cec5SDimitry Andric   OS << "\t.uleb128 ";
14000b57cec5SDimitry Andric   Value->print(OS, MAI);
14010b57cec5SDimitry Andric   EmitEOL();
14020b57cec5SDimitry Andric }
14030b57cec5SDimitry Andric 
14045ffd83dbSDimitry Andric void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
14050b57cec5SDimitry Andric   int64_t IntValue;
14060b57cec5SDimitry Andric   if (Value->evaluateAsAbsolute(IntValue)) {
14075ffd83dbSDimitry Andric     emitSLEB128IntValue(IntValue);
14080b57cec5SDimitry Andric     return;
14090b57cec5SDimitry Andric   }
14100b57cec5SDimitry Andric   OS << "\t.sleb128 ";
14110b57cec5SDimitry Andric   Value->print(OS, MAI);
14120b57cec5SDimitry Andric   EmitEOL();
14130b57cec5SDimitry Andric }
14140b57cec5SDimitry Andric 
14155ffd83dbSDimitry Andric void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {
14160b57cec5SDimitry Andric   assert(MAI->getDTPRel64Directive() != nullptr);
14170b57cec5SDimitry Andric   OS << MAI->getDTPRel64Directive();
14180b57cec5SDimitry Andric   Value->print(OS, MAI);
14190b57cec5SDimitry Andric   EmitEOL();
14200b57cec5SDimitry Andric }
14210b57cec5SDimitry Andric 
14225ffd83dbSDimitry Andric void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {
14230b57cec5SDimitry Andric   assert(MAI->getDTPRel32Directive() != nullptr);
14240b57cec5SDimitry Andric   OS << MAI->getDTPRel32Directive();
14250b57cec5SDimitry Andric   Value->print(OS, MAI);
14260b57cec5SDimitry Andric   EmitEOL();
14270b57cec5SDimitry Andric }
14280b57cec5SDimitry Andric 
14295ffd83dbSDimitry Andric void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {
14300b57cec5SDimitry Andric   assert(MAI->getTPRel64Directive() != nullptr);
14310b57cec5SDimitry Andric   OS << MAI->getTPRel64Directive();
14320b57cec5SDimitry Andric   Value->print(OS, MAI);
14330b57cec5SDimitry Andric   EmitEOL();
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric 
14365ffd83dbSDimitry Andric void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {
14370b57cec5SDimitry Andric   assert(MAI->getTPRel32Directive() != nullptr);
14380b57cec5SDimitry Andric   OS << MAI->getTPRel32Directive();
14390b57cec5SDimitry Andric   Value->print(OS, MAI);
14400b57cec5SDimitry Andric   EmitEOL();
14410b57cec5SDimitry Andric }
14420b57cec5SDimitry Andric 
14435ffd83dbSDimitry Andric void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {
14440b57cec5SDimitry Andric   assert(MAI->getGPRel64Directive() != nullptr);
14450b57cec5SDimitry Andric   OS << MAI->getGPRel64Directive();
14460b57cec5SDimitry Andric   Value->print(OS, MAI);
14470b57cec5SDimitry Andric   EmitEOL();
14480b57cec5SDimitry Andric }
14490b57cec5SDimitry Andric 
14505ffd83dbSDimitry Andric void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {
14510b57cec5SDimitry Andric   assert(MAI->getGPRel32Directive() != nullptr);
14520b57cec5SDimitry Andric   OS << MAI->getGPRel32Directive();
14530b57cec5SDimitry Andric   Value->print(OS, MAI);
14540b57cec5SDimitry Andric   EmitEOL();
14550b57cec5SDimitry Andric }
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
14580b57cec5SDimitry Andric                              SMLoc Loc) {
14590b57cec5SDimitry Andric   int64_t IntNumBytes;
14605ffd83dbSDimitry Andric   const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
14615ffd83dbSDimitry Andric   if (IsAbsolute && IntNumBytes == 0)
14620b57cec5SDimitry Andric     return;
14630b57cec5SDimitry Andric 
14640b57cec5SDimitry Andric   if (const char *ZeroDirective = MAI->getZeroDirective()) {
14655ffd83dbSDimitry Andric     if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {
14660b57cec5SDimitry Andric       // FIXME: Emit location directives
14670b57cec5SDimitry Andric       OS << ZeroDirective;
14680b57cec5SDimitry Andric       NumBytes.print(OS, MAI);
14690b57cec5SDimitry Andric       if (FillValue != 0)
14700b57cec5SDimitry Andric         OS << ',' << (int)FillValue;
14710b57cec5SDimitry Andric       EmitEOL();
14725ffd83dbSDimitry Andric     } else {
14735ffd83dbSDimitry Andric       if (!IsAbsolute)
14745ffd83dbSDimitry Andric         report_fatal_error(
14755ffd83dbSDimitry Andric             "Cannot emit non-absolute expression lengths of fill.");
14765ffd83dbSDimitry Andric       for (int i = 0; i < IntNumBytes; ++i) {
14775ffd83dbSDimitry Andric         OS << MAI->getData8bitsDirective() << (int)FillValue;
14785ffd83dbSDimitry Andric         EmitEOL();
14795ffd83dbSDimitry Andric       }
14805ffd83dbSDimitry Andric     }
14810b57cec5SDimitry Andric     return;
14820b57cec5SDimitry Andric   }
14830b57cec5SDimitry Andric 
14840b57cec5SDimitry Andric   MCStreamer::emitFill(NumBytes, FillValue);
14850b57cec5SDimitry Andric }
14860b57cec5SDimitry Andric 
14870b57cec5SDimitry Andric void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
14880b57cec5SDimitry Andric                              int64_t Expr, SMLoc Loc) {
14890b57cec5SDimitry Andric   // FIXME: Emit location directives
14900b57cec5SDimitry Andric   OS << "\t.fill\t";
14910b57cec5SDimitry Andric   NumValues.print(OS, MAI);
14920b57cec5SDimitry Andric   OS << ", " << Size << ", 0x";
14930b57cec5SDimitry Andric   OS.write_hex(truncateToSize(Expr, 4));
14940b57cec5SDimitry Andric   EmitEOL();
14950b57cec5SDimitry Andric }
14960b57cec5SDimitry Andric 
1497*0fca6ea1SDimitry Andric void MCAsmStreamer::emitAlignmentDirective(uint64_t ByteAlignment,
1498bdd1243dSDimitry Andric                                            std::optional<int64_t> Value,
14990b57cec5SDimitry Andric                                            unsigned ValueSize,
15000b57cec5SDimitry Andric                                            unsigned MaxBytesToEmit) {
15018bcb0991SDimitry Andric   if (MAI->useDotAlignForAlignment()) {
1502*0fca6ea1SDimitry Andric     if (!isPowerOf2_64(ByteAlignment))
15038bcb0991SDimitry Andric       report_fatal_error("Only power-of-two alignments are supported "
15048bcb0991SDimitry Andric                          "with .align.");
15058bcb0991SDimitry Andric     OS << "\t.align\t";
1506*0fca6ea1SDimitry Andric     OS << Log2_64(ByteAlignment);
15078bcb0991SDimitry Andric     EmitEOL();
15088bcb0991SDimitry Andric     return;
15098bcb0991SDimitry Andric   }
15108bcb0991SDimitry Andric 
15110b57cec5SDimitry Andric   // Some assemblers don't support non-power of two alignments, so we always
15120b57cec5SDimitry Andric   // emit alignments as a power of two if possible.
1513*0fca6ea1SDimitry Andric   if (isPowerOf2_64(ByteAlignment)) {
15140b57cec5SDimitry Andric     switch (ValueSize) {
15150b57cec5SDimitry Andric     default:
15160b57cec5SDimitry Andric       llvm_unreachable("Invalid size for machine code value!");
15170b57cec5SDimitry Andric     case 1:
15180b57cec5SDimitry Andric       OS << "\t.p2align\t";
15190b57cec5SDimitry Andric       break;
15200b57cec5SDimitry Andric     case 2:
15210b57cec5SDimitry Andric       OS << ".p2alignw ";
15220b57cec5SDimitry Andric       break;
15230b57cec5SDimitry Andric     case 4:
15240b57cec5SDimitry Andric       OS << ".p2alignl ";
15250b57cec5SDimitry Andric       break;
15260b57cec5SDimitry Andric     case 8:
15270b57cec5SDimitry Andric       llvm_unreachable("Unsupported alignment size!");
15280b57cec5SDimitry Andric     }
15290b57cec5SDimitry Andric 
1530*0fca6ea1SDimitry Andric     OS << Log2_64(ByteAlignment);
15310b57cec5SDimitry Andric 
1532bdd1243dSDimitry Andric     if (Value.has_value() || MaxBytesToEmit) {
1533bdd1243dSDimitry Andric       if (Value.has_value()) {
15340b57cec5SDimitry Andric         OS << ", 0x";
1535bdd1243dSDimitry Andric         OS.write_hex(truncateToSize(*Value, ValueSize));
1536bdd1243dSDimitry Andric       } else {
1537bdd1243dSDimitry Andric         OS << ", ";
1538bdd1243dSDimitry Andric       }
15390b57cec5SDimitry Andric 
15400b57cec5SDimitry Andric       if (MaxBytesToEmit)
15410b57cec5SDimitry Andric         OS << ", " << MaxBytesToEmit;
15420b57cec5SDimitry Andric     }
15430b57cec5SDimitry Andric     EmitEOL();
15440b57cec5SDimitry Andric     return;
15450b57cec5SDimitry Andric   }
15460b57cec5SDimitry Andric 
15470b57cec5SDimitry Andric   // Non-power of two alignment.  This is not widely supported by assemblers.
15480b57cec5SDimitry Andric   // FIXME: Parameterize this based on MAI.
15490b57cec5SDimitry Andric   switch (ValueSize) {
15500b57cec5SDimitry Andric   default: llvm_unreachable("Invalid size for machine code value!");
15510b57cec5SDimitry Andric   case 1: OS << ".balign";  break;
15520b57cec5SDimitry Andric   case 2: OS << ".balignw"; break;
15530b57cec5SDimitry Andric   case 4: OS << ".balignl"; break;
15540b57cec5SDimitry Andric   case 8: llvm_unreachable("Unsupported alignment size!");
15550b57cec5SDimitry Andric   }
15560b57cec5SDimitry Andric 
15570b57cec5SDimitry Andric   OS << ' ' << ByteAlignment;
1558bdd1243dSDimitry Andric   if (Value.has_value())
1559bdd1243dSDimitry Andric     OS << ", " << truncateToSize(*Value, ValueSize);
1560bdd1243dSDimitry Andric   else if (MaxBytesToEmit)
1561bdd1243dSDimitry Andric     OS << ", ";
15620b57cec5SDimitry Andric   if (MaxBytesToEmit)
15630b57cec5SDimitry Andric     OS << ", " << MaxBytesToEmit;
15640b57cec5SDimitry Andric   EmitEOL();
15650b57cec5SDimitry Andric }
15660b57cec5SDimitry Andric 
1567bdd1243dSDimitry Andric void MCAsmStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
1568bdd1243dSDimitry Andric                                          unsigned ValueSize,
1569bdd1243dSDimitry Andric                                          unsigned MaxBytesToEmit) {
1570bdd1243dSDimitry Andric   emitAlignmentDirective(Alignment.value(), Value, ValueSize, MaxBytesToEmit);
1571bdd1243dSDimitry Andric }
1572bdd1243dSDimitry Andric 
1573bdd1243dSDimitry Andric void MCAsmStreamer::emitCodeAlignment(Align Alignment,
1574349cc55cSDimitry Andric                                       const MCSubtargetInfo *STI,
15750b57cec5SDimitry Andric                                       unsigned MaxBytesToEmit) {
15760b57cec5SDimitry Andric   // Emit with a text fill value.
1577bdd1243dSDimitry Andric   if (MAI->getTextAlignFillValue())
1578bdd1243dSDimitry Andric     emitAlignmentDirective(Alignment.value(), MAI->getTextAlignFillValue(), 1,
1579bdd1243dSDimitry Andric                            MaxBytesToEmit);
1580bdd1243dSDimitry Andric   else
1581bdd1243dSDimitry Andric     emitAlignmentDirective(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);
15820b57cec5SDimitry Andric }
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
15850b57cec5SDimitry Andric                                       unsigned char Value,
15860b57cec5SDimitry Andric                                       SMLoc Loc) {
15870b57cec5SDimitry Andric   // FIXME: Verify that Offset is associated with the current section.
15880b57cec5SDimitry Andric   OS << ".org ";
15890b57cec5SDimitry Andric   Offset->print(OS, MAI);
15900b57cec5SDimitry Andric   OS << ", " << (unsigned)Value;
15910b57cec5SDimitry Andric   EmitEOL();
15920b57cec5SDimitry Andric }
15930b57cec5SDimitry Andric 
15945ffd83dbSDimitry Andric void MCAsmStreamer::emitFileDirective(StringRef Filename) {
15950b57cec5SDimitry Andric   assert(MAI->hasSingleParameterDotFile());
15960b57cec5SDimitry Andric   OS << "\t.file\t";
15970b57cec5SDimitry Andric   PrintQuotedString(Filename, OS);
15980b57cec5SDimitry Andric   EmitEOL();
15990b57cec5SDimitry Andric }
16000b57cec5SDimitry Andric 
1601fe6060f1SDimitry Andric void MCAsmStreamer::emitFileDirective(StringRef Filename,
1602*0fca6ea1SDimitry Andric                                       StringRef CompilerVersion,
1603fe6060f1SDimitry Andric                                       StringRef TimeStamp,
1604fe6060f1SDimitry Andric                                       StringRef Description) {
1605fe6060f1SDimitry Andric   assert(MAI->hasFourStringsDotFile());
1606fe6060f1SDimitry Andric   OS << "\t.file\t";
1607fe6060f1SDimitry Andric   PrintQuotedString(Filename, OS);
1608*0fca6ea1SDimitry Andric   bool useTimeStamp = !TimeStamp.empty();
1609*0fca6ea1SDimitry Andric   bool useCompilerVersion = !CompilerVersion.empty();
1610*0fca6ea1SDimitry Andric   bool useDescription = !Description.empty();
1611*0fca6ea1SDimitry Andric   if (useTimeStamp || useCompilerVersion || useDescription) {
1612fe6060f1SDimitry Andric     OS << ",";
1613*0fca6ea1SDimitry Andric     if (useTimeStamp)
1614fe6060f1SDimitry Andric       PrintQuotedString(TimeStamp, OS);
1615*0fca6ea1SDimitry Andric     if (useCompilerVersion || useDescription) {
1616*0fca6ea1SDimitry Andric       OS << ",";
1617*0fca6ea1SDimitry Andric       if (useCompilerVersion)
1618*0fca6ea1SDimitry Andric         PrintQuotedString(CompilerVersion, OS);
1619*0fca6ea1SDimitry Andric       if (useDescription) {
1620fe6060f1SDimitry Andric         OS << ",";
1621fe6060f1SDimitry Andric         PrintQuotedString(Description, OS);
1622fe6060f1SDimitry Andric       }
1623*0fca6ea1SDimitry Andric     }
1624*0fca6ea1SDimitry Andric   }
1625fe6060f1SDimitry Andric   EmitEOL();
1626fe6060f1SDimitry Andric }
1627fe6060f1SDimitry Andric 
1628fe6060f1SDimitry Andric void MCAsmStreamer::printDwarfFileDirective(
1629fe6060f1SDimitry Andric     unsigned FileNo, StringRef Directory, StringRef Filename,
1630bdd1243dSDimitry Andric     std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1631fe6060f1SDimitry Andric     bool UseDwarfDirectory, raw_svector_ostream &OS) const {
16320b57cec5SDimitry Andric   SmallString<128> FullPathName;
16330b57cec5SDimitry Andric 
16340b57cec5SDimitry Andric   if (!UseDwarfDirectory && !Directory.empty()) {
16350b57cec5SDimitry Andric     if (sys::path::is_absolute(Filename))
16360b57cec5SDimitry Andric       Directory = "";
16370b57cec5SDimitry Andric     else {
16380b57cec5SDimitry Andric       FullPathName = Directory;
16390b57cec5SDimitry Andric       sys::path::append(FullPathName, Filename);
16400b57cec5SDimitry Andric       Directory = "";
16410b57cec5SDimitry Andric       Filename = FullPathName;
16420b57cec5SDimitry Andric     }
16430b57cec5SDimitry Andric   }
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   OS << "\t.file\t" << FileNo << ' ';
16460b57cec5SDimitry Andric   if (!Directory.empty()) {
16470b57cec5SDimitry Andric     PrintQuotedString(Directory, OS);
16480b57cec5SDimitry Andric     OS << ' ';
16490b57cec5SDimitry Andric   }
16500b57cec5SDimitry Andric   PrintQuotedString(Filename, OS);
16510b57cec5SDimitry Andric   if (Checksum)
16520b57cec5SDimitry Andric     OS << " md5 0x" << Checksum->digest();
16530b57cec5SDimitry Andric   if (Source) {
16540b57cec5SDimitry Andric     OS << " source ";
16550b57cec5SDimitry Andric     PrintQuotedString(*Source, OS);
16560b57cec5SDimitry Andric   }
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric 
16590b57cec5SDimitry Andric Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
16600b57cec5SDimitry Andric     unsigned FileNo, StringRef Directory, StringRef Filename,
1661bdd1243dSDimitry Andric     std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
1662bdd1243dSDimitry Andric     unsigned CUID) {
16630b57cec5SDimitry Andric   assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric   MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
16660b57cec5SDimitry Andric   unsigned NumFiles = Table.getMCDwarfFiles().size();
16670b57cec5SDimitry Andric   Expected<unsigned> FileNoOrErr =
16680b57cec5SDimitry Andric       Table.tryGetFile(Directory, Filename, Checksum, Source,
16690b57cec5SDimitry Andric                        getContext().getDwarfVersion(), FileNo);
16700b57cec5SDimitry Andric   if (!FileNoOrErr)
16710b57cec5SDimitry Andric     return FileNoOrErr.takeError();
16720b57cec5SDimitry Andric   FileNo = FileNoOrErr.get();
1673fe6060f1SDimitry Andric 
1674fe6060f1SDimitry Andric   // Return early if this file is already emitted before or if target doesn't
1675fe6060f1SDimitry Andric   // support .file directive.
1676fe6060f1SDimitry Andric   if (NumFiles == Table.getMCDwarfFiles().size() ||
1677fe6060f1SDimitry Andric       !MAI->usesDwarfFileAndLocDirectives())
16780b57cec5SDimitry Andric     return FileNo;
16790b57cec5SDimitry Andric 
16800b57cec5SDimitry Andric   SmallString<128> Str;
16810b57cec5SDimitry Andric   raw_svector_ostream OS1(Str);
16820b57cec5SDimitry Andric   printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
16830b57cec5SDimitry Andric                           UseDwarfDirectory, OS1);
16840b57cec5SDimitry Andric 
16850b57cec5SDimitry Andric   if (MCTargetStreamer *TS = getTargetStreamer())
16860b57cec5SDimitry Andric     TS->emitDwarfFileDirective(OS1.str());
16870b57cec5SDimitry Andric   else
16885ffd83dbSDimitry Andric     emitRawText(OS1.str());
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric   return FileNo;
16910b57cec5SDimitry Andric }
16920b57cec5SDimitry Andric 
1693bdd1243dSDimitry Andric void MCAsmStreamer::emitDwarfFile0Directive(
1694bdd1243dSDimitry Andric     StringRef Directory, StringRef Filename,
1695bdd1243dSDimitry Andric     std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,
16960b57cec5SDimitry Andric     unsigned CUID) {
16970b57cec5SDimitry Andric   assert(CUID == 0);
16980b57cec5SDimitry Andric   // .file 0 is new for DWARF v5.
16990b57cec5SDimitry Andric   if (getContext().getDwarfVersion() < 5)
17000b57cec5SDimitry Andric     return;
17010b57cec5SDimitry Andric   // Inform MCDwarf about the root file.
17020b57cec5SDimitry Andric   getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
17030b57cec5SDimitry Andric                                       Source);
17040b57cec5SDimitry Andric 
1705fe6060f1SDimitry Andric   // Target doesn't support .loc/.file directives, return early.
1706fe6060f1SDimitry Andric   if (!MAI->usesDwarfFileAndLocDirectives())
1707fe6060f1SDimitry Andric     return;
1708fe6060f1SDimitry Andric 
17090b57cec5SDimitry Andric   SmallString<128> Str;
17100b57cec5SDimitry Andric   raw_svector_ostream OS1(Str);
17110b57cec5SDimitry Andric   printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
17120b57cec5SDimitry Andric                           UseDwarfDirectory, OS1);
17130b57cec5SDimitry Andric 
17140b57cec5SDimitry Andric   if (MCTargetStreamer *TS = getTargetStreamer())
17150b57cec5SDimitry Andric     TS->emitDwarfFileDirective(OS1.str());
17160b57cec5SDimitry Andric   else
17175ffd83dbSDimitry Andric     emitRawText(OS1.str());
17180b57cec5SDimitry Andric }
17190b57cec5SDimitry Andric 
17205ffd83dbSDimitry Andric void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
17210b57cec5SDimitry Andric                                           unsigned Column, unsigned Flags,
17225ffd83dbSDimitry Andric                                           unsigned Isa, unsigned Discriminator,
17230b57cec5SDimitry Andric                                           StringRef FileName) {
1724fe6060f1SDimitry Andric   // If target doesn't support .loc/.file directive, we need to record the lines
1725fe6060f1SDimitry Andric   // same way like we do in object mode.
1726fe6060f1SDimitry Andric   if (!MAI->usesDwarfFileAndLocDirectives()) {
1727fe6060f1SDimitry Andric     // In case we see two .loc directives in a row, make sure the
1728fe6060f1SDimitry Andric     // first one gets a line entry.
1729fe6060f1SDimitry Andric     MCDwarfLineEntry::make(this, getCurrentSectionOnly());
1730fe6060f1SDimitry Andric     this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1731fe6060f1SDimitry Andric                                             Discriminator, FileName);
1732fe6060f1SDimitry Andric     return;
1733fe6060f1SDimitry Andric   }
1734fe6060f1SDimitry Andric 
17350b57cec5SDimitry Andric   OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
17360b57cec5SDimitry Andric   if (MAI->supportsExtendedDwarfLocDirective()) {
17370b57cec5SDimitry Andric     if (Flags & DWARF2_FLAG_BASIC_BLOCK)
17380b57cec5SDimitry Andric       OS << " basic_block";
17390b57cec5SDimitry Andric     if (Flags & DWARF2_FLAG_PROLOGUE_END)
17400b57cec5SDimitry Andric       OS << " prologue_end";
17410b57cec5SDimitry Andric     if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
17420b57cec5SDimitry Andric       OS << " epilogue_begin";
17430b57cec5SDimitry Andric 
17440b57cec5SDimitry Andric     unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
17450b57cec5SDimitry Andric     if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
17460b57cec5SDimitry Andric       OS << " is_stmt ";
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric       if (Flags & DWARF2_FLAG_IS_STMT)
17490b57cec5SDimitry Andric         OS << "1";
17500b57cec5SDimitry Andric       else
17510b57cec5SDimitry Andric         OS << "0";
17520b57cec5SDimitry Andric     }
17530b57cec5SDimitry Andric 
17540b57cec5SDimitry Andric     if (Isa)
17550b57cec5SDimitry Andric       OS << " isa " << Isa;
17560b57cec5SDimitry Andric     if (Discriminator)
17570b57cec5SDimitry Andric       OS << " discriminator " << Discriminator;
17580b57cec5SDimitry Andric   }
17590b57cec5SDimitry Andric 
17600b57cec5SDimitry Andric   if (IsVerboseAsm) {
17610b57cec5SDimitry Andric     OS.PadToColumn(MAI->getCommentColumn());
17620b57cec5SDimitry Andric     OS << MAI->getCommentString() << ' ' << FileName << ':'
17630b57cec5SDimitry Andric        << Line << ':' << Column;
17640b57cec5SDimitry Andric   }
17650b57cec5SDimitry Andric   EmitEOL();
17665ffd83dbSDimitry Andric   this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
17675ffd83dbSDimitry Andric                                           Discriminator, FileName);
17680b57cec5SDimitry Andric }
17690b57cec5SDimitry Andric 
17700b57cec5SDimitry Andric MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
17710b57cec5SDimitry Andric   // Always use the zeroth line table, since asm syntax only supports one line
17720b57cec5SDimitry Andric   // table for now.
17730b57cec5SDimitry Andric   return MCStreamer::getDwarfLineTableSymbol(0);
17740b57cec5SDimitry Andric }
17750b57cec5SDimitry Andric 
177681ad6265SDimitry Andric bool MCAsmStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename,
17770b57cec5SDimitry Andric                                         ArrayRef<uint8_t> Checksum,
17780b57cec5SDimitry Andric                                         unsigned ChecksumKind) {
17790b57cec5SDimitry Andric   if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
17800b57cec5SDimitry Andric                                            ChecksumKind))
17810b57cec5SDimitry Andric     return false;
17820b57cec5SDimitry Andric 
17830b57cec5SDimitry Andric   OS << "\t.cv_file\t" << FileNo << ' ';
17840b57cec5SDimitry Andric   PrintQuotedString(Filename, OS);
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric   if (!ChecksumKind) {
17870b57cec5SDimitry Andric     EmitEOL();
17880b57cec5SDimitry Andric     return true;
17890b57cec5SDimitry Andric   }
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric   OS << ' ';
17920b57cec5SDimitry Andric   PrintQuotedString(toHex(Checksum), OS);
17930b57cec5SDimitry Andric   OS << ' ' << ChecksumKind;
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric   EmitEOL();
17960b57cec5SDimitry Andric   return true;
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric 
179981ad6265SDimitry Andric bool MCAsmStreamer::emitCVFuncIdDirective(unsigned FuncId) {
18000b57cec5SDimitry Andric   OS << "\t.cv_func_id " << FuncId << '\n';
180181ad6265SDimitry Andric   return MCStreamer::emitCVFuncIdDirective(FuncId);
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric 
180481ad6265SDimitry Andric bool MCAsmStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId,
18050b57cec5SDimitry Andric                                                 unsigned IAFunc,
18060b57cec5SDimitry Andric                                                 unsigned IAFile,
18070b57cec5SDimitry Andric                                                 unsigned IALine, unsigned IACol,
18080b57cec5SDimitry Andric                                                 SMLoc Loc) {
18090b57cec5SDimitry Andric   OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
18100b57cec5SDimitry Andric      << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
181181ad6265SDimitry Andric   return MCStreamer::emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
18120b57cec5SDimitry Andric                                                  IALine, IACol, Loc);
18130b57cec5SDimitry Andric }
18140b57cec5SDimitry Andric 
18155ffd83dbSDimitry Andric void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
18160b57cec5SDimitry Andric                                        unsigned Line, unsigned Column,
18170b57cec5SDimitry Andric                                        bool PrologueEnd, bool IsStmt,
18180b57cec5SDimitry Andric                                        StringRef FileName, SMLoc Loc) {
18190b57cec5SDimitry Andric   // Validate the directive.
18200b57cec5SDimitry Andric   if (!checkCVLocSection(FunctionId, FileNo, Loc))
18210b57cec5SDimitry Andric     return;
18220b57cec5SDimitry Andric 
18230b57cec5SDimitry Andric   OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
18240b57cec5SDimitry Andric      << Column;
18250b57cec5SDimitry Andric   if (PrologueEnd)
18260b57cec5SDimitry Andric     OS << " prologue_end";
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric   if (IsStmt)
18290b57cec5SDimitry Andric     OS << " is_stmt 1";
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric   if (IsVerboseAsm) {
18320b57cec5SDimitry Andric     OS.PadToColumn(MAI->getCommentColumn());
18330b57cec5SDimitry Andric     OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
18340b57cec5SDimitry Andric        << Column;
18350b57cec5SDimitry Andric   }
18360b57cec5SDimitry Andric   EmitEOL();
18370b57cec5SDimitry Andric }
18380b57cec5SDimitry Andric 
18395ffd83dbSDimitry Andric void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
18400b57cec5SDimitry Andric                                              const MCSymbol *FnStart,
18410b57cec5SDimitry Andric                                              const MCSymbol *FnEnd) {
18420b57cec5SDimitry Andric   OS << "\t.cv_linetable\t" << FunctionId << ", ";
18430b57cec5SDimitry Andric   FnStart->print(OS, MAI);
18440b57cec5SDimitry Andric   OS << ", ";
18450b57cec5SDimitry Andric   FnEnd->print(OS, MAI);
18460b57cec5SDimitry Andric   EmitEOL();
18475ffd83dbSDimitry Andric   this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
18480b57cec5SDimitry Andric }
18490b57cec5SDimitry Andric 
18505ffd83dbSDimitry Andric void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
18510b57cec5SDimitry Andric                                                    unsigned SourceFileId,
18520b57cec5SDimitry Andric                                                    unsigned SourceLineNum,
18530b57cec5SDimitry Andric                                                    const MCSymbol *FnStartSym,
18540b57cec5SDimitry Andric                                                    const MCSymbol *FnEndSym) {
18550b57cec5SDimitry Andric   OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
18560b57cec5SDimitry Andric      << ' ' << SourceLineNum << ' ';
18570b57cec5SDimitry Andric   FnStartSym->print(OS, MAI);
18580b57cec5SDimitry Andric   OS << ' ';
18590b57cec5SDimitry Andric   FnEndSym->print(OS, MAI);
18600b57cec5SDimitry Andric   EmitEOL();
18615ffd83dbSDimitry Andric   this->MCStreamer::emitCVInlineLinetableDirective(
18620b57cec5SDimitry Andric       PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
18630b57cec5SDimitry Andric }
18640b57cec5SDimitry Andric 
18658bcb0991SDimitry Andric void MCAsmStreamer::PrintCVDefRangePrefix(
18668bcb0991SDimitry Andric     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
18670b57cec5SDimitry Andric   OS << "\t.cv_def_range\t";
18680b57cec5SDimitry Andric   for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
18690b57cec5SDimitry Andric     OS << ' ';
18700b57cec5SDimitry Andric     Range.first->print(OS, MAI);
18710b57cec5SDimitry Andric     OS << ' ';
18720b57cec5SDimitry Andric     Range.second->print(OS, MAI);
18730b57cec5SDimitry Andric   }
18748bcb0991SDimitry Andric }
18758bcb0991SDimitry Andric 
18765ffd83dbSDimitry Andric void MCAsmStreamer::emitCVDefRangeDirective(
18778bcb0991SDimitry Andric     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
18788bcb0991SDimitry Andric     codeview::DefRangeRegisterRelHeader DRHdr) {
18798bcb0991SDimitry Andric   PrintCVDefRangePrefix(Ranges);
18808bcb0991SDimitry Andric   OS << ", reg_rel, ";
18818bcb0991SDimitry Andric   OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
18828bcb0991SDimitry Andric      << DRHdr.BasePointerOffset;
18830b57cec5SDimitry Andric   EmitEOL();
18848bcb0991SDimitry Andric }
18858bcb0991SDimitry Andric 
18865ffd83dbSDimitry Andric void MCAsmStreamer::emitCVDefRangeDirective(
18878bcb0991SDimitry Andric     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
18888bcb0991SDimitry Andric     codeview::DefRangeSubfieldRegisterHeader DRHdr) {
18898bcb0991SDimitry Andric   PrintCVDefRangePrefix(Ranges);
18908bcb0991SDimitry Andric   OS << ", subfield_reg, ";
18918bcb0991SDimitry Andric   OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
18928bcb0991SDimitry Andric   EmitEOL();
18938bcb0991SDimitry Andric }
18948bcb0991SDimitry Andric 
18955ffd83dbSDimitry Andric void MCAsmStreamer::emitCVDefRangeDirective(
18968bcb0991SDimitry Andric     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
18978bcb0991SDimitry Andric     codeview::DefRangeRegisterHeader DRHdr) {
18988bcb0991SDimitry Andric   PrintCVDefRangePrefix(Ranges);
18998bcb0991SDimitry Andric   OS << ", reg, ";
19008bcb0991SDimitry Andric   OS << DRHdr.Register;
19018bcb0991SDimitry Andric   EmitEOL();
19028bcb0991SDimitry Andric }
19038bcb0991SDimitry Andric 
19045ffd83dbSDimitry Andric void MCAsmStreamer::emitCVDefRangeDirective(
19058bcb0991SDimitry Andric     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
19068bcb0991SDimitry Andric     codeview::DefRangeFramePointerRelHeader DRHdr) {
19078bcb0991SDimitry Andric   PrintCVDefRangePrefix(Ranges);
19088bcb0991SDimitry Andric   OS << ", frame_ptr_rel, ";
19098bcb0991SDimitry Andric   OS << DRHdr.Offset;
19108bcb0991SDimitry Andric   EmitEOL();
19110b57cec5SDimitry Andric }
19120b57cec5SDimitry Andric 
19135ffd83dbSDimitry Andric void MCAsmStreamer::emitCVStringTableDirective() {
19140b57cec5SDimitry Andric   OS << "\t.cv_stringtable";
19150b57cec5SDimitry Andric   EmitEOL();
19160b57cec5SDimitry Andric }
19170b57cec5SDimitry Andric 
19185ffd83dbSDimitry Andric void MCAsmStreamer::emitCVFileChecksumsDirective() {
19190b57cec5SDimitry Andric   OS << "\t.cv_filechecksums";
19200b57cec5SDimitry Andric   EmitEOL();
19210b57cec5SDimitry Andric }
19220b57cec5SDimitry Andric 
19235ffd83dbSDimitry Andric void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
19240b57cec5SDimitry Andric   OS << "\t.cv_filechecksumoffset\t" << FileNo;
19250b57cec5SDimitry Andric   EmitEOL();
19260b57cec5SDimitry Andric }
19270b57cec5SDimitry Andric 
192881ad6265SDimitry Andric void MCAsmStreamer::emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
19290b57cec5SDimitry Andric   OS << "\t.cv_fpo_data\t";
19300b57cec5SDimitry Andric   ProcSym->print(OS, MAI);
19310b57cec5SDimitry Andric   EmitEOL();
19320b57cec5SDimitry Andric }
19330b57cec5SDimitry Andric 
19345ffd83dbSDimitry Andric void MCAsmStreamer::emitIdent(StringRef IdentString) {
19350b57cec5SDimitry Andric   assert(MAI->hasIdentDirective() && ".ident directive not supported");
19360b57cec5SDimitry Andric   OS << "\t.ident\t";
19370b57cec5SDimitry Andric   PrintQuotedString(IdentString, OS);
19380b57cec5SDimitry Andric   EmitEOL();
19390b57cec5SDimitry Andric }
19400b57cec5SDimitry Andric 
19415ffd83dbSDimitry Andric void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
19425ffd83dbSDimitry Andric   MCStreamer::emitCFISections(EH, Debug);
19430b57cec5SDimitry Andric   OS << "\t.cfi_sections ";
19440b57cec5SDimitry Andric   if (EH) {
19450b57cec5SDimitry Andric     OS << ".eh_frame";
19460b57cec5SDimitry Andric     if (Debug)
19470b57cec5SDimitry Andric       OS << ", .debug_frame";
19480b57cec5SDimitry Andric   } else if (Debug) {
19490b57cec5SDimitry Andric     OS << ".debug_frame";
19500b57cec5SDimitry Andric   }
19510b57cec5SDimitry Andric 
19520b57cec5SDimitry Andric   EmitEOL();
19530b57cec5SDimitry Andric }
19540b57cec5SDimitry Andric 
19555ffd83dbSDimitry Andric void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
19560b57cec5SDimitry Andric   OS << "\t.cfi_startproc";
19570b57cec5SDimitry Andric   if (Frame.IsSimple)
19580b57cec5SDimitry Andric     OS << " simple";
19590b57cec5SDimitry Andric   EmitEOL();
19600b57cec5SDimitry Andric }
19610b57cec5SDimitry Andric 
19625ffd83dbSDimitry Andric void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
19635ffd83dbSDimitry Andric   MCStreamer::emitCFIEndProcImpl(Frame);
19640b57cec5SDimitry Andric   OS << "\t.cfi_endproc";
19650b57cec5SDimitry Andric   EmitEOL();
19660b57cec5SDimitry Andric }
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric void MCAsmStreamer::EmitRegisterName(int64_t Register) {
19690b57cec5SDimitry Andric   if (!MAI->useDwarfRegNumForCFI()) {
19700b57cec5SDimitry Andric     // User .cfi_* directives can use arbitrary DWARF register numbers, not
19710b57cec5SDimitry Andric     // just ones that map to LLVM register numbers and have known names.
19720b57cec5SDimitry Andric     // Fall back to using the original number directly if no name is known.
19730b57cec5SDimitry Andric     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1974bdd1243dSDimitry Andric     if (std::optional<unsigned> LLVMRegister =
1975bdd1243dSDimitry Andric             MRI->getLLVMRegNum(Register, true)) {
19768bcb0991SDimitry Andric       InstPrinter->printRegName(OS, *LLVMRegister);
19770b57cec5SDimitry Andric       return;
19780b57cec5SDimitry Andric     }
19790b57cec5SDimitry Andric   }
19800b57cec5SDimitry Andric   OS << Register;
19810b57cec5SDimitry Andric }
19820b57cec5SDimitry Andric 
198306c3fb27SDimitry Andric void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) {
198406c3fb27SDimitry Andric   MCStreamer::emitCFIDefCfa(Register, Offset, Loc);
19850b57cec5SDimitry Andric   OS << "\t.cfi_def_cfa ";
19860b57cec5SDimitry Andric   EmitRegisterName(Register);
19870b57cec5SDimitry Andric   OS << ", " << Offset;
19880b57cec5SDimitry Andric   EmitEOL();
19890b57cec5SDimitry Andric }
19900b57cec5SDimitry Andric 
199106c3fb27SDimitry Andric void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) {
199206c3fb27SDimitry Andric   MCStreamer::emitCFIDefCfaOffset(Offset, Loc);
19930b57cec5SDimitry Andric   OS << "\t.cfi_def_cfa_offset " << Offset;
19940b57cec5SDimitry Andric   EmitEOL();
19950b57cec5SDimitry Andric }
19960b57cec5SDimitry Andric 
1997fe6060f1SDimitry Andric void MCAsmStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,
199806c3fb27SDimitry Andric                                             int64_t AddressSpace, SMLoc Loc) {
199906c3fb27SDimitry Andric   MCStreamer::emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace, Loc);
2000fe6060f1SDimitry Andric   OS << "\t.cfi_llvm_def_aspace_cfa ";
2001fe6060f1SDimitry Andric   EmitRegisterName(Register);
2002fe6060f1SDimitry Andric   OS << ", " << Offset;
2003fe6060f1SDimitry Andric   OS << ", " << AddressSpace;
2004fe6060f1SDimitry Andric   EmitEOL();
2005fe6060f1SDimitry Andric }
2006fe6060f1SDimitry Andric 
20070b57cec5SDimitry Andric static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
20080b57cec5SDimitry Andric   OS << "\t.cfi_escape ";
20090b57cec5SDimitry Andric   if (!Values.empty()) {
20100b57cec5SDimitry Andric     size_t e = Values.size() - 1;
20110b57cec5SDimitry Andric     for (size_t i = 0; i < e; ++i)
20120b57cec5SDimitry Andric       OS << format("0x%02x", uint8_t(Values[i])) << ", ";
20130b57cec5SDimitry Andric     OS << format("0x%02x", uint8_t(Values[e]));
20140b57cec5SDimitry Andric   }
20150b57cec5SDimitry Andric }
20160b57cec5SDimitry Andric 
201706c3fb27SDimitry Andric void MCAsmStreamer::emitCFIEscape(StringRef Values, SMLoc Loc) {
201806c3fb27SDimitry Andric   MCStreamer::emitCFIEscape(Values, Loc);
20190b57cec5SDimitry Andric   PrintCFIEscape(OS, Values);
20200b57cec5SDimitry Andric   EmitEOL();
20210b57cec5SDimitry Andric }
20220b57cec5SDimitry Andric 
202306c3fb27SDimitry Andric void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) {
202406c3fb27SDimitry Andric   MCStreamer::emitCFIGnuArgsSize(Size, Loc);
20250b57cec5SDimitry Andric 
20260b57cec5SDimitry Andric   uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
20270b57cec5SDimitry Andric   unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
20280b57cec5SDimitry Andric 
20290b57cec5SDimitry Andric   PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
20300b57cec5SDimitry Andric   EmitEOL();
20310b57cec5SDimitry Andric }
20320b57cec5SDimitry Andric 
203306c3fb27SDimitry Andric void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) {
203406c3fb27SDimitry Andric   MCStreamer::emitCFIDefCfaRegister(Register, Loc);
20350b57cec5SDimitry Andric   OS << "\t.cfi_def_cfa_register ";
20360b57cec5SDimitry Andric   EmitRegisterName(Register);
20370b57cec5SDimitry Andric   EmitEOL();
20380b57cec5SDimitry Andric }
20390b57cec5SDimitry Andric 
204006c3fb27SDimitry Andric void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) {
204106c3fb27SDimitry Andric   MCStreamer::emitCFIOffset(Register, Offset, Loc);
20420b57cec5SDimitry Andric   OS << "\t.cfi_offset ";
20430b57cec5SDimitry Andric   EmitRegisterName(Register);
20440b57cec5SDimitry Andric   OS << ", " << Offset;
20450b57cec5SDimitry Andric   EmitEOL();
20460b57cec5SDimitry Andric }
20470b57cec5SDimitry Andric 
20485ffd83dbSDimitry Andric void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
20490b57cec5SDimitry Andric                                        unsigned Encoding) {
20505ffd83dbSDimitry Andric   MCStreamer::emitCFIPersonality(Sym, Encoding);
20510b57cec5SDimitry Andric   OS << "\t.cfi_personality " << Encoding << ", ";
20520b57cec5SDimitry Andric   Sym->print(OS, MAI);
20530b57cec5SDimitry Andric   EmitEOL();
20540b57cec5SDimitry Andric }
20550b57cec5SDimitry Andric 
20565ffd83dbSDimitry Andric void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
20575ffd83dbSDimitry Andric   MCStreamer::emitCFILsda(Sym, Encoding);
20580b57cec5SDimitry Andric   OS << "\t.cfi_lsda " << Encoding << ", ";
20590b57cec5SDimitry Andric   Sym->print(OS, MAI);
20600b57cec5SDimitry Andric   EmitEOL();
20610b57cec5SDimitry Andric }
20620b57cec5SDimitry Andric 
206306c3fb27SDimitry Andric void MCAsmStreamer::emitCFIRememberState(SMLoc Loc) {
206406c3fb27SDimitry Andric   MCStreamer::emitCFIRememberState(Loc);
20650b57cec5SDimitry Andric   OS << "\t.cfi_remember_state";
20660b57cec5SDimitry Andric   EmitEOL();
20670b57cec5SDimitry Andric }
20680b57cec5SDimitry Andric 
206906c3fb27SDimitry Andric void MCAsmStreamer::emitCFIRestoreState(SMLoc Loc) {
207006c3fb27SDimitry Andric   MCStreamer::emitCFIRestoreState(Loc);
20710b57cec5SDimitry Andric   OS << "\t.cfi_restore_state";
20720b57cec5SDimitry Andric   EmitEOL();
20730b57cec5SDimitry Andric }
20740b57cec5SDimitry Andric 
207506c3fb27SDimitry Andric void MCAsmStreamer::emitCFIRestore(int64_t Register, SMLoc Loc) {
207606c3fb27SDimitry Andric   MCStreamer::emitCFIRestore(Register, Loc);
20770b57cec5SDimitry Andric   OS << "\t.cfi_restore ";
20780b57cec5SDimitry Andric   EmitRegisterName(Register);
20790b57cec5SDimitry Andric   EmitEOL();
20800b57cec5SDimitry Andric }
20810b57cec5SDimitry Andric 
208206c3fb27SDimitry Andric void MCAsmStreamer::emitCFISameValue(int64_t Register, SMLoc Loc) {
208306c3fb27SDimitry Andric   MCStreamer::emitCFISameValue(Register, Loc);
20840b57cec5SDimitry Andric   OS << "\t.cfi_same_value ";
20850b57cec5SDimitry Andric   EmitRegisterName(Register);
20860b57cec5SDimitry Andric   EmitEOL();
20870b57cec5SDimitry Andric }
20880b57cec5SDimitry Andric 
208906c3fb27SDimitry Andric void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset,
209006c3fb27SDimitry Andric                                      SMLoc Loc) {
209106c3fb27SDimitry Andric   MCStreamer::emitCFIRelOffset(Register, Offset, Loc);
20920b57cec5SDimitry Andric   OS << "\t.cfi_rel_offset ";
20930b57cec5SDimitry Andric   EmitRegisterName(Register);
20940b57cec5SDimitry Andric   OS << ", " << Offset;
20950b57cec5SDimitry Andric   EmitEOL();
20960b57cec5SDimitry Andric }
20970b57cec5SDimitry Andric 
209806c3fb27SDimitry Andric void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) {
209906c3fb27SDimitry Andric   MCStreamer::emitCFIAdjustCfaOffset(Adjustment, Loc);
21000b57cec5SDimitry Andric   OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
21010b57cec5SDimitry Andric   EmitEOL();
21020b57cec5SDimitry Andric }
21030b57cec5SDimitry Andric 
21045ffd83dbSDimitry Andric void MCAsmStreamer::emitCFISignalFrame() {
21055ffd83dbSDimitry Andric   MCStreamer::emitCFISignalFrame();
21060b57cec5SDimitry Andric   OS << "\t.cfi_signal_frame";
21070b57cec5SDimitry Andric   EmitEOL();
21080b57cec5SDimitry Andric }
21090b57cec5SDimitry Andric 
211006c3fb27SDimitry Andric void MCAsmStreamer::emitCFIUndefined(int64_t Register, SMLoc Loc) {
211106c3fb27SDimitry Andric   MCStreamer::emitCFIUndefined(Register, Loc);
21125ffd83dbSDimitry Andric   OS << "\t.cfi_undefined ";
21135ffd83dbSDimitry Andric   EmitRegisterName(Register);
21140b57cec5SDimitry Andric   EmitEOL();
21150b57cec5SDimitry Andric }
21160b57cec5SDimitry Andric 
211706c3fb27SDimitry Andric void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2,
211806c3fb27SDimitry Andric                                     SMLoc Loc) {
211906c3fb27SDimitry Andric   MCStreamer::emitCFIRegister(Register1, Register2, Loc);
21205ffd83dbSDimitry Andric   OS << "\t.cfi_register ";
21215ffd83dbSDimitry Andric   EmitRegisterName(Register1);
21225ffd83dbSDimitry Andric   OS << ", ";
21235ffd83dbSDimitry Andric   EmitRegisterName(Register2);
21240b57cec5SDimitry Andric   EmitEOL();
21250b57cec5SDimitry Andric }
21260b57cec5SDimitry Andric 
212706c3fb27SDimitry Andric void MCAsmStreamer::emitCFIWindowSave(SMLoc Loc) {
212806c3fb27SDimitry Andric   MCStreamer::emitCFIWindowSave(Loc);
21290b57cec5SDimitry Andric   OS << "\t.cfi_window_save";
21300b57cec5SDimitry Andric   EmitEOL();
21310b57cec5SDimitry Andric }
21320b57cec5SDimitry Andric 
213306c3fb27SDimitry Andric void MCAsmStreamer::emitCFINegateRAState(SMLoc Loc) {
213406c3fb27SDimitry Andric   MCStreamer::emitCFINegateRAState(Loc);
21350b57cec5SDimitry Andric   OS << "\t.cfi_negate_ra_state";
21360b57cec5SDimitry Andric   EmitEOL();
21370b57cec5SDimitry Andric }
21380b57cec5SDimitry Andric 
21395ffd83dbSDimitry Andric void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
21405ffd83dbSDimitry Andric   MCStreamer::emitCFIReturnColumn(Register);
21415ffd83dbSDimitry Andric   OS << "\t.cfi_return_column ";
21425ffd83dbSDimitry Andric   EmitRegisterName(Register);
21430b57cec5SDimitry Andric   EmitEOL();
21440b57cec5SDimitry Andric }
21450b57cec5SDimitry Andric 
2146*0fca6ea1SDimitry Andric void MCAsmStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) {
2147*0fca6ea1SDimitry Andric   MCStreamer::emitCFILabelDirective(Loc, Name);
2148*0fca6ea1SDimitry Andric   OS << "\t.cfi_label " << Name;
2149*0fca6ea1SDimitry Andric   EmitEOL();
2150*0fca6ea1SDimitry Andric }
2151*0fca6ea1SDimitry Andric 
21525ffd83dbSDimitry Andric void MCAsmStreamer::emitCFIBKeyFrame() {
21535ffd83dbSDimitry Andric   MCStreamer::emitCFIBKeyFrame();
21540b57cec5SDimitry Andric   OS << "\t.cfi_b_key_frame";
21550b57cec5SDimitry Andric   EmitEOL();
21560b57cec5SDimitry Andric }
21570b57cec5SDimitry Andric 
215881ad6265SDimitry Andric void MCAsmStreamer::emitCFIMTETaggedFrame() {
215981ad6265SDimitry Andric   MCStreamer::emitCFIMTETaggedFrame();
216081ad6265SDimitry Andric   OS << "\t.cfi_mte_tagged_frame";
216181ad6265SDimitry Andric   EmitEOL();
216281ad6265SDimitry Andric }
216381ad6265SDimitry Andric 
216481ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
216581ad6265SDimitry Andric   MCStreamer::emitWinCFIStartProc(Symbol, Loc);
21660b57cec5SDimitry Andric 
21670b57cec5SDimitry Andric   OS << ".seh_proc ";
21680b57cec5SDimitry Andric   Symbol->print(OS, MAI);
21690b57cec5SDimitry Andric   EmitEOL();
21700b57cec5SDimitry Andric }
21710b57cec5SDimitry Andric 
217281ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIEndProc(SMLoc Loc) {
217381ad6265SDimitry Andric   MCStreamer::emitWinCFIEndProc(Loc);
21740b57cec5SDimitry Andric 
21750b57cec5SDimitry Andric   OS << "\t.seh_endproc";
21760b57cec5SDimitry Andric   EmitEOL();
21770b57cec5SDimitry Andric }
21780b57cec5SDimitry Andric 
217981ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
218081ad6265SDimitry Andric   MCStreamer::emitWinCFIFuncletOrFuncEnd(Loc);
2181e8d8bef9SDimitry Andric 
2182e8d8bef9SDimitry Andric   OS << "\t.seh_endfunclet";
2183e8d8bef9SDimitry Andric   EmitEOL();
21840b57cec5SDimitry Andric }
21850b57cec5SDimitry Andric 
218681ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIStartChained(SMLoc Loc) {
218781ad6265SDimitry Andric   MCStreamer::emitWinCFIStartChained(Loc);
21880b57cec5SDimitry Andric 
21890b57cec5SDimitry Andric   OS << "\t.seh_startchained";
21900b57cec5SDimitry Andric   EmitEOL();
21910b57cec5SDimitry Andric }
21920b57cec5SDimitry Andric 
219381ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIEndChained(SMLoc Loc) {
219481ad6265SDimitry Andric   MCStreamer::emitWinCFIEndChained(Loc);
21950b57cec5SDimitry Andric 
21960b57cec5SDimitry Andric   OS << "\t.seh_endchained";
21970b57cec5SDimitry Andric   EmitEOL();
21980b57cec5SDimitry Andric }
21990b57cec5SDimitry Andric 
220081ad6265SDimitry Andric void MCAsmStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind,
22010b57cec5SDimitry Andric                                      bool Except, SMLoc Loc) {
220281ad6265SDimitry Andric   MCStreamer::emitWinEHHandler(Sym, Unwind, Except, Loc);
22030b57cec5SDimitry Andric 
22040b57cec5SDimitry Andric   OS << "\t.seh_handler ";
22050b57cec5SDimitry Andric   Sym->print(OS, MAI);
220681ad6265SDimitry Andric   char Marker = '@';
220781ad6265SDimitry Andric   const Triple &T = getContext().getTargetTriple();
220881ad6265SDimitry Andric   if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)
220981ad6265SDimitry Andric     Marker = '%';
22100b57cec5SDimitry Andric   if (Unwind)
221181ad6265SDimitry Andric     OS << ", " << Marker << "unwind";
22120b57cec5SDimitry Andric   if (Except)
221381ad6265SDimitry Andric     OS << ", " << Marker << "except";
22140b57cec5SDimitry Andric   EmitEOL();
22150b57cec5SDimitry Andric }
22160b57cec5SDimitry Andric 
221781ad6265SDimitry Andric void MCAsmStreamer::emitWinEHHandlerData(SMLoc Loc) {
221881ad6265SDimitry Andric   MCStreamer::emitWinEHHandlerData(Loc);
22190b57cec5SDimitry Andric 
222081ad6265SDimitry Andric   // Switch sections. Don't call switchSection directly, because that will
22210b57cec5SDimitry Andric   // cause the section switch to be visible in the emitted assembly.
22220b57cec5SDimitry Andric   // We only do this so the section switch that terminates the handler
22230b57cec5SDimitry Andric   // data block is visible.
22240b57cec5SDimitry Andric   WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
22258bcb0991SDimitry Andric 
22268bcb0991SDimitry Andric   // Do nothing if no frame is open. MCStreamer should've already reported an
22278bcb0991SDimitry Andric   // error.
22288bcb0991SDimitry Andric   if (!CurFrame)
22298bcb0991SDimitry Andric     return;
22308bcb0991SDimitry Andric 
22310b57cec5SDimitry Andric   MCSection *TextSec = &CurFrame->Function->getSection();
22320b57cec5SDimitry Andric   MCSection *XData = getAssociatedXDataSection(TextSec);
2233*0fca6ea1SDimitry Andric   switchSectionNoPrint(XData);
22340b57cec5SDimitry Andric 
22350b57cec5SDimitry Andric   OS << "\t.seh_handlerdata";
22360b57cec5SDimitry Andric   EmitEOL();
22370b57cec5SDimitry Andric }
22380b57cec5SDimitry Andric 
223981ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
224081ad6265SDimitry Andric   MCStreamer::emitWinCFIPushReg(Register, Loc);
22410b57cec5SDimitry Andric 
22428bcb0991SDimitry Andric   OS << "\t.seh_pushreg ";
22438bcb0991SDimitry Andric   InstPrinter->printRegName(OS, Register);
22440b57cec5SDimitry Andric   EmitEOL();
22450b57cec5SDimitry Andric }
22460b57cec5SDimitry Andric 
224781ad6265SDimitry Andric void MCAsmStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset,
22480b57cec5SDimitry Andric                                        SMLoc Loc) {
224981ad6265SDimitry Andric   MCStreamer::emitWinCFISetFrame(Register, Offset, Loc);
22500b57cec5SDimitry Andric 
22518bcb0991SDimitry Andric   OS << "\t.seh_setframe ";
22528bcb0991SDimitry Andric   InstPrinter->printRegName(OS, Register);
22538bcb0991SDimitry Andric   OS << ", " << Offset;
22540b57cec5SDimitry Andric   EmitEOL();
22550b57cec5SDimitry Andric }
22560b57cec5SDimitry Andric 
225781ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
225881ad6265SDimitry Andric   MCStreamer::emitWinCFIAllocStack(Size, Loc);
22590b57cec5SDimitry Andric 
22600b57cec5SDimitry Andric   OS << "\t.seh_stackalloc " << Size;
22610b57cec5SDimitry Andric   EmitEOL();
22620b57cec5SDimitry Andric }
22630b57cec5SDimitry Andric 
226481ad6265SDimitry Andric void MCAsmStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset,
22650b57cec5SDimitry Andric                                       SMLoc Loc) {
226681ad6265SDimitry Andric   MCStreamer::emitWinCFISaveReg(Register, Offset, Loc);
22670b57cec5SDimitry Andric 
22688bcb0991SDimitry Andric   OS << "\t.seh_savereg ";
22698bcb0991SDimitry Andric   InstPrinter->printRegName(OS, Register);
22708bcb0991SDimitry Andric   OS << ", " << Offset;
22710b57cec5SDimitry Andric   EmitEOL();
22720b57cec5SDimitry Andric }
22730b57cec5SDimitry Andric 
227481ad6265SDimitry Andric void MCAsmStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset,
22750b57cec5SDimitry Andric                                       SMLoc Loc) {
227681ad6265SDimitry Andric   MCStreamer::emitWinCFISaveXMM(Register, Offset, Loc);
22770b57cec5SDimitry Andric 
22788bcb0991SDimitry Andric   OS << "\t.seh_savexmm ";
22798bcb0991SDimitry Andric   InstPrinter->printRegName(OS, Register);
22808bcb0991SDimitry Andric   OS << ", " << Offset;
22810b57cec5SDimitry Andric   EmitEOL();
22820b57cec5SDimitry Andric }
22830b57cec5SDimitry Andric 
228481ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) {
228581ad6265SDimitry Andric   MCStreamer::emitWinCFIPushFrame(Code, Loc);
22860b57cec5SDimitry Andric 
22870b57cec5SDimitry Andric   OS << "\t.seh_pushframe";
22880b57cec5SDimitry Andric   if (Code)
22890b57cec5SDimitry Andric     OS << " @code";
22900b57cec5SDimitry Andric   EmitEOL();
22910b57cec5SDimitry Andric }
22920b57cec5SDimitry Andric 
229381ad6265SDimitry Andric void MCAsmStreamer::emitWinCFIEndProlog(SMLoc Loc) {
229481ad6265SDimitry Andric   MCStreamer::emitWinCFIEndProlog(Loc);
22950b57cec5SDimitry Andric 
22960b57cec5SDimitry Andric   OS << "\t.seh_endprologue";
22970b57cec5SDimitry Andric   EmitEOL();
22980b57cec5SDimitry Andric }
22990b57cec5SDimitry Andric 
23000b57cec5SDimitry Andric void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
23010b57cec5SDimitry Andric                                        const MCSymbolRefExpr *To,
23020b57cec5SDimitry Andric                                        uint64_t Count) {
23030b57cec5SDimitry Andric   OS << "\t.cg_profile ";
23040b57cec5SDimitry Andric   From->getSymbol().print(OS, MAI);
23050b57cec5SDimitry Andric   OS << ", ";
23060b57cec5SDimitry Andric   To->getSymbol().print(OS, MAI);
23070b57cec5SDimitry Andric   OS << ", " << Count;
23080b57cec5SDimitry Andric   EmitEOL();
23090b57cec5SDimitry Andric }
23100b57cec5SDimitry Andric 
23110b57cec5SDimitry Andric void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
23120b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI) {
231381ad6265SDimitry Andric   raw_ostream &OS = getCommentOS();
23140b57cec5SDimitry Andric   SmallString<256> Code;
23150b57cec5SDimitry Andric   SmallVector<MCFixup, 4> Fixups;
23160b57cec5SDimitry Andric 
23170b57cec5SDimitry Andric   // If we have no code emitter, don't emit code.
23180b57cec5SDimitry Andric   if (!getAssembler().getEmitterPtr())
23190b57cec5SDimitry Andric     return;
23200b57cec5SDimitry Andric 
232106c3fb27SDimitry Andric   getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric   // If we are showing fixups, create symbolic markers in the encoded
23240b57cec5SDimitry Andric   // representation. We do this by making a per-bit map to the fixup item index,
23250b57cec5SDimitry Andric   // then trying to display it as nicely as possible.
23260b57cec5SDimitry Andric   SmallVector<uint8_t, 64> FixupMap;
23270b57cec5SDimitry Andric   FixupMap.resize(Code.size() * 8);
23280b57cec5SDimitry Andric   for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
23290b57cec5SDimitry Andric     FixupMap[i] = 0;
23300b57cec5SDimitry Andric 
23310b57cec5SDimitry Andric   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
23320b57cec5SDimitry Andric     MCFixup &F = Fixups[i];
23330b57cec5SDimitry Andric     const MCFixupKindInfo &Info =
23340b57cec5SDimitry Andric         getAssembler().getBackend().getFixupKindInfo(F.getKind());
23350b57cec5SDimitry Andric     for (unsigned j = 0; j != Info.TargetSize; ++j) {
23360b57cec5SDimitry Andric       unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
23370b57cec5SDimitry Andric       assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
23380b57cec5SDimitry Andric       FixupMap[Index] = 1 + i;
23390b57cec5SDimitry Andric     }
23400b57cec5SDimitry Andric   }
23410b57cec5SDimitry Andric 
23420b57cec5SDimitry Andric   // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
23430b57cec5SDimitry Andric   // high order halfword of a 32-bit Thumb2 instruction is emitted first.
23440b57cec5SDimitry Andric   OS << "encoding: [";
23450b57cec5SDimitry Andric   for (unsigned i = 0, e = Code.size(); i != e; ++i) {
23460b57cec5SDimitry Andric     if (i)
23470b57cec5SDimitry Andric       OS << ',';
23480b57cec5SDimitry Andric 
23490b57cec5SDimitry Andric     // See if all bits are the same map entry.
23500b57cec5SDimitry Andric     uint8_t MapEntry = FixupMap[i * 8 + 0];
23510b57cec5SDimitry Andric     for (unsigned j = 1; j != 8; ++j) {
23520b57cec5SDimitry Andric       if (FixupMap[i * 8 + j] == MapEntry)
23530b57cec5SDimitry Andric         continue;
23540b57cec5SDimitry Andric 
23550b57cec5SDimitry Andric       MapEntry = uint8_t(~0U);
23560b57cec5SDimitry Andric       break;
23570b57cec5SDimitry Andric     }
23580b57cec5SDimitry Andric 
23590b57cec5SDimitry Andric     if (MapEntry != uint8_t(~0U)) {
23600b57cec5SDimitry Andric       if (MapEntry == 0) {
23610b57cec5SDimitry Andric         OS << format("0x%02x", uint8_t(Code[i]));
23620b57cec5SDimitry Andric       } else {
23630b57cec5SDimitry Andric         if (Code[i]) {
23640b57cec5SDimitry Andric           // FIXME: Some of the 8 bits require fix up.
23650b57cec5SDimitry Andric           OS << format("0x%02x", uint8_t(Code[i])) << '\''
23660b57cec5SDimitry Andric              << char('A' + MapEntry - 1) << '\'';
23670b57cec5SDimitry Andric         } else
23680b57cec5SDimitry Andric           OS << char('A' + MapEntry - 1);
23690b57cec5SDimitry Andric       }
23700b57cec5SDimitry Andric     } else {
23710b57cec5SDimitry Andric       // Otherwise, write out in binary.
23720b57cec5SDimitry Andric       OS << "0b";
23730b57cec5SDimitry Andric       for (unsigned j = 8; j--;) {
23740b57cec5SDimitry Andric         unsigned Bit = (Code[i] >> j) & 1;
23750b57cec5SDimitry Andric 
23760b57cec5SDimitry Andric         unsigned FixupBit;
23770b57cec5SDimitry Andric         if (MAI->isLittleEndian())
23780b57cec5SDimitry Andric           FixupBit = i * 8 + j;
23790b57cec5SDimitry Andric         else
23800b57cec5SDimitry Andric           FixupBit = i * 8 + (7-j);
23810b57cec5SDimitry Andric 
23820b57cec5SDimitry Andric         if (uint8_t MapEntry = FixupMap[FixupBit]) {
23830b57cec5SDimitry Andric           assert(Bit == 0 && "Encoder wrote into fixed up bit!");
23840b57cec5SDimitry Andric           OS << char('A' + MapEntry - 1);
23850b57cec5SDimitry Andric         } else
23860b57cec5SDimitry Andric           OS << Bit;
23870b57cec5SDimitry Andric       }
23880b57cec5SDimitry Andric     }
23890b57cec5SDimitry Andric   }
23900b57cec5SDimitry Andric   OS << "]\n";
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
23930b57cec5SDimitry Andric     MCFixup &F = Fixups[i];
23940b57cec5SDimitry Andric     const MCFixupKindInfo &Info =
23950b57cec5SDimitry Andric         getAssembler().getBackend().getFixupKindInfo(F.getKind());
239681ad6265SDimitry Andric     OS << "  fixup " << char('A' + i) << " - "
239781ad6265SDimitry Andric        << "offset: " << F.getOffset() << ", value: ";
239881ad6265SDimitry Andric     F.getValue()->print(OS, MAI);
239981ad6265SDimitry Andric     OS << ", kind: " << Info.Name << "\n";
24000b57cec5SDimitry Andric   }
24010b57cec5SDimitry Andric }
24020b57cec5SDimitry Andric 
24035ffd83dbSDimitry Andric void MCAsmStreamer::emitInstruction(const MCInst &Inst,
24040b57cec5SDimitry Andric                                     const MCSubtargetInfo &STI) {
24050b57cec5SDimitry Andric   assert(getCurrentSectionOnly() &&
24060b57cec5SDimitry Andric          "Cannot emit contents before setting section!");
24070b57cec5SDimitry Andric 
2408fe6060f1SDimitry Andric   if (!MAI->usesDwarfFileAndLocDirectives())
2409fe6060f1SDimitry Andric     // Now that a machine instruction has been assembled into this section, make
2410fe6060f1SDimitry Andric     // a line entry for any .loc directive that has been seen.
2411fe6060f1SDimitry Andric     MCDwarfLineEntry::make(this, getCurrentSectionOnly());
2412fe6060f1SDimitry Andric 
24130b57cec5SDimitry Andric   // Show the encoding in a comment if we have a code emitter.
24140b57cec5SDimitry Andric   AddEncodingComment(Inst, STI);
24150b57cec5SDimitry Andric 
24160b57cec5SDimitry Andric   // Show the MCInst if enabled.
24170b57cec5SDimitry Andric   if (ShowInst) {
241881ad6265SDimitry Andric     Inst.dump_pretty(getCommentOS(), InstPrinter.get(), "\n ");
241981ad6265SDimitry Andric     getCommentOS() << "\n";
24200b57cec5SDimitry Andric   }
24210b57cec5SDimitry Andric 
24220b57cec5SDimitry Andric   if(getTargetStreamer())
2423480093f4SDimitry Andric     getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
24240b57cec5SDimitry Andric   else
2425480093f4SDimitry Andric     InstPrinter->printInst(&Inst, 0, "", STI, OS);
24260b57cec5SDimitry Andric 
24270b57cec5SDimitry Andric   StringRef Comments = CommentToEmit;
24280b57cec5SDimitry Andric   if (Comments.size() && Comments.back() != '\n')
242981ad6265SDimitry Andric     getCommentOS() << "\n";
24300b57cec5SDimitry Andric 
24310b57cec5SDimitry Andric   EmitEOL();
24320b57cec5SDimitry Andric }
24330b57cec5SDimitry Andric 
243406c3fb27SDimitry Andric void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
243506c3fb27SDimitry Andric                                     uint64_t Type, uint64_t Attr,
243606c3fb27SDimitry Andric                                     uint64_t Discriminator,
243706c3fb27SDimitry Andric                                     const MCPseudoProbeInlineStack &InlineStack,
243806c3fb27SDimitry Andric                                     MCSymbol *FnSym) {
243906c3fb27SDimitry Andric   OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " " << Attr;
244006c3fb27SDimitry Andric   if (Discriminator)
244106c3fb27SDimitry Andric     OS << " " << Discriminator;
2442e8d8bef9SDimitry Andric   // Emit inline stack like
2443e8d8bef9SDimitry Andric   //  @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:11
2444e8d8bef9SDimitry Andric   for (const auto &Site : InlineStack)
2445e8d8bef9SDimitry Andric     OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);
2446bdd1243dSDimitry Andric 
2447bdd1243dSDimitry Andric   OS << " " << FnSym->getName();
2448bdd1243dSDimitry Andric 
2449e8d8bef9SDimitry Andric   EmitEOL();
2450e8d8bef9SDimitry Andric }
2451e8d8bef9SDimitry Andric 
2452bdd1243dSDimitry Andric void MCAsmStreamer::emitBundleAlignMode(Align Alignment) {
2453bdd1243dSDimitry Andric   OS << "\t.bundle_align_mode " << Log2(Alignment);
24540b57cec5SDimitry Andric   EmitEOL();
24550b57cec5SDimitry Andric }
24560b57cec5SDimitry Andric 
24575ffd83dbSDimitry Andric void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {
24580b57cec5SDimitry Andric   OS << "\t.bundle_lock";
24590b57cec5SDimitry Andric   if (AlignToEnd)
24600b57cec5SDimitry Andric     OS << " align_to_end";
24610b57cec5SDimitry Andric   EmitEOL();
24620b57cec5SDimitry Andric }
24630b57cec5SDimitry Andric 
24645ffd83dbSDimitry Andric void MCAsmStreamer::emitBundleUnlock() {
24650b57cec5SDimitry Andric   OS << "\t.bundle_unlock";
24660b57cec5SDimitry Andric   EmitEOL();
24670b57cec5SDimitry Andric }
24680b57cec5SDimitry Andric 
2469bdd1243dSDimitry Andric std::optional<std::pair<bool, std::string>>
24705ffd83dbSDimitry Andric MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
24710b57cec5SDimitry Andric                                   const MCExpr *Expr, SMLoc,
24720b57cec5SDimitry Andric                                   const MCSubtargetInfo &STI) {
24730b57cec5SDimitry Andric   OS << "\t.reloc ";
24740b57cec5SDimitry Andric   Offset.print(OS, MAI);
24750b57cec5SDimitry Andric   OS << ", " << Name;
24760b57cec5SDimitry Andric   if (Expr) {
24770b57cec5SDimitry Andric     OS << ", ";
24780b57cec5SDimitry Andric     Expr->print(OS, MAI);
24790b57cec5SDimitry Andric   }
24800b57cec5SDimitry Andric   EmitEOL();
2481bdd1243dSDimitry Andric   return std::nullopt;
24820b57cec5SDimitry Andric }
24830b57cec5SDimitry Andric 
24845ffd83dbSDimitry Andric void MCAsmStreamer::emitAddrsig() {
24850b57cec5SDimitry Andric   OS << "\t.addrsig";
24860b57cec5SDimitry Andric   EmitEOL();
24870b57cec5SDimitry Andric }
24880b57cec5SDimitry Andric 
24895ffd83dbSDimitry Andric void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
24900b57cec5SDimitry Andric   OS << "\t.addrsig_sym ";
24910b57cec5SDimitry Andric   Sym->print(OS, MAI);
24920b57cec5SDimitry Andric   EmitEOL();
24930b57cec5SDimitry Andric }
24940b57cec5SDimitry Andric 
24950b57cec5SDimitry Andric /// EmitRawText - If this file is backed by an assembly streamer, this dumps
24960b57cec5SDimitry Andric /// the specified string in the output .s file.  This capability is
24970b57cec5SDimitry Andric /// indicated by the hasRawTextSupport() predicate.
24985ffd83dbSDimitry Andric void MCAsmStreamer::emitRawTextImpl(StringRef String) {
2499*0fca6ea1SDimitry Andric   String.consume_back("\n");
25000b57cec5SDimitry Andric   OS << String;
25010b57cec5SDimitry Andric   EmitEOL();
25020b57cec5SDimitry Andric }
25030b57cec5SDimitry Andric 
25045ffd83dbSDimitry Andric void MCAsmStreamer::finishImpl() {
25050b57cec5SDimitry Andric   // If we are generating dwarf for assembly source files dump out the sections.
25060b57cec5SDimitry Andric   if (getContext().getGenDwarfForAssembly())
25070b57cec5SDimitry Andric     MCGenDwarfInfo::Emit(this);
25080b57cec5SDimitry Andric 
2509fe6060f1SDimitry Andric   // Now it is time to emit debug line sections if target doesn't support .loc
2510fe6060f1SDimitry Andric   // and .line directives.
2511fe6060f1SDimitry Andric   if (!MAI->usesDwarfFileAndLocDirectives()) {
2512fe6060f1SDimitry Andric     MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
2513fe6060f1SDimitry Andric     return;
2514fe6060f1SDimitry Andric   }
2515fe6060f1SDimitry Andric 
25160b57cec5SDimitry Andric   // Emit the label for the line table, if requested - since the rest of the
25170b57cec5SDimitry Andric   // line table will be defined by .loc/.file directives, and not emitted
25180b57cec5SDimitry Andric   // directly, the label is the only work required here.
25190b57cec5SDimitry Andric   const auto &Tables = getContext().getMCDwarfLineTables();
25200b57cec5SDimitry Andric   if (!Tables.empty()) {
25210b57cec5SDimitry Andric     assert(Tables.size() == 1 && "asm output only supports one line table");
25220b57cec5SDimitry Andric     if (auto *Label = Tables.begin()->second.getLabel()) {
252381ad6265SDimitry Andric       switchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
25245ffd83dbSDimitry Andric       emitLabel(Label);
25250b57cec5SDimitry Andric     }
25260b57cec5SDimitry Andric   }
25270b57cec5SDimitry Andric }
25280b57cec5SDimitry Andric 
2529fe6060f1SDimitry Andric void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
2530fe6060f1SDimitry Andric   // If the assembler on some target fills in the DWARF unit length, we
2531fe6060f1SDimitry Andric   // don't want to emit the length in the compiler. For example, the AIX
2532fe6060f1SDimitry Andric   // assembler requires the assembly file with the unit length omitted from
2533fe6060f1SDimitry Andric   // the debug section headers. In such cases, any label we placed occurs
2534fe6060f1SDimitry Andric   // after the implied length field. We need to adjust the reference here
2535fe6060f1SDimitry Andric   // to account for the offset introduced by the inserted length field.
2536fe6060f1SDimitry Andric   if (!MAI->needsDwarfSectionSizeInHeader())
2537fe6060f1SDimitry Andric     return;
2538fe6060f1SDimitry Andric   MCStreamer::emitDwarfUnitLength(Length, Comment);
2539fe6060f1SDimitry Andric }
2540fe6060f1SDimitry Andric 
2541fe6060f1SDimitry Andric MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix,
2542fe6060f1SDimitry Andric                                              const Twine &Comment) {
2543fe6060f1SDimitry Andric   // If the assembler on some target fills in the DWARF unit length, we
2544fe6060f1SDimitry Andric   // don't want to emit the length in the compiler. For example, the AIX
2545fe6060f1SDimitry Andric   // assembler requires the assembly file with the unit length omitted from
2546fe6060f1SDimitry Andric   // the debug section headers. In such cases, any label we placed occurs
2547fe6060f1SDimitry Andric   // after the implied length field. We need to adjust the reference here
2548fe6060f1SDimitry Andric   // to account for the offset introduced by the inserted length field.
2549fe6060f1SDimitry Andric   if (!MAI->needsDwarfSectionSizeInHeader())
2550fe6060f1SDimitry Andric     return getContext().createTempSymbol(Prefix + "_end");
2551fe6060f1SDimitry Andric   return MCStreamer::emitDwarfUnitLength(Prefix, Comment);
2552fe6060f1SDimitry Andric }
2553fe6060f1SDimitry Andric 
2554fe6060f1SDimitry Andric void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
2555fe6060f1SDimitry Andric   // If the assembler on some target fills in the DWARF unit length, we
2556fe6060f1SDimitry Andric   // don't want to emit the length in the compiler. For example, the AIX
2557fe6060f1SDimitry Andric   // assembler requires the assembly file with the unit length omitted from
2558fe6060f1SDimitry Andric   // the debug section headers. In such cases, any label we placed occurs
2559fe6060f1SDimitry Andric   // after the implied length field. We need to adjust the reference here
2560fe6060f1SDimitry Andric   // to account for the offset introduced by the inserted length field.
2561fe6060f1SDimitry Andric   MCContext &Ctx = getContext();
2562fe6060f1SDimitry Andric   if (!MAI->needsDwarfSectionSizeInHeader()) {
2563fe6060f1SDimitry Andric     MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_");
2564fe6060f1SDimitry Andric     // Emit the symbol which does not contain the unit length field.
2565fe6060f1SDimitry Andric     emitLabel(DebugLineSymTmp);
2566fe6060f1SDimitry Andric 
2567fe6060f1SDimitry Andric     // Adjust the outer reference to account for the offset introduced by the
2568fe6060f1SDimitry Andric     // inserted length field.
2569fe6060f1SDimitry Andric     unsigned LengthFieldSize =
2570fe6060f1SDimitry Andric         dwarf::getUnitLengthFieldByteSize(Ctx.getDwarfFormat());
2571fe6060f1SDimitry Andric     const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx);
2572fe6060f1SDimitry Andric     const MCExpr *OuterSym = MCBinaryExpr::createSub(
2573fe6060f1SDimitry Andric         MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx);
2574fe6060f1SDimitry Andric 
2575fe6060f1SDimitry Andric     emitAssignment(StartSym, OuterSym);
2576fe6060f1SDimitry Andric     return;
2577fe6060f1SDimitry Andric   }
2578fe6060f1SDimitry Andric   MCStreamer::emitDwarfLineStartLabel(StartSym);
2579fe6060f1SDimitry Andric }
2580fe6060f1SDimitry Andric 
2581fe6060f1SDimitry Andric void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section,
2582fe6060f1SDimitry Andric                                           MCSymbol *LastLabel) {
2583fe6060f1SDimitry Andric   // If the targets write the raw debug line data for assembly output (We can
2584fe6060f1SDimitry Andric   // not switch to Section and add the end symbol there for assembly output)
2585fe6060f1SDimitry Andric   // we currently use the .text end label as any section end. This will not
2586fe6060f1SDimitry Andric   // impact the debugability as we will jump to the caller of the last function
2587fe6060f1SDimitry Andric   // in the section before we come into the .text end address.
2588fe6060f1SDimitry Andric   assert(!MAI->usesDwarfFileAndLocDirectives() &&
2589fe6060f1SDimitry Andric          ".loc should not be generated together with raw data!");
2590fe6060f1SDimitry Andric 
2591fe6060f1SDimitry Andric   MCContext &Ctx = getContext();
2592fe6060f1SDimitry Andric 
2593fe6060f1SDimitry Andric   // FIXME: use section end symbol as end of the Section. We need to consider
2594fe6060f1SDimitry Andric   // the explicit sections and -ffunction-sections when we try to generate or
2595fe6060f1SDimitry Andric   // find section end symbol for the Section.
2596fe6060f1SDimitry Andric   MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection();
2597fe6060f1SDimitry Andric   assert(TextSection->hasEnded() && ".text section is not end!");
2598fe6060f1SDimitry Andric 
2599fe6060f1SDimitry Andric   MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx);
2600fe6060f1SDimitry Andric   const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
2601fe6060f1SDimitry Andric   emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
2602fe6060f1SDimitry Andric                            AsmInfo->getCodePointerSize());
2603fe6060f1SDimitry Andric }
2604fe6060f1SDimitry Andric 
2605fe6060f1SDimitry Andric // Generate DWARF line sections for assembly mode without .loc/.file
2606fe6060f1SDimitry Andric void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
2607fe6060f1SDimitry Andric                                              const MCSymbol *LastLabel,
2608fe6060f1SDimitry Andric                                              const MCSymbol *Label,
2609fe6060f1SDimitry Andric                                              unsigned PointerSize) {
2610fe6060f1SDimitry Andric   assert(!MAI->usesDwarfFileAndLocDirectives() &&
2611fe6060f1SDimitry Andric          ".loc/.file don't need raw data in debug line section!");
2612fe6060f1SDimitry Andric 
2613fe6060f1SDimitry Andric   // Set to new address.
2614fe6060f1SDimitry Andric   AddComment("Set address to " + Label->getName());
2615fe6060f1SDimitry Andric   emitIntValue(dwarf::DW_LNS_extended_op, 1);
2616fe6060f1SDimitry Andric   emitULEB128IntValue(PointerSize + 1);
2617fe6060f1SDimitry Andric   emitIntValue(dwarf::DW_LNE_set_address, 1);
2618fe6060f1SDimitry Andric   emitSymbolValue(Label, PointerSize);
2619fe6060f1SDimitry Andric 
2620fe6060f1SDimitry Andric   if (!LastLabel) {
2621fe6060f1SDimitry Andric     // Emit the sequence for the LineDelta (from 1) and a zero address delta.
2622fe6060f1SDimitry Andric     AddComment("Start sequence");
2623fe6060f1SDimitry Andric     MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0);
2624fe6060f1SDimitry Andric     return;
2625fe6060f1SDimitry Andric   }
2626fe6060f1SDimitry Andric 
2627fe6060f1SDimitry Andric   // INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence
2628fe6060f1SDimitry Andric   // for the end of the section.
2629fe6060f1SDimitry Andric   if (LineDelta == INT64_MAX) {
2630fe6060f1SDimitry Andric     AddComment("End sequence");
2631fe6060f1SDimitry Andric     emitIntValue(dwarf::DW_LNS_extended_op, 1);
2632fe6060f1SDimitry Andric     emitULEB128IntValue(1);
2633fe6060f1SDimitry Andric     emitIntValue(dwarf::DW_LNE_end_sequence, 1);
2634fe6060f1SDimitry Andric     return;
2635fe6060f1SDimitry Andric   }
2636fe6060f1SDimitry Andric 
2637fe6060f1SDimitry Andric   // Advance line.
2638fe6060f1SDimitry Andric   AddComment("Advance line " + Twine(LineDelta));
2639fe6060f1SDimitry Andric   emitIntValue(dwarf::DW_LNS_advance_line, 1);
2640fe6060f1SDimitry Andric   emitSLEB128IntValue(LineDelta);
2641fe6060f1SDimitry Andric   emitIntValue(dwarf::DW_LNS_copy, 1);
2642fe6060f1SDimitry Andric }
2643fe6060f1SDimitry Andric 
2644fe6060f1SDimitry Andric void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) {
2645fe6060f1SDimitry Andric   // Emit section end. This is used to tell the debug line section where the end
2646fe6060f1SDimitry Andric   // is for a text section if we don't use .loc to represent the debug line.
2647fe6060f1SDimitry Andric   if (MAI->usesDwarfFileAndLocDirectives())
2648fe6060f1SDimitry Andric     return;
2649fe6060f1SDimitry Andric 
2650*0fca6ea1SDimitry Andric   switchSectionNoPrint(Section);
2651fe6060f1SDimitry Andric 
2652fe6060f1SDimitry Andric   MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext());
2653fe6060f1SDimitry Andric 
2654fe6060f1SDimitry Andric   if (!Sym->isInSection())
2655fe6060f1SDimitry Andric     emitLabel(Sym);
2656fe6060f1SDimitry Andric }
2657fe6060f1SDimitry Andric 
26580b57cec5SDimitry Andric MCStreamer *llvm::createAsmStreamer(MCContext &Context,
26590b57cec5SDimitry Andric                                     std::unique_ptr<formatted_raw_ostream> OS,
26600b57cec5SDimitry Andric                                     MCInstPrinter *IP,
26610b57cec5SDimitry Andric                                     std::unique_ptr<MCCodeEmitter> &&CE,
2662*0fca6ea1SDimitry Andric                                     std::unique_ptr<MCAsmBackend> &&MAB) {
2663*0fca6ea1SDimitry Andric   return new MCAsmStreamer(Context, std::move(OS), IP, std::move(CE),
2664*0fca6ea1SDimitry Andric                            std::move(MAB));
26650b57cec5SDimitry Andric }
2666