LCOV - code coverage report
Current view: top level - lib/MC - MCAsmStreamer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 879 937 93.8 %
Date: 2017-09-14 15:23:50 Functions: 112 117 95.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/ADT/STLExtras.h"
      11             : #include "llvm/ADT/SmallString.h"
      12             : #include "llvm/ADT/StringExtras.h"
      13             : #include "llvm/ADT/Twine.h"
      14             : #include "llvm/MC/MCAsmBackend.h"
      15             : #include "llvm/MC/MCAsmInfo.h"
      16             : #include "llvm/MC/MCCodeEmitter.h"
      17             : #include "llvm/MC/MCCodeView.h"
      18             : #include "llvm/MC/MCContext.h"
      19             : #include "llvm/MC/MCExpr.h"
      20             : #include "llvm/MC/MCFixupKindInfo.h"
      21             : #include "llvm/MC/MCInst.h"
      22             : #include "llvm/MC/MCInstPrinter.h"
      23             : #include "llvm/MC/MCObjectFileInfo.h"
      24             : #include "llvm/MC/MCRegisterInfo.h"
      25             : #include "llvm/MC/MCSectionCOFF.h"
      26             : #include "llvm/MC/MCSectionMachO.h"
      27             : #include "llvm/MC/MCStreamer.h"
      28             : #include "llvm/MC/MCSymbolELF.h"
      29             : #include "llvm/Support/ErrorHandling.h"
      30             : #include "llvm/Support/Format.h"
      31             : #include "llvm/Support/FormattedStream.h"
      32             : #include "llvm/Support/LEB128.h"
      33             : #include "llvm/Support/MathExtras.h"
      34             : #include "llvm/Support/Path.h"
      35             : #include "llvm/Support/SourceMgr.h"
      36             : #include <cctype>
      37             : 
      38             : using namespace llvm;
      39             : 
      40             : namespace {
      41             : 
      42      156861 : class MCAsmStreamer final : public MCStreamer {
      43             :   std::unique_ptr<formatted_raw_ostream> OSOwner;
      44             :   formatted_raw_ostream &OS;
      45             :   const MCAsmInfo *MAI;
      46             :   std::unique_ptr<MCInstPrinter> InstPrinter;
      47             :   std::unique_ptr<MCCodeEmitter> Emitter;
      48             :   std::unique_ptr<MCAsmBackend> AsmBackend;
      49             : 
      50             :   SmallString<128> ExplicitCommentToEmit;
      51             :   SmallString<128> CommentToEmit;
      52             :   raw_svector_ostream CommentStream;
      53             : 
      54             :   unsigned IsVerboseAsm : 1;
      55             :   unsigned ShowInst : 1;
      56             :   unsigned UseDwarfDirectory : 1;
      57             : 
      58             :   void EmitRegisterName(int64_t Register);
      59             :   void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
      60             :   void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
      61             : 
      62             : public:
      63       17537 :   MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
      64             :                 bool isVerboseAsm, bool useDwarfDirectory,
      65             :                 MCInstPrinter *printer, MCCodeEmitter *emitter,
      66             :                 MCAsmBackend *asmbackend, bool showInst)
      67       70148 :       : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
      68       17537 :         MAI(Context.getAsmInfo()), InstPrinter(printer), Emitter(emitter),
      69             :         AsmBackend(asmbackend), CommentStream(CommentToEmit),
      70             :         IsVerboseAsm(isVerboseAsm), ShowInst(showInst),
      71      175370 :         UseDwarfDirectory(useDwarfDirectory) {
      72             :     assert(InstPrinter);
      73       17537 :     if (IsVerboseAsm)
      74       34562 :         InstPrinter->setCommentStream(CommentStream);
      75       17537 :   }
      76             : 
      77     4075695 :   inline void EmitEOL() {
      78             :     // Dump Explicit Comments here.
      79     4075695 :     emitExplicitComments();
      80             :     // If we don't have any comments, just emit a \n.
      81     4075695 :     if (!IsVerboseAsm) {
      82       63140 :       OS << '\n';
      83             :       return;
      84             :     }
      85     4012555 :     EmitCommentsAndEOL();
      86             :   }
      87             : 
      88             :   void EmitSyntaxDirective() override;
      89             : 
      90             :   void EmitCommentsAndEOL();
      91             : 
      92             :   /// isVerboseAsm - Return true if this streamer supports verbose assembly at
      93             :   /// all.
      94       48188 :   bool isVerboseAsm() const override { return IsVerboseAsm; }
      95             : 
      96             :   /// hasRawTextSupport - We support EmitRawText.
      97        2938 :   bool hasRawTextSupport() const override { return true; }
      98             : 
      99             :   /// AddComment - Add a comment that can be emitted to the generated .s
     100             :   /// file if applicable as a QoI issue to make the output of the compiler
     101             :   /// more readable.  This only affects the MCAsmStreamer, and only when
     102             :   /// verbose assembly output is enabled.
     103             :   void AddComment(const Twine &T, bool EOL = true) override;
     104             : 
     105             :   /// AddEncodingComment - Add a comment showing the encoding of an instruction.
     106             :   /// If PrintSchedInfo - is true then the comment sched:[x:y] should
     107             :   //    be added to output if it's being supported by target
     108             :   void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &,
     109             :                           bool PrintSchedInfo);
     110             : 
     111             :   /// GetCommentOS - Return a raw_ostream that comments can be written to.
     112             :   /// Unlike AddComment, you are required to terminate comments with \n if you
     113             :   /// use this method.
     114     2134252 :   raw_ostream &GetCommentOS() override {
     115     2508873 :     if (!IsVerboseAsm)
     116           0 :       return nulls();  // Discard comments unless in verbose asm mode.
     117     2508873 :     return CommentStream;
     118             :   }
     119             : 
     120             :   void emitRawComment(const Twine &T, bool TabPrefix = true) override;
     121             : 
     122             :   void addExplicitComment(const Twine &T) override;
     123             :   void emitExplicitComments() override;
     124             : 
     125             :   /// AddBlankLine - Emit a blank line to a .s file to pretty it up.
     126      474421 :   void AddBlankLine() override {
     127      474421 :     EmitEOL();
     128      474421 :   }
     129             : 
     130             :   /// @name MCStreamer Interface
     131             :   /// @{
     132             : 
     133             :   void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
     134             : 
     135             :   void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
     136             :   void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
     137             : 
     138             :   void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
     139             :   void EmitLinkerOptions(ArrayRef<std::string> Options) override;
     140             :   void EmitDataRegion(MCDataRegionType Kind) override;
     141             :   void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
     142             :                       unsigned Update) override;
     143             :   void EmitThumbFunc(MCSymbol *Func) override;
     144             : 
     145             :   void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
     146             :   void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
     147             :   bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
     148             : 
     149             :   void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
     150             :   void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
     151             :   void EmitCOFFSymbolStorageClass(int StorageClass) override;
     152             :   void EmitCOFFSymbolType(int Type) override;
     153             :   void EndCOFFSymbolDef() override;
     154             :   void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
     155             :   void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
     156             :   void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
     157             :   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
     158             :   void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     159             :                         unsigned ByteAlignment) override;
     160             : 
     161             :   /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
     162             :   ///
     163             :   /// @param Symbol - The common symbol to emit.
     164             :   /// @param Size - The size of the common symbol.
     165             :   /// @param ByteAlignment - The alignment of the common symbol in bytes.
     166             :   void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     167             :                              unsigned ByteAlignment) override;
     168             : 
     169             :   void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
     170             :                     uint64_t Size = 0, unsigned ByteAlignment = 0) override;
     171             : 
     172             :   void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
     173             :                       unsigned ByteAlignment = 0) override;
     174             : 
     175             :   void EmitBinaryData(StringRef Data) override;
     176             : 
     177             :   void EmitBytes(StringRef Data) override;
     178             : 
     179             :   void EmitValueImpl(const MCExpr *Value, unsigned Size,
     180             :                      SMLoc Loc = SMLoc()) override;
     181             :   void EmitIntValue(uint64_t Value, unsigned Size) override;
     182             : 
     183             :   void EmitULEB128Value(const MCExpr *Value) override;
     184             : 
     185             :   void EmitSLEB128Value(const MCExpr *Value) override;
     186             : 
     187             :   void EmitDTPRel32Value(const MCExpr *Value) override;
     188             :   void EmitDTPRel64Value(const MCExpr *Value) override;
     189             :   void EmitTPRel32Value(const MCExpr *Value) override;
     190             :   void EmitTPRel64Value(const MCExpr *Value) override;
     191             : 
     192             :   void EmitGPRel64Value(const MCExpr *Value) override;
     193             : 
     194             :   void EmitGPRel32Value(const MCExpr *Value) override;
     195             : 
     196             : 
     197             :   void emitFill(uint64_t NumBytes, uint8_t FillValue) override;
     198             : 
     199             :   void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
     200             :                 SMLoc Loc = SMLoc()) override;
     201             : 
     202             :   void emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) override;
     203             : 
     204             :   void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
     205             :                 SMLoc Loc = SMLoc()) override;
     206             : 
     207             :   void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
     208             :                             unsigned ValueSize = 1,
     209             :                             unsigned MaxBytesToEmit = 0) override;
     210             : 
     211             :   void EmitCodeAlignment(unsigned ByteAlignment,
     212             :                          unsigned MaxBytesToEmit = 0) override;
     213             : 
     214             :   void emitValueToOffset(const MCExpr *Offset,
     215             :                          unsigned char Value,
     216             :                          SMLoc Loc) override;
     217             : 
     218             :   void EmitFileDirective(StringRef Filename) override;
     219             :   unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
     220             :                                   StringRef Filename,
     221             :                                   unsigned CUID = 0) override;
     222             :   void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
     223             :                              unsigned Column, unsigned Flags,
     224             :                              unsigned Isa, unsigned Discriminator,
     225             :                              StringRef FileName) override;
     226             :   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
     227             : 
     228             :   bool EmitCVFileDirective(unsigned FileNo, StringRef Filename) override;
     229             :   bool EmitCVFuncIdDirective(unsigned FuncId) override;
     230             :   bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
     231             :                                    unsigned IAFile, unsigned IALine,
     232             :                                    unsigned IACol, SMLoc Loc) override;
     233             :   void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
     234             :                           unsigned Column, bool PrologueEnd, bool IsStmt,
     235             :                           StringRef FileName, SMLoc Loc) override;
     236             :   void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
     237             :                                 const MCSymbol *FnEnd) override;
     238             :   void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
     239             :                                       unsigned SourceFileId,
     240             :                                       unsigned SourceLineNum,
     241             :                                       const MCSymbol *FnStartSym,
     242             :                                       const MCSymbol *FnEndSym) override;
     243             :   void EmitCVDefRangeDirective(
     244             :       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
     245             :       StringRef FixedSizePortion) override;
     246             :   void EmitCVStringTableDirective() override;
     247             :   void EmitCVFileChecksumsDirective() override;
     248             : 
     249             :   void EmitIdent(StringRef IdentString) override;
     250             :   void EmitCFISections(bool EH, bool Debug) override;
     251             :   void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
     252             :   void EmitCFIDefCfaOffset(int64_t Offset) override;
     253             :   void EmitCFIDefCfaRegister(int64_t Register) override;
     254             :   void EmitCFIOffset(int64_t Register, int64_t Offset) override;
     255             :   void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
     256             :   void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
     257             :   void EmitCFIRememberState() override;
     258             :   void EmitCFIRestoreState() override;
     259             :   void EmitCFISameValue(int64_t Register) override;
     260             :   void EmitCFIRelOffset(int64_t Register, int64_t Offset) override;
     261             :   void EmitCFIAdjustCfaOffset(int64_t Adjustment) override;
     262             :   void EmitCFIEscape(StringRef Values) override;
     263             :   void EmitCFIGnuArgsSize(int64_t Size) override;
     264             :   void EmitCFISignalFrame() override;
     265             :   void EmitCFIUndefined(int64_t Register) override;
     266             :   void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
     267             :   void EmitCFIWindowSave() override;
     268             :   void EmitCFIReturnColumn(int64_t Register) override;
     269             : 
     270             :   void EmitWinCFIStartProc(const MCSymbol *Symbol) override;
     271             :   void EmitWinCFIEndProc() override;
     272             :   void EmitWinCFIStartChained() override;
     273             :   void EmitWinCFIEndChained() override;
     274             :   void EmitWinCFIPushReg(unsigned Register) override;
     275             :   void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override;
     276             :   void EmitWinCFIAllocStack(unsigned Size) override;
     277             :   void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override;
     278             :   void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override;
     279             :   void EmitWinCFIPushFrame(bool Code) override;
     280             :   void EmitWinCFIEndProlog() override;
     281             : 
     282             :   void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override;
     283             :   void EmitWinEHHandlerData() override;
     284             : 
     285             :   void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
     286             :                        bool PrintSchedInfo) override;
     287             : 
     288             :   void EmitBundleAlignMode(unsigned AlignPow2) override;
     289             :   void EmitBundleLock(bool AlignToEnd) override;
     290             :   void EmitBundleUnlock() override;
     291             : 
     292             :   bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
     293             :                           const MCExpr *Expr, SMLoc Loc) override;
     294             : 
     295             :   /// EmitRawText - If this file is backed by an assembly streamer, this dumps
     296             :   /// the specified string in the output .s file.  This capability is
     297             :   /// indicated by the hasRawTextSupport() predicate.
     298             :   void EmitRawTextImpl(StringRef String) override;
     299             : 
     300             :   void FinishImpl() override;
     301             : };
     302             : 
     303             : } // end anonymous namespace.
     304             : 
     305             : /// AddComment - Add a comment that can be emitted to the generated .s
     306             : /// file if applicable as a QoI issue to make the output of the compiler
     307             : /// more readable.  This only affects the MCAsmStreamer, and only when
     308             : /// verbose assembly output is enabled.
     309             : /// By deafult EOL is set to true so that each comment goes on its own line.
     310       78917 : void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
     311       78917 :   if (!IsVerboseAsm) return;
     312             : 
     313       77803 :   T.toVector(CommentToEmit);
     314             :  
     315       77803 :   if (EOL)
     316       75461 :     CommentToEmit.push_back('\n'); // Place comment in a new line.
     317             : }
     318             : 
     319     4012555 : void MCAsmStreamer::EmitCommentsAndEOL() {
     320     6937657 :   if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
     321     5850204 :     OS << '\n';
     322     2925102 :     return;
     323             :   }
     324             : 
     325     2174906 :   StringRef Comments = CommentToEmit;
     326             : 
     327             :   assert(Comments.back() == '\n' &&
     328             :          "Comment array not newline terminated");
     329             :   do {
     330             :     // Emit a line of comments.
     331     1106927 :     OS.PadToColumn(MAI->getCommentColumn());
     332     1106927 :     size_t Position = Comments.find('\n');
     333     4427708 :     OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
     334             : 
     335     2213854 :     Comments = Comments.substr(Position+1);
     336     1106927 :   } while (!Comments.empty());
     337             : 
     338     2174906 :   CommentToEmit.clear();
     339             : }
     340             : 
     341             : static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
     342             :   assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
     343       64029 :   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
     344             : }
     345             : 
     346      445531 : void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
     347      445531 :   if (TabPrefix)
     348       20116 :     OS << '\t';
     349      891062 :   OS << MAI->getCommentString() << T;
     350      445531 :   EmitEOL();
     351      445531 : }
     352             : 
     353         156 : void MCAsmStreamer::addExplicitComment(const Twine &T) {
     354         156 :   StringRef c = T.getSingleStringRef();
     355         312 :   if (c.equals(StringRef(MAI->getSeparatorString())))
     356          23 :     return;
     357         150 :   if (c.startswith(StringRef("//"))) {
     358          34 :     ExplicitCommentToEmit.append("\t");
     359          34 :     ExplicitCommentToEmit.append(MAI->getCommentString());
     360             :     // drop //
     361         119 :     ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
     362         128 :   } else if (c.startswith(StringRef("/*"))) {
     363          12 :     size_t p = 2, len = c.size() - 2;
     364             :     // emit each line in comment as separate newline.
     365             :     do {
     366          26 :       size_t newp = std::min(len, c.find_first_of("\r\n", p));
     367          26 :       ExplicitCommentToEmit.append("\t");
     368          26 :       ExplicitCommentToEmit.append(MAI->getCommentString());
     369          78 :       ExplicitCommentToEmit.append(c.slice(p, newp).str());
     370             :       // If we have another line in this comment add line
     371          13 :       if (newp < len)
     372           2 :         ExplicitCommentToEmit.append("\n");
     373          13 :       p = newp + 1;
     374          13 :     } while (p < len);
     375         104 :   } else if (c.startswith(StringRef(MAI->getCommentString()))) {
     376         176 :     ExplicitCommentToEmit.append("\t");
     377         440 :     ExplicitCommentToEmit.append(c.str());
     378          32 :   } else if (c.front() == '#') {
     379             : 
     380          32 :     ExplicitCommentToEmit.append("\t");
     381          32 :     ExplicitCommentToEmit.append(MAI->getCommentString());
     382         112 :     ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
     383             :   } else
     384             :     assert(false && "Unexpected Assembly Comment");
     385             :   // full line comments immediately output
     386         133 :   if (c.back() == '\n')
     387         108 :     emitExplicitComments();
     388             : }
     389             : 
     390     4075803 : void MCAsmStreamer::emitExplicitComments() {
     391     8151606 :   StringRef Comments = ExplicitCommentToEmit;
     392     4075803 :   if (!Comments.empty())
     393         129 :     OS << Comments;
     394     8151606 :   ExplicitCommentToEmit.clear();
     395     4075803 : }
     396             : 
     397      121468 : void MCAsmStreamer::ChangeSection(MCSection *Section,
     398             :                                   const MCExpr *Subsection) {
     399             :   assert(Section && "Cannot switch to a null section!");
     400      485872 :   Section->PrintSwitchToSection(
     401      364404 :       *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS,
     402      121468 :       Subsection);
     403      121467 : }
     404             : 
     405      351004 : void MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
     406      351004 :   MCStreamer::EmitLabel(Symbol, Loc);
     407             : 
     408      351003 :   Symbol->print(OS, MAI);
     409      351003 :   OS << MAI->getLabelSuffix();
     410             : 
     411      351003 :   EmitEOL();
     412      351003 : }
     413             : 
     414         227 : void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
     415         227 :   StringRef str = MCLOHIdToName(Kind);
     416             : 
     417             : #ifndef NDEBUG
     418             :   int NbArgs = MCLOHIdToNbArgs(Kind);
     419             :   assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
     420             :   assert(str != "" && "Invalid LOH name");
     421             : #endif
     422             : 
     423         454 :   OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
     424         227 :   bool IsFirst = true;
     425        1197 :   for (const MCSymbol *Arg : Args) {
     426         516 :     if (!IsFirst)
     427         289 :       OS << ", ";
     428         516 :     IsFirst = false;
     429         516 :     Arg->print(OS, MAI);
     430             :   }
     431         227 :   EmitEOL();
     432         227 : }
     433             : 
     434       16403 : void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
     435       16403 :   switch (Flag) {
     436        2441 :   case MCAF_SyntaxUnified:         OS << "\t.syntax unified"; break;
     437        2184 :   case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
     438        9222 :   case MCAF_Code16:                OS << '\t'<< MAI->getCode16Directive();break;
     439       14330 :   case MCAF_Code32:                OS << '\t'<< MAI->getCode32Directive();break;
     440           4 :   case MCAF_Code64:                OS << '\t'<< MAI->getCode64Directive();break;
     441             :   }
     442       16403 :   EmitEOL();
     443       16403 : }
     444             : 
     445           5 : void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
     446             :   assert(!Options.empty() && "At least one option is required!");
     447          15 :   OS << "\t.linker_option \"" << Options[0] << '"';
     448           7 :   for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
     449           5 :          ie = Options.end(); it != ie; ++it) {
     450           8 :     OS << ", " << '"' << *it << '"';
     451             :   }
     452           5 :   EmitEOL();
     453           5 : }
     454             : 
     455        2598 : void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
     456        2598 :   if (!MAI->doesSupportDataRegionDirectives())
     457             :     return;
     458         840 :   switch (Kind) {
     459         370 :   case MCDR_DataRegion:            OS << "\t.data_region"; break;
     460          16 :   case MCDR_DataRegionJT8:         OS << "\t.data_region jt8"; break;
     461           0 :   case MCDR_DataRegionJT16:        OS << "\t.data_region jt16"; break;
     462          34 :   case MCDR_DataRegionJT32:        OS << "\t.data_region jt32"; break;
     463         420 :   case MCDR_DataRegionEnd:         OS << "\t.end_data_region"; break;
     464             :   }
     465         840 :   EmitEOL();
     466             : }
     467             : 
     468         873 : void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
     469             :                                    unsigned Minor, unsigned Update) {
     470         873 :   switch (Kind) {
     471          26 :   case MCVM_WatchOSVersionMin:    OS << "\t.watchos_version_min"; break;
     472          18 :   case MCVM_TvOSVersionMin:       OS << "\t.tvos_version_min"; break;
     473         180 :   case MCVM_IOSVersionMin:        OS << "\t.ios_version_min"; break;
     474         649 :   case MCVM_OSXVersionMin:        OS << "\t.macosx_version_min"; break;
     475             :   }
     476        2619 :   OS << " " << Major << ", " << Minor;
     477         873 :   if (Update)
     478          43 :     OS << ", " << Update;
     479         873 :   EmitEOL();
     480         873 : }
     481             : 
     482        4459 : void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
     483             :   // This needs to emit to a temporary string to get properly quoted
     484             :   // MCSymbols when they have spaces in them.
     485        4459 :   OS << "\t.thumb_func";
     486             :   // Only Mach-O hasSubsectionsViaSymbols()
     487        4459 :   if (MAI->hasSubsectionsViaSymbols()) {
     488        2512 :     OS << '\t';
     489        1256 :     Func->print(OS, MAI);
     490             :   }
     491        4459 :   EmitEOL();
     492        4459 : }
     493             : 
     494        1598 : void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
     495        1598 :   Symbol->print(OS, MAI);
     496        1598 :   OS << " = ";
     497        1598 :   Value->print(OS, MAI);
     498             : 
     499        1598 :   EmitEOL();
     500             : 
     501        1598 :   MCStreamer::EmitAssignment(Symbol, Value);
     502        1598 : }
     503             : 
     504           0 : void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
     505           0 :   OS << ".weakref ";
     506           0 :   Alias->print(OS, MAI);
     507           0 :   OS << ", ";
     508           0 :   Symbol->print(OS, MAI);
     509           0 :   EmitEOL();
     510           0 : }
     511             : 
     512      267955 : bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
     513             :                                         MCSymbolAttr Attribute) {
     514      267955 :   switch (Attribute) {
     515           0 :   case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
     516      124826 :   case MCSA_ELF_TypeFunction:    /// .type _foo, STT_FUNC  # aka @function
     517             :   case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
     518             :   case MCSA_ELF_TypeObject:      /// .type _foo, STT_OBJECT  # aka @object
     519             :   case MCSA_ELF_TypeTLS:         /// .type _foo, STT_TLS     # aka @tls_object
     520             :   case MCSA_ELF_TypeCommon:      /// .type _foo, STT_COMMON  # aka @common
     521             :   case MCSA_ELF_TypeNoType:      /// .type _foo, STT_NOTYPE  # aka @notype
     522             :   case MCSA_ELF_TypeGnuUniqueObject:  /// .type _foo, @gnu_unique_object
     523      124826 :     if (!MAI->hasDotTypeDotSizeDirective())
     524             :       return false; // Symbol attribute not supported
     525      124758 :     OS << "\t.type\t";
     526      124758 :     Symbol->print(OS, MAI);
     527      499032 :     OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
     528      124758 :     switch (Attribute) {
     529             :     default: return false;
     530      115634 :     case MCSA_ELF_TypeFunction:    OS << "function"; break;
     531           1 :     case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
     532        9121 :     case MCSA_ELF_TypeObject:      OS << "object"; break;
     533           0 :     case MCSA_ELF_TypeTLS:         OS << "tls_object"; break;
     534           0 :     case MCSA_ELF_TypeCommon:      OS << "common"; break;
     535           0 :     case MCSA_ELF_TypeNoType:      OS << "no_type"; break;
     536           2 :     case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
     537             :     }
     538      124758 :     EmitEOL();
     539      124758 :     return true;
     540      141316 :   case MCSA_Global: // .globl/.global
     541      141316 :     OS << MAI->getGlobalDirective();
     542      141316 :     break;
     543         317 :   case MCSA_Hidden:         OS << "\t.hidden\t";          break;
     544         570 :   case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
     545           0 :   case MCSA_Internal:       OS << "\t.internal\t";        break;
     546           9 :   case MCSA_LazyReference:  OS << "\t.lazy_reference\t";  break;
     547         137 :   case MCSA_Local:          OS << "\t.local\t";           break;
     548          98 :   case MCSA_NoDeadStrip:
     549          98 :     if (!MAI->hasNoDeadStrip())
     550             :       return false;
     551          52 :     OS << "\t.no_dead_strip\t";
     552          52 :     break;
     553           4 :   case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
     554           8 :   case MCSA_AltEntry:       OS << "\t.alt_entry\t";       break;
     555          68 :   case MCSA_PrivateExtern:
     556          68 :     OS << "\t.private_extern\t";
     557          68 :     break;
     558          42 :   case MCSA_Protected:      OS << "\t.protected\t";       break;
     559           4 :   case MCSA_Reference:      OS << "\t.reference\t";       break;
     560         305 :   case MCSA_Weak:           OS << MAI->getWeakDirective(); break;
     561         147 :   case MCSA_WeakDefinition:
     562         147 :     OS << "\t.weak_definition\t";
     563         147 :     break;
     564             :       // .weak_reference
     565          91 :   case MCSA_WeakReference:  OS << MAI->getWeakRefDirective(); break;
     566          13 :   case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
     567             :   }
     568             : 
     569      143083 :   Symbol->print(OS, MAI);
     570      143083 :   EmitEOL();
     571             : 
     572      143083 :   return true;
     573             : }
     574             : 
     575           3 : void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
     576           6 :   OS << ".desc" << ' ';
     577           3 :   Symbol->print(OS, MAI);
     578           9 :   OS << ',' << DescValue;
     579           3 :   EmitEOL();
     580           3 : }
     581             : 
     582        5460 : void MCAsmStreamer::EmitSyntaxDirective() {
     583        5460 :   if (MAI->getAssemblerDialect() == 1) {
     584          20 :     OS << "\t.intel_syntax noprefix";
     585          20 :     EmitEOL();
     586             :   }
     587             :   // FIXME: Currently emit unprefix'ed registers.
     588             :   // The intel_syntax directive has one optional argument 
     589             :   // with may have a value of prefix or noprefix.
     590        5460 : }
     591             : 
     592        2260 : void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
     593        2260 :   OS << "\t.def\t ";
     594        2260 :   Symbol->print(OS, MAI);
     595        4520 :   OS << ';';
     596        2260 :   EmitEOL();
     597        2260 : }
     598             : 
     599        2260 : void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
     600        6780 :   OS << "\t.scl\t" << StorageClass << ';';
     601        2260 :   EmitEOL();
     602        2260 : }
     603             : 
     604        2260 : void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
     605        6780 :   OS << "\t.type\t" << Type << ';';
     606        2260 :   EmitEOL();
     607        2260 : }
     608             : 
     609        2260 : void MCAsmStreamer::EndCOFFSymbolDef() {
     610        2260 :   OS << "\t.endef";
     611        2260 :   EmitEOL();
     612        2260 : }
     613             : 
     614          28 : void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
     615          28 :   OS << "\t.safeseh\t";
     616          28 :   Symbol->print(OS, MAI);
     617          28 :   EmitEOL();
     618          28 : }
     619             : 
     620          67 : void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
     621          67 :   OS << "\t.secidx\t";
     622          67 :   Symbol->print(OS, MAI);
     623          67 :   EmitEOL();
     624          67 : }
     625             : 
     626         201 : void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
     627         201 :   OS << "\t.secrel32\t";
     628         201 :   Symbol->print(OS, MAI);
     629         201 :   if (Offset != 0)
     630           4 :     OS << '+' << Offset;
     631         201 :   EmitEOL();
     632         201 : }
     633             : 
     634      122610 : void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
     635             :   assert(MAI->hasDotTypeDotSizeDirective());
     636      122610 :   OS << "\t.size\t";
     637      122610 :   Symbol->print(OS, MAI);
     638      122610 :   OS << ", ";
     639      122610 :   Value->print(OS, MAI);
     640      122610 :   EmitEOL();
     641      122610 : }
     642             : 
     643        2215 : void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     644             :                                      unsigned ByteAlignment) {
     645        2215 :   OS << "\t.comm\t";
     646        2215 :   Symbol->print(OS, MAI);
     647        4430 :   OS << ',' << Size;
     648             : 
     649        2215 :   if (ByteAlignment != 0) {
     650        2083 :     if (MAI->getCOMMDirectiveAlignmentIsInBytes())
     651        3844 :       OS << ',' << ByteAlignment;
     652             :     else
     653         483 :       OS << ',' << Log2_32(ByteAlignment);
     654             :   }
     655        2215 :   EmitEOL();
     656        2215 : }
     657             : 
     658             : /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
     659             : ///
     660             : /// @param Symbol - The common symbol to emit.
     661             : /// @param Size - The size of the common symbol.
     662          25 : void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
     663             :                                           unsigned ByteAlign) {
     664          25 :   OS << "\t.lcomm\t";
     665          25 :   Symbol->print(OS, MAI);
     666          50 :   OS << ',' << Size;
     667             : 
     668          25 :   if (ByteAlign > 1) {
     669          16 :     switch (MAI->getLCOMMDirectiveAlignmentType()) {
     670           0 :     case LCOMM::NoAlignment:
     671           0 :       llvm_unreachable("alignment not supported on .lcomm!");
     672          15 :     case LCOMM::ByteAlignment:
     673          30 :       OS << ',' << ByteAlign;
     674             :       break;
     675           1 :     case LCOMM::Log2Alignment:
     676             :       assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
     677           3 :       OS << ',' << Log2_32(ByteAlign);
     678             :       break;
     679             :     }
     680             :   }
     681          25 :   EmitEOL();
     682          25 : }
     683             : 
     684         278 : void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
     685             :                                  uint64_t Size, unsigned ByteAlignment) {
     686         278 :   if (Symbol)
     687         554 :     AssignFragment(Symbol, &Section->getDummyFragment());
     688             : 
     689             :   // Note: a .zerofill directive does not switch sections.
     690         278 :   OS << ".zerofill ";
     691             : 
     692             :   // This is a mach-o specific directive.
     693         278 :   const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
     694         834 :   OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
     695             : 
     696         278 :   if (Symbol) {
     697         554 :     OS << ',';
     698         277 :     Symbol->print(OS, MAI);
     699         554 :     OS << ',' << Size;
     700         277 :     if (ByteAlignment != 0)
     701         831 :       OS << ',' << Log2_32(ByteAlignment);
     702             :   }
     703         278 :   EmitEOL();
     704         278 : }
     705             : 
     706             : // .tbss sym, size, align
     707             : // This depends that the symbol has already been mangled from the original,
     708             : // e.g. _a.
     709          73 : void MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
     710             :                                    uint64_t Size, unsigned ByteAlignment) {
     711         146 :   AssignFragment(Symbol, &Section->getDummyFragment());
     712             : 
     713             :   assert(Symbol && "Symbol shouldn't be NULL!");
     714             :   // Instead of using the Section we'll just use the shortcut.
     715             :   // This is a mach-o specific directive and section.
     716          73 :   OS << ".tbss ";
     717          73 :   Symbol->print(OS, MAI);
     718          73 :   OS << ", " << Size;
     719             : 
     720             :   // Output align if we have it.  We default to 1 so don't bother printing
     721             :   // that.
     722         115 :   if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
     723             : 
     724          73 :   EmitEOL();
     725          73 : }
     726             : 
     727        8112 : static inline char toOctal(int X) { return (X&7)+'0'; }
     728             : 
     729       16319 : static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
     730       16319 :   OS << '"';
     731             : 
     732      192120 :   for (unsigned i = 0, e = Data.size(); i != e; ++i) {
     733      318964 :     unsigned char C = Data[i];
     734      159635 :     if (C == '"' || C == '\\') {
     735         306 :       OS << '\\' << (char)C;
     736         153 :       continue;
     737             :     }
     738             : 
     739      315487 :     if (isprint((unsigned char)C)) {
     740      312316 :       OS << (char)C;
     741      156158 :       continue;
     742             :     }
     743             : 
     744        3171 :     switch (C) {
     745          21 :       case '\b': OS << "\\b"; break;
     746           4 :       case '\f': OS << "\\f"; break;
     747         378 :       case '\n': OS << "\\n"; break;
     748           1 :       case '\r': OS << "\\r"; break;
     749          63 :       case '\t': OS << "\\t"; break;
     750        2704 :       default:
     751        2704 :         OS << '\\';
     752        8112 :         OS << toOctal(C >> 6);
     753        8112 :         OS << toOctal(C >> 3);
     754        5408 :         OS << toOctal(C >> 0);
     755             :         break;
     756             :     }
     757             :   }
     758             : 
     759       16319 :   OS << '"';
     760       16319 : }
     761             : 
     762       32619 : void MCAsmStreamer::EmitBytes(StringRef Data) {
     763             :   assert(getCurrentSectionOnly() &&
     764             :          "Cannot emit contents before setting section!");
     765       32619 :   if (Data.empty()) return;
     766             : 
     767       32619 :   if (Data.size() == 1) {
     768       27731 :     OS << MAI->getData8bitsDirective();
     769       83193 :     OS << (unsigned)(unsigned char)Data[0];
     770       27731 :     EmitEOL();
     771       27731 :     return;
     772             :   }
     773             : 
     774             :   // If the data ends with 0 and the target supports .asciz, use it, otherwise
     775             :   // use .ascii
     776        9776 :   if (MAI->getAscizDirective() && Data.back() == 0) {
     777        4206 :     OS << MAI->getAscizDirective();
     778        8412 :     Data = Data.substr(0, Data.size()-1);
     779             :   } else {
     780         682 :     OS << MAI->getAsciiDirective();
     781             :   }
     782             : 
     783        4888 :   PrintQuotedString(Data, OS);
     784        4888 :   EmitEOL();
     785             : }
     786             : 
     787         562 : void MCAsmStreamer::EmitBinaryData(StringRef Data) {
     788             :   // This is binary data. Print it in a grid of hex bytes for readability.
     789         562 :   const size_t Cols = 4;
     790        2452 :   for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
     791        2656 :     size_t J = I, EJ = std::min(I + Cols, Data.size());
     792             :     assert(EJ > 0);
     793        1328 :     OS << MAI->getData8bitsDirective();
     794        7200 :     for (; J < EJ - 1; ++J)
     795        8808 :       OS << format("0x%02x", uint8_t(Data[J])) << ", ";
     796        3984 :     OS << format("0x%02x", uint8_t(Data[J]));
     797        1328 :     EmitEOL();
     798             :   }
     799         562 : }
     800             : 
     801      328625 : void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
     802      328625 :   EmitValue(MCConstantExpr::create(Value, getContext()), Size);
     803      328625 : }
     804             : 
     805      350620 : void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
     806             :                                   SMLoc Loc) {
     807             :   assert(Size <= 8 && "Invalid size");
     808             :   assert(getCurrentSectionOnly() &&
     809             :          "Cannot emit contents before setting section!");
     810      350620 :   const char *Directive = nullptr;
     811      350620 :   switch (Size) {
     812             :   default: break;
     813       87913 :   case 1: Directive = MAI->getData8bitsDirective();  break;
     814       28322 :   case 2: Directive = MAI->getData16bitsDirective(); break;
     815      202080 :   case 4: Directive = MAI->getData32bitsDirective(); break;
     816       32305 :   case 8: Directive = MAI->getData64bitsDirective(); break;
     817             :   }
     818             : 
     819      350620 :   if (!Directive) {
     820             :     int64_t IntValue;
     821         432 :     if (!Value->evaluateAsAbsolute(IntValue))
     822           0 :       report_fatal_error("Don't know how to emit this value.");
     823             : 
     824             :     // We couldn't handle the requested integer size so we fallback by breaking
     825             :     // the request down into several, smaller, integers.
     826             :     // Since sizes greater or equal to "Size" are invalid, we use the greatest
     827             :     // power of 2 that is less than "Size" as our largest piece of granularity.
     828         432 :     bool IsLittleEndian = MAI->isLittleEndian();
     829        1296 :     for (unsigned Emitted = 0; Emitted != Size;) {
     830         864 :       unsigned Remaining = Size - Emitted;
     831             :       // The size of our partial emission must be a power of two less than
     832             :       // Size.
     833        2592 :       unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
     834             :       // Calculate the byte offset of our partial emission taking into account
     835             :       // the endianness of the target.
     836         864 :       unsigned ByteOffset =
     837         864 :           IsLittleEndian ? Emitted : (Remaining - EmissionSize);
     838         864 :       uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
     839             :       // We truncate our partial emission to fit within the bounds of the
     840             :       // emission domain.  This produces nicer output and silences potential
     841             :       // truncation warnings when round tripping through another assembler.
     842         864 :       uint64_t Shift = 64 - EmissionSize * 8;
     843             :       assert(Shift < static_cast<uint64_t>(
     844             :                          std::numeric_limits<unsigned long long>::digits) &&
     845             :              "undefined behavior");
     846         864 :       ValueToEmit &= ~0ULL >> Shift;
     847         864 :       EmitIntValue(ValueToEmit, EmissionSize);
     848         864 :       Emitted += EmissionSize;
     849             :     }
     850             :     return;
     851             :   }
     852             : 
     853             :   assert(Directive && "Invalid size for machine code value!");
     854      350188 :   OS << Directive;
     855      350188 :   Value->print(OS, MAI);
     856      350188 :   EmitEOL();
     857             : }
     858             : 
     859           5 : void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
     860             :   int64_t IntValue;
     861           5 :   if (Value->evaluateAsAbsolute(IntValue)) {
     862           4 :     EmitULEB128IntValue(IntValue);
     863           4 :     return;
     864             :   }
     865           1 :   OS << ".uleb128 ";
     866           1 :   Value->print(OS, MAI);
     867           1 :   EmitEOL();
     868             : }
     869             : 
     870           4 : void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
     871             :   int64_t IntValue;
     872           4 :   if (Value->evaluateAsAbsolute(IntValue)) {
     873           4 :     EmitSLEB128IntValue(IntValue);
     874           4 :     return;
     875             :   }
     876           0 :   OS << ".sleb128 ";
     877           0 :   Value->print(OS, MAI);
     878           0 :   EmitEOL();
     879             : }
     880             : 
     881           3 : void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) {
     882             :   assert(MAI->getDTPRel64Directive() != nullptr);
     883           3 :   OS << MAI->getDTPRel64Directive();
     884           3 :   Value->print(OS, MAI);
     885           3 :   EmitEOL();
     886           3 : }
     887             : 
     888           3 : void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) {
     889             :   assert(MAI->getDTPRel32Directive() != nullptr);
     890           3 :   OS << MAI->getDTPRel32Directive();
     891           3 :   Value->print(OS, MAI);
     892           3 :   EmitEOL();
     893           3 : }
     894             : 
     895           2 : void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) {
     896             :   assert(MAI->getTPRel64Directive() != nullptr);
     897           2 :   OS << MAI->getTPRel64Directive();
     898           2 :   Value->print(OS, MAI);
     899           2 :   EmitEOL();
     900           2 : }
     901             : 
     902           2 : void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) {
     903             :   assert(MAI->getTPRel32Directive() != nullptr);
     904           2 :   OS << MAI->getTPRel32Directive();
     905           2 :   Value->print(OS, MAI);
     906           2 :   EmitEOL();
     907           2 : }
     908             : 
     909           8 : void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
     910             :   assert(MAI->getGPRel64Directive() != nullptr);
     911           8 :   OS << MAI->getGPRel64Directive();
     912           8 :   Value->print(OS, MAI);
     913           8 :   EmitEOL();
     914           8 : }
     915             : 
     916           5 : void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
     917             :   assert(MAI->getGPRel32Directive() != nullptr);
     918           5 :   OS << MAI->getGPRel32Directive();
     919           5 :   Value->print(OS, MAI);
     920           5 :   EmitEOL();
     921           5 : }
     922             : 
     923             : /// emitFill - Emit NumBytes bytes worth of the value specified by
     924             : /// FillValue.  This implements directives such as '.space'.
     925       39771 : void MCAsmStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
     926       39771 :   if (NumBytes == 0) return;
     927             : 
     928       13355 :   const MCExpr *E = MCConstantExpr::create(NumBytes, getContext());
     929       13355 :   emitFill(*E, FillValue);
     930             : }
     931             : 
     932       13406 : void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
     933             :                              SMLoc Loc) {
     934       13406 :   if (const char *ZeroDirective = MAI->getZeroDirective()) {
     935             :     // FIXME: Emit location directives
     936       13406 :     OS << ZeroDirective;
     937       13406 :     NumBytes.print(OS, MAI);
     938       13406 :     if (FillValue != 0)
     939        2882 :       OS << ',' << (int)FillValue;
     940       13406 :     EmitEOL();
     941       13406 :     return;
     942             :   }
     943             : 
     944           0 :   MCStreamer::emitFill(NumBytes, FillValue);
     945             : }
     946             : 
     947           0 : void MCAsmStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) {
     948           0 :   if (NumValues == 0)
     949             :     return;
     950             : 
     951           0 :   const MCExpr *E = MCConstantExpr::create(NumValues, getContext());
     952           0 :   emitFill(*E, Size, Expr);
     953             : }
     954             : 
     955          17 : void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
     956             :                              int64_t Expr, SMLoc Loc) {
     957             :   // FIXME: Emit location directives
     958          17 :   OS << "\t.fill\t";
     959          17 :   NumValues.print(OS, MAI);
     960          17 :   OS << ", " << Size << ", 0x";
     961          34 :   OS.write_hex(truncateToSize(Expr, 4));
     962          17 :   EmitEOL();
     963          17 : }
     964             : 
     965      159510 : void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
     966             :                                          unsigned ValueSize,
     967             :                                          unsigned MaxBytesToEmit) {
     968             :   // Some assemblers don't support non-power of two alignments, so we always
     969             :   // emit alignments as a power of two if possible.
     970      159510 :   if (isPowerOf2_32(ByteAlignment)) {
     971      159508 :     switch (ValueSize) {
     972           0 :     default:
     973           0 :       llvm_unreachable("Invalid size for machine code value!");
     974      159497 :     case 1:
     975      159497 :       OS << "\t.p2align\t";
     976      159497 :       break;
     977           4 :     case 2:
     978           4 :       OS << ".p2alignw ";
     979           4 :       break;
     980           7 :     case 4:
     981           7 :       OS << ".p2alignl ";
     982           7 :       break;
     983           0 :     case 8:
     984           0 :       llvm_unreachable("Unsupported alignment size!");
     985             :     }
     986             : 
     987      478524 :     OS << Log2_32(ByteAlignment);
     988             : 
     989      159508 :     if (Value || MaxBytesToEmit) {
     990       64010 :       OS << ", 0x";
     991      128020 :       OS.write_hex(truncateToSize(Value, ValueSize));
     992             : 
     993       64010 :       if (MaxBytesToEmit)
     994           1 :         OS << ", " << MaxBytesToEmit;
     995             :     }
     996      159508 :     EmitEOL();
     997      159508 :     return;
     998             :   }
     999             : 
    1000             :   // Non-power of two alignment.  This is not widely supported by assemblers.
    1001             :   // FIXME: Parameterize this based on MAI.
    1002           2 :   switch (ValueSize) {
    1003           0 :   default: llvm_unreachable("Invalid size for machine code value!");
    1004           2 :   case 1: OS << ".balign";  break;
    1005           0 :   case 2: OS << ".balignw"; break;
    1006           0 :   case 4: OS << ".balignl"; break;
    1007           0 :   case 8: llvm_unreachable("Unsupported alignment size!");
    1008             :   }
    1009             : 
    1010           6 :   OS << ' ' << ByteAlignment;
    1011           4 :   OS << ", " << truncateToSize(Value, ValueSize);
    1012           2 :   if (MaxBytesToEmit)
    1013           0 :     OS << ", " << MaxBytesToEmit;
    1014           2 :   EmitEOL();
    1015             : }
    1016             : 
    1017      136436 : void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
    1018             :                                       unsigned MaxBytesToEmit) {
    1019             :   // Emit with a text fill value.
    1020      136436 :   EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
    1021             :                        1, MaxBytesToEmit);
    1022      136436 : }
    1023             : 
    1024           9 : void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
    1025             :                                       unsigned char Value,
    1026             :                                       SMLoc Loc) {
    1027             :   // FIXME: Verify that Offset is associated with the current section.
    1028           9 :   OS << ".org ";
    1029           9 :   Offset->print(OS, MAI);
    1030          18 :   OS << ", " << (unsigned)Value;
    1031           9 :   EmitEOL();
    1032           9 : }
    1033             : 
    1034       10725 : void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
    1035             :   assert(MAI->hasSingleParameterDotFile());
    1036       10725 :   OS << "\t.file\t";
    1037       10725 :   PrintQuotedString(Filename, OS);
    1038       10725 :   EmitEOL();
    1039       10725 : }
    1040             : 
    1041        2366 : unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
    1042             :                                                StringRef Directory,
    1043             :                                                StringRef Filename,
    1044             :                                                unsigned CUID) {
    1045             :   assert(CUID == 0);
    1046             : 
    1047        4732 :   MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
    1048        4732 :   unsigned NumFiles = Table.getMCDwarfFiles().size();
    1049        2366 :   FileNo = Table.getFile(Directory, Filename, FileNo);
    1050        2366 :   if (FileNo == 0)
    1051             :     return 0;
    1052        4732 :   if (NumFiles == Table.getMCDwarfFiles().size())
    1053             :     return FileNo;
    1054             : 
    1055         288 :   SmallString<128> FullPathName;
    1056             : 
    1057         537 :   if (!UseDwarfDirectory && !Directory.empty()) {
    1058          54 :     if (sys::path::is_absolute(Filename))
    1059           0 :       Directory = "";
    1060             :     else {
    1061          54 :       FullPathName = Directory;
    1062         216 :       sys::path::append(FullPathName, Filename);
    1063          54 :       Directory = "";
    1064          54 :       Filename = FullPathName;
    1065             :     }
    1066             :   }
    1067             : 
    1068         864 :   OS << "\t.file\t" << FileNo << ' ';
    1069         288 :   if (!Directory.empty()) {
    1070          30 :     PrintQuotedString(Directory, OS);
    1071          30 :     OS << ' ';
    1072             :   }
    1073         288 :   PrintQuotedString(Filename, OS);
    1074         288 :   EmitEOL();
    1075             : 
    1076         288 :   return FileNo;
    1077             : }
    1078             : 
    1079        1183 : void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
    1080             :                                           unsigned Column, unsigned Flags,
    1081             :                                           unsigned Isa,
    1082             :                                           unsigned Discriminator,
    1083             :                                           StringRef FileName) {
    1084        4732 :   OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
    1085        1183 :   if (Flags & DWARF2_FLAG_BASIC_BLOCK)
    1086           0 :     OS << " basic_block";
    1087        1183 :   if (Flags & DWARF2_FLAG_PROLOGUE_END)
    1088         271 :     OS << " prologue_end";
    1089        1183 :   if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
    1090           0 :     OS << " epilogue_begin";
    1091             : 
    1092        2366 :   unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
    1093        1183 :   if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
    1094         249 :     OS << " is_stmt ";
    1095             : 
    1096         249 :     if (Flags & DWARF2_FLAG_IS_STMT)
    1097         106 :       OS << "1";
    1098             :     else
    1099         143 :       OS << "0";
    1100             :   }
    1101             : 
    1102        1183 :   if (Isa)
    1103           1 :     OS << " isa " << Isa;
    1104        1183 :   if (Discriminator)
    1105           4 :     OS << " discriminator " << Discriminator;
    1106             : 
    1107        1183 :   if (IsVerboseAsm) {
    1108        1044 :     OS.PadToColumn(MAI->getCommentColumn());
    1109        3132 :     OS << MAI->getCommentString() << ' ' << FileName << ':'
    1110        2088 :        << Line << ':' << Column;
    1111             :   }
    1112        1183 :   EmitEOL();
    1113        1183 :   this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
    1114             :                                           Isa, Discriminator, FileName);
    1115        1183 : }
    1116             : 
    1117         257 : MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
    1118             :   // Always use the zeroth line table, since asm syntax only supports one line
    1119             :   // table for now.
    1120         257 :   return MCStreamer::getDwarfLineTableSymbol(0);
    1121             : }
    1122             : 
    1123          51 : bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename) {
    1124          51 :   if (!getContext().getCVContext().addFile(FileNo, Filename))
    1125             :     return false;
    1126             : 
    1127         153 :   OS << "\t.cv_file\t" << FileNo << ' ';
    1128             : 
    1129          51 :   PrintQuotedString(Filename, OS);
    1130          51 :   EmitEOL();
    1131          51 :   return true;
    1132             : }
    1133             : 
    1134          62 : bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
    1135         186 :   OS << "\t.cv_func_id " << FuncId << '\n';
    1136          62 :   return MCStreamer::EmitCVFuncIdDirective(FuncId);
    1137             : }
    1138             : 
    1139           9 : bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
    1140             :                                                 unsigned IAFunc,
    1141             :                                                 unsigned IAFile,
    1142             :                                                 unsigned IALine, unsigned IACol,
    1143             :                                                 SMLoc Loc) {
    1144          27 :   OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
    1145          63 :      << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
    1146           9 :   return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
    1147           9 :                                                  IALine, IACol, Loc);
    1148             : }
    1149             : 
    1150         233 : void MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
    1151             :                                        unsigned Line, unsigned Column,
    1152             :                                        bool PrologueEnd, bool IsStmt,
    1153             :                                        StringRef FileName, SMLoc Loc) {
    1154         932 :   OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
    1155         233 :      << Column;
    1156         233 :   if (PrologueEnd)
    1157           0 :     OS << " prologue_end";
    1158             : 
    1159         466 :   unsigned OldIsStmt = getContext().getCVContext().getCurrentCVLoc().isStmt();
    1160         233 :   if (IsStmt != OldIsStmt) {
    1161          44 :     OS << " is_stmt ";
    1162             : 
    1163          44 :     if (IsStmt)
    1164           0 :       OS << "1";
    1165             :     else
    1166          44 :       OS << "0";
    1167             :   }
    1168             : 
    1169         233 :   if (IsVerboseAsm) {
    1170         233 :     OS.PadToColumn(MAI->getCommentColumn());
    1171        1165 :     OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
    1172             :        << Column;
    1173             :   }
    1174         233 :   EmitEOL();
    1175         233 :   this->MCStreamer::EmitCVLocDirective(FunctionId, FileNo, Line, Column,
    1176             :                                        PrologueEnd, IsStmt, FileName, Loc);
    1177         233 : }
    1178             : 
    1179          58 : void MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
    1180             :                                              const MCSymbol *FnStart,
    1181             :                                              const MCSymbol *FnEnd) {
    1182         116 :   OS << "\t.cv_linetable\t" << FunctionId << ", ";
    1183          58 :   FnStart->print(OS, MAI);
    1184          58 :   OS << ", ";
    1185          58 :   FnEnd->print(OS, MAI);
    1186          58 :   EmitEOL();
    1187          58 :   this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
    1188          58 : }
    1189             : 
    1190           7 : void MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
    1191             :                                                    unsigned SourceFileId,
    1192             :                                                    unsigned SourceLineNum,
    1193             :                                                    const MCSymbol *FnStartSym,
    1194             :                                                    const MCSymbol *FnEndSym) {
    1195          28 :   OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
    1196          21 :      << ' ' << SourceLineNum << ' ';
    1197           7 :   FnStartSym->print(OS, MAI);
    1198          14 :   OS << ' ';
    1199           7 :   FnEndSym->print(OS, MAI);
    1200           7 :   EmitEOL();
    1201           7 :   this->MCStreamer::EmitCVInlineLinetableDirective(
    1202             :       PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
    1203           7 : }
    1204             : 
    1205          34 : void MCAsmStreamer::EmitCVDefRangeDirective(
    1206             :     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
    1207             :     StringRef FixedSizePortion) {
    1208          34 :   OS << "\t.cv_def_range\t";
    1209         104 :   for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
    1210          72 :     OS << ' ';
    1211          36 :     Range.first->print(OS, MAI);
    1212          72 :     OS << ' ';
    1213          36 :     Range.second->print(OS, MAI);
    1214             :   }
    1215          34 :   OS << ", ";
    1216          34 :   PrintQuotedString(FixedSizePortion, OS);
    1217          34 :   EmitEOL();
    1218          34 :   this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
    1219          34 : }
    1220             : 
    1221          45 : void MCAsmStreamer::EmitCVStringTableDirective() {
    1222          45 :   OS << "\t.cv_stringtable";
    1223          45 :   EmitEOL();
    1224          45 : }
    1225             : 
    1226          45 : void MCAsmStreamer::EmitCVFileChecksumsDirective() {
    1227          45 :   OS << "\t.cv_filechecksums";
    1228          45 :   EmitEOL();
    1229          45 : }
    1230             : 
    1231         303 : void MCAsmStreamer::EmitIdent(StringRef IdentString) {
    1232             :   assert(MAI->hasIdentDirective() && ".ident directive not supported");
    1233         303 :   OS << "\t.ident\t";
    1234         303 :   PrintQuotedString(IdentString, OS);
    1235         303 :   EmitEOL();
    1236         303 : }
    1237             : 
    1238         118 : void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) {
    1239         118 :   MCStreamer::EmitCFISections(EH, Debug);
    1240         118 :   OS << "\t.cfi_sections ";
    1241         118 :   if (EH) {
    1242           0 :     OS << ".eh_frame";
    1243           0 :     if (Debug)
    1244           0 :       OS << ", .debug_frame";
    1245         118 :   } else if (Debug) {
    1246         118 :     OS << ".debug_frame";
    1247             :   }
    1248             : 
    1249         118 :   EmitEOL();
    1250         118 : }
    1251             : 
    1252       72376 : void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
    1253       72376 :   OS << "\t.cfi_startproc";
    1254       72376 :   if (Frame.IsSimple)
    1255           2 :     OS << " simple";
    1256       72376 :   EmitEOL();
    1257       72376 : }
    1258             : 
    1259       72375 : void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
    1260       72375 :   MCStreamer::EmitCFIEndProcImpl(Frame);
    1261       72375 :   OS << "\t.cfi_endproc";
    1262       72375 :   EmitEOL();
    1263       72375 : }
    1264             : 
    1265       20415 : void MCAsmStreamer::EmitRegisterName(int64_t Register) {
    1266       20415 :   if (!MAI->useDwarfRegNumForCFI()) {
    1267       17548 :     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
    1268       17548 :     unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true);
    1269       35096 :     InstPrinter->printRegName(OS, LLVMRegister);
    1270             :   } else {
    1271        2867 :     OS << Register;
    1272             :   }
    1273       20415 : }
    1274             : 
    1275        1726 : void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
    1276        1726 :   MCStreamer::EmitCFIDefCfa(Register, Offset);
    1277        1726 :   OS << "\t.cfi_def_cfa ";
    1278        1726 :   EmitRegisterName(Register);
    1279        1726 :   OS << ", " << Offset;
    1280        1726 :   EmitEOL();
    1281        1726 : }
    1282             : 
    1283        9338 : void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
    1284        9338 :   MCStreamer::EmitCFIDefCfaOffset(Offset);
    1285        9338 :   OS << "\t.cfi_def_cfa_offset " << Offset;
    1286        9338 :   EmitEOL();
    1287        9338 : }
    1288             : 
    1289          17 : static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
    1290          17 :   OS << "\t.cfi_escape ";
    1291          17 :   if (!Values.empty()) {
    1292          17 :     size_t e = Values.size() - 1;
    1293          34 :     for (size_t i = 0; i < e; ++i)
    1294          51 :       OS << format("0x%02x", uint8_t(Values[i])) << ", ";
    1295          51 :     OS << format("0x%02x", uint8_t(Values[e]));
    1296             :   }
    1297          17 : }
    1298             : 
    1299           0 : void MCAsmStreamer::EmitCFIEscape(StringRef Values) {
    1300           0 :   MCStreamer::EmitCFIEscape(Values);
    1301           0 :   PrintCFIEscape(OS, Values);
    1302           0 :   EmitEOL();
    1303           0 : }
    1304             : 
    1305          17 : void MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) {
    1306          17 :   MCStreamer::EmitCFIGnuArgsSize(Size);
    1307             : 
    1308          17 :   uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
    1309          34 :   unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
    1310             : 
    1311          34 :   PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
    1312          17 :   EmitEOL();
    1313          17 : }
    1314             : 
    1315        1863 : void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) {
    1316        1863 :   MCStreamer::EmitCFIDefCfaRegister(Register);
    1317        1863 :   OS << "\t.cfi_def_cfa_register ";
    1318        1863 :   EmitRegisterName(Register);
    1319        1863 :   EmitEOL();
    1320        1863 : }
    1321             : 
    1322       16804 : void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
    1323       16804 :   this->MCStreamer::EmitCFIOffset(Register, Offset);
    1324       16804 :   OS << "\t.cfi_offset ";
    1325       16804 :   EmitRegisterName(Register);
    1326       16804 :   OS << ", " << Offset;
    1327       16804 :   EmitEOL();
    1328       16804 : }
    1329             : 
    1330         176 : void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
    1331             :                                        unsigned Encoding) {
    1332         176 :   MCStreamer::EmitCFIPersonality(Sym, Encoding);
    1333         352 :   OS << "\t.cfi_personality " << Encoding << ", ";
    1334         176 :   Sym->print(OS, MAI);
    1335         176 :   EmitEOL();
    1336         176 : }
    1337             : 
    1338         176 : void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
    1339         176 :   MCStreamer::EmitCFILsda(Sym, Encoding);
    1340         352 :   OS << "\t.cfi_lsda " << Encoding << ", ";
    1341         176 :   Sym->print(OS, MAI);
    1342         176 :   EmitEOL();
    1343         176 : }
    1344             : 
    1345          28 : void MCAsmStreamer::EmitCFIRememberState() {
    1346          28 :   MCStreamer::EmitCFIRememberState();
    1347          28 :   OS << "\t.cfi_remember_state";
    1348          28 :   EmitEOL();
    1349          28 : }
    1350             : 
    1351          28 : void MCAsmStreamer::EmitCFIRestoreState() {
    1352          28 :   MCStreamer::EmitCFIRestoreState();
    1353          28 :   OS << "\t.cfi_restore_state";
    1354          28 :   EmitEOL();
    1355          28 : }
    1356             : 
    1357           2 : void MCAsmStreamer::EmitCFISameValue(int64_t Register) {
    1358           2 :   MCStreamer::EmitCFISameValue(Register);
    1359           2 :   OS << "\t.cfi_same_value ";
    1360           2 :   EmitRegisterName(Register);
    1361           2 :   EmitEOL();
    1362           2 : }
    1363             : 
    1364          20 : void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
    1365          20 :   MCStreamer::EmitCFIRelOffset(Register, Offset);
    1366          20 :   OS << "\t.cfi_rel_offset ";
    1367          20 :   EmitRegisterName(Register);
    1368          20 :   OS << ", " << Offset;
    1369          20 :   EmitEOL();
    1370          20 : }
    1371             : 
    1372        1383 : void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
    1373        1383 :   MCStreamer::EmitCFIAdjustCfaOffset(Adjustment);
    1374        1383 :   OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
    1375        1383 :   EmitEOL();
    1376        1383 : }
    1377             : 
    1378           0 : void MCAsmStreamer::EmitCFISignalFrame() {
    1379           0 :   MCStreamer::EmitCFISignalFrame();
    1380           0 :   OS << "\t.cfi_signal_frame";
    1381           0 :   EmitEOL();
    1382           0 : }
    1383             : 
    1384           0 : void MCAsmStreamer::EmitCFIUndefined(int64_t Register) {
    1385           0 :   MCStreamer::EmitCFIUndefined(Register);
    1386           0 :   OS << "\t.cfi_undefined " << Register;
    1387           0 :   EmitEOL();
    1388           0 : }
    1389             : 
    1390         371 : void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
    1391         371 :   MCStreamer::EmitCFIRegister(Register1, Register2);
    1392         371 :   OS << "\t.cfi_register " << Register1 << ", " << Register2;
    1393         371 :   EmitEOL();
    1394         371 : }
    1395             : 
    1396         370 : void MCAsmStreamer::EmitCFIWindowSave() {
    1397         370 :   MCStreamer::EmitCFIWindowSave();
    1398         370 :   OS << "\t.cfi_window_save";
    1399         370 :   EmitEOL();
    1400         370 : }
    1401             : 
    1402           3 : void MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
    1403           3 :   MCStreamer::EmitCFIReturnColumn(Register);
    1404           3 :   OS << "\t.cfi_return_column " << Register;
    1405           3 :   EmitEOL();
    1406           3 : }
    1407             : 
    1408         323 : void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
    1409         323 :   MCStreamer::EmitWinCFIStartProc(Symbol);
    1410             : 
    1411         323 :   OS << ".seh_proc ";
    1412         323 :   Symbol->print(OS, MAI);
    1413         323 :   EmitEOL();
    1414         323 : }
    1415             : 
    1416         323 : void MCAsmStreamer::EmitWinCFIEndProc() {
    1417         323 :   MCStreamer::EmitWinCFIEndProc();
    1418             : 
    1419         323 :   OS << "\t.seh_endproc";
    1420         323 :   EmitEOL();
    1421         323 : }
    1422             : 
    1423           1 : void MCAsmStreamer::EmitWinCFIStartChained() {
    1424           1 :   MCStreamer::EmitWinCFIStartChained();
    1425             : 
    1426           1 :   OS << "\t.seh_startchained";
    1427           1 :   EmitEOL();
    1428           1 : }
    1429             : 
    1430           1 : void MCAsmStreamer::EmitWinCFIEndChained() {
    1431           1 :   MCStreamer::EmitWinCFIEndChained();
    1432             : 
    1433           1 :   OS << "\t.seh_endchained";
    1434           1 :   EmitEOL();
    1435           1 : }
    1436             : 
    1437         122 : void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
    1438             :                                       bool Except) {
    1439         122 :   MCStreamer::EmitWinEHHandler(Sym, Unwind, Except);
    1440             : 
    1441         122 :   OS << "\t.seh_handler ";
    1442         122 :   Sym->print(OS, MAI);
    1443         122 :   if (Unwind)
    1444         121 :     OS << ", @unwind";
    1445         122 :   if (Except)
    1446         122 :     OS << ", @except";
    1447         122 :   EmitEOL();
    1448         122 : }
    1449             : 
    1450         323 : void MCAsmStreamer::EmitWinEHHandlerData() {
    1451         323 :   MCStreamer::EmitWinEHHandlerData();
    1452             : 
    1453             :   // Switch sections. Don't call SwitchSection directly, because that will
    1454             :   // cause the section switch to be visible in the emitted assembly.
    1455             :   // We only do this so the section switch that terminates the handler
    1456             :   // data block is visible.
    1457         323 :   WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
    1458         646 :   MCSection *TextSec = &CurFrame->Function->getSection();
    1459         323 :   MCSection *XData = getAssociatedXDataSection(TextSec);
    1460         646 :   SwitchSectionNoChange(XData);
    1461             : 
    1462         323 :   OS << "\t.seh_handlerdata";
    1463         323 :   EmitEOL();
    1464         323 : }
    1465             : 
    1466         332 : void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) {
    1467         332 :   MCStreamer::EmitWinCFIPushReg(Register);
    1468             : 
    1469         664 :   OS << "\t.seh_pushreg " << Register;
    1470         332 :   EmitEOL();
    1471         332 : }
    1472             : 
    1473          88 : void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
    1474          88 :   MCStreamer::EmitWinCFISetFrame(Register, Offset);
    1475             : 
    1476         264 :   OS << "\t.seh_setframe " << Register << ", " << Offset;
    1477          88 :   EmitEOL();
    1478          88 : }
    1479             : 
    1480         294 : void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) {
    1481         294 :   MCStreamer::EmitWinCFIAllocStack(Size);
    1482             : 
    1483         588 :   OS << "\t.seh_stackalloc " << Size;
    1484         294 :   EmitEOL();
    1485         294 : }
    1486             : 
    1487           1 : void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
    1488           1 :   MCStreamer::EmitWinCFISaveReg(Register, Offset);
    1489             : 
    1490           3 :   OS << "\t.seh_savereg " << Register << ", " << Offset;
    1491           1 :   EmitEOL();
    1492           1 : }
    1493             : 
    1494         142 : void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
    1495         142 :   MCStreamer::EmitWinCFISaveXMM(Register, Offset);
    1496             : 
    1497         426 :   OS << "\t.seh_savexmm " << Register << ", " << Offset;
    1498         142 :   EmitEOL();
    1499         142 : }
    1500             : 
    1501           1 : void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) {
    1502           1 :   MCStreamer::EmitWinCFIPushFrame(Code);
    1503             : 
    1504           1 :   OS << "\t.seh_pushframe";
    1505           1 :   if (Code)
    1506           1 :     OS << " @code";
    1507           1 :   EmitEOL();
    1508           1 : }
    1509             : 
    1510         322 : void MCAsmStreamer::EmitWinCFIEndProlog() {
    1511         322 :   MCStreamer::EmitWinCFIEndProlog();
    1512             : 
    1513         322 :   OS << "\t.seh_endprologue";
    1514         322 :   EmitEOL();
    1515         322 : }
    1516             : 
    1517      306421 : void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
    1518             :                                        const MCSubtargetInfo &STI,
    1519             :                                        bool PrintSchedInfo) {
    1520      306421 :   raw_ostream &OS = GetCommentOS();
    1521      612841 :   SmallString<256> Code;
    1522      612841 :   SmallVector<MCFixup, 4> Fixups;
    1523      612841 :   raw_svector_ostream VecOS(Code);
    1524      612842 :   Emitter->encodeInstruction(Inst, VecOS, Fixups, STI);
    1525             : 
    1526             :   // If we are showing fixups, create symbolic markers in the encoded
    1527             :   // representation. We do this by making a per-bit map to the fixup item index,
    1528             :   // then trying to display it as nicely as possible.
    1529      612840 :   SmallVector<uint8_t, 64> FixupMap;
    1530      306420 :   FixupMap.resize(Code.size() * 8);
    1531    15738448 :   for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
    1532    30251216 :     FixupMap[i] = 0;
    1533             : 
    1534      618195 :   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    1535       10710 :     MCFixup &F = Fixups[i];
    1536       10710 :     const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
    1537      102870 :     for (unsigned j = 0; j != Info.TargetSize; ++j) {
    1538       97515 :       unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
    1539             :       assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
    1540      195030 :       FixupMap[Index] = 1 + i;
    1541             :     }
    1542             :   }
    1543             : 
    1544             :   // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
    1545             :   // high order halfword of a 32-bit Thumb2 instruction is emitted first.
    1546      306420 :   OS << "encoding: [";
    1547     2503541 :   for (unsigned i = 0, e = Code.size(); i != e; ++i) {
    1548     1890701 :     if (i)
    1549             :       OS << ',';
    1550             : 
    1551             :     // See if all bits are the same map entry.
    1552     3781402 :     uint8_t MapEntry = FixupMap[i * 8 + 0];
    1553    15116903 :     for (unsigned j = 1; j != 8; ++j) {
    1554    26456788 :       if (FixupMap[i * 8 + j] == MapEntry)
    1555             :         continue;
    1556             : 
    1557             :       MapEntry = uint8_t(~0U);
    1558             :       break;
    1559             :     }
    1560             : 
    1561     1890701 :     if (MapEntry != uint8_t(~0U)) {
    1562     1888509 :       if (MapEntry == 0) {
    1563     5633130 :         OS << format("0x%02x", uint8_t(Code[i]));
    1564             :       } else {
    1565       21598 :         if (Code[i]) {
    1566             :           // FIXME: Some of the 8 bits require fix up.
    1567        2010 :           OS << format("0x%02x", uint8_t(Code[i])) << '\''
    1568        1206 :              << char('A' + MapEntry - 1) << '\'';
    1569             :         } else
    1570       10397 :           OS << char('A' + MapEntry - 1);
    1571             :       }
    1572             :     } else {
    1573             :       // Otherwise, write out in binary.
    1574        2192 :       OS << "0b";
    1575        2192 :       for (unsigned j = 8; j--;) {
    1576       35072 :         unsigned Bit = (Code[i] >> j) & 1;
    1577             : 
    1578             :         unsigned FixupBit;
    1579       17536 :         if (MAI->isLittleEndian())
    1580        8824 :           FixupBit = i * 8 + j;
    1581             :         else
    1582        8712 :           FixupBit = i * 8 + (7-j);
    1583             : 
    1584       35072 :         if (uint8_t MapEntry = FixupMap[FixupBit]) {
    1585             :           assert(Bit == 0 && "Encoder wrote into fixed up bit!");
    1586       11123 :           OS << char('A' + MapEntry - 1);
    1587             :         } else
    1588             :           OS << Bit;
    1589             :       }
    1590             :     }
    1591             :   }
    1592      306420 :   OS << "]";
    1593             :   // If we are not going to add fixup or schedul comments after this point then
    1594             :   // we have to end the current comment line with "\n".
    1595      306420 :   if (Fixups.size() || !PrintSchedInfo)
    1596      306420 :     OS << "\n";
    1597             : 
    1598      618195 :   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    1599       10710 :     MCFixup &F = Fixups[i];
    1600       10710 :     const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
    1601       16065 :     OS << "  fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
    1602       10710 :        << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
    1603             :   }
    1604      306420 : }
    1605             : 
    1606     1618766 : void MCAsmStreamer::EmitInstruction(const MCInst &Inst,
    1607             :                                     const MCSubtargetInfo &STI,
    1608             :                                     bool PrintSchedInfo) {
    1609             :   assert(getCurrentSectionOnly() &&
    1610             :          "Cannot emit contents before setting section!");
    1611             : 
    1612             :   // Show the encoding in a comment if we have a code emitter.
    1613     3237532 :   if (Emitter)
    1614      306421 :     AddEncodingComment(Inst, STI, PrintSchedInfo);
    1615             : 
    1616             :   // Show the MCInst if enabled.
    1617     1618765 :   if (ShowInst) {
    1618        1135 :     if (PrintSchedInfo)
    1619           0 :       GetCommentOS() << "\n";
    1620        3405 :     Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
    1621        1135 :     GetCommentOS() << "\n";
    1622             :   }
    1623             : 
    1624     3237530 :   if(getTargetStreamer())
    1625     2832498 :     getTargetStreamer()->prettyPrintAsm(*InstPrinter, OS, Inst, STI);
    1626             :   else
    1627     2023797 :     InstPrinter->printInst(&Inst, OS, "", STI);
    1628             : 
    1629     1618765 :   if (PrintSchedInfo) {
    1630       34668 :     std::string SI = STI.getSchedInfoStr(Inst);
    1631       17334 :     if (!SI.empty())
    1632       16682 :       GetCommentOS() << SI;
    1633             :   }
    1634             : 
    1635     3237530 :   StringRef Comments = CommentToEmit;
    1636     2037213 :   if (Comments.size() && Comments.back() != '\n')
    1637       49248 :     GetCommentOS() << "\n";
    1638             : 
    1639     1618765 :   EmitEOL();
    1640     1618765 : }
    1641             : 
    1642           1 : void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
    1643           2 :   OS << "\t.bundle_align_mode " << AlignPow2;
    1644           1 :   EmitEOL();
    1645           1 : }
    1646             : 
    1647           4 : void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
    1648           4 :   OS << "\t.bundle_lock";
    1649           4 :   if (AlignToEnd)
    1650           3 :     OS << " align_to_end";
    1651           4 :   EmitEOL();
    1652           4 : }
    1653             : 
    1654           2 : void MCAsmStreamer::EmitBundleUnlock() {
    1655           2 :   OS << "\t.bundle_unlock";
    1656           2 :   EmitEOL();
    1657           2 : }
    1658             : 
    1659          18 : bool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
    1660             :                                        const MCExpr *Expr, SMLoc) {
    1661          18 :   OS << "\t.reloc ";
    1662          18 :   Offset.print(OS, MAI);
    1663          18 :   OS << ", " << Name;
    1664          18 :   if (Expr) {
    1665          15 :     OS << ", ";
    1666          15 :     Expr->print(OS, MAI);
    1667             :   }
    1668          18 :   EmitEOL();
    1669          18 :   return false;
    1670             : }
    1671             : 
    1672             : /// EmitRawText - If this file is backed by an assembly streamer, this dumps
    1673             : /// the specified string in the output .s file.  This capability is
    1674             : /// indicated by the hasRawTextSupport() predicate.
    1675        9624 : void MCAsmStreamer::EmitRawTextImpl(StringRef String) {
    1676       17736 :   if (!String.empty() && String.back() == '\n')
    1677       16026 :     String = String.substr(0, String.size()-1);
    1678        9624 :   OS << String;
    1679        9624 :   EmitEOL();
    1680        9624 : }
    1681             : 
    1682       16260 : void MCAsmStreamer::FinishImpl() {
    1683             :   // If we are generating dwarf for assembly source files dump out the sections.
    1684       16260 :   if (getContext().getGenDwarfForAssembly())
    1685           5 :     MCGenDwarfInfo::Emit(this);
    1686             : 
    1687             :   // Emit the label for the line table, if requested - since the rest of the
    1688             :   // line table will be defined by .loc/.file directives, and not emitted
    1689             :   // directly, the label is the only work required here.
    1690       32520 :   auto &Tables = getContext().getMCDwarfLineTables();
    1691       16260 :   if (!Tables.empty()) {
    1692             :     assert(Tables.size() == 1 && "asm output only supports one line table");
    1693         504 :     if (auto *Label = Tables.begin()->second.getLabel()) {
    1694         248 :       SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
    1695         248 :       EmitLabel(Label);
    1696             :     }
    1697             :   }
    1698       16260 : }
    1699             : 
    1700       17537 : MCStreamer *llvm::createAsmStreamer(MCContext &Context,
    1701             :                                     std::unique_ptr<formatted_raw_ostream> OS,
    1702             :                                     bool isVerboseAsm, bool useDwarfDirectory,
    1703             :                                     MCInstPrinter *IP, MCCodeEmitter *CE,
    1704             :                                     MCAsmBackend *MAB, bool ShowInst) {
    1705       17537 :   return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
    1706       35074 :                            useDwarfDirectory, IP, CE, MAB, ShowInst);
    1707             : }

Generated by: LCOV version 1.13