Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp
35233 views
//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ADT/SmallString.h"9#include "llvm/ADT/StringExtras.h"10#include "llvm/ADT/Twine.h"11#include "llvm/DebugInfo/CodeView/SymbolRecord.h"12#include "llvm/MC/MCAsmBackend.h"13#include "llvm/MC/MCAsmInfo.h"14#include "llvm/MC/MCAssembler.h"15#include "llvm/MC/MCCodeEmitter.h"16#include "llvm/MC/MCCodeView.h"17#include "llvm/MC/MCContext.h"18#include "llvm/MC/MCExpr.h"19#include "llvm/MC/MCFixupKindInfo.h"20#include "llvm/MC/MCInst.h"21#include "llvm/MC/MCInstPrinter.h"22#include "llvm/MC/MCObjectFileInfo.h"23#include "llvm/MC/MCObjectWriter.h"24#include "llvm/MC/MCPseudoProbe.h"25#include "llvm/MC/MCRegister.h"26#include "llvm/MC/MCRegisterInfo.h"27#include "llvm/MC/MCSectionMachO.h"28#include "llvm/MC/MCStreamer.h"29#include "llvm/MC/MCSymbolXCOFF.h"30#include "llvm/MC/TargetRegistry.h"31#include "llvm/Support/Casting.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Support/Format.h"34#include "llvm/Support/FormattedStream.h"35#include "llvm/Support/LEB128.h"36#include "llvm/Support/MathExtras.h"37#include "llvm/Support/Path.h"38#include <algorithm>39#include <optional>4041using namespace llvm;4243namespace {4445class MCAsmStreamer final : public MCStreamer {46std::unique_ptr<formatted_raw_ostream> OSOwner;47formatted_raw_ostream &OS;48const MCAsmInfo *MAI;49std::unique_ptr<MCInstPrinter> InstPrinter;50std::unique_ptr<MCAssembler> Assembler;5152SmallString<128> ExplicitCommentToEmit;53SmallString<128> CommentToEmit;54raw_svector_ostream CommentStream;55raw_null_ostream NullStream;5657bool IsVerboseAsm = false;58bool ShowInst = false;59bool UseDwarfDirectory = false;6061void EmitRegisterName(int64_t Register);62void PrintQuotedString(StringRef Data, raw_ostream &OS) const;63void printDwarfFileDirective(unsigned FileNo, StringRef Directory,64StringRef Filename,65std::optional<MD5::MD5Result> Checksum,66std::optional<StringRef> Source,67bool UseDwarfDirectory,68raw_svector_ostream &OS) const;69void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;70void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;7172public:73MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,74MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,75std::unique_ptr<MCAsmBackend> asmbackend)76: MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),77MAI(Context.getAsmInfo()), InstPrinter(printer),78Assembler(std::make_unique<MCAssembler>(79Context, std::move(asmbackend), std::move(emitter),80(asmbackend) ? asmbackend->createObjectWriter(NullStream)81: nullptr)),82CommentStream(CommentToEmit) {83assert(InstPrinter);84if (Assembler->getBackendPtr())85setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());8687Context.setUseNamesOnTempLabels(true);8889auto *TO = Context.getTargetOptions();90if (!TO)91return;92IsVerboseAsm = TO->AsmVerbose;93if (IsVerboseAsm)94InstPrinter->setCommentStream(CommentStream);95ShowInst = TO->ShowMCInst;96switch (TO->MCUseDwarfDirectory) {97case MCTargetOptions::DisableDwarfDirectory:98UseDwarfDirectory = false;99break;100case MCTargetOptions::EnableDwarfDirectory:101UseDwarfDirectory = true;102break;103case MCTargetOptions::DefaultDwarfDirectory:104UseDwarfDirectory =105Context.getAsmInfo()->enableDwarfFileDirectoryDefault();106break;107}108}109110MCAssembler &getAssembler() { return *Assembler; }111MCAssembler *getAssemblerPtr() override { return nullptr; }112113inline void EmitEOL() {114// Dump Explicit Comments here.115emitExplicitComments();116// If we don't have any comments, just emit a \n.117if (!IsVerboseAsm) {118OS << '\n';119return;120}121EmitCommentsAndEOL();122}123124void emitSyntaxDirective() override;125126void EmitCommentsAndEOL();127128/// Return true if this streamer supports verbose assembly at all.129bool isVerboseAsm() const override { return IsVerboseAsm; }130131/// Do we support EmitRawText?132bool hasRawTextSupport() const override { return true; }133134/// Add a comment that can be emitted to the generated .s file to make the135/// output of the compiler more readable. This only affects the MCAsmStreamer136/// and only when verbose assembly output is enabled.137void AddComment(const Twine &T, bool EOL = true) override;138139/// Add a comment showing the encoding of an instruction.140void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);141142/// Return a raw_ostream that comments can be written to.143/// Unlike AddComment, you are required to terminate comments with \n if you144/// use this method.145raw_ostream &getCommentOS() override {146if (!IsVerboseAsm)147return nulls(); // Discard comments unless in verbose asm mode.148return CommentStream;149}150151void emitRawComment(const Twine &T, bool TabPrefix = true) override;152153void addExplicitComment(const Twine &T) override;154void emitExplicitComments() override;155156/// Emit a blank line to a .s file to pretty it up.157void addBlankLine() override { EmitEOL(); }158159/// @name MCStreamer Interface160/// @{161162void changeSection(MCSection *Section, uint32_t Subsection) override;163164void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,165bool KeepOriginalSym) override;166167void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;168169void emitGNUAttribute(unsigned Tag, unsigned Value) override;170171StringRef getMnemonic(MCInst &MI) override {172auto [Ptr, Bits] = InstPrinter->getMnemonic(&MI);173assert((Bits != 0 || Ptr == nullptr) &&174"Invalid char pointer for instruction with no mnemonic");175return Ptr;176}177178void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;179180void emitAssemblerFlag(MCAssemblerFlag Flag) override;181void emitLinkerOptions(ArrayRef<std::string> Options) override;182void emitDataRegion(MCDataRegionType Kind) override;183void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,184unsigned Update, VersionTuple SDKVersion) override;185void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,186unsigned Update, VersionTuple SDKVersion) override;187void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,188unsigned Minor, unsigned Update,189VersionTuple SDKVersion) override;190void emitThumbFunc(MCSymbol *Func) override;191192void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;193void emitConditionalAssignment(MCSymbol *Symbol,194const MCExpr *Value) override;195void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;196bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;197198void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;199void beginCOFFSymbolDef(const MCSymbol *Symbol) override;200void emitCOFFSymbolStorageClass(int StorageClass) override;201void emitCOFFSymbolType(int Type) override;202void endCOFFSymbolDef() override;203void emitCOFFSafeSEH(MCSymbol const *Symbol) override;204void emitCOFFSymbolIndex(MCSymbol const *Symbol) override;205void emitCOFFSectionIndex(MCSymbol const *Symbol) override;206void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;207void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;208void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,209MCSymbol *CsectSym, Align Alignment) override;210void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,211MCSymbolAttr Linkage,212MCSymbolAttr Visibility) override;213void emitXCOFFRenameDirective(const MCSymbol *Name,214StringRef Rename) override;215216void emitXCOFFRefDirective(const MCSymbol *Symbol) override;217218void emitXCOFFExceptDirective(const MCSymbol *Symbol,219const MCSymbol *Trap,220unsigned Lang, unsigned Reason,221unsigned FunctionSize, bool hasDebug) override;222void emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) override;223224void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;225void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,226Align ByteAlignment) override;227228/// Emit a local common (.lcomm) symbol.229///230/// @param Symbol - The common symbol to emit.231/// @param Size - The size of the common symbol.232/// @param ByteAlignment - The alignment of the common symbol in bytes.233void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,234Align ByteAlignment) override;235236void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,237uint64_t Size = 0, Align ByteAlignment = Align(1),238SMLoc Loc = SMLoc()) override;239240void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,241Align ByteAlignment = Align(1)) override;242243void emitBinaryData(StringRef Data) override;244245void emitBytes(StringRef Data) override;246247void emitValueImpl(const MCExpr *Value, unsigned Size,248SMLoc Loc = SMLoc()) override;249void emitIntValue(uint64_t Value, unsigned Size) override;250void emitIntValueInHex(uint64_t Value, unsigned Size) override;251void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;252253void emitULEB128Value(const MCExpr *Value) override;254255void emitSLEB128Value(const MCExpr *Value) override;256257void emitDTPRel32Value(const MCExpr *Value) override;258void emitDTPRel64Value(const MCExpr *Value) override;259void emitTPRel32Value(const MCExpr *Value) override;260void emitTPRel64Value(const MCExpr *Value) override;261262void emitGPRel64Value(const MCExpr *Value) override;263264void emitGPRel32Value(const MCExpr *Value) override;265266void emitFill(const MCExpr &NumBytes, uint64_t FillValue,267SMLoc Loc = SMLoc()) override;268269void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,270SMLoc Loc = SMLoc()) override;271272void emitAlignmentDirective(uint64_t ByteAlignment,273std::optional<int64_t> Value, unsigned ValueSize,274unsigned MaxBytesToEmit);275276void emitValueToAlignment(Align Alignment, int64_t Value = 0,277unsigned ValueSize = 1,278unsigned MaxBytesToEmit = 0) override;279280void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI,281unsigned MaxBytesToEmit = 0) override;282283void emitValueToOffset(const MCExpr *Offset,284unsigned char Value,285SMLoc Loc) override;286287void emitFileDirective(StringRef Filename) override;288void emitFileDirective(StringRef Filename, StringRef CompilerVersion,289StringRef TimeStamp, StringRef Description) override;290Expected<unsigned> tryEmitDwarfFileDirective(291unsigned FileNo, StringRef Directory, StringRef Filename,292std::optional<MD5::MD5Result> Checksum = std::nullopt,293std::optional<StringRef> Source = std::nullopt,294unsigned CUID = 0) override;295void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,296std::optional<MD5::MD5Result> Checksum,297std::optional<StringRef> Source,298unsigned CUID = 0) override;299void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,300unsigned Flags, unsigned Isa,301unsigned Discriminator,302StringRef FileName) override;303MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;304305bool emitCVFileDirective(unsigned FileNo, StringRef Filename,306ArrayRef<uint8_t> Checksum,307unsigned ChecksumKind) override;308bool emitCVFuncIdDirective(unsigned FuncId) override;309bool emitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,310unsigned IAFile, unsigned IALine,311unsigned IACol, SMLoc Loc) override;312void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,313unsigned Column, bool PrologueEnd, bool IsStmt,314StringRef FileName, SMLoc Loc) override;315void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,316const MCSymbol *FnEnd) override;317void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,318unsigned SourceFileId,319unsigned SourceLineNum,320const MCSymbol *FnStartSym,321const MCSymbol *FnEndSym) override;322323void PrintCVDefRangePrefix(324ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);325326void emitCVDefRangeDirective(327ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,328codeview::DefRangeRegisterRelHeader DRHdr) override;329330void emitCVDefRangeDirective(331ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,332codeview::DefRangeSubfieldRegisterHeader DRHdr) override;333334void emitCVDefRangeDirective(335ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,336codeview::DefRangeRegisterHeader DRHdr) override;337338void emitCVDefRangeDirective(339ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,340codeview::DefRangeFramePointerRelHeader DRHdr) override;341342void emitCVStringTableDirective() override;343void emitCVFileChecksumsDirective() override;344void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;345void emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;346347void emitIdent(StringRef IdentString) override;348void emitCFIBKeyFrame() override;349void emitCFIMTETaggedFrame() override;350void emitCFISections(bool EH, bool Debug) override;351void emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) override;352void emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) override;353void emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) override;354void emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,355int64_t AddressSpace, SMLoc Loc) override;356void emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) override;357void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;358void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;359void emitCFIRememberState(SMLoc Loc) override;360void emitCFIRestoreState(SMLoc Loc) override;361void emitCFIRestore(int64_t Register, SMLoc Loc) override;362void emitCFISameValue(int64_t Register, SMLoc Loc) override;363void emitCFIRelOffset(int64_t Register, int64_t Offset, SMLoc Loc) override;364void emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) override;365void emitCFIEscape(StringRef Values, SMLoc Loc) override;366void emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) override;367void emitCFISignalFrame() override;368void emitCFIUndefined(int64_t Register, SMLoc Loc) override;369void emitCFIRegister(int64_t Register1, int64_t Register2,370SMLoc Loc) override;371void emitCFIWindowSave(SMLoc Loc) override;372void emitCFINegateRAState(SMLoc Loc) override;373void emitCFIReturnColumn(int64_t Register) override;374void emitCFILabelDirective(SMLoc Loc, StringRef Name) override;375376void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;377void emitWinCFIEndProc(SMLoc Loc) override;378void emitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;379void emitWinCFIStartChained(SMLoc Loc) override;380void emitWinCFIEndChained(SMLoc Loc) override;381void emitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;382void emitWinCFISetFrame(MCRegister Register, unsigned Offset,383SMLoc Loc) override;384void emitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;385void emitWinCFISaveReg(MCRegister Register, unsigned Offset,386SMLoc Loc) override;387void emitWinCFISaveXMM(MCRegister Register, unsigned Offset,388SMLoc Loc) override;389void emitWinCFIPushFrame(bool Code, SMLoc Loc) override;390void emitWinCFIEndProlog(SMLoc Loc) override;391392void emitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,393SMLoc Loc) override;394void emitWinEHHandlerData(SMLoc Loc) override;395396void emitCGProfileEntry(const MCSymbolRefExpr *From,397const MCSymbolRefExpr *To, uint64_t Count) override;398399void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;400401void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,402uint64_t Attr, uint64_t Discriminator,403const MCPseudoProbeInlineStack &InlineStack,404MCSymbol *FnSym) override;405406void emitBundleAlignMode(Align Alignment) override;407void emitBundleLock(bool AlignToEnd) override;408void emitBundleUnlock() override;409410std::optional<std::pair<bool, std::string>>411emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,412SMLoc Loc, const MCSubtargetInfo &STI) override;413414void emitAddrsig() override;415void emitAddrsigSym(const MCSymbol *Sym) override;416417/// If this file is backed by an assembly streamer, this dumps the specified418/// string in the output .s file. This capability is indicated by the419/// hasRawTextSupport() predicate.420void emitRawTextImpl(StringRef String) override;421422void finishImpl() override;423424void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override;425426MCSymbol *emitDwarfUnitLength(const Twine &Prefix,427const Twine &Comment) override;428429void emitDwarfLineStartLabel(MCSymbol *StartSym) override;430431void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override;432433void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,434const MCSymbol *Label,435unsigned PointerSize) override;436437void doFinalizationAtSectionEnd(MCSection *Section) override;438};439440} // end anonymous namespace.441442void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {443if (!IsVerboseAsm) return;444445T.toVector(CommentToEmit);446447if (EOL)448CommentToEmit.push_back('\n'); // Place comment in a new line.449}450451void MCAsmStreamer::EmitCommentsAndEOL() {452if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {453OS << '\n';454return;455}456457StringRef Comments = CommentToEmit;458459assert(Comments.back() == '\n' &&460"Comment array not newline terminated");461do {462// Emit a line of comments.463OS.PadToColumn(MAI->getCommentColumn());464size_t Position = Comments.find('\n');465OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';466467Comments = Comments.substr(Position+1);468} while (!Comments.empty());469470CommentToEmit.clear();471}472473static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {474assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");475return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));476}477478void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {479if (TabPrefix)480OS << '\t';481OS << MAI->getCommentString() << T;482EmitEOL();483}484485void MCAsmStreamer::addExplicitComment(const Twine &T) {486StringRef c = T.getSingleStringRef();487if (c == MAI->getSeparatorString())488return;489if (c.starts_with(StringRef("//"))) {490ExplicitCommentToEmit.append("\t");491ExplicitCommentToEmit.append(MAI->getCommentString());492// drop //493ExplicitCommentToEmit.append(c.slice(2, c.size()).str());494} else if (c.starts_with(StringRef("/*"))) {495size_t p = 2, len = c.size() - 2;496// emit each line in comment as separate newline.497do {498size_t newp = std::min(len, c.find_first_of("\r\n", p));499ExplicitCommentToEmit.append("\t");500ExplicitCommentToEmit.append(MAI->getCommentString());501ExplicitCommentToEmit.append(c.slice(p, newp).str());502// If we have another line in this comment add line503if (newp < len)504ExplicitCommentToEmit.append("\n");505p = newp + 1;506} while (p < len);507} else if (c.starts_with(StringRef(MAI->getCommentString()))) {508ExplicitCommentToEmit.append("\t");509ExplicitCommentToEmit.append(c.str());510} else if (c.front() == '#') {511512ExplicitCommentToEmit.append("\t");513ExplicitCommentToEmit.append(MAI->getCommentString());514ExplicitCommentToEmit.append(c.slice(1, c.size()).str());515} else516assert(false && "Unexpected Assembly Comment");517// full line comments immediately output518if (c.back() == '\n')519emitExplicitComments();520}521522void MCAsmStreamer::emitExplicitComments() {523StringRef Comments = ExplicitCommentToEmit;524if (!Comments.empty())525OS << Comments;526ExplicitCommentToEmit.clear();527}528529void MCAsmStreamer::changeSection(MCSection *Section, uint32_t Subsection) {530if (MCTargetStreamer *TS = getTargetStreamer()) {531TS->changeSection(getCurrentSection().first, Section, Subsection, OS);532} else {533Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS,534Subsection);535}536MCStreamer::changeSection(Section, Subsection);537}538539void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,540StringRef Name,541bool KeepOriginalSym) {542OS << ".symver ";543OriginalSym->print(OS, MAI);544OS << ", " << Name;545if (!KeepOriginalSym && !Name.contains("@@@"))546OS << ", remove";547EmitEOL();548}549550void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {551MCStreamer::emitLabel(Symbol, Loc);552553Symbol->print(OS, MAI);554OS << MAI->getLabelSuffix();555556EmitEOL();557}558559void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {560StringRef str = MCLOHIdToName(Kind);561562#ifndef NDEBUG563int NbArgs = MCLOHIdToNbArgs(Kind);564assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");565assert(str != "" && "Invalid LOH name");566#endif567568OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";569bool IsFirst = true;570for (const MCSymbol *Arg : Args) {571if (!IsFirst)572OS << ", ";573IsFirst = false;574Arg->print(OS, MAI);575}576EmitEOL();577}578579void MCAsmStreamer::emitGNUAttribute(unsigned Tag, unsigned Value) {580OS << "\t.gnu_attribute " << Tag << ", " << Value << "\n";581}582583void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {584switch (Flag) {585case MCAF_SyntaxUnified: OS << "\t.syntax unified"; break;586case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;587case MCAF_Code16: OS << '\t'<< MAI->getCode16Directive();break;588case MCAF_Code32: OS << '\t'<< MAI->getCode32Directive();break;589case MCAF_Code64: OS << '\t'<< MAI->getCode64Directive();break;590}591EmitEOL();592}593594void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {595assert(!Options.empty() && "At least one option is required!");596OS << "\t.linker_option \"" << Options[0] << '"';597for (const std::string &Opt : llvm::drop_begin(Options))598OS << ", " << '"' << Opt << '"';599EmitEOL();600}601602void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {603if (!MAI->doesSupportDataRegionDirectives())604return;605switch (Kind) {606case MCDR_DataRegion: OS << "\t.data_region"; break;607case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;608case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;609case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;610case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;611}612EmitEOL();613}614615static const char *getVersionMinDirective(MCVersionMinType Type) {616switch (Type) {617case MCVM_WatchOSVersionMin: return ".watchos_version_min";618case MCVM_TvOSVersionMin: return ".tvos_version_min";619case MCVM_IOSVersionMin: return ".ios_version_min";620case MCVM_OSXVersionMin: return ".macosx_version_min";621}622llvm_unreachable("Invalid MC version min type");623}624625static void EmitSDKVersionSuffix(raw_ostream &OS,626const VersionTuple &SDKVersion) {627if (SDKVersion.empty())628return;629OS << '\t' << "sdk_version " << SDKVersion.getMajor();630if (auto Minor = SDKVersion.getMinor()) {631OS << ", " << *Minor;632if (auto Subminor = SDKVersion.getSubminor()) {633OS << ", " << *Subminor;634}635}636}637638void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,639unsigned Minor, unsigned Update,640VersionTuple SDKVersion) {641OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;642if (Update)643OS << ", " << Update;644EmitSDKVersionSuffix(OS, SDKVersion);645EmitEOL();646}647648static const char *getPlatformName(MachO::PlatformType Type) {649switch (Type) {650#define PLATFORM(platform, id, name, build_name, target, tapi_target, \651marketing) \652case MachO::PLATFORM_##platform: \653return #build_name;654#include "llvm/BinaryFormat/MachO.def"655}656llvm_unreachable("Invalid Mach-O platform type");657}658659void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,660unsigned Minor, unsigned Update,661VersionTuple SDKVersion) {662const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);663OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;664if (Update)665OS << ", " << Update;666EmitSDKVersionSuffix(OS, SDKVersion);667EmitEOL();668}669670void MCAsmStreamer::emitDarwinTargetVariantBuildVersion(671unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,672VersionTuple SDKVersion) {673emitBuildVersion(Platform, Major, Minor, Update, SDKVersion);674}675676void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {677// This needs to emit to a temporary string to get properly quoted678// MCSymbols when they have spaces in them.679OS << "\t.thumb_func";680// Only Mach-O hasSubsectionsViaSymbols()681if (MAI->hasSubsectionsViaSymbols()) {682OS << '\t';683Func->print(OS, MAI);684}685EmitEOL();686}687688void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {689// Do not emit a .set on inlined target assignments.690bool EmitSet = true;691if (auto *E = dyn_cast<MCTargetExpr>(Value))692if (E->inlineAssignedExpr())693EmitSet = false;694if (EmitSet) {695OS << ".set ";696Symbol->print(OS, MAI);697OS << ", ";698Value->print(OS, MAI);699700EmitEOL();701}702703MCStreamer::emitAssignment(Symbol, Value);704}705706void MCAsmStreamer::emitConditionalAssignment(MCSymbol *Symbol,707const MCExpr *Value) {708OS << ".lto_set_conditional ";709Symbol->print(OS, MAI);710OS << ", ";711Value->print(OS, MAI);712EmitEOL();713}714715void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {716OS << ".weakref ";717Alias->print(OS, MAI);718OS << ", ";719Symbol->print(OS, MAI);720EmitEOL();721}722723bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,724MCSymbolAttr Attribute) {725switch (Attribute) {726case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");727case MCSA_ELF_TypeFunction: /// .type _foo, STT_FUNC # aka @function728case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC729case MCSA_ELF_TypeObject: /// .type _foo, STT_OBJECT # aka @object730case MCSA_ELF_TypeTLS: /// .type _foo, STT_TLS # aka @tls_object731case MCSA_ELF_TypeCommon: /// .type _foo, STT_COMMON # aka @common732case MCSA_ELF_TypeNoType: /// .type _foo, STT_NOTYPE # aka @notype733case MCSA_ELF_TypeGnuUniqueObject: /// .type _foo, @gnu_unique_object734if (!MAI->hasDotTypeDotSizeDirective())735return false; // Symbol attribute not supported736OS << "\t.type\t";737Symbol->print(OS, MAI);738OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');739switch (Attribute) {740default: return false;741case MCSA_ELF_TypeFunction: OS << "function"; break;742case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;743case MCSA_ELF_TypeObject: OS << "object"; break;744case MCSA_ELF_TypeTLS: OS << "tls_object"; break;745case MCSA_ELF_TypeCommon: OS << "common"; break;746case MCSA_ELF_TypeNoType: OS << "notype"; break;747case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;748}749EmitEOL();750return true;751case MCSA_Global: // .globl/.global752OS << MAI->getGlobalDirective();753break;754case MCSA_LGlobal: OS << "\t.lglobl\t"; break;755case MCSA_Hidden: OS << "\t.hidden\t"; break;756case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;757case MCSA_Internal: OS << "\t.internal\t"; break;758case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break;759case MCSA_Local: OS << "\t.local\t"; break;760case MCSA_NoDeadStrip:761if (!MAI->hasNoDeadStrip())762return false;763OS << "\t.no_dead_strip\t";764break;765case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;766case MCSA_AltEntry: OS << "\t.alt_entry\t"; break;767case MCSA_PrivateExtern:768OS << "\t.private_extern\t";769break;770case MCSA_Protected: OS << "\t.protected\t"; break;771case MCSA_Reference: OS << "\t.reference\t"; break;772case MCSA_Extern:773OS << "\t.extern\t";774break;775case MCSA_Weak: OS << MAI->getWeakDirective(); break;776case MCSA_WeakDefinition:777OS << "\t.weak_definition\t";778break;779// .weak_reference780case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;781case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;782case MCSA_Cold:783// Assemblers currently do not support a .cold directive.784case MCSA_Exported:785// Non-AIX assemblers currently do not support exported visibility.786return false;787case MCSA_Memtag:788OS << "\t.memtag\t";789break;790case MCSA_WeakAntiDep:791OS << "\t.weak_anti_dep\t";792break;793}794795Symbol->print(OS, MAI);796EmitEOL();797798return true;799}800801void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {802OS << ".desc" << ' ';803Symbol->print(OS, MAI);804OS << ',' << DescValue;805EmitEOL();806}807808void MCAsmStreamer::emitSyntaxDirective() {809if (MAI->getAssemblerDialect() == 1) {810OS << "\t.intel_syntax noprefix";811EmitEOL();812}813// FIXME: Currently emit unprefix'ed registers.814// The intel_syntax directive has one optional argument815// with may have a value of prefix or noprefix.816}817818void MCAsmStreamer::beginCOFFSymbolDef(const MCSymbol *Symbol) {819OS << "\t.def\t";820Symbol->print(OS, MAI);821OS << ';';822EmitEOL();823}824825void MCAsmStreamer::emitCOFFSymbolStorageClass(int StorageClass) {826OS << "\t.scl\t" << StorageClass << ';';827EmitEOL();828}829830void MCAsmStreamer::emitCOFFSymbolType(int Type) {831OS << "\t.type\t" << Type << ';';832EmitEOL();833}834835void MCAsmStreamer::endCOFFSymbolDef() {836OS << "\t.endef";837EmitEOL();838}839840void MCAsmStreamer::emitCOFFSafeSEH(MCSymbol const *Symbol) {841OS << "\t.safeseh\t";842Symbol->print(OS, MAI);843EmitEOL();844}845846void MCAsmStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {847OS << "\t.symidx\t";848Symbol->print(OS, MAI);849EmitEOL();850}851852void MCAsmStreamer::emitCOFFSectionIndex(MCSymbol const *Symbol) {853OS << "\t.secidx\t";854Symbol->print(OS, MAI);855EmitEOL();856}857858void MCAsmStreamer::emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {859OS << "\t.secrel32\t";860Symbol->print(OS, MAI);861if (Offset != 0)862OS << '+' << Offset;863EmitEOL();864}865866void MCAsmStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {867OS << "\t.rva\t";868Symbol->print(OS, MAI);869if (Offset > 0)870OS << '+' << Offset;871else if (Offset < 0)872OS << '-' << -Offset;873EmitEOL();874}875876// We need an XCOFF-specific version of this directive as the AIX syntax877// requires a QualName argument identifying the csect name and storage mapping878// class to appear before the alignment if we are specifying it.879void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,880uint64_t Size,881MCSymbol *CsectSym,882Align Alignment) {883assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&884"We only support writing log base-2 alignment format with XCOFF.");885886OS << "\t.lcomm\t";887LabelSym->print(OS, MAI);888OS << ',' << Size << ',';889CsectSym->print(OS, MAI);890OS << ',' << Log2(Alignment);891892EmitEOL();893894// Print symbol's rename (original name contains invalid character(s)) if895// there is one.896MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym);897if (XSym->hasRename())898emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());899}900901void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(902MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {903904switch (Linkage) {905case MCSA_Global:906OS << MAI->getGlobalDirective();907break;908case MCSA_Weak:909OS << MAI->getWeakDirective();910break;911case MCSA_Extern:912OS << "\t.extern\t";913break;914case MCSA_LGlobal:915OS << "\t.lglobl\t";916break;917default:918report_fatal_error("unhandled linkage type");919}920921Symbol->print(OS, MAI);922923switch (Visibility) {924case MCSA_Invalid:925// Nothing to do.926break;927case MCSA_Hidden:928OS << ",hidden";929break;930case MCSA_Protected:931OS << ",protected";932break;933case MCSA_Exported:934OS << ",exported";935break;936default:937report_fatal_error("unexpected value for Visibility type");938}939EmitEOL();940941// Print symbol's rename (original name contains invalid character(s)) if942// there is one.943if (cast<MCSymbolXCOFF>(Symbol)->hasRename())944emitXCOFFRenameDirective(Symbol,945cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());946}947948void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,949StringRef Rename) {950OS << "\t.rename\t";951Name->print(OS, MAI);952const char DQ = '"';953OS << ',' << DQ;954for (char C : Rename) {955// To escape a double quote character, the character should be doubled.956if (C == DQ)957OS << DQ;958OS << C;959}960OS << DQ;961EmitEOL();962}963964void MCAsmStreamer::emitXCOFFRefDirective(const MCSymbol *Symbol) {965OS << "\t.ref ";966Symbol->print(OS, MAI);967EmitEOL();968}969970void MCAsmStreamer::emitXCOFFExceptDirective(const MCSymbol *Symbol,971const MCSymbol *Trap,972unsigned Lang,973unsigned Reason,974unsigned FunctionSize,975bool hasDebug) {976OS << "\t.except\t";977Symbol->print(OS, MAI);978OS << ", " << Lang << ", " << Reason;979EmitEOL();980}981982void MCAsmStreamer::emitXCOFFCInfoSym(StringRef Name, StringRef Metadata) {983const char InfoDirective[] = "\t.info ";984const char *Separator = ", ";985constexpr int WordSize = sizeof(uint32_t);986987// Start by emitting the .info pseudo-op and C_INFO symbol name.988OS << InfoDirective;989PrintQuotedString(Name, OS);990OS << Separator;991992size_t MetadataSize = Metadata.size();993994// Emit the 4-byte length of the metadata.995OS << format_hex(MetadataSize, 10) << Separator;996997// Nothing left to do if there's no metadata.998if (MetadataSize == 0) {999EmitEOL();1000return;1001}10021003// Metadata needs to be padded out to an even word size when generating1004// assembly because the .info pseudo-op can only generate words of data. We1005// apply the same restriction to the object case for consistency, however the1006// linker doesn't require padding, so it will only save bytes specified by the1007// length and discard any padding.1008uint32_t PaddedSize = alignTo(MetadataSize, WordSize);1009uint32_t PaddingSize = PaddedSize - MetadataSize;10101011// Write out the payload a word at a time.1012//1013// The assembler has a limit on the number of operands in an expression,1014// so we need multiple .info pseudo-ops. We choose a small number of words1015// per pseudo-op to keep the assembly readable.1016constexpr int WordsPerDirective = 5;1017// Force emitting a new directive to keep the first directive purely about the1018// name and size of the note.1019int WordsBeforeNextDirective = 0;1020auto PrintWord = [&](const uint8_t *WordPtr) {1021if (WordsBeforeNextDirective-- == 0) {1022EmitEOL();1023OS << InfoDirective;1024WordsBeforeNextDirective = WordsPerDirective;1025}1026OS << Separator;1027uint32_t Word = llvm::support::endian::read32be(WordPtr);1028OS << format_hex(Word, 10);1029};10301031size_t Index = 0;1032for (; Index + WordSize <= MetadataSize; Index += WordSize)1033PrintWord(reinterpret_cast<const uint8_t *>(Metadata.data()) + Index);10341035// If there is padding, then we have at least one byte of payload left1036// to emit.1037if (PaddingSize) {1038assert(PaddedSize - Index == WordSize);1039std::array<uint8_t, WordSize> LastWord = {0};1040::memcpy(LastWord.data(), Metadata.data() + Index, MetadataSize - Index);1041PrintWord(LastWord.data());1042}1043EmitEOL();1044}10451046void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {1047assert(MAI->hasDotTypeDotSizeDirective());1048OS << "\t.size\t";1049Symbol->print(OS, MAI);1050OS << ", ";1051Value->print(OS, MAI);1052EmitEOL();1053}10541055void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,1056Align ByteAlignment) {1057OS << "\t.comm\t";1058Symbol->print(OS, MAI);1059OS << ',' << Size;10601061if (MAI->getCOMMDirectiveAlignmentIsInBytes())1062OS << ',' << ByteAlignment.value();1063else1064OS << ',' << Log2(ByteAlignment);1065EmitEOL();10661067// Print symbol's rename (original name contains invalid character(s)) if1068// there is one.1069MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);1070if (XSym && XSym->hasRename())1071emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());1072}10731074void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,1075Align ByteAlign) {1076OS << "\t.lcomm\t";1077Symbol->print(OS, MAI);1078OS << ',' << Size;10791080if (ByteAlign > 1) {1081switch (MAI->getLCOMMDirectiveAlignmentType()) {1082case LCOMM::NoAlignment:1083llvm_unreachable("alignment not supported on .lcomm!");1084case LCOMM::ByteAlignment:1085OS << ',' << ByteAlign.value();1086break;1087case LCOMM::Log2Alignment:1088OS << ',' << Log2(ByteAlign);1089break;1090}1091}1092EmitEOL();1093}10941095void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,1096uint64_t Size, Align ByteAlignment,1097SMLoc Loc) {1098if (Symbol)1099Symbol->setFragment(&Section->getDummyFragment());11001101// Note: a .zerofill directive does not switch sections.1102OS << ".zerofill ";11031104assert(Section->getVariant() == MCSection::SV_MachO &&1105".zerofill is a Mach-O specific directive");1106// This is a mach-o specific directive.11071108const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);1109OS << MOSection->getSegmentName() << "," << MOSection->getName();11101111if (Symbol) {1112OS << ',';1113Symbol->print(OS, MAI);1114OS << ',' << Size;1115OS << ',' << Log2(ByteAlignment);1116}1117EmitEOL();1118}11191120// .tbss sym, size, align1121// This depends that the symbol has already been mangled from the original,1122// e.g. _a.1123void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,1124uint64_t Size, Align ByteAlignment) {1125Symbol->setFragment(&Section->getDummyFragment());11261127// Instead of using the Section we'll just use the shortcut.11281129assert(Section->getVariant() == MCSection::SV_MachO &&1130".zerofill is a Mach-O specific directive");1131// This is a mach-o specific directive and section.11321133OS << ".tbss ";1134Symbol->print(OS, MAI);1135OS << ", " << Size;11361137// Output align if we have it. We default to 1 so don't bother printing1138// that.1139if (ByteAlignment > 1)1140OS << ", " << Log2(ByteAlignment);11411142EmitEOL();1143}11441145static inline bool isPrintableString(StringRef Data) {1146const auto BeginPtr = Data.begin(), EndPtr = Data.end();1147for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {1148if (!isPrint(C))1149return false;1150}1151return isPrint(Data.back()) || Data.back() == 0;1152}11531154static inline char toOctal(int X) { return (X&7)+'0'; }11551156static void PrintByteList(StringRef Data, raw_ostream &OS,1157MCAsmInfo::AsmCharLiteralSyntax ACLS) {1158assert(!Data.empty() && "Cannot generate an empty list.");1159const auto printCharacterInOctal = [&OS](unsigned char C) {1160OS << '0';1161OS << toOctal(C >> 6);1162OS << toOctal(C >> 3);1163OS << toOctal(C >> 0);1164};1165const auto printOneCharacterFor = [printCharacterInOctal](1166auto printOnePrintingCharacter) {1167return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {1168if (isPrint(C)) {1169printOnePrintingCharacter(static_cast<char>(C));1170return;1171}1172printCharacterInOctal(C);1173};1174};1175const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {1176const auto BeginPtr = Data.begin(), EndPtr = Data.end();1177for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {1178printOneCharacter(C);1179OS << ',';1180}1181printOneCharacter(*(EndPtr - 1));1182};1183switch (ACLS) {1184case MCAsmInfo::ACLS_Unknown:1185printCharacterList(printCharacterInOctal);1186return;1187case MCAsmInfo::ACLS_SingleQuotePrefix:1188printCharacterList(printOneCharacterFor([&OS](char C) {1189const char AsmCharLitBuf[2] = {'\'', C};1190OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));1191}));1192return;1193}1194llvm_unreachable("Invalid AsmCharLiteralSyntax value!");1195}11961197void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const {1198OS << '"';11991200if (MAI->hasPairedDoubleQuoteStringConstants()) {1201for (unsigned char C : Data) {1202if (C == '"')1203OS << "\"\"";1204else1205OS << (char)C;1206}1207} else {1208for (unsigned char C : Data) {1209if (C == '"' || C == '\\') {1210OS << '\\' << (char)C;1211continue;1212}12131214if (isPrint((unsigned char)C)) {1215OS << (char)C;1216continue;1217}12181219switch (C) {1220case '\b':1221OS << "\\b";1222break;1223case '\f':1224OS << "\\f";1225break;1226case '\n':1227OS << "\\n";1228break;1229case '\r':1230OS << "\\r";1231break;1232case '\t':1233OS << "\\t";1234break;1235default:1236OS << '\\';1237OS << toOctal(C >> 6);1238OS << toOctal(C >> 3);1239OS << toOctal(C >> 0);1240break;1241}1242}1243}12441245OS << '"';1246}12471248void MCAsmStreamer::emitBytes(StringRef Data) {1249assert(getCurrentSectionOnly() &&1250"Cannot emit contents before setting section!");1251if (Data.empty()) return;12521253const auto emitAsString = [this](StringRef Data) {1254// If the data ends with 0 and the target supports .asciz, use it, otherwise1255// use .ascii or a byte-list directive1256if (MAI->getAscizDirective() && Data.back() == 0) {1257OS << MAI->getAscizDirective();1258Data = Data.substr(0, Data.size() - 1);1259} else if (LLVM_LIKELY(MAI->getAsciiDirective())) {1260OS << MAI->getAsciiDirective();1261} else if (MAI->hasPairedDoubleQuoteStringConstants() &&1262isPrintableString(Data)) {1263// For target with DoubleQuoteString constants, .string and .byte are used1264// as replacement of .asciz and .ascii.1265assert(MAI->getPlainStringDirective() &&1266"hasPairedDoubleQuoteStringConstants target must support "1267"PlainString Directive");1268assert(MAI->getByteListDirective() &&1269"hasPairedDoubleQuoteStringConstants target must support ByteList "1270"Directive");1271if (Data.back() == 0) {1272OS << MAI->getPlainStringDirective();1273Data = Data.substr(0, Data.size() - 1);1274} else {1275OS << MAI->getByteListDirective();1276}1277} else if (MAI->getByteListDirective()) {1278OS << MAI->getByteListDirective();1279PrintByteList(Data, OS, MAI->characterLiteralSyntax());1280EmitEOL();1281return true;1282} else {1283return false;1284}12851286PrintQuotedString(Data, OS);1287EmitEOL();1288return true;1289};12901291if (Data.size() != 1 && emitAsString(Data))1292return;12931294// Only single byte is provided or no ascii, asciz, or byte-list directives1295// are applicable. Emit as vector of individual 8bits data elements.1296if (MCTargetStreamer *TS = getTargetStreamer()) {1297TS->emitRawBytes(Data);1298return;1299}1300const char *Directive = MAI->getData8bitsDirective();1301for (const unsigned char C : Data.bytes()) {1302OS << Directive << (unsigned)C;1303EmitEOL();1304}1305}13061307void MCAsmStreamer::emitBinaryData(StringRef Data) {1308// This is binary data. Print it in a grid of hex bytes for readability.1309const size_t Cols = 4;1310for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {1311size_t J = I, EJ = std::min(I + Cols, Data.size());1312assert(EJ > 0);1313OS << MAI->getData8bitsDirective();1314for (; J < EJ - 1; ++J)1315OS << format("0x%02x", uint8_t(Data[J])) << ", ";1316OS << format("0x%02x", uint8_t(Data[J]));1317EmitEOL();1318}1319}13201321void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {1322emitValue(MCConstantExpr::create(Value, getContext()), Size);1323}13241325void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {1326emitValue(MCConstantExpr::create(Value, getContext(), true), Size);1327}13281329void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,1330unsigned Size) {1331emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);1332}13331334void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,1335SMLoc Loc) {1336assert(Size <= 8 && "Invalid size");1337assert(getCurrentSectionOnly() &&1338"Cannot emit contents before setting section!");1339const char *Directive = nullptr;1340switch (Size) {1341default: break;1342case 1: Directive = MAI->getData8bitsDirective(); break;1343case 2: Directive = MAI->getData16bitsDirective(); break;1344case 4: Directive = MAI->getData32bitsDirective(); break;1345case 8: Directive = MAI->getData64bitsDirective(); break;1346}13471348if (!Directive) {1349int64_t IntValue;1350if (!Value->evaluateAsAbsolute(IntValue))1351report_fatal_error("Don't know how to emit this value.");13521353// We couldn't handle the requested integer size so we fallback by breaking1354// the request down into several, smaller, integers.1355// Since sizes greater or equal to "Size" are invalid, we use the greatest1356// power of 2 that is less than "Size" as our largest piece of granularity.1357bool IsLittleEndian = MAI->isLittleEndian();1358for (unsigned Emitted = 0; Emitted != Size;) {1359unsigned Remaining = Size - Emitted;1360// The size of our partial emission must be a power of two less than1361// Size.1362unsigned EmissionSize = llvm::bit_floor(std::min(Remaining, Size - 1));1363// Calculate the byte offset of our partial emission taking into account1364// the endianness of the target.1365unsigned ByteOffset =1366IsLittleEndian ? Emitted : (Remaining - EmissionSize);1367uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);1368// We truncate our partial emission to fit within the bounds of the1369// emission domain. This produces nicer output and silences potential1370// truncation warnings when round tripping through another assembler.1371uint64_t Shift = 64 - EmissionSize * 8;1372assert(Shift < static_cast<uint64_t>(1373std::numeric_limits<unsigned long long>::digits) &&1374"undefined behavior");1375ValueToEmit &= ~0ULL >> Shift;1376emitIntValue(ValueToEmit, EmissionSize);1377Emitted += EmissionSize;1378}1379return;1380}13811382assert(Directive && "Invalid size for machine code value!");1383OS << Directive;1384if (MCTargetStreamer *TS = getTargetStreamer()) {1385TS->emitValue(Value);1386} else {1387Value->print(OS, MAI);1388EmitEOL();1389}1390}13911392void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {1393int64_t IntValue;1394if (Value->evaluateAsAbsolute(IntValue)) {1395emitULEB128IntValue(IntValue);1396return;1397}1398OS << "\t.uleb128 ";1399Value->print(OS, MAI);1400EmitEOL();1401}14021403void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {1404int64_t IntValue;1405if (Value->evaluateAsAbsolute(IntValue)) {1406emitSLEB128IntValue(IntValue);1407return;1408}1409OS << "\t.sleb128 ";1410Value->print(OS, MAI);1411EmitEOL();1412}14131414void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {1415assert(MAI->getDTPRel64Directive() != nullptr);1416OS << MAI->getDTPRel64Directive();1417Value->print(OS, MAI);1418EmitEOL();1419}14201421void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {1422assert(MAI->getDTPRel32Directive() != nullptr);1423OS << MAI->getDTPRel32Directive();1424Value->print(OS, MAI);1425EmitEOL();1426}14271428void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {1429assert(MAI->getTPRel64Directive() != nullptr);1430OS << MAI->getTPRel64Directive();1431Value->print(OS, MAI);1432EmitEOL();1433}14341435void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {1436assert(MAI->getTPRel32Directive() != nullptr);1437OS << MAI->getTPRel32Directive();1438Value->print(OS, MAI);1439EmitEOL();1440}14411442void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {1443assert(MAI->getGPRel64Directive() != nullptr);1444OS << MAI->getGPRel64Directive();1445Value->print(OS, MAI);1446EmitEOL();1447}14481449void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {1450assert(MAI->getGPRel32Directive() != nullptr);1451OS << MAI->getGPRel32Directive();1452Value->print(OS, MAI);1453EmitEOL();1454}14551456void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,1457SMLoc Loc) {1458int64_t IntNumBytes;1459const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);1460if (IsAbsolute && IntNumBytes == 0)1461return;14621463if (const char *ZeroDirective = MAI->getZeroDirective()) {1464if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {1465// FIXME: Emit location directives1466OS << ZeroDirective;1467NumBytes.print(OS, MAI);1468if (FillValue != 0)1469OS << ',' << (int)FillValue;1470EmitEOL();1471} else {1472if (!IsAbsolute)1473report_fatal_error(1474"Cannot emit non-absolute expression lengths of fill.");1475for (int i = 0; i < IntNumBytes; ++i) {1476OS << MAI->getData8bitsDirective() << (int)FillValue;1477EmitEOL();1478}1479}1480return;1481}14821483MCStreamer::emitFill(NumBytes, FillValue);1484}14851486void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,1487int64_t Expr, SMLoc Loc) {1488// FIXME: Emit location directives1489OS << "\t.fill\t";1490NumValues.print(OS, MAI);1491OS << ", " << Size << ", 0x";1492OS.write_hex(truncateToSize(Expr, 4));1493EmitEOL();1494}14951496void MCAsmStreamer::emitAlignmentDirective(uint64_t ByteAlignment,1497std::optional<int64_t> Value,1498unsigned ValueSize,1499unsigned MaxBytesToEmit) {1500if (MAI->useDotAlignForAlignment()) {1501if (!isPowerOf2_64(ByteAlignment))1502report_fatal_error("Only power-of-two alignments are supported "1503"with .align.");1504OS << "\t.align\t";1505OS << Log2_64(ByteAlignment);1506EmitEOL();1507return;1508}15091510// Some assemblers don't support non-power of two alignments, so we always1511// emit alignments as a power of two if possible.1512if (isPowerOf2_64(ByteAlignment)) {1513switch (ValueSize) {1514default:1515llvm_unreachable("Invalid size for machine code value!");1516case 1:1517OS << "\t.p2align\t";1518break;1519case 2:1520OS << ".p2alignw ";1521break;1522case 4:1523OS << ".p2alignl ";1524break;1525case 8:1526llvm_unreachable("Unsupported alignment size!");1527}15281529OS << Log2_64(ByteAlignment);15301531if (Value.has_value() || MaxBytesToEmit) {1532if (Value.has_value()) {1533OS << ", 0x";1534OS.write_hex(truncateToSize(*Value, ValueSize));1535} else {1536OS << ", ";1537}15381539if (MaxBytesToEmit)1540OS << ", " << MaxBytesToEmit;1541}1542EmitEOL();1543return;1544}15451546// Non-power of two alignment. This is not widely supported by assemblers.1547// FIXME: Parameterize this based on MAI.1548switch (ValueSize) {1549default: llvm_unreachable("Invalid size for machine code value!");1550case 1: OS << ".balign"; break;1551case 2: OS << ".balignw"; break;1552case 4: OS << ".balignl"; break;1553case 8: llvm_unreachable("Unsupported alignment size!");1554}15551556OS << ' ' << ByteAlignment;1557if (Value.has_value())1558OS << ", " << truncateToSize(*Value, ValueSize);1559else if (MaxBytesToEmit)1560OS << ", ";1561if (MaxBytesToEmit)1562OS << ", " << MaxBytesToEmit;1563EmitEOL();1564}15651566void MCAsmStreamer::emitValueToAlignment(Align Alignment, int64_t Value,1567unsigned ValueSize,1568unsigned MaxBytesToEmit) {1569emitAlignmentDirective(Alignment.value(), Value, ValueSize, MaxBytesToEmit);1570}15711572void MCAsmStreamer::emitCodeAlignment(Align Alignment,1573const MCSubtargetInfo *STI,1574unsigned MaxBytesToEmit) {1575// Emit with a text fill value.1576if (MAI->getTextAlignFillValue())1577emitAlignmentDirective(Alignment.value(), MAI->getTextAlignFillValue(), 1,1578MaxBytesToEmit);1579else1580emitAlignmentDirective(Alignment.value(), std::nullopt, 1, MaxBytesToEmit);1581}15821583void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,1584unsigned char Value,1585SMLoc Loc) {1586// FIXME: Verify that Offset is associated with the current section.1587OS << ".org ";1588Offset->print(OS, MAI);1589OS << ", " << (unsigned)Value;1590EmitEOL();1591}15921593void MCAsmStreamer::emitFileDirective(StringRef Filename) {1594assert(MAI->hasSingleParameterDotFile());1595OS << "\t.file\t";1596PrintQuotedString(Filename, OS);1597EmitEOL();1598}15991600void MCAsmStreamer::emitFileDirective(StringRef Filename,1601StringRef CompilerVersion,1602StringRef TimeStamp,1603StringRef Description) {1604assert(MAI->hasFourStringsDotFile());1605OS << "\t.file\t";1606PrintQuotedString(Filename, OS);1607bool useTimeStamp = !TimeStamp.empty();1608bool useCompilerVersion = !CompilerVersion.empty();1609bool useDescription = !Description.empty();1610if (useTimeStamp || useCompilerVersion || useDescription) {1611OS << ",";1612if (useTimeStamp)1613PrintQuotedString(TimeStamp, OS);1614if (useCompilerVersion || useDescription) {1615OS << ",";1616if (useCompilerVersion)1617PrintQuotedString(CompilerVersion, OS);1618if (useDescription) {1619OS << ",";1620PrintQuotedString(Description, OS);1621}1622}1623}1624EmitEOL();1625}16261627void MCAsmStreamer::printDwarfFileDirective(1628unsigned FileNo, StringRef Directory, StringRef Filename,1629std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,1630bool UseDwarfDirectory, raw_svector_ostream &OS) const {1631SmallString<128> FullPathName;16321633if (!UseDwarfDirectory && !Directory.empty()) {1634if (sys::path::is_absolute(Filename))1635Directory = "";1636else {1637FullPathName = Directory;1638sys::path::append(FullPathName, Filename);1639Directory = "";1640Filename = FullPathName;1641}1642}16431644OS << "\t.file\t" << FileNo << ' ';1645if (!Directory.empty()) {1646PrintQuotedString(Directory, OS);1647OS << ' ';1648}1649PrintQuotedString(Filename, OS);1650if (Checksum)1651OS << " md5 0x" << Checksum->digest();1652if (Source) {1653OS << " source ";1654PrintQuotedString(*Source, OS);1655}1656}16571658Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(1659unsigned FileNo, StringRef Directory, StringRef Filename,1660std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,1661unsigned CUID) {1662assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");16631664MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);1665unsigned NumFiles = Table.getMCDwarfFiles().size();1666Expected<unsigned> FileNoOrErr =1667Table.tryGetFile(Directory, Filename, Checksum, Source,1668getContext().getDwarfVersion(), FileNo);1669if (!FileNoOrErr)1670return FileNoOrErr.takeError();1671FileNo = FileNoOrErr.get();16721673// Return early if this file is already emitted before or if target doesn't1674// support .file directive.1675if (NumFiles == Table.getMCDwarfFiles().size() ||1676!MAI->usesDwarfFileAndLocDirectives())1677return FileNo;16781679SmallString<128> Str;1680raw_svector_ostream OS1(Str);1681printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,1682UseDwarfDirectory, OS1);16831684if (MCTargetStreamer *TS = getTargetStreamer())1685TS->emitDwarfFileDirective(OS1.str());1686else1687emitRawText(OS1.str());16881689return FileNo;1690}16911692void MCAsmStreamer::emitDwarfFile0Directive(1693StringRef Directory, StringRef Filename,1694std::optional<MD5::MD5Result> Checksum, std::optional<StringRef> Source,1695unsigned CUID) {1696assert(CUID == 0);1697// .file 0 is new for DWARF v5.1698if (getContext().getDwarfVersion() < 5)1699return;1700// Inform MCDwarf about the root file.1701getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,1702Source);17031704// Target doesn't support .loc/.file directives, return early.1705if (!MAI->usesDwarfFileAndLocDirectives())1706return;17071708SmallString<128> Str;1709raw_svector_ostream OS1(Str);1710printDwarfFileDirective(0, Directory, Filename, Checksum, Source,1711UseDwarfDirectory, OS1);17121713if (MCTargetStreamer *TS = getTargetStreamer())1714TS->emitDwarfFileDirective(OS1.str());1715else1716emitRawText(OS1.str());1717}17181719void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,1720unsigned Column, unsigned Flags,1721unsigned Isa, unsigned Discriminator,1722StringRef FileName) {1723// If target doesn't support .loc/.file directive, we need to record the lines1724// same way like we do in object mode.1725if (!MAI->usesDwarfFileAndLocDirectives()) {1726// In case we see two .loc directives in a row, make sure the1727// first one gets a line entry.1728MCDwarfLineEntry::make(this, getCurrentSectionOnly());1729this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,1730Discriminator, FileName);1731return;1732}17331734OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;1735if (MAI->supportsExtendedDwarfLocDirective()) {1736if (Flags & DWARF2_FLAG_BASIC_BLOCK)1737OS << " basic_block";1738if (Flags & DWARF2_FLAG_PROLOGUE_END)1739OS << " prologue_end";1740if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)1741OS << " epilogue_begin";17421743unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();1744if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {1745OS << " is_stmt ";17461747if (Flags & DWARF2_FLAG_IS_STMT)1748OS << "1";1749else1750OS << "0";1751}17521753if (Isa)1754OS << " isa " << Isa;1755if (Discriminator)1756OS << " discriminator " << Discriminator;1757}17581759if (IsVerboseAsm) {1760OS.PadToColumn(MAI->getCommentColumn());1761OS << MAI->getCommentString() << ' ' << FileName << ':'1762<< Line << ':' << Column;1763}1764EmitEOL();1765this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,1766Discriminator, FileName);1767}17681769MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {1770// Always use the zeroth line table, since asm syntax only supports one line1771// table for now.1772return MCStreamer::getDwarfLineTableSymbol(0);1773}17741775bool MCAsmStreamer::emitCVFileDirective(unsigned FileNo, StringRef Filename,1776ArrayRef<uint8_t> Checksum,1777unsigned ChecksumKind) {1778if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,1779ChecksumKind))1780return false;17811782OS << "\t.cv_file\t" << FileNo << ' ';1783PrintQuotedString(Filename, OS);17841785if (!ChecksumKind) {1786EmitEOL();1787return true;1788}17891790OS << ' ';1791PrintQuotedString(toHex(Checksum), OS);1792OS << ' ' << ChecksumKind;17931794EmitEOL();1795return true;1796}17971798bool MCAsmStreamer::emitCVFuncIdDirective(unsigned FuncId) {1799OS << "\t.cv_func_id " << FuncId << '\n';1800return MCStreamer::emitCVFuncIdDirective(FuncId);1801}18021803bool MCAsmStreamer::emitCVInlineSiteIdDirective(unsigned FunctionId,1804unsigned IAFunc,1805unsigned IAFile,1806unsigned IALine, unsigned IACol,1807SMLoc Loc) {1808OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc1809<< " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';1810return MCStreamer::emitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,1811IALine, IACol, Loc);1812}18131814void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,1815unsigned Line, unsigned Column,1816bool PrologueEnd, bool IsStmt,1817StringRef FileName, SMLoc Loc) {1818// Validate the directive.1819if (!checkCVLocSection(FunctionId, FileNo, Loc))1820return;18211822OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "1823<< Column;1824if (PrologueEnd)1825OS << " prologue_end";18261827if (IsStmt)1828OS << " is_stmt 1";18291830if (IsVerboseAsm) {1831OS.PadToColumn(MAI->getCommentColumn());1832OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'1833<< Column;1834}1835EmitEOL();1836}18371838void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,1839const MCSymbol *FnStart,1840const MCSymbol *FnEnd) {1841OS << "\t.cv_linetable\t" << FunctionId << ", ";1842FnStart->print(OS, MAI);1843OS << ", ";1844FnEnd->print(OS, MAI);1845EmitEOL();1846this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);1847}18481849void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,1850unsigned SourceFileId,1851unsigned SourceLineNum,1852const MCSymbol *FnStartSym,1853const MCSymbol *FnEndSym) {1854OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId1855<< ' ' << SourceLineNum << ' ';1856FnStartSym->print(OS, MAI);1857OS << ' ';1858FnEndSym->print(OS, MAI);1859EmitEOL();1860this->MCStreamer::emitCVInlineLinetableDirective(1861PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);1862}18631864void MCAsmStreamer::PrintCVDefRangePrefix(1865ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {1866OS << "\t.cv_def_range\t";1867for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {1868OS << ' ';1869Range.first->print(OS, MAI);1870OS << ' ';1871Range.second->print(OS, MAI);1872}1873}18741875void MCAsmStreamer::emitCVDefRangeDirective(1876ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,1877codeview::DefRangeRegisterRelHeader DRHdr) {1878PrintCVDefRangePrefix(Ranges);1879OS << ", reg_rel, ";1880OS << DRHdr.Register << ", " << DRHdr.Flags << ", "1881<< DRHdr.BasePointerOffset;1882EmitEOL();1883}18841885void MCAsmStreamer::emitCVDefRangeDirective(1886ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,1887codeview::DefRangeSubfieldRegisterHeader DRHdr) {1888PrintCVDefRangePrefix(Ranges);1889OS << ", subfield_reg, ";1890OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;1891EmitEOL();1892}18931894void MCAsmStreamer::emitCVDefRangeDirective(1895ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,1896codeview::DefRangeRegisterHeader DRHdr) {1897PrintCVDefRangePrefix(Ranges);1898OS << ", reg, ";1899OS << DRHdr.Register;1900EmitEOL();1901}19021903void MCAsmStreamer::emitCVDefRangeDirective(1904ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,1905codeview::DefRangeFramePointerRelHeader DRHdr) {1906PrintCVDefRangePrefix(Ranges);1907OS << ", frame_ptr_rel, ";1908OS << DRHdr.Offset;1909EmitEOL();1910}19111912void MCAsmStreamer::emitCVStringTableDirective() {1913OS << "\t.cv_stringtable";1914EmitEOL();1915}19161917void MCAsmStreamer::emitCVFileChecksumsDirective() {1918OS << "\t.cv_filechecksums";1919EmitEOL();1920}19211922void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {1923OS << "\t.cv_filechecksumoffset\t" << FileNo;1924EmitEOL();1925}19261927void MCAsmStreamer::emitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {1928OS << "\t.cv_fpo_data\t";1929ProcSym->print(OS, MAI);1930EmitEOL();1931}19321933void MCAsmStreamer::emitIdent(StringRef IdentString) {1934assert(MAI->hasIdentDirective() && ".ident directive not supported");1935OS << "\t.ident\t";1936PrintQuotedString(IdentString, OS);1937EmitEOL();1938}19391940void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {1941MCStreamer::emitCFISections(EH, Debug);1942OS << "\t.cfi_sections ";1943if (EH) {1944OS << ".eh_frame";1945if (Debug)1946OS << ", .debug_frame";1947} else if (Debug) {1948OS << ".debug_frame";1949}19501951EmitEOL();1952}19531954void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {1955OS << "\t.cfi_startproc";1956if (Frame.IsSimple)1957OS << " simple";1958EmitEOL();1959}19601961void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {1962MCStreamer::emitCFIEndProcImpl(Frame);1963OS << "\t.cfi_endproc";1964EmitEOL();1965}19661967void MCAsmStreamer::EmitRegisterName(int64_t Register) {1968if (!MAI->useDwarfRegNumForCFI()) {1969// User .cfi_* directives can use arbitrary DWARF register numbers, not1970// just ones that map to LLVM register numbers and have known names.1971// Fall back to using the original number directly if no name is known.1972const MCRegisterInfo *MRI = getContext().getRegisterInfo();1973if (std::optional<unsigned> LLVMRegister =1974MRI->getLLVMRegNum(Register, true)) {1975InstPrinter->printRegName(OS, *LLVMRegister);1976return;1977}1978}1979OS << Register;1980}19811982void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset, SMLoc Loc) {1983MCStreamer::emitCFIDefCfa(Register, Offset, Loc);1984OS << "\t.cfi_def_cfa ";1985EmitRegisterName(Register);1986OS << ", " << Offset;1987EmitEOL();1988}19891990void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset, SMLoc Loc) {1991MCStreamer::emitCFIDefCfaOffset(Offset, Loc);1992OS << "\t.cfi_def_cfa_offset " << Offset;1993EmitEOL();1994}19951996void MCAsmStreamer::emitCFILLVMDefAspaceCfa(int64_t Register, int64_t Offset,1997int64_t AddressSpace, SMLoc Loc) {1998MCStreamer::emitCFILLVMDefAspaceCfa(Register, Offset, AddressSpace, Loc);1999OS << "\t.cfi_llvm_def_aspace_cfa ";2000EmitRegisterName(Register);2001OS << ", " << Offset;2002OS << ", " << AddressSpace;2003EmitEOL();2004}20052006static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {2007OS << "\t.cfi_escape ";2008if (!Values.empty()) {2009size_t e = Values.size() - 1;2010for (size_t i = 0; i < e; ++i)2011OS << format("0x%02x", uint8_t(Values[i])) << ", ";2012OS << format("0x%02x", uint8_t(Values[e]));2013}2014}20152016void MCAsmStreamer::emitCFIEscape(StringRef Values, SMLoc Loc) {2017MCStreamer::emitCFIEscape(Values, Loc);2018PrintCFIEscape(OS, Values);2019EmitEOL();2020}20212022void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size, SMLoc Loc) {2023MCStreamer::emitCFIGnuArgsSize(Size, Loc);20242025uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };2026unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;20272028PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));2029EmitEOL();2030}20312032void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register, SMLoc Loc) {2033MCStreamer::emitCFIDefCfaRegister(Register, Loc);2034OS << "\t.cfi_def_cfa_register ";2035EmitRegisterName(Register);2036EmitEOL();2037}20382039void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset, SMLoc Loc) {2040MCStreamer::emitCFIOffset(Register, Offset, Loc);2041OS << "\t.cfi_offset ";2042EmitRegisterName(Register);2043OS << ", " << Offset;2044EmitEOL();2045}20462047void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,2048unsigned Encoding) {2049MCStreamer::emitCFIPersonality(Sym, Encoding);2050OS << "\t.cfi_personality " << Encoding << ", ";2051Sym->print(OS, MAI);2052EmitEOL();2053}20542055void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {2056MCStreamer::emitCFILsda(Sym, Encoding);2057OS << "\t.cfi_lsda " << Encoding << ", ";2058Sym->print(OS, MAI);2059EmitEOL();2060}20612062void MCAsmStreamer::emitCFIRememberState(SMLoc Loc) {2063MCStreamer::emitCFIRememberState(Loc);2064OS << "\t.cfi_remember_state";2065EmitEOL();2066}20672068void MCAsmStreamer::emitCFIRestoreState(SMLoc Loc) {2069MCStreamer::emitCFIRestoreState(Loc);2070OS << "\t.cfi_restore_state";2071EmitEOL();2072}20732074void MCAsmStreamer::emitCFIRestore(int64_t Register, SMLoc Loc) {2075MCStreamer::emitCFIRestore(Register, Loc);2076OS << "\t.cfi_restore ";2077EmitRegisterName(Register);2078EmitEOL();2079}20802081void MCAsmStreamer::emitCFISameValue(int64_t Register, SMLoc Loc) {2082MCStreamer::emitCFISameValue(Register, Loc);2083OS << "\t.cfi_same_value ";2084EmitRegisterName(Register);2085EmitEOL();2086}20872088void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset,2089SMLoc Loc) {2090MCStreamer::emitCFIRelOffset(Register, Offset, Loc);2091OS << "\t.cfi_rel_offset ";2092EmitRegisterName(Register);2093OS << ", " << Offset;2094EmitEOL();2095}20962097void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment, SMLoc Loc) {2098MCStreamer::emitCFIAdjustCfaOffset(Adjustment, Loc);2099OS << "\t.cfi_adjust_cfa_offset " << Adjustment;2100EmitEOL();2101}21022103void MCAsmStreamer::emitCFISignalFrame() {2104MCStreamer::emitCFISignalFrame();2105OS << "\t.cfi_signal_frame";2106EmitEOL();2107}21082109void MCAsmStreamer::emitCFIUndefined(int64_t Register, SMLoc Loc) {2110MCStreamer::emitCFIUndefined(Register, Loc);2111OS << "\t.cfi_undefined ";2112EmitRegisterName(Register);2113EmitEOL();2114}21152116void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2,2117SMLoc Loc) {2118MCStreamer::emitCFIRegister(Register1, Register2, Loc);2119OS << "\t.cfi_register ";2120EmitRegisterName(Register1);2121OS << ", ";2122EmitRegisterName(Register2);2123EmitEOL();2124}21252126void MCAsmStreamer::emitCFIWindowSave(SMLoc Loc) {2127MCStreamer::emitCFIWindowSave(Loc);2128OS << "\t.cfi_window_save";2129EmitEOL();2130}21312132void MCAsmStreamer::emitCFINegateRAState(SMLoc Loc) {2133MCStreamer::emitCFINegateRAState(Loc);2134OS << "\t.cfi_negate_ra_state";2135EmitEOL();2136}21372138void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {2139MCStreamer::emitCFIReturnColumn(Register);2140OS << "\t.cfi_return_column ";2141EmitRegisterName(Register);2142EmitEOL();2143}21442145void MCAsmStreamer::emitCFILabelDirective(SMLoc Loc, StringRef Name) {2146MCStreamer::emitCFILabelDirective(Loc, Name);2147OS << "\t.cfi_label " << Name;2148EmitEOL();2149}21502151void MCAsmStreamer::emitCFIBKeyFrame() {2152MCStreamer::emitCFIBKeyFrame();2153OS << "\t.cfi_b_key_frame";2154EmitEOL();2155}21562157void MCAsmStreamer::emitCFIMTETaggedFrame() {2158MCStreamer::emitCFIMTETaggedFrame();2159OS << "\t.cfi_mte_tagged_frame";2160EmitEOL();2161}21622163void MCAsmStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {2164MCStreamer::emitWinCFIStartProc(Symbol, Loc);21652166OS << ".seh_proc ";2167Symbol->print(OS, MAI);2168EmitEOL();2169}21702171void MCAsmStreamer::emitWinCFIEndProc(SMLoc Loc) {2172MCStreamer::emitWinCFIEndProc(Loc);21732174OS << "\t.seh_endproc";2175EmitEOL();2176}21772178void MCAsmStreamer::emitWinCFIFuncletOrFuncEnd(SMLoc Loc) {2179MCStreamer::emitWinCFIFuncletOrFuncEnd(Loc);21802181OS << "\t.seh_endfunclet";2182EmitEOL();2183}21842185void MCAsmStreamer::emitWinCFIStartChained(SMLoc Loc) {2186MCStreamer::emitWinCFIStartChained(Loc);21872188OS << "\t.seh_startchained";2189EmitEOL();2190}21912192void MCAsmStreamer::emitWinCFIEndChained(SMLoc Loc) {2193MCStreamer::emitWinCFIEndChained(Loc);21942195OS << "\t.seh_endchained";2196EmitEOL();2197}21982199void MCAsmStreamer::emitWinEHHandler(const MCSymbol *Sym, bool Unwind,2200bool Except, SMLoc Loc) {2201MCStreamer::emitWinEHHandler(Sym, Unwind, Except, Loc);22022203OS << "\t.seh_handler ";2204Sym->print(OS, MAI);2205char Marker = '@';2206const Triple &T = getContext().getTargetTriple();2207if (T.getArch() == Triple::arm || T.getArch() == Triple::thumb)2208Marker = '%';2209if (Unwind)2210OS << ", " << Marker << "unwind";2211if (Except)2212OS << ", " << Marker << "except";2213EmitEOL();2214}22152216void MCAsmStreamer::emitWinEHHandlerData(SMLoc Loc) {2217MCStreamer::emitWinEHHandlerData(Loc);22182219// Switch sections. Don't call switchSection directly, because that will2220// cause the section switch to be visible in the emitted assembly.2221// We only do this so the section switch that terminates the handler2222// data block is visible.2223WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();22242225// Do nothing if no frame is open. MCStreamer should've already reported an2226// error.2227if (!CurFrame)2228return;22292230MCSection *TextSec = &CurFrame->Function->getSection();2231MCSection *XData = getAssociatedXDataSection(TextSec);2232switchSectionNoPrint(XData);22332234OS << "\t.seh_handlerdata";2235EmitEOL();2236}22372238void MCAsmStreamer::emitWinCFIPushReg(MCRegister Register, SMLoc Loc) {2239MCStreamer::emitWinCFIPushReg(Register, Loc);22402241OS << "\t.seh_pushreg ";2242InstPrinter->printRegName(OS, Register);2243EmitEOL();2244}22452246void MCAsmStreamer::emitWinCFISetFrame(MCRegister Register, unsigned Offset,2247SMLoc Loc) {2248MCStreamer::emitWinCFISetFrame(Register, Offset, Loc);22492250OS << "\t.seh_setframe ";2251InstPrinter->printRegName(OS, Register);2252OS << ", " << Offset;2253EmitEOL();2254}22552256void MCAsmStreamer::emitWinCFIAllocStack(unsigned Size, SMLoc Loc) {2257MCStreamer::emitWinCFIAllocStack(Size, Loc);22582259OS << "\t.seh_stackalloc " << Size;2260EmitEOL();2261}22622263void MCAsmStreamer::emitWinCFISaveReg(MCRegister Register, unsigned Offset,2264SMLoc Loc) {2265MCStreamer::emitWinCFISaveReg(Register, Offset, Loc);22662267OS << "\t.seh_savereg ";2268InstPrinter->printRegName(OS, Register);2269OS << ", " << Offset;2270EmitEOL();2271}22722273void MCAsmStreamer::emitWinCFISaveXMM(MCRegister Register, unsigned Offset,2274SMLoc Loc) {2275MCStreamer::emitWinCFISaveXMM(Register, Offset, Loc);22762277OS << "\t.seh_savexmm ";2278InstPrinter->printRegName(OS, Register);2279OS << ", " << Offset;2280EmitEOL();2281}22822283void MCAsmStreamer::emitWinCFIPushFrame(bool Code, SMLoc Loc) {2284MCStreamer::emitWinCFIPushFrame(Code, Loc);22852286OS << "\t.seh_pushframe";2287if (Code)2288OS << " @code";2289EmitEOL();2290}22912292void MCAsmStreamer::emitWinCFIEndProlog(SMLoc Loc) {2293MCStreamer::emitWinCFIEndProlog(Loc);22942295OS << "\t.seh_endprologue";2296EmitEOL();2297}22982299void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,2300const MCSymbolRefExpr *To,2301uint64_t Count) {2302OS << "\t.cg_profile ";2303From->getSymbol().print(OS, MAI);2304OS << ", ";2305To->getSymbol().print(OS, MAI);2306OS << ", " << Count;2307EmitEOL();2308}23092310void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,2311const MCSubtargetInfo &STI) {2312raw_ostream &OS = getCommentOS();2313SmallString<256> Code;2314SmallVector<MCFixup, 4> Fixups;23152316// If we have no code emitter, don't emit code.2317if (!getAssembler().getEmitterPtr())2318return;23192320getAssembler().getEmitter().encodeInstruction(Inst, Code, Fixups, STI);23212322// If we are showing fixups, create symbolic markers in the encoded2323// representation. We do this by making a per-bit map to the fixup item index,2324// then trying to display it as nicely as possible.2325SmallVector<uint8_t, 64> FixupMap;2326FixupMap.resize(Code.size() * 8);2327for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)2328FixupMap[i] = 0;23292330for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {2331MCFixup &F = Fixups[i];2332const MCFixupKindInfo &Info =2333getAssembler().getBackend().getFixupKindInfo(F.getKind());2334for (unsigned j = 0; j != Info.TargetSize; ++j) {2335unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;2336assert(Index < Code.size() * 8 && "Invalid offset in fixup!");2337FixupMap[Index] = 1 + i;2338}2339}23402341// FIXME: Note the fixup comments for Thumb2 are completely bogus since the2342// high order halfword of a 32-bit Thumb2 instruction is emitted first.2343OS << "encoding: [";2344for (unsigned i = 0, e = Code.size(); i != e; ++i) {2345if (i)2346OS << ',';23472348// See if all bits are the same map entry.2349uint8_t MapEntry = FixupMap[i * 8 + 0];2350for (unsigned j = 1; j != 8; ++j) {2351if (FixupMap[i * 8 + j] == MapEntry)2352continue;23532354MapEntry = uint8_t(~0U);2355break;2356}23572358if (MapEntry != uint8_t(~0U)) {2359if (MapEntry == 0) {2360OS << format("0x%02x", uint8_t(Code[i]));2361} else {2362if (Code[i]) {2363// FIXME: Some of the 8 bits require fix up.2364OS << format("0x%02x", uint8_t(Code[i])) << '\''2365<< char('A' + MapEntry - 1) << '\'';2366} else2367OS << char('A' + MapEntry - 1);2368}2369} else {2370// Otherwise, write out in binary.2371OS << "0b";2372for (unsigned j = 8; j--;) {2373unsigned Bit = (Code[i] >> j) & 1;23742375unsigned FixupBit;2376if (MAI->isLittleEndian())2377FixupBit = i * 8 + j;2378else2379FixupBit = i * 8 + (7-j);23802381if (uint8_t MapEntry = FixupMap[FixupBit]) {2382assert(Bit == 0 && "Encoder wrote into fixed up bit!");2383OS << char('A' + MapEntry - 1);2384} else2385OS << Bit;2386}2387}2388}2389OS << "]\n";23902391for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {2392MCFixup &F = Fixups[i];2393const MCFixupKindInfo &Info =2394getAssembler().getBackend().getFixupKindInfo(F.getKind());2395OS << " fixup " << char('A' + i) << " - "2396<< "offset: " << F.getOffset() << ", value: ";2397F.getValue()->print(OS, MAI);2398OS << ", kind: " << Info.Name << "\n";2399}2400}24012402void MCAsmStreamer::emitInstruction(const MCInst &Inst,2403const MCSubtargetInfo &STI) {2404assert(getCurrentSectionOnly() &&2405"Cannot emit contents before setting section!");24062407if (!MAI->usesDwarfFileAndLocDirectives())2408// Now that a machine instruction has been assembled into this section, make2409// a line entry for any .loc directive that has been seen.2410MCDwarfLineEntry::make(this, getCurrentSectionOnly());24112412// Show the encoding in a comment if we have a code emitter.2413AddEncodingComment(Inst, STI);24142415// Show the MCInst if enabled.2416if (ShowInst) {2417Inst.dump_pretty(getCommentOS(), InstPrinter.get(), "\n ");2418getCommentOS() << "\n";2419}24202421if(getTargetStreamer())2422getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);2423else2424InstPrinter->printInst(&Inst, 0, "", STI, OS);24252426StringRef Comments = CommentToEmit;2427if (Comments.size() && Comments.back() != '\n')2428getCommentOS() << "\n";24292430EmitEOL();2431}24322433void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,2434uint64_t Type, uint64_t Attr,2435uint64_t Discriminator,2436const MCPseudoProbeInlineStack &InlineStack,2437MCSymbol *FnSym) {2438OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " " << Attr;2439if (Discriminator)2440OS << " " << Discriminator;2441// Emit inline stack like2442// @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:112443for (const auto &Site : InlineStack)2444OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);24452446OS << " " << FnSym->getName();24472448EmitEOL();2449}24502451void MCAsmStreamer::emitBundleAlignMode(Align Alignment) {2452OS << "\t.bundle_align_mode " << Log2(Alignment);2453EmitEOL();2454}24552456void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {2457OS << "\t.bundle_lock";2458if (AlignToEnd)2459OS << " align_to_end";2460EmitEOL();2461}24622463void MCAsmStreamer::emitBundleUnlock() {2464OS << "\t.bundle_unlock";2465EmitEOL();2466}24672468std::optional<std::pair<bool, std::string>>2469MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,2470const MCExpr *Expr, SMLoc,2471const MCSubtargetInfo &STI) {2472OS << "\t.reloc ";2473Offset.print(OS, MAI);2474OS << ", " << Name;2475if (Expr) {2476OS << ", ";2477Expr->print(OS, MAI);2478}2479EmitEOL();2480return std::nullopt;2481}24822483void MCAsmStreamer::emitAddrsig() {2484OS << "\t.addrsig";2485EmitEOL();2486}24872488void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {2489OS << "\t.addrsig_sym ";2490Sym->print(OS, MAI);2491EmitEOL();2492}24932494/// EmitRawText - If this file is backed by an assembly streamer, this dumps2495/// the specified string in the output .s file. This capability is2496/// indicated by the hasRawTextSupport() predicate.2497void MCAsmStreamer::emitRawTextImpl(StringRef String) {2498String.consume_back("\n");2499OS << String;2500EmitEOL();2501}25022503void MCAsmStreamer::finishImpl() {2504// If we are generating dwarf for assembly source files dump out the sections.2505if (getContext().getGenDwarfForAssembly())2506MCGenDwarfInfo::Emit(this);25072508// Now it is time to emit debug line sections if target doesn't support .loc2509// and .line directives.2510if (!MAI->usesDwarfFileAndLocDirectives()) {2511MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());2512return;2513}25142515// Emit the label for the line table, if requested - since the rest of the2516// line table will be defined by .loc/.file directives, and not emitted2517// directly, the label is the only work required here.2518const auto &Tables = getContext().getMCDwarfLineTables();2519if (!Tables.empty()) {2520assert(Tables.size() == 1 && "asm output only supports one line table");2521if (auto *Label = Tables.begin()->second.getLabel()) {2522switchSection(getContext().getObjectFileInfo()->getDwarfLineSection());2523emitLabel(Label);2524}2525}2526}25272528void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {2529// If the assembler on some target fills in the DWARF unit length, we2530// don't want to emit the length in the compiler. For example, the AIX2531// assembler requires the assembly file with the unit length omitted from2532// the debug section headers. In such cases, any label we placed occurs2533// after the implied length field. We need to adjust the reference here2534// to account for the offset introduced by the inserted length field.2535if (!MAI->needsDwarfSectionSizeInHeader())2536return;2537MCStreamer::emitDwarfUnitLength(Length, Comment);2538}25392540MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix,2541const Twine &Comment) {2542// If the assembler on some target fills in the DWARF unit length, we2543// don't want to emit the length in the compiler. For example, the AIX2544// assembler requires the assembly file with the unit length omitted from2545// the debug section headers. In such cases, any label we placed occurs2546// after the implied length field. We need to adjust the reference here2547// to account for the offset introduced by the inserted length field.2548if (!MAI->needsDwarfSectionSizeInHeader())2549return getContext().createTempSymbol(Prefix + "_end");2550return MCStreamer::emitDwarfUnitLength(Prefix, Comment);2551}25522553void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {2554// If the assembler on some target fills in the DWARF unit length, we2555// don't want to emit the length in the compiler. For example, the AIX2556// assembler requires the assembly file with the unit length omitted from2557// the debug section headers. In such cases, any label we placed occurs2558// after the implied length field. We need to adjust the reference here2559// to account for the offset introduced by the inserted length field.2560MCContext &Ctx = getContext();2561if (!MAI->needsDwarfSectionSizeInHeader()) {2562MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_");2563// Emit the symbol which does not contain the unit length field.2564emitLabel(DebugLineSymTmp);25652566// Adjust the outer reference to account for the offset introduced by the2567// inserted length field.2568unsigned LengthFieldSize =2569dwarf::getUnitLengthFieldByteSize(Ctx.getDwarfFormat());2570const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx);2571const MCExpr *OuterSym = MCBinaryExpr::createSub(2572MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx);25732574emitAssignment(StartSym, OuterSym);2575return;2576}2577MCStreamer::emitDwarfLineStartLabel(StartSym);2578}25792580void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section,2581MCSymbol *LastLabel) {2582// If the targets write the raw debug line data for assembly output (We can2583// not switch to Section and add the end symbol there for assembly output)2584// we currently use the .text end label as any section end. This will not2585// impact the debugability as we will jump to the caller of the last function2586// in the section before we come into the .text end address.2587assert(!MAI->usesDwarfFileAndLocDirectives() &&2588".loc should not be generated together with raw data!");25892590MCContext &Ctx = getContext();25912592// FIXME: use section end symbol as end of the Section. We need to consider2593// the explicit sections and -ffunction-sections when we try to generate or2594// find section end symbol for the Section.2595MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection();2596assert(TextSection->hasEnded() && ".text section is not end!");25972598MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx);2599const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();2600emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,2601AsmInfo->getCodePointerSize());2602}26032604// Generate DWARF line sections for assembly mode without .loc/.file2605void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,2606const MCSymbol *LastLabel,2607const MCSymbol *Label,2608unsigned PointerSize) {2609assert(!MAI->usesDwarfFileAndLocDirectives() &&2610".loc/.file don't need raw data in debug line section!");26112612// Set to new address.2613AddComment("Set address to " + Label->getName());2614emitIntValue(dwarf::DW_LNS_extended_op, 1);2615emitULEB128IntValue(PointerSize + 1);2616emitIntValue(dwarf::DW_LNE_set_address, 1);2617emitSymbolValue(Label, PointerSize);26182619if (!LastLabel) {2620// Emit the sequence for the LineDelta (from 1) and a zero address delta.2621AddComment("Start sequence");2622MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0);2623return;2624}26252626// INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence2627// for the end of the section.2628if (LineDelta == INT64_MAX) {2629AddComment("End sequence");2630emitIntValue(dwarf::DW_LNS_extended_op, 1);2631emitULEB128IntValue(1);2632emitIntValue(dwarf::DW_LNE_end_sequence, 1);2633return;2634}26352636// Advance line.2637AddComment("Advance line " + Twine(LineDelta));2638emitIntValue(dwarf::DW_LNS_advance_line, 1);2639emitSLEB128IntValue(LineDelta);2640emitIntValue(dwarf::DW_LNS_copy, 1);2641}26422643void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) {2644// Emit section end. This is used to tell the debug line section where the end2645// is for a text section if we don't use .loc to represent the debug line.2646if (MAI->usesDwarfFileAndLocDirectives())2647return;26482649switchSectionNoPrint(Section);26502651MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext());26522653if (!Sym->isInSection())2654emitLabel(Sym);2655}26562657MCStreamer *llvm::createAsmStreamer(MCContext &Context,2658std::unique_ptr<formatted_raw_ostream> OS,2659MCInstPrinter *IP,2660std::unique_ptr<MCCodeEmitter> &&CE,2661std::unique_ptr<MCAsmBackend> &&MAB) {2662return new MCAsmStreamer(Context, std::move(OS), IP, std::move(CE),2663std::move(MAB));2664}266526662667