1296417Sdim//===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
2195098Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6195098Sed//
7195098Sed//===----------------------------------------------------------------------===//
8195098Sed
9341825Sdim#include "llvm/ADT/Optional.h"
10280031Sdim#include "llvm/ADT/STLExtras.h"
11249423Sdim#include "llvm/ADT/SmallString.h"
12249423Sdim#include "llvm/ADT/StringExtras.h"
13249423Sdim#include "llvm/ADT/Twine.h"
14360784Sdim#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
15249423Sdim#include "llvm/MC/MCAsmBackend.h"
16198090Srdivacky#include "llvm/MC/MCAsmInfo.h"
17341825Sdim#include "llvm/MC/MCAssembler.h"
18198090Srdivacky#include "llvm/MC/MCCodeEmitter.h"
19314564Sdim#include "llvm/MC/MCCodeView.h"
20195098Sed#include "llvm/MC/MCContext.h"
21198090Srdivacky#include "llvm/MC/MCExpr.h"
22218893Sdim#include "llvm/MC/MCFixupKindInfo.h"
23195340Sed#include "llvm/MC/MCInst.h"
24198090Srdivacky#include "llvm/MC/MCInstPrinter.h"
25226633Sdim#include "llvm/MC/MCObjectFileInfo.h"
26341825Sdim#include "llvm/MC/MCObjectWriter.h"
27360784Sdim#include "llvm/MC/MCRegister.h"
28226633Sdim#include "llvm/MC/MCRegisterInfo.h"
29198090Srdivacky#include "llvm/MC/MCSectionMachO.h"
30309124Sdim#include "llvm/MC/MCStreamer.h"
31198090Srdivacky#include "llvm/Support/ErrorHandling.h"
32198090Srdivacky#include "llvm/Support/Format.h"
33202878Srdivacky#include "llvm/Support/FormattedStream.h"
34296417Sdim#include "llvm/Support/LEB128.h"
35249423Sdim#include "llvm/Support/MathExtras.h"
36261991Sdim#include "llvm/Support/Path.h"
37341825Sdim#include "llvm/Support/TargetRegistry.h"
38218893Sdim#include <cctype>
39296417Sdim
40195098Sedusing namespace llvm;
41195098Sed
42195098Sednamespace {
43195098Sed
44288943Sdimclass MCAsmStreamer final : public MCStreamer {
45288943Sdim  std::unique_ptr<formatted_raw_ostream> OSOwner;
46202878Srdivacky  formatted_raw_ostream &OS;
47261991Sdim  const MCAsmInfo *MAI;
48276479Sdim  std::unique_ptr<MCInstPrinter> InstPrinter;
49341825Sdim  std::unique_ptr<MCAssembler> Assembler;
50218893Sdim
51309124Sdim  SmallString<128> ExplicitCommentToEmit;
52202878Srdivacky  SmallString<128> CommentToEmit;
53202878Srdivacky  raw_svector_ostream CommentStream;
54341825Sdim  raw_null_ostream NullStream;
55203954Srdivacky
56203954Srdivacky  unsigned IsVerboseAsm : 1;
57203954Srdivacky  unsigned ShowInst : 1;
58234353Sdim  unsigned UseDwarfDirectory : 1;
59203954Srdivacky
60223017Sdim  void EmitRegisterName(int64_t Register);
61276479Sdim  void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
62276479Sdim  void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
63223017Sdim
64198090Srdivackypublic:
65288943Sdim  MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
66276479Sdim                bool isVerboseAsm, bool useDwarfDirectory,
67341825Sdim                MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
68341825Sdim                std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
69288943Sdim      : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
70341825Sdim        MAI(Context.getAsmInfo()), InstPrinter(printer),
71360784Sdim        Assembler(std::make_unique<MCAssembler>(
72341825Sdim            Context, std::move(asmbackend), std::move(emitter),
73341825Sdim            (asmbackend) ? asmbackend->createObjectWriter(NullStream)
74341825Sdim                         : nullptr)),
75341825Sdim        CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
76341825Sdim        ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
77288943Sdim    assert(InstPrinter);
78288943Sdim    if (IsVerboseAsm)
79288943Sdim        InstPrinter->setCommentStream(CommentStream);
80360784Sdim    if (Assembler->getBackendPtr())
81360784Sdim      setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
82203954Srdivacky  }
83195098Sed
84341825Sdim  MCAssembler &getAssembler() { return *Assembler; }
85341825Sdim  MCAssembler *getAssemblerPtr() override { return nullptr; }
86341825Sdim
87202878Srdivacky  inline void EmitEOL() {
88309124Sdim    // Dump Explicit Comments here.
89309124Sdim    emitExplicitComments();
90202878Srdivacky    // If we don't have any comments, just emit a \n.
91202878Srdivacky    if (!IsVerboseAsm) {
92202878Srdivacky      OS << '\n';
93202878Srdivacky      return;
94202878Srdivacky    }
95202878Srdivacky    EmitCommentsAndEOL();
96202878Srdivacky  }
97296417Sdim
98296417Sdim  void EmitSyntaxDirective() override;
99296417Sdim
100202878Srdivacky  void EmitCommentsAndEOL();
101203954Srdivacky
102341825Sdim  /// Return true if this streamer supports verbose assembly at all.
103276479Sdim  bool isVerboseAsm() const override { return IsVerboseAsm; }
104218893Sdim
105341825Sdim  /// Do we support EmitRawText?
106276479Sdim  bool hasRawTextSupport() const override { return true; }
107203954Srdivacky
108341825Sdim  /// Add a comment that can be emitted to the generated .s file to make the
109341825Sdim  /// output of the compiler more readable. This only affects the MCAsmStreamer
110341825Sdim  /// and only when verbose assembly output is enabled.
111314564Sdim  void AddComment(const Twine &T, bool EOL = true) override;
112203954Srdivacky
113341825Sdim  /// Add a comment showing the encoding of an instruction.
114353358Sdim  void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
115203954Srdivacky
116341825Sdim  /// Return a raw_ostream that comments can be written to.
117202878Srdivacky  /// Unlike AddComment, you are required to terminate comments with \n if you
118202878Srdivacky  /// use this method.
119276479Sdim  raw_ostream &GetCommentOS() override {
120202878Srdivacky    if (!IsVerboseAsm)
121202878Srdivacky      return nulls();  // Discard comments unless in verbose asm mode.
122202878Srdivacky    return CommentStream;
123202878Srdivacky  }
124203954Srdivacky
125276479Sdim  void emitRawComment(const Twine &T, bool TabPrefix = true) override;
126276479Sdim
127309124Sdim  void addExplicitComment(const Twine &T) override;
128309124Sdim  void emitExplicitComments() override;
129309124Sdim
130341825Sdim  /// Emit a blank line to a .s file to pretty it up.
131276479Sdim  void AddBlankLine() override {
132202878Srdivacky    EmitEOL();
133202878Srdivacky  }
134203954Srdivacky
135198090Srdivacky  /// @name MCStreamer Interface
136198090Srdivacky  /// @{
137195098Sed
138288943Sdim  void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
139195098Sed
140331366Sdim  void emitELFSymverDirective(StringRef AliasName,
141331366Sdim                              const MCSymbol *Aliasee) override;
142331366Sdim
143276479Sdim  void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
144321369Sdim  void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
145249423Sdim
146276479Sdim  void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
147276479Sdim  void EmitLinkerOptions(ArrayRef<std::string> Options) override;
148276479Sdim  void EmitDataRegion(MCDataRegionType Kind) override;
149276479Sdim  void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
150344779Sdim                      unsigned Update, VersionTuple SDKVersion) override;
151327952Sdim  void EmitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
152344779Sdim                        unsigned Update, VersionTuple SDKVersion) override;
153276479Sdim  void EmitThumbFunc(MCSymbol *Func) override;
154218893Sdim
155276479Sdim  void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
156276479Sdim  void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
157276479Sdim  bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
158249423Sdim
159276479Sdim  void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
160276479Sdim  void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
161276479Sdim  void EmitCOFFSymbolStorageClass(int StorageClass) override;
162276479Sdim  void EmitCOFFSymbolType(int Type) override;
163276479Sdim  void EndCOFFSymbolDef() override;
164288943Sdim  void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
165341825Sdim  void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
166276479Sdim  void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
167314564Sdim  void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
168341825Sdim  void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
169360784Sdim  void EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
170360784Sdim                                  MCSymbol *CsectSym,
171360784Sdim                                  unsigned ByteAlign) override;
172314564Sdim  void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
173276479Sdim  void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
174276479Sdim                        unsigned ByteAlignment) override;
175195098Sed
176341825Sdim  /// Emit a local common (.lcomm) symbol.
177202878Srdivacky  ///
178202878Srdivacky  /// @param Symbol - The common symbol to emit.
179202878Srdivacky  /// @param Size - The size of the common symbol.
180243830Sdim  /// @param ByteAlignment - The alignment of the common symbol in bytes.
181276479Sdim  void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
182276479Sdim                             unsigned ByteAlignment) override;
183218893Sdim
184288943Sdim  void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
185341825Sdim                    uint64_t Size = 0, unsigned ByteAlignment = 0,
186341825Sdim                    SMLoc Loc = SMLoc()) override;
187195098Sed
188288943Sdim  void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
189288943Sdim                      unsigned ByteAlignment = 0) override;
190218893Sdim
191309124Sdim  void EmitBinaryData(StringRef Data) override;
192309124Sdim
193276479Sdim  void EmitBytes(StringRef Data) override;
194195098Sed
195276479Sdim  void EmitValueImpl(const MCExpr *Value, unsigned Size,
196296417Sdim                     SMLoc Loc = SMLoc()) override;
197276479Sdim  void EmitIntValue(uint64_t Value, unsigned Size) override;
198353358Sdim  void EmitIntValueInHex(uint64_t Value, unsigned Size) override;
199218893Sdim
200276479Sdim  void EmitULEB128Value(const MCExpr *Value) override;
201218893Sdim
202276479Sdim  void EmitSLEB128Value(const MCExpr *Value) override;
203218893Sdim
204314564Sdim  void EmitDTPRel32Value(const MCExpr *Value) override;
205314564Sdim  void EmitDTPRel64Value(const MCExpr *Value) override;
206314564Sdim  void EmitTPRel32Value(const MCExpr *Value) override;
207314564Sdim  void EmitTPRel64Value(const MCExpr *Value) override;
208314564Sdim
209276479Sdim  void EmitGPRel64Value(const MCExpr *Value) override;
210234353Sdim
211276479Sdim  void EmitGPRel32Value(const MCExpr *Value) override;
212195098Sed
213309124Sdim  void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
214309124Sdim                SMLoc Loc = SMLoc()) override;
215309124Sdim
216309124Sdim  void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
217309124Sdim                SMLoc Loc = SMLoc()) override;
218309124Sdim
219276479Sdim  void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
220276479Sdim                            unsigned ValueSize = 1,
221276479Sdim                            unsigned MaxBytesToEmit = 0) override;
222195098Sed
223276479Sdim  void EmitCodeAlignment(unsigned ByteAlignment,
224276479Sdim                         unsigned MaxBytesToEmit = 0) override;
225204642Srdivacky
226296417Sdim  void emitValueToOffset(const MCExpr *Offset,
227314564Sdim                         unsigned char Value,
228314564Sdim                         SMLoc Loc) override;
229203954Srdivacky
230276479Sdim  void EmitFileDirective(StringRef Filename) override;
231341825Sdim  Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
232341825Sdim                                               StringRef Directory,
233341825Sdim                                               StringRef Filename,
234353358Sdim                                               Optional<MD5::MD5Result> Checksum = None,
235341825Sdim                                               Optional<StringRef> Source = None,
236341825Sdim                                               unsigned CUID = 0) override;
237341825Sdim  void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
238353358Sdim                               Optional<MD5::MD5Result> Checksum,
239341825Sdim                               Optional<StringRef> Source,
240341825Sdim                               unsigned CUID = 0) override;
241276479Sdim  void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
242276479Sdim                             unsigned Column, unsigned Flags,
243276479Sdim                             unsigned Isa, unsigned Discriminator,
244276479Sdim                             StringRef FileName) override;
245276479Sdim  MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
246203954Srdivacky
247327952Sdim  bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
248327952Sdim                           ArrayRef<uint8_t> Checksum,
249327952Sdim                           unsigned ChecksumKind) override;
250314564Sdim  bool EmitCVFuncIdDirective(unsigned FuncId) override;
251314564Sdim  bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
252314564Sdim                                   unsigned IAFile, unsigned IALine,
253314564Sdim                                   unsigned IACol, SMLoc Loc) override;
254309124Sdim  void EmitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
255309124Sdim                          unsigned Column, bool PrologueEnd, bool IsStmt,
256314564Sdim                          StringRef FileName, SMLoc Loc) override;
257309124Sdim  void EmitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
258309124Sdim                                const MCSymbol *FnEnd) override;
259314564Sdim  void EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
260314564Sdim                                      unsigned SourceFileId,
261314564Sdim                                      unsigned SourceLineNum,
262314564Sdim                                      const MCSymbol *FnStartSym,
263314564Sdim                                      const MCSymbol *FnEndSym) override;
264360784Sdim
265360784Sdim  void PrintCVDefRangePrefix(
266360784Sdim      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
267360784Sdim
268309124Sdim  void EmitCVDefRangeDirective(
269309124Sdim      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
270360784Sdim      codeview::DefRangeRegisterRelHeader DRHdr) override;
271360784Sdim
272360784Sdim  void EmitCVDefRangeDirective(
273360784Sdim      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
274360784Sdim      codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
275360784Sdim
276360784Sdim  void EmitCVDefRangeDirective(
277360784Sdim      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
278360784Sdim      codeview::DefRangeRegisterHeader DRHdr) override;
279360784Sdim
280360784Sdim  void EmitCVDefRangeDirective(
281360784Sdim      ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
282360784Sdim      codeview::DefRangeFramePointerRelHeader DRHdr) override;
283360784Sdim
284309124Sdim  void EmitCVStringTableDirective() override;
285309124Sdim  void EmitCVFileChecksumsDirective() override;
286327952Sdim  void EmitCVFileChecksumOffsetDirective(unsigned FileNo) override;
287327952Sdim  void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
288309124Sdim
289276479Sdim  void EmitIdent(StringRef IdentString) override;
290344779Sdim  void EmitCFIBKeyFrame() override;
291276479Sdim  void EmitCFISections(bool EH, bool Debug) override;
292276479Sdim  void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
293276479Sdim  void EmitCFIDefCfaOffset(int64_t Offset) override;
294276479Sdim  void EmitCFIDefCfaRegister(int64_t Register) override;
295276479Sdim  void EmitCFIOffset(int64_t Register, int64_t Offset) override;
296276479Sdim  void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
297276479Sdim  void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
298276479Sdim  void EmitCFIRememberState() override;
299276479Sdim  void EmitCFIRestoreState() override;
300327952Sdim  void EmitCFIRestore(int64_t Register) override;
301276479Sdim  void EmitCFISameValue(int64_t Register) override;
302276479Sdim  void EmitCFIRelOffset(int64_t Register, int64_t Offset) override;
303276479Sdim  void EmitCFIAdjustCfaOffset(int64_t Adjustment) override;
304296417Sdim  void EmitCFIEscape(StringRef Values) override;
305296417Sdim  void EmitCFIGnuArgsSize(int64_t Size) override;
306276479Sdim  void EmitCFISignalFrame() override;
307276479Sdim  void EmitCFIUndefined(int64_t Register) override;
308276479Sdim  void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
309276479Sdim  void EmitCFIWindowSave() override;
310344779Sdim  void EmitCFINegateRAState() override;
311327952Sdim  void EmitCFIReturnColumn(int64_t Register) override;
312218893Sdim
313327952Sdim  void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
314327952Sdim  void EmitWinCFIEndProc(SMLoc Loc) override;
315344779Sdim  void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
316327952Sdim  void EmitWinCFIStartChained(SMLoc Loc) override;
317327952Sdim  void EmitWinCFIEndChained(SMLoc Loc) override;
318360784Sdim  void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
319360784Sdim  void EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
320327952Sdim                          SMLoc Loc) override;
321327952Sdim  void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
322360784Sdim  void EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
323327952Sdim                         SMLoc Loc) override;
324360784Sdim  void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
325327952Sdim                         SMLoc Loc) override;
326327952Sdim  void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
327327952Sdim  void EmitWinCFIEndProlog(SMLoc Loc) override;
328223017Sdim
329327952Sdim  void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
330327952Sdim                        SMLoc Loc) override;
331327952Sdim  void EmitWinEHHandlerData(SMLoc Loc) override;
332218893Sdim
333341825Sdim  void emitCGProfileEntry(const MCSymbolRefExpr *From,
334341825Sdim                          const MCSymbolRefExpr *To, uint64_t Count) override;
335341825Sdim
336353358Sdim  void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
337249423Sdim
338276479Sdim  void EmitBundleAlignMode(unsigned AlignPow2) override;
339276479Sdim  void EmitBundleLock(bool AlignToEnd) override;
340276479Sdim  void EmitBundleUnlock() override;
341276479Sdim
342296417Sdim  bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
343341825Sdim                          const MCExpr *Expr, SMLoc Loc,
344341825Sdim                          const MCSubtargetInfo &STI) override;
345296417Sdim
346341825Sdim  void EmitAddrsig() override;
347341825Sdim  void EmitAddrsigSym(const MCSymbol *Sym) override;
348341825Sdim
349341825Sdim  /// If this file is backed by an assembly streamer, this dumps the specified
350341825Sdim  /// string in the output .s file. This capability is indicated by the
351341825Sdim  /// hasRawTextSupport() predicate.
352276479Sdim  void EmitRawTextImpl(StringRef String) override;
353218893Sdim
354276479Sdim  void FinishImpl() override;
355198090Srdivacky};
356195098Sed
357198090Srdivacky} // end anonymous namespace.
358195098Sed
359314564Sdimvoid MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
360202878Srdivacky  if (!IsVerboseAsm) return;
361218893Sdim
362202878Srdivacky  T.toVector(CommentToEmit);
363341825Sdim
364314564Sdim  if (EOL)
365314564Sdim    CommentToEmit.push_back('\n'); // Place comment in a new line.
366202878Srdivacky}
367202878Srdivacky
368202878Srdivackyvoid MCAsmStreamer::EmitCommentsAndEOL() {
369202878Srdivacky  if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
370202878Srdivacky    OS << '\n';
371202878Srdivacky    return;
372202878Srdivacky  }
373218893Sdim
374288943Sdim  StringRef Comments = CommentToEmit;
375218893Sdim
376202878Srdivacky  assert(Comments.back() == '\n' &&
377202878Srdivacky         "Comment array not newline terminated");
378202878Srdivacky  do {
379202878Srdivacky    // Emit a line of comments.
380261991Sdim    OS.PadToColumn(MAI->getCommentColumn());
381202878Srdivacky    size_t Position = Comments.find('\n');
382261991Sdim    OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
383218893Sdim
384202878Srdivacky    Comments = Comments.substr(Position+1);
385202878Srdivacky  } while (!Comments.empty());
386218893Sdim
387202878Srdivacky  CommentToEmit.clear();
388202878Srdivacky}
389202878Srdivacky
390195098Sedstatic inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
391309124Sdim  assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
392195098Sed  return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
393195098Sed}
394195098Sed
395276479Sdimvoid MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
396276479Sdim  if (TabPrefix)
397276479Sdim    OS << '\t';
398276479Sdim  OS << MAI->getCommentString() << T;
399276479Sdim  EmitEOL();
400276479Sdim}
401276479Sdim
402309124Sdimvoid MCAsmStreamer::addExplicitComment(const Twine &T) {
403309124Sdim  StringRef c = T.getSingleStringRef();
404309124Sdim  if (c.equals(StringRef(MAI->getSeparatorString())))
405309124Sdim    return;
406309124Sdim  if (c.startswith(StringRef("//"))) {
407309124Sdim    ExplicitCommentToEmit.append("\t");
408309124Sdim    ExplicitCommentToEmit.append(MAI->getCommentString());
409309124Sdim    // drop //
410309124Sdim    ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
411309124Sdim  } else if (c.startswith(StringRef("/*"))) {
412309124Sdim    size_t p = 2, len = c.size() - 2;
413309124Sdim    // emit each line in comment as separate newline.
414309124Sdim    do {
415309124Sdim      size_t newp = std::min(len, c.find_first_of("\r\n", p));
416309124Sdim      ExplicitCommentToEmit.append("\t");
417309124Sdim      ExplicitCommentToEmit.append(MAI->getCommentString());
418309124Sdim      ExplicitCommentToEmit.append(c.slice(p, newp).str());
419309124Sdim      // If we have another line in this comment add line
420309124Sdim      if (newp < len)
421309124Sdim        ExplicitCommentToEmit.append("\n");
422309124Sdim      p = newp + 1;
423309124Sdim    } while (p < len);
424309124Sdim  } else if (c.startswith(StringRef(MAI->getCommentString()))) {
425309124Sdim    ExplicitCommentToEmit.append("\t");
426309124Sdim    ExplicitCommentToEmit.append(c.str());
427309124Sdim  } else if (c.front() == '#') {
428314564Sdim
429314564Sdim    ExplicitCommentToEmit.append("\t");
430314564Sdim    ExplicitCommentToEmit.append(MAI->getCommentString());
431314564Sdim    ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
432309124Sdim  } else
433309124Sdim    assert(false && "Unexpected Assembly Comment");
434309124Sdim  // full line comments immediately output
435309124Sdim  if (c.back() == '\n')
436309124Sdim    emitExplicitComments();
437309124Sdim}
438309124Sdim
439309124Sdimvoid MCAsmStreamer::emitExplicitComments() {
440309124Sdim  StringRef Comments = ExplicitCommentToEmit;
441309124Sdim  if (!Comments.empty())
442309124Sdim    OS << Comments;
443309124Sdim  ExplicitCommentToEmit.clear();
444309124Sdim}
445309124Sdim
446288943Sdimvoid MCAsmStreamer::ChangeSection(MCSection *Section,
447251662Sdim                                  const MCExpr *Subsection) {
448198090Srdivacky  assert(Section && "Cannot switch to a null section!");
449327952Sdim  if (MCTargetStreamer *TS = getTargetStreamer()) {
450327952Sdim    TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
451327952Sdim  } else {
452327952Sdim    Section->PrintSwitchToSection(
453327952Sdim        *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS,
454327952Sdim        Subsection);
455327952Sdim  }
456195098Sed}
457195098Sed
458331366Sdimvoid MCAsmStreamer::emitELFSymverDirective(StringRef AliasName,
459331366Sdim                                           const MCSymbol *Aliasee) {
460331366Sdim  OS << ".symver ";
461331366Sdim  Aliasee->print(OS, MAI);
462331366Sdim  OS << ", " << AliasName;
463331366Sdim  EmitEOL();
464331366Sdim}
465331366Sdim
466321369Sdimvoid MCAsmStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
467321369Sdim  MCStreamer::EmitLabel(Symbol, Loc);
468195098Sed
469288943Sdim  Symbol->print(OS, MAI);
470288943Sdim  OS << MAI->getLabelSuffix();
471288943Sdim
472202878Srdivacky  EmitEOL();
473195098Sed}
474195098Sed
475276479Sdimvoid MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
476276479Sdim  StringRef str = MCLOHIdToName(Kind);
477249423Sdim
478276479Sdim#ifndef NDEBUG
479276479Sdim  int NbArgs = MCLOHIdToNbArgs(Kind);
480276479Sdim  assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
481276479Sdim  assert(str != "" && "Invalid LOH name");
482276479Sdim#endif
483276479Sdim
484276479Sdim  OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
485276479Sdim  bool IsFirst = true;
486309124Sdim  for (const MCSymbol *Arg : Args) {
487276479Sdim    if (!IsFirst)
488276479Sdim      OS << ", ";
489276479Sdim    IsFirst = false;
490309124Sdim    Arg->print(OS, MAI);
491276479Sdim  }
492249423Sdim  EmitEOL();
493249423Sdim}
494249423Sdim
495202878Srdivackyvoid MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
496198090Srdivacky  switch (Flag) {
497218893Sdim  case MCAF_SyntaxUnified:         OS << "\t.syntax unified"; break;
498202878Srdivacky  case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
499261991Sdim  case MCAF_Code16:                OS << '\t'<< MAI->getCode16Directive();break;
500261991Sdim  case MCAF_Code32:                OS << '\t'<< MAI->getCode32Directive();break;
501261991Sdim  case MCAF_Code64:                OS << '\t'<< MAI->getCode64Directive();break;
502195098Sed  }
503202878Srdivacky  EmitEOL();
504198090Srdivacky}
505195098Sed
506249423Sdimvoid MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
507249423Sdim  assert(!Options.empty() && "At least one option is required!");
508249423Sdim  OS << "\t.linker_option \"" << Options[0] << '"';
509249423Sdim  for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
510249423Sdim         ie = Options.end(); it != ie; ++it) {
511249423Sdim    OS << ", " << '"' << *it << '"';
512249423Sdim  }
513309124Sdim  EmitEOL();
514249423Sdim}
515249423Sdim
516239462Sdimvoid MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
517261991Sdim  if (!MAI->doesSupportDataRegionDirectives())
518239462Sdim    return;
519239462Sdim  switch (Kind) {
520239462Sdim  case MCDR_DataRegion:            OS << "\t.data_region"; break;
521239462Sdim  case MCDR_DataRegionJT8:         OS << "\t.data_region jt8"; break;
522239462Sdim  case MCDR_DataRegionJT16:        OS << "\t.data_region jt16"; break;
523239462Sdim  case MCDR_DataRegionJT32:        OS << "\t.data_region jt32"; break;
524239462Sdim  case MCDR_DataRegionEnd:         OS << "\t.end_data_region"; break;
525239462Sdim  }
526239462Sdim  EmitEOL();
527239462Sdim}
528239462Sdim
529327952Sdimstatic const char *getVersionMinDirective(MCVersionMinType Type) {
530327952Sdim  switch (Type) {
531327952Sdim  case MCVM_WatchOSVersionMin: return ".watchos_version_min";
532327952Sdim  case MCVM_TvOSVersionMin:    return ".tvos_version_min";
533327952Sdim  case MCVM_IOSVersionMin:     return ".ios_version_min";
534327952Sdim  case MCVM_OSXVersionMin:     return ".macosx_version_min";
535327952Sdim  }
536327952Sdim  llvm_unreachable("Invalid MC version min type");
537327952Sdim}
538327952Sdim
539344779Sdimstatic void EmitSDKVersionSuffix(raw_ostream &OS,
540344779Sdim                                 const VersionTuple &SDKVersion) {
541344779Sdim  if (SDKVersion.empty())
542344779Sdim    return;
543344779Sdim  OS << '\t' << "sdk_version " << SDKVersion.getMajor();
544344779Sdim  if (auto Minor = SDKVersion.getMinor()) {
545344779Sdim    OS << ", " << *Minor;
546344779Sdim    if (auto Subminor = SDKVersion.getSubminor()) {
547344779Sdim      OS << ", " << *Subminor;
548344779Sdim    }
549344779Sdim  }
550344779Sdim}
551344779Sdim
552327952Sdimvoid MCAsmStreamer::EmitVersionMin(MCVersionMinType Type, unsigned Major,
553344779Sdim                                   unsigned Minor, unsigned Update,
554344779Sdim                                   VersionTuple SDKVersion) {
555327952Sdim  OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
556327952Sdim  if (Update)
557327952Sdim    OS << ", " << Update;
558344779Sdim  EmitSDKVersionSuffix(OS, SDKVersion);
559327952Sdim  EmitEOL();
560327952Sdim}
561327952Sdim
562327952Sdimstatic const char *getPlatformName(MachO::PlatformType Type) {
563327952Sdim  switch (Type) {
564344779Sdim  case MachO::PLATFORM_MACOS:            return "macos";
565344779Sdim  case MachO::PLATFORM_IOS:              return "ios";
566344779Sdim  case MachO::PLATFORM_TVOS:             return "tvos";
567344779Sdim  case MachO::PLATFORM_WATCHOS:          return "watchos";
568344779Sdim  case MachO::PLATFORM_BRIDGEOS:         return "bridgeos";
569353358Sdim  case MachO::PLATFORM_MACCATALYST:      return "macCatalyst";
570344779Sdim  case MachO::PLATFORM_IOSSIMULATOR:     return "iossimulator";
571344779Sdim  case MachO::PLATFORM_TVOSSIMULATOR:    return "tvossimulator";
572344779Sdim  case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
573276479Sdim  }
574327952Sdim  llvm_unreachable("Invalid Mach-O platform type");
575327952Sdim}
576327952Sdim
577327952Sdimvoid MCAsmStreamer::EmitBuildVersion(unsigned Platform, unsigned Major,
578344779Sdim                                     unsigned Minor, unsigned Update,
579344779Sdim                                     VersionTuple SDKVersion) {
580327952Sdim  const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
581327952Sdim  OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
582276479Sdim  if (Update)
583276479Sdim    OS << ", " << Update;
584344779Sdim  EmitSDKVersionSuffix(OS, SDKVersion);
585276479Sdim  EmitEOL();
586276479Sdim}
587276479Sdim
588218893Sdimvoid MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
589218893Sdim  // This needs to emit to a temporary string to get properly quoted
590218893Sdim  // MCSymbols when they have spaces in them.
591218893Sdim  OS << "\t.thumb_func";
592223017Sdim  // Only Mach-O hasSubsectionsViaSymbols()
593288943Sdim  if (MAI->hasSubsectionsViaSymbols()) {
594288943Sdim    OS << '\t';
595288943Sdim    Func->print(OS, MAI);
596288943Sdim  }
597218893Sdim  EmitEOL();
598218893Sdim}
599218893Sdim
600198090Srdivackyvoid MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
601341825Sdim  // Do not emit a .set on inlined target assignments.
602341825Sdim  bool EmitSet = true;
603341825Sdim  if (auto *E = dyn_cast<MCTargetExpr>(Value))
604341825Sdim    if (E->inlineAssignedExpr())
605341825Sdim      EmitSet = false;
606341825Sdim  if (EmitSet) {
607341825Sdim    OS << ".set ";
608341825Sdim    Symbol->print(OS, MAI);
609341825Sdim    OS << ", ";
610341825Sdim    Value->print(OS, MAI);
611288943Sdim
612341825Sdim    EmitEOL();
613341825Sdim  }
614198396Srdivacky
615276479Sdim  MCStreamer::EmitAssignment(Symbol, Value);
616195098Sed}
617195098Sed
618218893Sdimvoid MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
619288943Sdim  OS << ".weakref ";
620288943Sdim  Alias->print(OS, MAI);
621288943Sdim  OS << ", ";
622288943Sdim  Symbol->print(OS, MAI);
623218893Sdim  EmitEOL();
624218893Sdim}
625218893Sdim
626261991Sdimbool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
627202878Srdivacky                                        MCSymbolAttr Attribute) {
628195098Sed  switch (Attribute) {
629234353Sdim  case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
630203954Srdivacky  case MCSA_ELF_TypeFunction:    /// .type _foo, STT_FUNC  # aka @function
631203954Srdivacky  case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
632203954Srdivacky  case MCSA_ELF_TypeObject:      /// .type _foo, STT_OBJECT  # aka @object
633203954Srdivacky  case MCSA_ELF_TypeTLS:         /// .type _foo, STT_TLS     # aka @tls_object
634203954Srdivacky  case MCSA_ELF_TypeCommon:      /// .type _foo, STT_COMMON  # aka @common
635203954Srdivacky  case MCSA_ELF_TypeNoType:      /// .type _foo, STT_NOTYPE  # aka @notype
636218893Sdim  case MCSA_ELF_TypeGnuUniqueObject:  /// .type _foo, @gnu_unique_object
637261991Sdim    if (!MAI->hasDotTypeDotSizeDirective())
638261991Sdim      return false; // Symbol attribute not supported
639288943Sdim    OS << "\t.type\t";
640288943Sdim    Symbol->print(OS, MAI);
641288943Sdim    OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
642203954Srdivacky    switch (Attribute) {
643261991Sdim    default: return false;
644203954Srdivacky    case MCSA_ELF_TypeFunction:    OS << "function"; break;
645203954Srdivacky    case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
646203954Srdivacky    case MCSA_ELF_TypeObject:      OS << "object"; break;
647203954Srdivacky    case MCSA_ELF_TypeTLS:         OS << "tls_object"; break;
648203954Srdivacky    case MCSA_ELF_TypeCommon:      OS << "common"; break;
649341825Sdim    case MCSA_ELF_TypeNoType:      OS << "notype"; break;
650218893Sdim    case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
651203954Srdivacky    }
652203954Srdivacky    EmitEOL();
653261991Sdim    return true;
654203954Srdivacky  case MCSA_Global: // .globl/.global
655261991Sdim    OS << MAI->getGlobalDirective();
656203954Srdivacky    break;
657360784Sdim  case MCSA_LGlobal:        OS << "\t.lglobl\t";          break;
658210299Sed  case MCSA_Hidden:         OS << "\t.hidden\t";          break;
659210299Sed  case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
660210299Sed  case MCSA_Internal:       OS << "\t.internal\t";        break;
661210299Sed  case MCSA_LazyReference:  OS << "\t.lazy_reference\t";  break;
662210299Sed  case MCSA_Local:          OS << "\t.local\t";           break;
663280031Sdim  case MCSA_NoDeadStrip:
664280031Sdim    if (!MAI->hasNoDeadStrip())
665280031Sdim      return false;
666280031Sdim    OS << "\t.no_dead_strip\t";
667280031Sdim    break;
668218893Sdim  case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
669309124Sdim  case MCSA_AltEntry:       OS << "\t.alt_entry\t";       break;
670221345Sdim  case MCSA_PrivateExtern:
671221345Sdim    OS << "\t.private_extern\t";
672221345Sdim    break;
673210299Sed  case MCSA_Protected:      OS << "\t.protected\t";       break;
674210299Sed  case MCSA_Reference:      OS << "\t.reference\t";       break;
675280031Sdim  case MCSA_Weak:           OS << MAI->getWeakDirective(); break;
676221345Sdim  case MCSA_WeakDefinition:
677221345Sdim    OS << "\t.weak_definition\t";
678221345Sdim    break;
679202878Srdivacky      // .weak_reference
680261991Sdim  case MCSA_WeakReference:  OS << MAI->getWeakRefDirective(); break;
681210299Sed  case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
682353358Sdim  case MCSA_Cold:
683353358Sdim    // Assemblers currently do not support a .cold directive.
684353358Sdim    return false;
685195098Sed  }
686195098Sed
687288943Sdim  Symbol->print(OS, MAI);
688202878Srdivacky  EmitEOL();
689261991Sdim
690261991Sdim  return true;
691195098Sed}
692195098Sed
693198090Srdivackyvoid MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
694288943Sdim  OS << ".desc" << ' ';
695288943Sdim  Symbol->print(OS, MAI);
696288943Sdim  OS << ',' << DescValue;
697202878Srdivacky  EmitEOL();
698198090Srdivacky}
699198090Srdivacky
700296417Sdimvoid MCAsmStreamer::EmitSyntaxDirective() {
701309124Sdim  if (MAI->getAssemblerDialect() == 1) {
702309124Sdim    OS << "\t.intel_syntax noprefix";
703309124Sdim    EmitEOL();
704309124Sdim  }
705296417Sdim  // FIXME: Currently emit unprefix'ed registers.
706341825Sdim  // The intel_syntax directive has one optional argument
707296417Sdim  // with may have a value of prefix or noprefix.
708296417Sdim}
709296417Sdim
710208599Srdivackyvoid MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
711288943Sdim  OS << "\t.def\t ";
712288943Sdim  Symbol->print(OS, MAI);
713288943Sdim  OS << ';';
714208599Srdivacky  EmitEOL();
715208599Srdivacky}
716208599Srdivacky
717208599Srdivackyvoid MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
718208599Srdivacky  OS << "\t.scl\t" << StorageClass << ';';
719208599Srdivacky  EmitEOL();
720208599Srdivacky}
721208599Srdivacky
722208599Srdivackyvoid MCAsmStreamer::EmitCOFFSymbolType (int Type) {
723208599Srdivacky  OS << "\t.type\t" << Type << ';';
724208599Srdivacky  EmitEOL();
725208599Srdivacky}
726208599Srdivacky
727208599Srdivackyvoid MCAsmStreamer::EndCOFFSymbolDef() {
728208599Srdivacky  OS << "\t.endef";
729208599Srdivacky  EmitEOL();
730208599Srdivacky}
731208599Srdivacky
732288943Sdimvoid MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
733288943Sdim  OS << "\t.safeseh\t";
734288943Sdim  Symbol->print(OS, MAI);
735288943Sdim  EmitEOL();
736288943Sdim}
737288943Sdim
738341825Sdimvoid MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
739341825Sdim  OS << "\t.symidx\t";
740341825Sdim  Symbol->print(OS, MAI);
741341825Sdim  EmitEOL();
742341825Sdim}
743341825Sdim
744276479Sdimvoid MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
745288943Sdim  OS << "\t.secidx\t";
746288943Sdim  Symbol->print(OS, MAI);
747276479Sdim  EmitEOL();
748276479Sdim}
749276479Sdim
750314564Sdimvoid MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
751288943Sdim  OS << "\t.secrel32\t";
752288943Sdim  Symbol->print(OS, MAI);
753314564Sdim  if (Offset != 0)
754314564Sdim    OS << '+' << Offset;
755234353Sdim  EmitEOL();
756234353Sdim}
757234353Sdim
758341825Sdimvoid MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
759341825Sdim  OS << "\t.rva\t";
760341825Sdim  Symbol->print(OS, MAI);
761341825Sdim  if (Offset > 0)
762341825Sdim    OS << '+' << Offset;
763341825Sdim  else if (Offset < 0)
764341825Sdim    OS << '-' << -Offset;
765341825Sdim  EmitEOL();
766341825Sdim}
767341825Sdim
768360784Sdim// We need an XCOFF-specific version of this directive as the AIX syntax
769360784Sdim// requires a QualName argument identifying the csect name and storage mapping
770360784Sdim// class to appear before the alignment if we are specifying it.
771360784Sdimvoid MCAsmStreamer::EmitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
772360784Sdim                                               uint64_t Size,
773360784Sdim                                               MCSymbol *CsectSym,
774360784Sdim                                               unsigned ByteAlignment) {
775360784Sdim  assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
776360784Sdim         "We only support writing log base-2 alignment format with XCOFF.");
777360784Sdim  assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.");
778360784Sdim
779360784Sdim  OS << "\t.lcomm\t";
780360784Sdim  LabelSym->print(OS, MAI);
781360784Sdim  OS << ',' << Size << ',';
782360784Sdim  CsectSym->print(OS, MAI);
783360784Sdim  OS << ',' << Log2_32(ByteAlignment);
784360784Sdim
785360784Sdim  EmitEOL();
786360784Sdim}
787360784Sdim
788314564Sdimvoid MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
789261991Sdim  assert(MAI->hasDotTypeDotSizeDirective());
790288943Sdim  OS << "\t.size\t";
791288943Sdim  Symbol->print(OS, MAI);
792288943Sdim  OS << ", ";
793288943Sdim  Value->print(OS, MAI);
794309124Sdim  EmitEOL();
795203954Srdivacky}
796203954Srdivacky
797202878Srdivackyvoid MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
798198090Srdivacky                                     unsigned ByteAlignment) {
799288943Sdim  OS << "\t.comm\t";
800288943Sdim  Symbol->print(OS, MAI);
801288943Sdim  OS << ',' << Size;
802288943Sdim
803203954Srdivacky  if (ByteAlignment != 0) {
804261991Sdim    if (MAI->getCOMMDirectiveAlignmentIsInBytes())
805202878Srdivacky      OS << ',' << ByteAlignment;
806202878Srdivacky    else
807202878Srdivacky      OS << ',' << Log2_32(ByteAlignment);
808202878Srdivacky  }
809202878Srdivacky  EmitEOL();
810198090Srdivacky}
811198090Srdivacky
812226633Sdimvoid MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
813226633Sdim                                          unsigned ByteAlign) {
814288943Sdim  OS << "\t.lcomm\t";
815288943Sdim  Symbol->print(OS, MAI);
816288943Sdim  OS << ',' << Size;
817288943Sdim
818226633Sdim  if (ByteAlign > 1) {
819261991Sdim    switch (MAI->getLCOMMDirectiveAlignmentType()) {
820243830Sdim    case LCOMM::NoAlignment:
821243830Sdim      llvm_unreachable("alignment not supported on .lcomm!");
822243830Sdim    case LCOMM::ByteAlignment:
823243830Sdim      OS << ',' << ByteAlign;
824243830Sdim      break;
825243830Sdim    case LCOMM::Log2Alignment:
826243830Sdim      assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
827243830Sdim      OS << ',' << Log2_32(ByteAlign);
828243830Sdim      break;
829243830Sdim    }
830226633Sdim  }
831202878Srdivacky  EmitEOL();
832202878Srdivacky}
833202878Srdivacky
834288943Sdimvoid MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
835341825Sdim                                 uint64_t Size, unsigned ByteAlignment,
836341825Sdim                                 SMLoc Loc) {
837261991Sdim  if (Symbol)
838296417Sdim    AssignFragment(Symbol, &Section->getDummyFragment());
839261991Sdim
840198090Srdivacky  // Note: a .zerofill directive does not switch sections.
841198090Srdivacky  OS << ".zerofill ";
842218893Sdim
843341825Sdim  assert(Section->getVariant() == MCSection::SV_MachO &&
844341825Sdim         ".zerofill is a Mach-O specific directive");
845198090Srdivacky  // This is a mach-o specific directive.
846341825Sdim
847198090Srdivacky  const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
848198090Srdivacky  OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
849218893Sdim
850276479Sdim  if (Symbol) {
851288943Sdim    OS << ',';
852288943Sdim    Symbol->print(OS, MAI);
853288943Sdim    OS << ',' << Size;
854198090Srdivacky    if (ByteAlignment != 0)
855198090Srdivacky      OS << ',' << Log2_32(ByteAlignment);
856198090Srdivacky  }
857202878Srdivacky  EmitEOL();
858198090Srdivacky}
859198090Srdivacky
860208599Srdivacky// .tbss sym, size, align
861208599Srdivacky// This depends that the symbol has already been mangled from the original,
862208599Srdivacky// e.g. _a.
863288943Sdimvoid MCAsmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
864208599Srdivacky                                   uint64_t Size, unsigned ByteAlignment) {
865296417Sdim  AssignFragment(Symbol, &Section->getDummyFragment());
866261991Sdim
867276479Sdim  assert(Symbol && "Symbol shouldn't be NULL!");
868208599Srdivacky  // Instead of using the Section we'll just use the shortcut.
869341825Sdim
870341825Sdim  assert(Section->getVariant() == MCSection::SV_MachO &&
871341825Sdim         ".zerofill is a Mach-O specific directive");
872208599Srdivacky  // This is a mach-o specific directive and section.
873341825Sdim
874288943Sdim  OS << ".tbss ";
875288943Sdim  Symbol->print(OS, MAI);
876288943Sdim  OS << ", " << Size;
877218893Sdim
878208599Srdivacky  // Output align if we have it.  We default to 1 so don't bother printing
879208599Srdivacky  // that.
880208599Srdivacky  if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
881218893Sdim
882208599Srdivacky  EmitEOL();
883208599Srdivacky}
884208599Srdivacky
885202878Srdivackystatic inline char toOctal(int X) { return (X&7)+'0'; }
886202878Srdivacky
887203954Srdivackystatic void PrintQuotedString(StringRef Data, raw_ostream &OS) {
888203954Srdivacky  OS << '"';
889218893Sdim
890203954Srdivacky  for (unsigned i = 0, e = Data.size(); i != e; ++i) {
891203954Srdivacky    unsigned char C = Data[i];
892203954Srdivacky    if (C == '"' || C == '\\') {
893203954Srdivacky      OS << '\\' << (char)C;
894203954Srdivacky      continue;
895203954Srdivacky    }
896218893Sdim
897341825Sdim    if (isPrint((unsigned char)C)) {
898203954Srdivacky      OS << (char)C;
899203954Srdivacky      continue;
900203954Srdivacky    }
901218893Sdim
902203954Srdivacky    switch (C) {
903203954Srdivacky      case '\b': OS << "\\b"; break;
904203954Srdivacky      case '\f': OS << "\\f"; break;
905203954Srdivacky      case '\n': OS << "\\n"; break;
906203954Srdivacky      case '\r': OS << "\\r"; break;
907203954Srdivacky      case '\t': OS << "\\t"; break;
908203954Srdivacky      default:
909203954Srdivacky        OS << '\\';
910203954Srdivacky        OS << toOctal(C >> 6);
911203954Srdivacky        OS << toOctal(C >> 3);
912203954Srdivacky        OS << toOctal(C >> 0);
913203954Srdivacky        break;
914203954Srdivacky    }
915203954Srdivacky  }
916218893Sdim
917203954Srdivacky  OS << '"';
918203954Srdivacky}
919203954Srdivacky
920261991Sdimvoid MCAsmStreamer::EmitBytes(StringRef Data) {
921314564Sdim  assert(getCurrentSectionOnly() &&
922251662Sdim         "Cannot emit contents before setting section!");
923202878Srdivacky  if (Data.empty()) return;
924218893Sdim
925327952Sdim  // If only single byte is provided or no ascii or asciz directives is
926327952Sdim  // supported, emit as vector of 8bits data.
927327952Sdim  if (Data.size() == 1 ||
928327952Sdim      !(MAI->getAscizDirective() || MAI->getAsciiDirective())) {
929344779Sdim    if (MCTargetStreamer *TS = getTargetStreamer()) {
930344779Sdim      TS->emitRawBytes(Data);
931344779Sdim    } else {
932344779Sdim      const char *Directive = MAI->getData8bitsDirective();
933344779Sdim      for (const unsigned char C : Data.bytes()) {
934344779Sdim        OS << Directive << (unsigned)C;
935344779Sdim        EmitEOL();
936344779Sdim      }
937327952Sdim    }
938202878Srdivacky    return;
939202878Srdivacky  }
940202878Srdivacky
941202878Srdivacky  // If the data ends with 0 and the target supports .asciz, use it, otherwise
942202878Srdivacky  // use .ascii
943261991Sdim  if (MAI->getAscizDirective() && Data.back() == 0) {
944261991Sdim    OS << MAI->getAscizDirective();
945202878Srdivacky    Data = Data.substr(0, Data.size()-1);
946202878Srdivacky  } else {
947261991Sdim    OS << MAI->getAsciiDirective();
948202878Srdivacky  }
949202878Srdivacky
950203954Srdivacky  PrintQuotedString(Data, OS);
951202878Srdivacky  EmitEOL();
952195098Sed}
953195098Sed
954309124Sdimvoid MCAsmStreamer::EmitBinaryData(StringRef Data) {
955309124Sdim  // This is binary data. Print it in a grid of hex bytes for readability.
956309124Sdim  const size_t Cols = 4;
957309124Sdim  for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
958309124Sdim    size_t J = I, EJ = std::min(I + Cols, Data.size());
959309124Sdim    assert(EJ > 0);
960309124Sdim    OS << MAI->getData8bitsDirective();
961309124Sdim    for (; J < EJ - 1; ++J)
962309124Sdim      OS << format("0x%02x", uint8_t(Data[J])) << ", ";
963309124Sdim    OS << format("0x%02x", uint8_t(Data[J]));
964309124Sdim    EmitEOL();
965309124Sdim  }
966309124Sdim}
967309124Sdim
968261991Sdimvoid MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
969288943Sdim  EmitValue(MCConstantExpr::create(Value, getContext()), Size);
970218893Sdim}
971218893Sdim
972353358Sdimvoid MCAsmStreamer::EmitIntValueInHex(uint64_t Value, unsigned Size) {
973353358Sdim  EmitValue(MCConstantExpr::create(Value, getContext(), true), Size);
974353358Sdim}
975353358Sdim
976276479Sdimvoid MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
977296417Sdim                                  SMLoc Loc) {
978276479Sdim  assert(Size <= 8 && "Invalid size");
979314564Sdim  assert(getCurrentSectionOnly() &&
980251662Sdim         "Cannot emit contents before setting section!");
981276479Sdim  const char *Directive = nullptr;
982195098Sed  switch (Size) {
983202878Srdivacky  default: break;
984261991Sdim  case 1: Directive = MAI->getData8bitsDirective();  break;
985261991Sdim  case 2: Directive = MAI->getData16bitsDirective(); break;
986261991Sdim  case 4: Directive = MAI->getData32bitsDirective(); break;
987276479Sdim  case 8: Directive = MAI->getData64bitsDirective(); break;
988276479Sdim  }
989276479Sdim
990276479Sdim  if (!Directive) {
991218893Sdim    int64_t IntValue;
992288943Sdim    if (!Value->evaluateAsAbsolute(IntValue))
993218893Sdim      report_fatal_error("Don't know how to emit this value.");
994276479Sdim
995276479Sdim    // We couldn't handle the requested integer size so we fallback by breaking
996309124Sdim    // the request down into several, smaller, integers.
997309124Sdim    // Since sizes greater or equal to "Size" are invalid, we use the greatest
998309124Sdim    // power of 2 that is less than "Size" as our largest piece of granularity.
999276479Sdim    bool IsLittleEndian = MAI->isLittleEndian();
1000276479Sdim    for (unsigned Emitted = 0; Emitted != Size;) {
1001276479Sdim      unsigned Remaining = Size - Emitted;
1002276479Sdim      // The size of our partial emission must be a power of two less than
1003309124Sdim      // Size.
1004309124Sdim      unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
1005276479Sdim      // Calculate the byte offset of our partial emission taking into account
1006276479Sdim      // the endianness of the target.
1007276479Sdim      unsigned ByteOffset =
1008276479Sdim          IsLittleEndian ? Emitted : (Remaining - EmissionSize);
1009276479Sdim      uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
1010276479Sdim      // We truncate our partial emission to fit within the bounds of the
1011276479Sdim      // emission domain.  This produces nicer output and silences potential
1012276479Sdim      // truncation warnings when round tripping through another assembler.
1013280031Sdim      uint64_t Shift = 64 - EmissionSize * 8;
1014280031Sdim      assert(Shift < static_cast<uint64_t>(
1015280031Sdim                         std::numeric_limits<unsigned long long>::digits) &&
1016280031Sdim             "undefined behavior");
1017280031Sdim      ValueToEmit &= ~0ULL >> Shift;
1018276479Sdim      EmitIntValue(ValueToEmit, EmissionSize);
1019276479Sdim      Emitted += EmissionSize;
1020202878Srdivacky    }
1021202878Srdivacky    return;
1022195098Sed  }
1023218893Sdim
1024202878Srdivacky  assert(Directive && "Invalid size for machine code value!");
1025288943Sdim  OS << Directive;
1026327952Sdim  if (MCTargetStreamer *TS = getTargetStreamer()) {
1027327952Sdim    TS->emitValue(Value);
1028327952Sdim  } else {
1029327952Sdim    Value->print(OS, MAI);
1030327952Sdim    EmitEOL();
1031327952Sdim  }
1032202878Srdivacky}
1033195098Sed
1034221345Sdimvoid MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
1035218893Sdim  int64_t IntValue;
1036288943Sdim  if (Value->evaluateAsAbsolute(IntValue)) {
1037221345Sdim    EmitULEB128IntValue(IntValue);
1038218893Sdim    return;
1039202878Srdivacky  }
1040341825Sdim  OS << "\t.uleb128 ";
1041288943Sdim  Value->print(OS, MAI);
1042202878Srdivacky  EmitEOL();
1043195098Sed}
1044195098Sed
1045221345Sdimvoid MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
1046218893Sdim  int64_t IntValue;
1047288943Sdim  if (Value->evaluateAsAbsolute(IntValue)) {
1048221345Sdim    EmitSLEB128IntValue(IntValue);
1049218893Sdim    return;
1050218893Sdim  }
1051341825Sdim  OS << "\t.sleb128 ";
1052288943Sdim  Value->print(OS, MAI);
1053218893Sdim  EmitEOL();
1054218893Sdim}
1055218893Sdim
1056314564Sdimvoid MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) {
1057314564Sdim  assert(MAI->getDTPRel64Directive() != nullptr);
1058314564Sdim  OS << MAI->getDTPRel64Directive();
1059314564Sdim  Value->print(OS, MAI);
1060314564Sdim  EmitEOL();
1061314564Sdim}
1062314564Sdim
1063314564Sdimvoid MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) {
1064314564Sdim  assert(MAI->getDTPRel32Directive() != nullptr);
1065314564Sdim  OS << MAI->getDTPRel32Directive();
1066314564Sdim  Value->print(OS, MAI);
1067314564Sdim  EmitEOL();
1068314564Sdim}
1069314564Sdim
1070314564Sdimvoid MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) {
1071314564Sdim  assert(MAI->getTPRel64Directive() != nullptr);
1072314564Sdim  OS << MAI->getTPRel64Directive();
1073314564Sdim  Value->print(OS, MAI);
1074314564Sdim  EmitEOL();
1075314564Sdim}
1076314564Sdim
1077314564Sdimvoid MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) {
1078314564Sdim  assert(MAI->getTPRel32Directive() != nullptr);
1079314564Sdim  OS << MAI->getTPRel32Directive();
1080314564Sdim  Value->print(OS, MAI);
1081314564Sdim  EmitEOL();
1082314564Sdim}
1083314564Sdim
1084234353Sdimvoid MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
1085276479Sdim  assert(MAI->getGPRel64Directive() != nullptr);
1086288943Sdim  OS << MAI->getGPRel64Directive();
1087288943Sdim  Value->print(OS, MAI);
1088234353Sdim  EmitEOL();
1089234353Sdim}
1090234353Sdim
1091203954Srdivackyvoid MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
1092276479Sdim  assert(MAI->getGPRel32Directive() != nullptr);
1093288943Sdim  OS << MAI->getGPRel32Directive();
1094288943Sdim  Value->print(OS, MAI);
1095203954Srdivacky  EmitEOL();
1096203954Srdivacky}
1097203954Srdivacky
1098309124Sdimvoid MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
1099309124Sdim                             SMLoc Loc) {
1100328594Semaste  int64_t IntNumBytes;
1101328594Semaste  if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0)
1102328594Semaste    return;
1103328594Semaste
1104261991Sdim  if (const char *ZeroDirective = MAI->getZeroDirective()) {
1105309124Sdim    // FIXME: Emit location directives
1106309124Sdim    OS << ZeroDirective;
1107309124Sdim    NumBytes.print(OS, MAI);
1108261991Sdim    if (FillValue != 0)
1109261991Sdim      OS << ',' << (int)FillValue;
1110261991Sdim    EmitEOL();
1111261991Sdim    return;
1112261991Sdim  }
1113202878Srdivacky
1114309124Sdim  MCStreamer::emitFill(NumBytes, FillValue);
1115202878Srdivacky}
1116202878Srdivacky
1117309124Sdimvoid MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
1118309124Sdim                             int64_t Expr, SMLoc Loc) {
1119309124Sdim  // FIXME: Emit location directives
1120309124Sdim  OS << "\t.fill\t";
1121309124Sdim  NumValues.print(OS, MAI);
1122309124Sdim  OS << ", " << Size << ", 0x";
1123309124Sdim  OS.write_hex(truncateToSize(Expr, 4));
1124309124Sdim  EmitEOL();
1125309124Sdim}
1126309124Sdim
1127195098Sedvoid MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
1128195098Sed                                         unsigned ValueSize,
1129195098Sed                                         unsigned MaxBytesToEmit) {
1130360784Sdim  if (MAI->useDotAlignForAlignment()) {
1131360784Sdim    if (!isPowerOf2_32(ByteAlignment))
1132360784Sdim      report_fatal_error("Only power-of-two alignments are supported "
1133360784Sdim                         "with .align.");
1134360784Sdim    OS << "\t.align\t";
1135360784Sdim    OS << Log2_32(ByteAlignment);
1136360784Sdim    EmitEOL();
1137360784Sdim    return;
1138360784Sdim  }
1139360784Sdim
1140198090Srdivacky  // Some assemblers don't support non-power of two alignments, so we always
1141198090Srdivacky  // emit alignments as a power of two if possible.
1142198090Srdivacky  if (isPowerOf2_32(ByteAlignment)) {
1143198090Srdivacky    switch (ValueSize) {
1144276479Sdim    default:
1145276479Sdim      llvm_unreachable("Invalid size for machine code value!");
1146276479Sdim    case 1:
1147309124Sdim      OS << "\t.p2align\t";
1148276479Sdim      break;
1149276479Sdim    case 2:
1150276479Sdim      OS << ".p2alignw ";
1151276479Sdim      break;
1152276479Sdim    case 4:
1153276479Sdim      OS << ".p2alignl ";
1154276479Sdim      break;
1155276479Sdim    case 8:
1156276479Sdim      llvm_unreachable("Unsupported alignment size!");
1157198090Srdivacky    }
1158218893Sdim
1159309124Sdim    OS << Log2_32(ByteAlignment);
1160195098Sed
1161198090Srdivacky    if (Value || MaxBytesToEmit) {
1162198090Srdivacky      OS << ", 0x";
1163198090Srdivacky      OS.write_hex(truncateToSize(Value, ValueSize));
1164198090Srdivacky
1165218893Sdim      if (MaxBytesToEmit)
1166198090Srdivacky        OS << ", " << MaxBytesToEmit;
1167198090Srdivacky    }
1168202878Srdivacky    EmitEOL();
1169198090Srdivacky    return;
1170198090Srdivacky  }
1171218893Sdim
1172198090Srdivacky  // Non-power of two alignment.  This is not widely supported by assemblers.
1173198090Srdivacky  // FIXME: Parameterize this based on MAI.
1174195098Sed  switch (ValueSize) {
1175198090Srdivacky  default: llvm_unreachable("Invalid size for machine code value!");
1176198090Srdivacky  case 1: OS << ".balign";  break;
1177198090Srdivacky  case 2: OS << ".balignw"; break;
1178198090Srdivacky  case 4: OS << ".balignl"; break;
1179198090Srdivacky  case 8: llvm_unreachable("Unsupported alignment size!");
1180195098Sed  }
1181195098Sed
1182198090Srdivacky  OS << ' ' << ByteAlignment;
1183195098Sed  OS << ", " << truncateToSize(Value, ValueSize);
1184218893Sdim  if (MaxBytesToEmit)
1185195098Sed    OS << ", " << MaxBytesToEmit;
1186202878Srdivacky  EmitEOL();
1187195098Sed}
1188195098Sed
1189204642Srdivackyvoid MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
1190204642Srdivacky                                      unsigned MaxBytesToEmit) {
1191204642Srdivacky  // Emit with a text fill value.
1192261991Sdim  EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
1193204642Srdivacky                       1, MaxBytesToEmit);
1194204642Srdivacky}
1195204642Srdivacky
1196296417Sdimvoid MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
1197314564Sdim                                      unsigned char Value,
1198314564Sdim                                      SMLoc Loc) {
1199195098Sed  // FIXME: Verify that Offset is associated with the current section.
1200288943Sdim  OS << ".org ";
1201288943Sdim  Offset->print(OS, MAI);
1202288943Sdim  OS << ", " << (unsigned)Value;
1203202878Srdivacky  EmitEOL();
1204195098Sed}
1205195098Sed
1206203954Srdivackyvoid MCAsmStreamer::EmitFileDirective(StringRef Filename) {
1207261991Sdim  assert(MAI->hasSingleParameterDotFile());
1208203954Srdivacky  OS << "\t.file\t";
1209203954Srdivacky  PrintQuotedString(Filename, OS);
1210203954Srdivacky  EmitEOL();
1211203954Srdivacky}
1212198090Srdivacky
1213341825Sdimstatic void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
1214341825Sdim                                    StringRef Filename,
1215353358Sdim                                    Optional<MD5::MD5Result> Checksum,
1216341825Sdim                                    Optional<StringRef> Source,
1217341825Sdim                                    bool UseDwarfDirectory,
1218341825Sdim                                    raw_svector_ostream &OS) {
1219276479Sdim  SmallString<128> FullPathName;
1220276479Sdim
1221234353Sdim  if (!UseDwarfDirectory && !Directory.empty()) {
1222234353Sdim    if (sys::path::is_absolute(Filename))
1223276479Sdim      Directory = "";
1224276479Sdim    else {
1225276479Sdim      FullPathName = Directory;
1226276479Sdim      sys::path::append(FullPathName, Filename);
1227276479Sdim      Directory = "";
1228276479Sdim      Filename = FullPathName;
1229276479Sdim    }
1230276479Sdim  }
1231234353Sdim
1232341825Sdim  OS << "\t.file\t" << FileNo << ' ';
1233341825Sdim  if (!Directory.empty()) {
1234341825Sdim    PrintQuotedString(Directory, OS);
1235341825Sdim    OS << ' ';
1236341825Sdim  }
1237341825Sdim  PrintQuotedString(Filename, OS);
1238341825Sdim  if (Checksum)
1239341825Sdim    OS << " md5 0x" << Checksum->digest();
1240341825Sdim  if (Source) {
1241341825Sdim    OS << " source ";
1242341825Sdim    PrintQuotedString(*Source, OS);
1243341825Sdim  }
1244341825Sdim}
1245341825Sdim
1246341825SdimExpected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
1247341825Sdim    unsigned FileNo, StringRef Directory, StringRef Filename,
1248353358Sdim    Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) {
1249341825Sdim  assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
1250341825Sdim
1251341825Sdim  MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
1252341825Sdim  unsigned NumFiles = Table.getMCDwarfFiles().size();
1253341825Sdim  Expected<unsigned> FileNoOrErr =
1254353358Sdim      Table.tryGetFile(Directory, Filename, Checksum, Source,
1255353358Sdim                       getContext().getDwarfVersion(), FileNo);
1256341825Sdim  if (!FileNoOrErr)
1257341825Sdim    return FileNoOrErr.takeError();
1258341825Sdim  FileNo = FileNoOrErr.get();
1259341825Sdim  if (NumFiles == Table.getMCDwarfFiles().size())
1260341825Sdim    return FileNo;
1261341825Sdim
1262327952Sdim  SmallString<128> Str;
1263327952Sdim  raw_svector_ostream OS1(Str);
1264341825Sdim  printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
1265341825Sdim                          UseDwarfDirectory, OS1);
1266341825Sdim
1267341825Sdim  if (MCTargetStreamer *TS = getTargetStreamer())
1268327952Sdim    TS->emitDwarfFileDirective(OS1.str());
1269341825Sdim  else
1270327952Sdim    EmitRawText(OS1.str());
1271234353Sdim
1272276479Sdim  return FileNo;
1273218893Sdim}
1274218893Sdim
1275341825Sdimvoid MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
1276341825Sdim                                            StringRef Filename,
1277353358Sdim                                            Optional<MD5::MD5Result> Checksum,
1278341825Sdim                                            Optional<StringRef> Source,
1279341825Sdim                                            unsigned CUID) {
1280341825Sdim  assert(CUID == 0);
1281341825Sdim  // .file 0 is new for DWARF v5.
1282341825Sdim  if (getContext().getDwarfVersion() < 5)
1283341825Sdim    return;
1284341825Sdim  // Inform MCDwarf about the root file.
1285341825Sdim  getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
1286341825Sdim                                      Source);
1287341825Sdim
1288341825Sdim  SmallString<128> Str;
1289341825Sdim  raw_svector_ostream OS1(Str);
1290341825Sdim  printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
1291341825Sdim                          UseDwarfDirectory, OS1);
1292341825Sdim
1293341825Sdim  if (MCTargetStreamer *TS = getTargetStreamer())
1294341825Sdim    TS->emitDwarfFileDirective(OS1.str());
1295341825Sdim  else
1296341825Sdim    EmitRawText(OS1.str());
1297341825Sdim}
1298341825Sdim
1299218893Sdimvoid MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
1300218893Sdim                                          unsigned Column, unsigned Flags,
1301218893Sdim                                          unsigned Isa,
1302221345Sdim                                          unsigned Discriminator,
1303221345Sdim                                          StringRef FileName) {
1304218893Sdim  OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
1305341825Sdim  if (MAI->supportsExtendedDwarfLocDirective()) {
1306341825Sdim    if (Flags & DWARF2_FLAG_BASIC_BLOCK)
1307341825Sdim      OS << " basic_block";
1308341825Sdim    if (Flags & DWARF2_FLAG_PROLOGUE_END)
1309341825Sdim      OS << " prologue_end";
1310341825Sdim    if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
1311341825Sdim      OS << " epilogue_begin";
1312218893Sdim
1313341825Sdim    unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
1314341825Sdim    if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
1315341825Sdim      OS << " is_stmt ";
1316218893Sdim
1317341825Sdim      if (Flags & DWARF2_FLAG_IS_STMT)
1318341825Sdim        OS << "1";
1319341825Sdim      else
1320341825Sdim        OS << "0";
1321341825Sdim    }
1322341825Sdim
1323341825Sdim    if (Isa)
1324341825Sdim      OS << " isa " << Isa;
1325341825Sdim    if (Discriminator)
1326341825Sdim      OS << " discriminator " << Discriminator;
1327218893Sdim  }
1328218893Sdim
1329221345Sdim  if (IsVerboseAsm) {
1330261991Sdim    OS.PadToColumn(MAI->getCommentColumn());
1331261991Sdim    OS << MAI->getCommentString() << ' ' << FileName << ':'
1332221345Sdim       << Line << ':' << Column;
1333221345Sdim  }
1334203954Srdivacky  EmitEOL();
1335280031Sdim  this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
1336280031Sdim                                          Isa, Discriminator, FileName);
1337203954Srdivacky}
1338203954Srdivacky
1339276479SdimMCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
1340276479Sdim  // Always use the zeroth line table, since asm syntax only supports one line
1341276479Sdim  // table for now.
1342276479Sdim  return MCStreamer::getDwarfLineTableSymbol(0);
1343276479Sdim}
1344276479Sdim
1345327952Sdimbool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
1346327952Sdim                                        ArrayRef<uint8_t> Checksum,
1347327952Sdim                                        unsigned ChecksumKind) {
1348327952Sdim  if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1349327952Sdim                                           ChecksumKind))
1350314564Sdim    return false;
1351309124Sdim
1352309124Sdim  OS << "\t.cv_file\t" << FileNo << ' ';
1353327952Sdim  PrintQuotedString(Filename, OS);
1354309124Sdim
1355327952Sdim  if (!ChecksumKind) {
1356327952Sdim    EmitEOL();
1357327952Sdim    return true;
1358327952Sdim  }
1359327952Sdim
1360327952Sdim  OS << ' ';
1361327952Sdim  PrintQuotedString(toHex(Checksum), OS);
1362327952Sdim  OS << ' ' << ChecksumKind;
1363327952Sdim
1364309124Sdim  EmitEOL();
1365314564Sdim  return true;
1366314564Sdim}
1367309124Sdim
1368314564Sdimbool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
1369314564Sdim  OS << "\t.cv_func_id " << FuncId << '\n';
1370314564Sdim  return MCStreamer::EmitCVFuncIdDirective(FuncId);
1371309124Sdim}
1372309124Sdim
1373314564Sdimbool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
1374314564Sdim                                                unsigned IAFunc,
1375314564Sdim                                                unsigned IAFile,
1376314564Sdim                                                unsigned IALine, unsigned IACol,
1377314564Sdim                                                SMLoc Loc) {
1378314564Sdim  OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
1379314564Sdim     << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
1380314564Sdim  return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
1381314564Sdim                                                 IALine, IACol, Loc);
1382314564Sdim}
1383314564Sdim
1384309124Sdimvoid MCAsmStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
1385309124Sdim                                       unsigned Line, unsigned Column,
1386309124Sdim                                       bool PrologueEnd, bool IsStmt,
1387314564Sdim                                       StringRef FileName, SMLoc Loc) {
1388344779Sdim  // Validate the directive.
1389344779Sdim  if (!checkCVLocSection(FunctionId, FileNo, Loc))
1390344779Sdim    return;
1391344779Sdim
1392309124Sdim  OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
1393309124Sdim     << Column;
1394309124Sdim  if (PrologueEnd)
1395309124Sdim    OS << " prologue_end";
1396309124Sdim
1397344779Sdim  if (IsStmt)
1398344779Sdim    OS << " is_stmt 1";
1399309124Sdim
1400309124Sdim  if (IsVerboseAsm) {
1401309124Sdim    OS.PadToColumn(MAI->getCommentColumn());
1402314564Sdim    OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
1403314564Sdim       << Column;
1404309124Sdim  }
1405309124Sdim  EmitEOL();
1406309124Sdim}
1407309124Sdim
1408309124Sdimvoid MCAsmStreamer::EmitCVLinetableDirective(unsigned FunctionId,
1409309124Sdim                                             const MCSymbol *FnStart,
1410309124Sdim                                             const MCSymbol *FnEnd) {
1411309124Sdim  OS << "\t.cv_linetable\t" << FunctionId << ", ";
1412309124Sdim  FnStart->print(OS, MAI);
1413309124Sdim  OS << ", ";
1414309124Sdim  FnEnd->print(OS, MAI);
1415309124Sdim  EmitEOL();
1416309124Sdim  this->MCStreamer::EmitCVLinetableDirective(FunctionId, FnStart, FnEnd);
1417309124Sdim}
1418309124Sdim
1419314564Sdimvoid MCAsmStreamer::EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
1420314564Sdim                                                   unsigned SourceFileId,
1421314564Sdim                                                   unsigned SourceLineNum,
1422314564Sdim                                                   const MCSymbol *FnStartSym,
1423314564Sdim                                                   const MCSymbol *FnEndSym) {
1424309124Sdim  OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
1425309124Sdim     << ' ' << SourceLineNum << ' ';
1426309124Sdim  FnStartSym->print(OS, MAI);
1427309124Sdim  OS << ' ';
1428309124Sdim  FnEndSym->print(OS, MAI);
1429309124Sdim  EmitEOL();
1430309124Sdim  this->MCStreamer::EmitCVInlineLinetableDirective(
1431314564Sdim      PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
1432309124Sdim}
1433309124Sdim
1434360784Sdimvoid MCAsmStreamer::PrintCVDefRangePrefix(
1435360784Sdim    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
1436309124Sdim  OS << "\t.cv_def_range\t";
1437309124Sdim  for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
1438309124Sdim    OS << ' ';
1439309124Sdim    Range.first->print(OS, MAI);
1440309124Sdim    OS << ' ';
1441309124Sdim    Range.second->print(OS, MAI);
1442309124Sdim  }
1443360784Sdim}
1444360784Sdim
1445360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective(
1446360784Sdim    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1447360784Sdim    codeview::DefRangeRegisterRelHeader DRHdr) {
1448360784Sdim  PrintCVDefRangePrefix(Ranges);
1449360784Sdim  OS << ", reg_rel, ";
1450360784Sdim  OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
1451360784Sdim     << DRHdr.BasePointerOffset;
1452309124Sdim  EmitEOL();
1453309124Sdim}
1454309124Sdim
1455360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective(
1456360784Sdim    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1457360784Sdim    codeview::DefRangeSubfieldRegisterHeader DRHdr) {
1458360784Sdim  PrintCVDefRangePrefix(Ranges);
1459360784Sdim  OS << ", subfield_reg, ";
1460360784Sdim  OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
1461360784Sdim  EmitEOL();
1462360784Sdim}
1463360784Sdim
1464360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective(
1465360784Sdim    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1466360784Sdim    codeview::DefRangeRegisterHeader DRHdr) {
1467360784Sdim  PrintCVDefRangePrefix(Ranges);
1468360784Sdim  OS << ", reg, ";
1469360784Sdim  OS << DRHdr.Register;
1470360784Sdim  EmitEOL();
1471360784Sdim}
1472360784Sdim
1473360784Sdimvoid MCAsmStreamer::EmitCVDefRangeDirective(
1474360784Sdim    ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1475360784Sdim    codeview::DefRangeFramePointerRelHeader DRHdr) {
1476360784Sdim  PrintCVDefRangePrefix(Ranges);
1477360784Sdim  OS << ", frame_ptr_rel, ";
1478360784Sdim  OS << DRHdr.Offset;
1479360784Sdim  EmitEOL();
1480360784Sdim}
1481360784Sdim
1482309124Sdimvoid MCAsmStreamer::EmitCVStringTableDirective() {
1483309124Sdim  OS << "\t.cv_stringtable";
1484309124Sdim  EmitEOL();
1485309124Sdim}
1486309124Sdim
1487309124Sdimvoid MCAsmStreamer::EmitCVFileChecksumsDirective() {
1488309124Sdim  OS << "\t.cv_filechecksums";
1489309124Sdim  EmitEOL();
1490309124Sdim}
1491309124Sdim
1492327952Sdimvoid MCAsmStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
1493327952Sdim  OS << "\t.cv_filechecksumoffset\t" << FileNo;
1494327952Sdim  EmitEOL();
1495327952Sdim}
1496327952Sdim
1497327952Sdimvoid MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
1498327952Sdim  OS << "\t.cv_fpo_data\t";
1499327952Sdim  ProcSym->print(OS, MAI);
1500327952Sdim  EmitEOL();
1501327952Sdim}
1502327952Sdim
1503261991Sdimvoid MCAsmStreamer::EmitIdent(StringRef IdentString) {
1504261991Sdim  assert(MAI->hasIdentDirective() && ".ident directive not supported");
1505261991Sdim  OS << "\t.ident\t";
1506261991Sdim  PrintQuotedString(IdentString, OS);
1507261991Sdim  EmitEOL();
1508261991Sdim}
1509261991Sdim
1510223017Sdimvoid MCAsmStreamer::EmitCFISections(bool EH, bool Debug) {
1511223017Sdim  MCStreamer::EmitCFISections(EH, Debug);
1512223017Sdim  OS << "\t.cfi_sections ";
1513223017Sdim  if (EH) {
1514223017Sdim    OS << ".eh_frame";
1515223017Sdim    if (Debug)
1516223017Sdim      OS << ", .debug_frame";
1517223017Sdim  } else if (Debug) {
1518223017Sdim    OS << ".debug_frame";
1519223017Sdim  }
1520223017Sdim
1521223017Sdim  EmitEOL();
1522223017Sdim}
1523223017Sdim
1524234353Sdimvoid MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
1525218893Sdim  OS << "\t.cfi_startproc";
1526276479Sdim  if (Frame.IsSimple)
1527276479Sdim    OS << " simple";
1528218893Sdim  EmitEOL();
1529218893Sdim}
1530218893Sdim
1531234353Sdimvoid MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
1532276479Sdim  MCStreamer::EmitCFIEndProcImpl(Frame);
1533218893Sdim  OS << "\t.cfi_endproc";
1534218893Sdim  EmitEOL();
1535221345Sdim}
1536218893Sdim
1537223017Sdimvoid MCAsmStreamer::EmitRegisterName(int64_t Register) {
1538288943Sdim  if (!MAI->useDwarfRegNumForCFI()) {
1539327952Sdim    // User .cfi_* directives can use arbitrary DWARF register numbers, not
1540327952Sdim    // just ones that map to LLVM register numbers and have known names.
1541327952Sdim    // Fall back to using the original number directly if no name is known.
1542261991Sdim    const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1543360784Sdim    if (Optional<unsigned> LLVMRegister = MRI->getLLVMRegNum(Register, true)) {
1544360784Sdim      InstPrinter->printRegName(OS, *LLVMRegister);
1545327952Sdim      return;
1546327952Sdim    }
1547223017Sdim  }
1548327952Sdim  OS << Register;
1549223017Sdim}
1550223017Sdim
1551221345Sdimvoid MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
1552221345Sdim  MCStreamer::EmitCFIDefCfa(Register, Offset);
1553223017Sdim  OS << "\t.cfi_def_cfa ";
1554223017Sdim  EmitRegisterName(Register);
1555223017Sdim  OS << ", " << Offset;
1556221345Sdim  EmitEOL();
1557218893Sdim}
1558218893Sdim
1559221345Sdimvoid MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
1560221345Sdim  MCStreamer::EmitCFIDefCfaOffset(Offset);
1561218893Sdim  OS << "\t.cfi_def_cfa_offset " << Offset;
1562218893Sdim  EmitEOL();
1563218893Sdim}
1564218893Sdim
1565296417Sdimstatic void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
1566296417Sdim  OS << "\t.cfi_escape ";
1567296417Sdim  if (!Values.empty()) {
1568296417Sdim    size_t e = Values.size() - 1;
1569296417Sdim    for (size_t i = 0; i < e; ++i)
1570296417Sdim      OS << format("0x%02x", uint8_t(Values[i])) << ", ";
1571296417Sdim    OS << format("0x%02x", uint8_t(Values[e]));
1572296417Sdim  }
1573296417Sdim}
1574296417Sdim
1575296417Sdimvoid MCAsmStreamer::EmitCFIEscape(StringRef Values) {
1576296417Sdim  MCStreamer::EmitCFIEscape(Values);
1577296417Sdim  PrintCFIEscape(OS, Values);
1578296417Sdim  EmitEOL();
1579296417Sdim}
1580296417Sdim
1581296417Sdimvoid MCAsmStreamer::EmitCFIGnuArgsSize(int64_t Size) {
1582296417Sdim  MCStreamer::EmitCFIGnuArgsSize(Size);
1583309124Sdim
1584296417Sdim  uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
1585296417Sdim  unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
1586309124Sdim
1587296417Sdim  PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
1588296417Sdim  EmitEOL();
1589296417Sdim}
1590296417Sdim
1591221345Sdimvoid MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) {
1592221345Sdim  MCStreamer::EmitCFIDefCfaRegister(Register);
1593223017Sdim  OS << "\t.cfi_def_cfa_register ";
1594223017Sdim  EmitRegisterName(Register);
1595218893Sdim  EmitEOL();
1596218893Sdim}
1597218893Sdim
1598221345Sdimvoid MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
1599221345Sdim  this->MCStreamer::EmitCFIOffset(Register, Offset);
1600223017Sdim  OS << "\t.cfi_offset ";
1601223017Sdim  EmitRegisterName(Register);
1602223017Sdim  OS << ", " << Offset;
1603218893Sdim  EmitEOL();
1604218893Sdim}
1605218893Sdim
1606221345Sdimvoid MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
1607218893Sdim                                       unsigned Encoding) {
1608221345Sdim  MCStreamer::EmitCFIPersonality(Sym, Encoding);
1609288943Sdim  OS << "\t.cfi_personality " << Encoding << ", ";
1610288943Sdim  Sym->print(OS, MAI);
1611218893Sdim  EmitEOL();
1612218893Sdim}
1613218893Sdim
1614221345Sdimvoid MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
1615221345Sdim  MCStreamer::EmitCFILsda(Sym, Encoding);
1616288943Sdim  OS << "\t.cfi_lsda " << Encoding << ", ";
1617288943Sdim  Sym->print(OS, MAI);
1618218893Sdim  EmitEOL();
1619221345Sdim}
1620218893Sdim
1621221345Sdimvoid MCAsmStreamer::EmitCFIRememberState() {
1622221345Sdim  MCStreamer::EmitCFIRememberState();
1623221345Sdim  OS << "\t.cfi_remember_state";
1624221345Sdim  EmitEOL();
1625218893Sdim}
1626218893Sdim
1627221345Sdimvoid MCAsmStreamer::EmitCFIRestoreState() {
1628221345Sdim  MCStreamer::EmitCFIRestoreState();
1629221345Sdim  OS << "\t.cfi_restore_state";
1630221345Sdim  EmitEOL();
1631221345Sdim}
1632221345Sdim
1633327952Sdimvoid MCAsmStreamer::EmitCFIRestore(int64_t Register) {
1634327952Sdim  MCStreamer::EmitCFIRestore(Register);
1635327952Sdim  OS << "\t.cfi_restore ";
1636327952Sdim  EmitRegisterName(Register);
1637327952Sdim  EmitEOL();
1638327952Sdim}
1639327952Sdim
1640221345Sdimvoid MCAsmStreamer::EmitCFISameValue(int64_t Register) {
1641221345Sdim  MCStreamer::EmitCFISameValue(Register);
1642223017Sdim  OS << "\t.cfi_same_value ";
1643223017Sdim  EmitRegisterName(Register);
1644221345Sdim  EmitEOL();
1645221345Sdim}
1646221345Sdim
1647221345Sdimvoid MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
1648221345Sdim  MCStreamer::EmitCFIRelOffset(Register, Offset);
1649223017Sdim  OS << "\t.cfi_rel_offset ";
1650223017Sdim  EmitRegisterName(Register);
1651223017Sdim  OS << ", " << Offset;
1652221345Sdim  EmitEOL();
1653221345Sdim}
1654221345Sdim
1655221345Sdimvoid MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
1656221345Sdim  MCStreamer::EmitCFIAdjustCfaOffset(Adjustment);
1657221345Sdim  OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
1658221345Sdim  EmitEOL();
1659221345Sdim}
1660221345Sdim
1661234353Sdimvoid MCAsmStreamer::EmitCFISignalFrame() {
1662234353Sdim  MCStreamer::EmitCFISignalFrame();
1663239462Sdim  OS << "\t.cfi_signal_frame";
1664234353Sdim  EmitEOL();
1665234353Sdim}
1666234353Sdim
1667249423Sdimvoid MCAsmStreamer::EmitCFIUndefined(int64_t Register) {
1668249423Sdim  MCStreamer::EmitCFIUndefined(Register);
1669249423Sdim  OS << "\t.cfi_undefined " << Register;
1670249423Sdim  EmitEOL();
1671249423Sdim}
1672249423Sdim
1673249423Sdimvoid MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
1674249423Sdim  MCStreamer::EmitCFIRegister(Register1, Register2);
1675249423Sdim  OS << "\t.cfi_register " << Register1 << ", " << Register2;
1676249423Sdim  EmitEOL();
1677249423Sdim}
1678249423Sdim
1679261991Sdimvoid MCAsmStreamer::EmitCFIWindowSave() {
1680261991Sdim  MCStreamer::EmitCFIWindowSave();
1681261991Sdim  OS << "\t.cfi_window_save";
1682261991Sdim  EmitEOL();
1683261991Sdim}
1684261991Sdim
1685344779Sdimvoid MCAsmStreamer::EmitCFINegateRAState() {
1686344779Sdim  MCStreamer::EmitCFINegateRAState();
1687344779Sdim  OS << "\t.cfi_negate_ra_state";
1688344779Sdim  EmitEOL();
1689344779Sdim}
1690344779Sdim
1691327952Sdimvoid MCAsmStreamer::EmitCFIReturnColumn(int64_t Register) {
1692327952Sdim  MCStreamer::EmitCFIReturnColumn(Register);
1693327952Sdim  OS << "\t.cfi_return_column " << Register;
1694327952Sdim  EmitEOL();
1695327952Sdim}
1696223017Sdim
1697344779Sdimvoid MCAsmStreamer::EmitCFIBKeyFrame() {
1698344779Sdim  MCStreamer::EmitCFIBKeyFrame();
1699344779Sdim  OS << "\t.cfi_b_key_frame";
1700344779Sdim  EmitEOL();
1701344779Sdim}
1702344779Sdim
1703327952Sdimvoid MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
1704327952Sdim  MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
1705327952Sdim
1706288943Sdim  OS << ".seh_proc ";
1707288943Sdim  Symbol->print(OS, MAI);
1708223017Sdim  EmitEOL();
1709223017Sdim}
1710223017Sdim
1711327952Sdimvoid MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
1712327952Sdim  MCStreamer::EmitWinCFIEndProc(Loc);
1713223017Sdim
1714223017Sdim  OS << "\t.seh_endproc";
1715223017Sdim  EmitEOL();
1716223017Sdim}
1717223017Sdim
1718344779Sdim// TODO: Implement
1719344779Sdimvoid MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
1720344779Sdim}
1721344779Sdim
1722327952Sdimvoid MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
1723327952Sdim  MCStreamer::EmitWinCFIStartChained(Loc);
1724223017Sdim
1725223017Sdim  OS << "\t.seh_startchained";
1726223017Sdim  EmitEOL();
1727223017Sdim}
1728223017Sdim
1729327952Sdimvoid MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
1730327952Sdim  MCStreamer::EmitWinCFIEndChained(Loc);
1731223017Sdim
1732223017Sdim  OS << "\t.seh_endchained";
1733223017Sdim  EmitEOL();
1734223017Sdim}
1735223017Sdim
1736276479Sdimvoid MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
1737327952Sdim                                     bool Except, SMLoc Loc) {
1738327952Sdim  MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
1739223017Sdim
1740288943Sdim  OS << "\t.seh_handler ";
1741288943Sdim  Sym->print(OS, MAI);
1742223017Sdim  if (Unwind)
1743223017Sdim    OS << ", @unwind";
1744223017Sdim  if (Except)
1745223017Sdim    OS << ", @except";
1746223017Sdim  EmitEOL();
1747223017Sdim}
1748223017Sdim
1749327952Sdimvoid MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
1750327952Sdim  MCStreamer::EmitWinEHHandlerData(Loc);
1751223017Sdim
1752223017Sdim  // Switch sections. Don't call SwitchSection directly, because that will
1753223017Sdim  // cause the section switch to be visible in the emitted assembly.
1754223017Sdim  // We only do this so the section switch that terminates the handler
1755223017Sdim  // data block is visible.
1756280031Sdim  WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
1757360784Sdim
1758360784Sdim  // Do nothing if no frame is open. MCStreamer should've already reported an
1759360784Sdim  // error.
1760360784Sdim  if (!CurFrame)
1761360784Sdim    return;
1762360784Sdim
1763309124Sdim  MCSection *TextSec = &CurFrame->Function->getSection();
1764309124Sdim  MCSection *XData = getAssociatedXDataSection(TextSec);
1765288943Sdim  SwitchSectionNoChange(XData);
1766223017Sdim
1767223017Sdim  OS << "\t.seh_handlerdata";
1768223017Sdim  EmitEOL();
1769223017Sdim}
1770223017Sdim
1771360784Sdimvoid MCAsmStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
1772327952Sdim  MCStreamer::EmitWinCFIPushReg(Register, Loc);
1773223017Sdim
1774360784Sdim  OS << "\t.seh_pushreg ";
1775360784Sdim  InstPrinter->printRegName(OS, Register);
1776223017Sdim  EmitEOL();
1777223017Sdim}
1778223017Sdim
1779360784Sdimvoid MCAsmStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
1780327952Sdim                                       SMLoc Loc) {
1781327952Sdim  MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
1782223017Sdim
1783360784Sdim  OS << "\t.seh_setframe ";
1784360784Sdim  InstPrinter->printRegName(OS, Register);
1785360784Sdim  OS << ", " << Offset;
1786223017Sdim  EmitEOL();
1787223017Sdim}
1788223017Sdim
1789327952Sdimvoid MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
1790327952Sdim  MCStreamer::EmitWinCFIAllocStack(Size, Loc);
1791223017Sdim
1792223017Sdim  OS << "\t.seh_stackalloc " << Size;
1793223017Sdim  EmitEOL();
1794223017Sdim}
1795223017Sdim
1796360784Sdimvoid MCAsmStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
1797327952Sdim                                      SMLoc Loc) {
1798327952Sdim  MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
1799223017Sdim
1800360784Sdim  OS << "\t.seh_savereg ";
1801360784Sdim  InstPrinter->printRegName(OS, Register);
1802360784Sdim  OS << ", " << Offset;
1803223017Sdim  EmitEOL();
1804223017Sdim}
1805223017Sdim
1806360784Sdimvoid MCAsmStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
1807327952Sdim                                      SMLoc Loc) {
1808327952Sdim  MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
1809223017Sdim
1810360784Sdim  OS << "\t.seh_savexmm ";
1811360784Sdim  InstPrinter->printRegName(OS, Register);
1812360784Sdim  OS << ", " << Offset;
1813223017Sdim  EmitEOL();
1814223017Sdim}
1815223017Sdim
1816327952Sdimvoid MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
1817327952Sdim  MCStreamer::EmitWinCFIPushFrame(Code, Loc);
1818223017Sdim
1819223017Sdim  OS << "\t.seh_pushframe";
1820223017Sdim  if (Code)
1821223017Sdim    OS << " @code";
1822223017Sdim  EmitEOL();
1823223017Sdim}
1824223017Sdim
1825327952Sdimvoid MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
1826327952Sdim  MCStreamer::EmitWinCFIEndProlog(Loc);
1827223017Sdim
1828223017Sdim  OS << "\t.seh_endprologue";
1829223017Sdim  EmitEOL();
1830223017Sdim}
1831223017Sdim
1832341825Sdimvoid MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
1833341825Sdim                                       const MCSymbolRefExpr *To,
1834341825Sdim                                       uint64_t Count) {
1835341825Sdim  OS << "\t.cg_profile ";
1836341825Sdim  From->getSymbol().print(OS, MAI);
1837341825Sdim  OS << ", ";
1838341825Sdim  To->getSymbol().print(OS, MAI);
1839341825Sdim  OS << ", " << Count;
1840341825Sdim  EmitEOL();
1841341825Sdim}
1842341825Sdim
1843276479Sdimvoid MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
1844353358Sdim                                       const MCSubtargetInfo &STI) {
1845203954Srdivacky  raw_ostream &OS = GetCommentOS();
1846203954Srdivacky  SmallString<256> Code;
1847203954Srdivacky  SmallVector<MCFixup, 4> Fixups;
1848203954Srdivacky  raw_svector_ostream VecOS(Code);
1849203954Srdivacky
1850341825Sdim  // If we have no code emitter, don't emit code.
1851341825Sdim  if (!getAssembler().getEmitterPtr())
1852341825Sdim    return;
1853341825Sdim
1854341825Sdim  getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
1855341825Sdim
1856203954Srdivacky  // If we are showing fixups, create symbolic markers in the encoded
1857203954Srdivacky  // representation. We do this by making a per-bit map to the fixup item index,
1858203954Srdivacky  // then trying to display it as nicely as possible.
1859203954Srdivacky  SmallVector<uint8_t, 64> FixupMap;
1860203954Srdivacky  FixupMap.resize(Code.size() * 8);
1861203954Srdivacky  for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
1862203954Srdivacky    FixupMap[i] = 0;
1863203954Srdivacky
1864203954Srdivacky  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
1865203954Srdivacky    MCFixup &F = Fixups[i];
1866341825Sdim    const MCFixupKindInfo &Info =
1867341825Sdim        getAssembler().getBackend().getFixupKindInfo(F.getKind());
1868203954Srdivacky    for (unsigned j = 0; j != Info.TargetSize; ++j) {
1869203954Srdivacky      unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
1870203954Srdivacky      assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
1871203954Srdivacky      FixupMap[Index] = 1 + i;
1872203954Srdivacky    }
1873203954Srdivacky  }
1874203954Srdivacky
1875224145Sdim  // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
1876218893Sdim  // high order halfword of a 32-bit Thumb2 instruction is emitted first.
1877203954Srdivacky  OS << "encoding: [";
1878203954Srdivacky  for (unsigned i = 0, e = Code.size(); i != e; ++i) {
1879203954Srdivacky    if (i)
1880203954Srdivacky      OS << ',';
1881203954Srdivacky
1882203954Srdivacky    // See if all bits are the same map entry.
1883203954Srdivacky    uint8_t MapEntry = FixupMap[i * 8 + 0];
1884203954Srdivacky    for (unsigned j = 1; j != 8; ++j) {
1885203954Srdivacky      if (FixupMap[i * 8 + j] == MapEntry)
1886203954Srdivacky        continue;
1887203954Srdivacky
1888203954Srdivacky      MapEntry = uint8_t(~0U);
1889203954Srdivacky      break;
1890203954Srdivacky    }
1891203954Srdivacky
1892203954Srdivacky    if (MapEntry != uint8_t(~0U)) {
1893203954Srdivacky      if (MapEntry == 0) {
1894203954Srdivacky        OS << format("0x%02x", uint8_t(Code[i]));
1895203954Srdivacky      } else {
1896218893Sdim        if (Code[i]) {
1897218893Sdim          // FIXME: Some of the 8 bits require fix up.
1898218893Sdim          OS << format("0x%02x", uint8_t(Code[i])) << '\''
1899218893Sdim             << char('A' + MapEntry - 1) << '\'';
1900218893Sdim        } else
1901218893Sdim          OS << char('A' + MapEntry - 1);
1902198090Srdivacky      }
1903203954Srdivacky    } else {
1904203954Srdivacky      // Otherwise, write out in binary.
1905203954Srdivacky      OS << "0b";
1906203954Srdivacky      for (unsigned j = 8; j--;) {
1907203954Srdivacky        unsigned Bit = (Code[i] >> j) & 1;
1908221345Sdim
1909218893Sdim        unsigned FixupBit;
1910261991Sdim        if (MAI->isLittleEndian())
1911218893Sdim          FixupBit = i * 8 + j;
1912218893Sdim        else
1913218893Sdim          FixupBit = i * 8 + (7-j);
1914221345Sdim
1915218893Sdim        if (uint8_t MapEntry = FixupMap[FixupBit]) {
1916203954Srdivacky          assert(Bit == 0 && "Encoder wrote into fixed up bit!");
1917203954Srdivacky          OS << char('A' + MapEntry - 1);
1918203954Srdivacky        } else
1919203954Srdivacky          OS << Bit;
1920203954Srdivacky      }
1921198090Srdivacky    }
1922203954Srdivacky  }
1923353358Sdim  OS << "]\n";
1924198090Srdivacky
1925203954Srdivacky  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
1926203954Srdivacky    MCFixup &F = Fixups[i];
1927341825Sdim    const MCFixupKindInfo &Info =
1928341825Sdim        getAssembler().getBackend().getFixupKindInfo(F.getKind());
1929203954Srdivacky    OS << "  fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
1930203954Srdivacky       << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
1931195340Sed  }
1932203954Srdivacky}
1933198090Srdivacky
1934314564Sdimvoid MCAsmStreamer::EmitInstruction(const MCInst &Inst,
1935353358Sdim                                    const MCSubtargetInfo &STI) {
1936314564Sdim  assert(getCurrentSectionOnly() &&
1937251662Sdim         "Cannot emit contents before setting section!");
1938203954Srdivacky
1939203954Srdivacky  // Show the encoding in a comment if we have a code emitter.
1940353358Sdim  AddEncodingComment(Inst, STI);
1941203954Srdivacky
1942203954Srdivacky  // Show the MCInst if enabled.
1943208599Srdivacky  if (ShowInst) {
1944288943Sdim    Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
1945208599Srdivacky    GetCommentOS() << "\n";
1946208599Srdivacky  }
1947208599Srdivacky
1948288943Sdim  if(getTargetStreamer())
1949360784Sdim    getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
1950203954Srdivacky  else
1951360784Sdim    InstPrinter->printInst(&Inst, 0, "", STI, OS);
1952288943Sdim
1953321369Sdim  StringRef Comments = CommentToEmit;
1954321369Sdim  if (Comments.size() && Comments.back() != '\n')
1955321369Sdim    GetCommentOS() << "\n";
1956321369Sdim
1957202878Srdivacky  EmitEOL();
1958195098Sed}
1959195098Sed
1960249423Sdimvoid MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
1961249423Sdim  OS << "\t.bundle_align_mode " << AlignPow2;
1962249423Sdim  EmitEOL();
1963249423Sdim}
1964249423Sdim
1965249423Sdimvoid MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
1966249423Sdim  OS << "\t.bundle_lock";
1967249423Sdim  if (AlignToEnd)
1968249423Sdim    OS << " align_to_end";
1969249423Sdim  EmitEOL();
1970249423Sdim}
1971249423Sdim
1972249423Sdimvoid MCAsmStreamer::EmitBundleUnlock() {
1973249423Sdim  OS << "\t.bundle_unlock";
1974249423Sdim  EmitEOL();
1975249423Sdim}
1976249423Sdim
1977296417Sdimbool MCAsmStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
1978341825Sdim                                       const MCExpr *Expr, SMLoc,
1979341825Sdim                                       const MCSubtargetInfo &STI) {
1980296417Sdim  OS << "\t.reloc ";
1981296417Sdim  Offset.print(OS, MAI);
1982296417Sdim  OS << ", " << Name;
1983296417Sdim  if (Expr) {
1984296417Sdim    OS << ", ";
1985296417Sdim    Expr->print(OS, MAI);
1986296417Sdim  }
1987296417Sdim  EmitEOL();
1988296417Sdim  return false;
1989296417Sdim}
1990296417Sdim
1991341825Sdimvoid MCAsmStreamer::EmitAddrsig() {
1992341825Sdim  OS << "\t.addrsig";
1993341825Sdim  EmitEOL();
1994341825Sdim}
1995341825Sdim
1996341825Sdimvoid MCAsmStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
1997341825Sdim  OS << "\t.addrsig_sym ";
1998341825Sdim  Sym->print(OS, MAI);
1999341825Sdim  EmitEOL();
2000341825Sdim}
2001341825Sdim
2002218893Sdim/// EmitRawText - If this file is backed by an assembly streamer, this dumps
2003206274Srdivacky/// the specified string in the output .s file.  This capability is
2004206274Srdivacky/// indicated by the hasRawTextSupport() predicate.
2005261991Sdimvoid MCAsmStreamer::EmitRawTextImpl(StringRef String) {
2006206274Srdivacky  if (!String.empty() && String.back() == '\n')
2007206274Srdivacky    String = String.substr(0, String.size()-1);
2008206274Srdivacky  OS << String;
2009206274Srdivacky  EmitEOL();
2010206274Srdivacky}
2011206274Srdivacky
2012234353Sdimvoid MCAsmStreamer::FinishImpl() {
2013234353Sdim  // If we are generating dwarf for assembly source files dump out the sections.
2014234353Sdim  if (getContext().getGenDwarfForAssembly())
2015276479Sdim    MCGenDwarfInfo::Emit(this);
2016234353Sdim
2017276479Sdim  // Emit the label for the line table, if requested - since the rest of the
2018276479Sdim  // line table will be defined by .loc/.file directives, and not emitted
2019276479Sdim  // directly, the label is the only work required here.
2020353358Sdim  const auto &Tables = getContext().getMCDwarfLineTables();
2021276479Sdim  if (!Tables.empty()) {
2022276479Sdim    assert(Tables.size() == 1 && "asm output only supports one line table");
2023276479Sdim    if (auto *Label = Tables.begin()->second.getLabel()) {
2024276479Sdim      SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
2025276479Sdim      EmitLabel(Label);
2026276479Sdim    }
2027276479Sdim  }
2028195098Sed}
2029261991Sdim
2030202878SrdivackyMCStreamer *llvm::createAsmStreamer(MCContext &Context,
2031288943Sdim                                    std::unique_ptr<formatted_raw_ostream> OS,
2032276479Sdim                                    bool isVerboseAsm, bool useDwarfDirectory,
2033341825Sdim                                    MCInstPrinter *IP,
2034341825Sdim                                    std::unique_ptr<MCCodeEmitter> &&CE,
2035341825Sdim                                    std::unique_ptr<MCAsmBackend> &&MAB,
2036341825Sdim                                    bool ShowInst) {
2037288943Sdim  return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
2038341825Sdim                           useDwarfDirectory, IP, std::move(CE), std::move(MAB),
2039341825Sdim                           ShowInst);
2040195098Sed}
2041