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