1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/ADT/Optional.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/StringExtras.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
15 #include "llvm/MC/MCAsmBackend.h"
16 #include "llvm/MC/MCAsmInfo.h"
17 #include "llvm/MC/MCAssembler.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCCodeView.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCFixupKindInfo.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/MC/MCInstPrinter.h"
25 #include "llvm/MC/MCObjectFileInfo.h"
26 #include "llvm/MC/MCObjectWriter.h"
27 #include "llvm/MC/MCPseudoProbe.h"
28 #include "llvm/MC/MCRegister.h"
29 #include "llvm/MC/MCRegisterInfo.h"
30 #include "llvm/MC/MCSectionMachO.h"
31 #include "llvm/MC/MCStreamer.h"
32 #include "llvm/MC/MCSymbolXCOFF.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/Format.h"
35 #include "llvm/Support/FormattedStream.h"
36 #include "llvm/Support/LEB128.h"
37 #include "llvm/Support/MathExtras.h"
38 #include "llvm/Support/Path.h"
39 #include "llvm/Support/TargetRegistry.h"
40 #include <cctype>
41 
42 using namespace llvm;
43 
44 namespace {
45 
46 class MCAsmStreamer final : public MCStreamer {
47   std::unique_ptr<formatted_raw_ostream> OSOwner;
48   formatted_raw_ostream &OS;
49   const MCAsmInfo *MAI;
50   std::unique_ptr<MCInstPrinter> InstPrinter;
51   std::unique_ptr<MCAssembler> Assembler;
52 
53   SmallString<128> ExplicitCommentToEmit;
54   SmallString<128> CommentToEmit;
55   raw_svector_ostream CommentStream;
56   raw_null_ostream NullStream;
57 
58   unsigned IsVerboseAsm : 1;
59   unsigned ShowInst : 1;
60   unsigned UseDwarfDirectory : 1;
61 
62   void EmitRegisterName(int64_t Register);
63   void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
64   void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
65 
66 public:
MCAsmStreamer(MCContext & Context,std::unique_ptr<formatted_raw_ostream> os,bool isVerboseAsm,bool useDwarfDirectory,MCInstPrinter * printer,std::unique_ptr<MCCodeEmitter> emitter,std::unique_ptr<MCAsmBackend> asmbackend,bool showInst)67   MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
68                 bool isVerboseAsm, bool useDwarfDirectory,
69                 MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
70                 std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
71       : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
72         MAI(Context.getAsmInfo()), InstPrinter(printer),
73         Assembler(std::make_unique<MCAssembler>(
74             Context, std::move(asmbackend), std::move(emitter),
75             (asmbackend) ? asmbackend->createObjectWriter(NullStream)
76                          : nullptr)),
77         CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
78         ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
79     assert(InstPrinter);
80     if (IsVerboseAsm)
81         InstPrinter->setCommentStream(CommentStream);
82     if (Assembler->getBackendPtr())
83       setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
84 
85     Context.setUseNamesOnTempLabels(true);
86   }
87 
getAssembler()88   MCAssembler &getAssembler() { return *Assembler; }
getAssemblerPtr()89   MCAssembler *getAssemblerPtr() override { return nullptr; }
90 
EmitEOL()91   inline void EmitEOL() {
92     // Dump Explicit Comments here.
93     emitExplicitComments();
94     // If we don't have any comments, just emit a \n.
95     if (!IsVerboseAsm) {
96       OS << '\n';
97       return;
98     }
99     EmitCommentsAndEOL();
100   }
101 
102   void emitSyntaxDirective() override;
103 
104   void EmitCommentsAndEOL();
105 
106   /// Return true if this streamer supports verbose assembly at all.
isVerboseAsm() const107   bool isVerboseAsm() const override { return IsVerboseAsm; }
108 
109   /// Do we support EmitRawText?
hasRawTextSupport() const110   bool hasRawTextSupport() const override { return true; }
111 
112   /// Add a comment that can be emitted to the generated .s file to make the
113   /// output of the compiler more readable. This only affects the MCAsmStreamer
114   /// and only when verbose assembly output is enabled.
115   void AddComment(const Twine &T, bool EOL = true) override;
116 
117   /// Add a comment showing the encoding of an instruction.
118   void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
119 
120   /// Return a raw_ostream that comments can be written to.
121   /// Unlike AddComment, you are required to terminate comments with \n if you
122   /// use this method.
GetCommentOS()123   raw_ostream &GetCommentOS() override {
124     if (!IsVerboseAsm)
125       return nulls();  // Discard comments unless in verbose asm mode.
126     return CommentStream;
127   }
128 
129   void emitRawComment(const Twine &T, bool TabPrefix = true) override;
130 
131   void addExplicitComment(const Twine &T) override;
132   void emitExplicitComments() override;
133 
134   /// Emit a blank line to a .s file to pretty it up.
AddBlankLine()135   void AddBlankLine() override {
136     EmitEOL();
137   }
138 
139   /// @name MCStreamer Interface
140   /// @{
141 
142   void changeSection(MCSection *Section, const MCExpr *Subsection) override;
143 
144   void emitELFSymverDirective(StringRef AliasName,
145                               const MCSymbol *Aliasee) override;
146 
147   void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
148 
getMnemonic(MCInst & MI)149   StringRef getMnemonic(MCInst &MI) override {
150     return InstPrinter->getMnemonic(&MI).first;
151   }
152 
153   void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
154 
155   void emitAssemblerFlag(MCAssemblerFlag Flag) override;
156   void emitLinkerOptions(ArrayRef<std::string> Options) override;
157   void emitDataRegion(MCDataRegionType Kind) override;
158   void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
159                       unsigned Update, VersionTuple SDKVersion) override;
160   void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
161                         unsigned Update, VersionTuple SDKVersion) override;
162   void emitThumbFunc(MCSymbol *Func) override;
163 
164   void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
165   void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
166   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
167 
168   void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
169   void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
170   void EmitCOFFSymbolStorageClass(int StorageClass) override;
171   void EmitCOFFSymbolType(int Type) override;
172   void EndCOFFSymbolDef() override;
173   void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
174   void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
175   void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
176   void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
177   void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
178   void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
179                                   MCSymbol *CsectSym,
180                                   unsigned ByteAlign) override;
181   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
182                                             MCSymbolAttr Linakge,
183                                             MCSymbolAttr Visibility) override;
184   void emitXCOFFRenameDirective(const MCSymbol *Name,
185                                 StringRef Rename) override;
186 
187   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
188   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
189                         unsigned ByteAlignment) override;
190 
191   /// Emit a local common (.lcomm) symbol.
192   ///
193   /// @param Symbol - The common symbol to emit.
194   /// @param Size - The size of the common symbol.
195   /// @param ByteAlignment - The alignment of the common symbol in bytes.
196   void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
197                              unsigned ByteAlignment) override;
198 
199   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
200                     uint64_t Size = 0, unsigned ByteAlignment = 0,
201                     SMLoc Loc = SMLoc()) override;
202 
203   void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
204                       unsigned ByteAlignment = 0) override;
205 
206   void emitBinaryData(StringRef Data) override;
207 
208   void emitBytes(StringRef Data) override;
209 
210   void emitValueImpl(const MCExpr *Value, unsigned Size,
211                      SMLoc Loc = SMLoc()) override;
212   void emitIntValue(uint64_t Value, unsigned Size) override;
213   void emitIntValueInHex(uint64_t Value, unsigned Size) override;
214   void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
215 
216   void emitULEB128Value(const MCExpr *Value) override;
217 
218   void emitSLEB128Value(const MCExpr *Value) override;
219 
220   void emitDTPRel32Value(const MCExpr *Value) override;
221   void emitDTPRel64Value(const MCExpr *Value) override;
222   void emitTPRel32Value(const MCExpr *Value) override;
223   void emitTPRel64Value(const MCExpr *Value) override;
224 
225   void emitGPRel64Value(const MCExpr *Value) override;
226 
227   void emitGPRel32Value(const MCExpr *Value) override;
228 
229   void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
230                 SMLoc Loc = SMLoc()) override;
231 
232   void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
233                 SMLoc Loc = SMLoc()) override;
234 
235   void emitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
236                             unsigned ValueSize = 1,
237                             unsigned MaxBytesToEmit = 0) override;
238 
239   void emitCodeAlignment(unsigned ByteAlignment,
240                          unsigned MaxBytesToEmit = 0) override;
241 
242   void emitValueToOffset(const MCExpr *Offset,
243                          unsigned char Value,
244                          SMLoc Loc) override;
245 
246   void emitFileDirective(StringRef Filename) override;
247   Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
248                                                StringRef Directory,
249                                                StringRef Filename,
250                                                Optional<MD5::MD5Result> Checksum = None,
251                                                Optional<StringRef> Source = None,
252                                                unsigned CUID = 0) override;
253   void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
254                                Optional<MD5::MD5Result> Checksum,
255                                Optional<StringRef> Source,
256                                unsigned CUID = 0) override;
257   void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
258                              unsigned Flags, unsigned Isa,
259                              unsigned Discriminator,
260                              StringRef FileName) override;
261   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
262 
263   bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
264                            ArrayRef<uint8_t> Checksum,
265                            unsigned ChecksumKind) override;
266   bool EmitCVFuncIdDirective(unsigned FuncId) override;
267   bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
268                                    unsigned IAFile, unsigned IALine,
269                                    unsigned IACol, SMLoc Loc) override;
270   void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
271                           unsigned Column, bool PrologueEnd, bool IsStmt,
272                           StringRef FileName, SMLoc Loc) override;
273   void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
274                                 const MCSymbol *FnEnd) override;
275   void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
276                                       unsigned SourceFileId,
277                                       unsigned SourceLineNum,
278                                       const MCSymbol *FnStartSym,
279                                       const MCSymbol *FnEndSym) override;
280 
281   void PrintCVDefRangePrefix(
282       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
283 
284   void emitCVDefRangeDirective(
285       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
286       codeview::DefRangeRegisterRelHeader DRHdr) override;
287 
288   void emitCVDefRangeDirective(
289       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
290       codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
291 
292   void emitCVDefRangeDirective(
293       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
294       codeview::DefRangeRegisterHeader DRHdr) override;
295 
296   void emitCVDefRangeDirective(
297       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
298       codeview::DefRangeFramePointerRelHeader DRHdr) override;
299 
300   void emitCVStringTableDirective() override;
301   void emitCVFileChecksumsDirective() override;
302   void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
303   void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
304 
305   void emitIdent(StringRef IdentString) override;
306   void emitCFIBKeyFrame() override;
307   void emitCFISections(bool EH, bool Debug) override;
308   void emitCFIDefCfa(int64_t Register, int64_t Offset) override;
309   void emitCFIDefCfaOffset(int64_t Offset) override;
310   void emitCFIDefCfaRegister(int64_t Register) override;
311   void emitCFIOffset(int64_t Register, int64_t Offset) override;
312   void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
313   void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
314   void emitCFIRememberState() override;
315   void emitCFIRestoreState() override;
316   void emitCFIRestore(int64_t Register) override;
317   void emitCFISameValue(int64_t Register) override;
318   void emitCFIRelOffset(int64_t Register, int64_t Offset) override;
319   void emitCFIAdjustCfaOffset(int64_t Adjustment) override;
320   void emitCFIEscape(StringRef Values) override;
321   void emitCFIGnuArgsSize(int64_t Size) override;
322   void emitCFISignalFrame() override;
323   void emitCFIUndefined(int64_t Register) override;
324   void emitCFIRegister(int64_t Register1, int64_t Register2) override;
325   void emitCFIWindowSave() override;
326   void emitCFINegateRAState() override;
327   void emitCFIReturnColumn(int64_t Register) override;
328 
329   void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
330   void EmitWinCFIEndProc(SMLoc Loc) override;
331   void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
332   void EmitWinCFIStartChained(SMLoc Loc) override;
333   void EmitWinCFIEndChained(SMLoc Loc) override;
334   void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
335   void EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
336                           SMLoc Loc) override;
337   void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
338   void EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
339                          SMLoc Loc) override;
340   void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
341                          SMLoc Loc) override;
342   void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
343   void EmitWinCFIEndProlog(SMLoc Loc) override;
344 
345   void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
346                         SMLoc Loc) override;
347   void EmitWinEHHandlerData(SMLoc Loc) override;
348 
349   void emitCGProfileEntry(const MCSymbolRefExpr *From,
350                           const MCSymbolRefExpr *To, uint64_t Count) override;
351 
352   void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
353 
354   void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
355                        uint64_t Attr,
356                        const MCPseudoProbeInlineStack &InlineStack) override;
357 
358   void emitBundleAlignMode(unsigned AlignPow2) override;
359   void emitBundleLock(bool AlignToEnd) override;
360   void emitBundleUnlock() override;
361 
362   Optional<std::pair<bool, std::string>>
363   emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
364                      SMLoc Loc, const MCSubtargetInfo &STI) override;
365 
366   void emitAddrsig() override;
367   void emitAddrsigSym(const MCSymbol *Sym) override;
368 
369   /// If this file is backed by an assembly streamer, this dumps the specified
370   /// string in the output .s file. This capability is indicated by the
371   /// hasRawTextSupport() predicate.
372   void emitRawTextImpl(StringRef String) override;
373 
374   void finishImpl() override;
375 };
376 
377 } // end anonymous namespace.
378 
AddComment(const Twine & T,bool EOL)379 void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
380   if (!IsVerboseAsm) return;
381 
382   T.toVector(CommentToEmit);
383 
384   if (EOL)
385     CommentToEmit.push_back('\n'); // Place comment in a new line.
386 }
387 
EmitCommentsAndEOL()388 void MCAsmStreamer::EmitCommentsAndEOL() {
389   if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
390     OS << '\n';
391     return;
392   }
393 
394   StringRef Comments = CommentToEmit;
395 
396   assert(Comments.back() == '\n' &&
397          "Comment array not newline terminated");
398   do {
399     // Emit a line of comments.
400     OS.PadToColumn(MAI->getCommentColumn());
401     size_t Position = Comments.find('\n');
402     OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
403 
404     Comments = Comments.substr(Position+1);
405   } while (!Comments.empty());
406 
407   CommentToEmit.clear();
408 }
409 
truncateToSize(int64_t Value,unsigned Bytes)410 static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
411   assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
412   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
413 }
414 
emitRawComment(const Twine & T,bool TabPrefix)415 void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
416   if (TabPrefix)
417     OS << '\t';
418   OS << MAI->getCommentString() << T;
419   EmitEOL();
420 }
421 
addExplicitComment(const Twine & T)422 void MCAsmStreamer::addExplicitComment(const Twine &T) {
423   StringRef c = T.getSingleStringRef();
424   if (c.equals(StringRef(MAI->getSeparatorString())))
425     return;
426   if (c.startswith(StringRef("//"))) {
427     ExplicitCommentToEmit.append("\t");
428     ExplicitCommentToEmit.append(MAI->getCommentString());
429     // drop //
430     ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
431   } else if (c.startswith(StringRef("/*"))) {
432     size_t p = 2, len = c.size() - 2;
433     // emit each line in comment as separate newline.
434     do {
435       size_t newp = std::min(len, c.find_first_of("\r\n", p));
436       ExplicitCommentToEmit.append("\t");
437       ExplicitCommentToEmit.append(MAI->getCommentString());
438       ExplicitCommentToEmit.append(c.slice(p, newp).str());
439       // If we have another line in this comment add line
440       if (newp < len)
441         ExplicitCommentToEmit.append("\n");
442       p = newp + 1;
443     } while (p < len);
444   } else if (c.startswith(StringRef(MAI->getCommentString()))) {
445     ExplicitCommentToEmit.append("\t");
446     ExplicitCommentToEmit.append(c.str());
447   } else if (c.front() == '#') {
448 
449     ExplicitCommentToEmit.append("\t");
450     ExplicitCommentToEmit.append(MAI->getCommentString());
451     ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
452   } else
453     assert(false && "Unexpected Assembly Comment");
454   // full line comments immediately output
455   if (c.back() == '\n')
456     emitExplicitComments();
457 }
458 
emitExplicitComments()459 void MCAsmStreamer::emitExplicitComments() {
460   StringRef Comments = ExplicitCommentToEmit;
461   if (!Comments.empty())
462     OS << Comments;
463   ExplicitCommentToEmit.clear();
464 }
465 
changeSection(MCSection * Section,const MCExpr * Subsection)466 void MCAsmStreamer::changeSection(MCSection *Section,
467                                   const MCExpr *Subsection) {
468   assert(Section && "Cannot switch to a null section!");
469   if (MCTargetStreamer *TS = getTargetStreamer()) {
470     TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
471   } else {
472     Section->PrintSwitchToSection(
473         *MAI, getContext().getObjectFileInfo()->getTargetTriple(), OS,
474         Subsection);
475   }
476 }
477 
emitELFSymverDirective(StringRef AliasName,const MCSymbol * Aliasee)478 void MCAsmStreamer::emitELFSymverDirective(StringRef AliasName,
479                                            const MCSymbol *Aliasee) {
480   OS << ".symver ";
481   Aliasee->print(OS, MAI);
482   OS << ", " << AliasName;
483   EmitEOL();
484 }
485 
emitLabel(MCSymbol * Symbol,SMLoc Loc)486 void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
487   MCStreamer::emitLabel(Symbol, Loc);
488 
489   Symbol->print(OS, MAI);
490   OS << MAI->getLabelSuffix();
491 
492   EmitEOL();
493 }
494 
emitLOHDirective(MCLOHType Kind,const MCLOHArgs & Args)495 void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
496   StringRef str = MCLOHIdToName(Kind);
497 
498 #ifndef NDEBUG
499   int NbArgs = MCLOHIdToNbArgs(Kind);
500   assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
501   assert(str != "" && "Invalid LOH name");
502 #endif
503 
504   OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
505   bool IsFirst = true;
506   for (const MCSymbol *Arg : Args) {
507     if (!IsFirst)
508       OS << ", ";
509     IsFirst = false;
510     Arg->print(OS, MAI);
511   }
512   EmitEOL();
513 }
514 
emitAssemblerFlag(MCAssemblerFlag Flag)515 void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
516   switch (Flag) {
517   case MCAF_SyntaxUnified:         OS << "\t.syntax unified"; break;
518   case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
519   case MCAF_Code16:                OS << '\t'<< MAI->getCode16Directive();break;
520   case MCAF_Code32:                OS << '\t'<< MAI->getCode32Directive();break;
521   case MCAF_Code64:                OS << '\t'<< MAI->getCode64Directive();break;
522   }
523   EmitEOL();
524 }
525 
emitLinkerOptions(ArrayRef<std::string> Options)526 void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
527   assert(!Options.empty() && "At least one option is required!");
528   OS << "\t.linker_option \"" << Options[0] << '"';
529   for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
530          ie = Options.end(); it != ie; ++it) {
531     OS << ", " << '"' << *it << '"';
532   }
533   EmitEOL();
534 }
535 
emitDataRegion(MCDataRegionType Kind)536 void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
537   if (!MAI->doesSupportDataRegionDirectives())
538     return;
539   switch (Kind) {
540   case MCDR_DataRegion:            OS << "\t.data_region"; break;
541   case MCDR_DataRegionJT8:         OS << "\t.data_region jt8"; break;
542   case MCDR_DataRegionJT16:        OS << "\t.data_region jt16"; break;
543   case MCDR_DataRegionJT32:        OS << "\t.data_region jt32"; break;
544   case MCDR_DataRegionEnd:         OS << "\t.end_data_region"; break;
545   }
546   EmitEOL();
547 }
548 
getVersionMinDirective(MCVersionMinType Type)549 static const char *getVersionMinDirective(MCVersionMinType Type) {
550   switch (Type) {
551   case MCVM_WatchOSVersionMin: return ".watchos_version_min";
552   case MCVM_TvOSVersionMin:    return ".tvos_version_min";
553   case MCVM_IOSVersionMin:     return ".ios_version_min";
554   case MCVM_OSXVersionMin:     return ".macosx_version_min";
555   }
556   llvm_unreachable("Invalid MC version min type");
557 }
558 
EmitSDKVersionSuffix(raw_ostream & OS,const VersionTuple & SDKVersion)559 static void EmitSDKVersionSuffix(raw_ostream &OS,
560                                  const VersionTuple &SDKVersion) {
561   if (SDKVersion.empty())
562     return;
563   OS << '\t' << "sdk_version " << SDKVersion.getMajor();
564   if (auto Minor = SDKVersion.getMinor()) {
565     OS << ", " << *Minor;
566     if (auto Subminor = SDKVersion.getSubminor()) {
567       OS << ", " << *Subminor;
568     }
569   }
570 }
571 
emitVersionMin(MCVersionMinType Type,unsigned Major,unsigned Minor,unsigned Update,VersionTuple SDKVersion)572 void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
573                                    unsigned Minor, unsigned Update,
574                                    VersionTuple SDKVersion) {
575   OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
576   if (Update)
577     OS << ", " << Update;
578   EmitSDKVersionSuffix(OS, SDKVersion);
579   EmitEOL();
580 }
581 
getPlatformName(MachO::PlatformType Type)582 static const char *getPlatformName(MachO::PlatformType Type) {
583   switch (Type) {
584   case MachO::PLATFORM_MACOS:            return "macos";
585   case MachO::PLATFORM_IOS:              return "ios";
586   case MachO::PLATFORM_TVOS:             return "tvos";
587   case MachO::PLATFORM_WATCHOS:          return "watchos";
588   case MachO::PLATFORM_BRIDGEOS:         return "bridgeos";
589   case MachO::PLATFORM_MACCATALYST:      return "macCatalyst";
590   case MachO::PLATFORM_IOSSIMULATOR:     return "iossimulator";
591   case MachO::PLATFORM_TVOSSIMULATOR:    return "tvossimulator";
592   case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
593   case MachO::PLATFORM_DRIVERKIT:        return "driverkit";
594   }
595   llvm_unreachable("Invalid Mach-O platform type");
596 }
597 
emitBuildVersion(unsigned Platform,unsigned Major,unsigned Minor,unsigned Update,VersionTuple SDKVersion)598 void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
599                                      unsigned Minor, unsigned Update,
600                                      VersionTuple SDKVersion) {
601   const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
602   OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
603   if (Update)
604     OS << ", " << Update;
605   EmitSDKVersionSuffix(OS, SDKVersion);
606   EmitEOL();
607 }
608 
emitThumbFunc(MCSymbol * Func)609 void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {
610   // This needs to emit to a temporary string to get properly quoted
611   // MCSymbols when they have spaces in them.
612   OS << "\t.thumb_func";
613   // Only Mach-O hasSubsectionsViaSymbols()
614   if (MAI->hasSubsectionsViaSymbols()) {
615     OS << '\t';
616     Func->print(OS, MAI);
617   }
618   EmitEOL();
619 }
620 
emitAssignment(MCSymbol * Symbol,const MCExpr * Value)621 void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
622   // Do not emit a .set on inlined target assignments.
623   bool EmitSet = true;
624   if (auto *E = dyn_cast<MCTargetExpr>(Value))
625     if (E->inlineAssignedExpr())
626       EmitSet = false;
627   if (EmitSet) {
628     OS << ".set ";
629     Symbol->print(OS, MAI);
630     OS << ", ";
631     Value->print(OS, MAI);
632 
633     EmitEOL();
634   }
635 
636   MCStreamer::emitAssignment(Symbol, Value);
637 }
638 
emitWeakReference(MCSymbol * Alias,const MCSymbol * Symbol)639 void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
640   OS << ".weakref ";
641   Alias->print(OS, MAI);
642   OS << ", ";
643   Symbol->print(OS, MAI);
644   EmitEOL();
645 }
646 
emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)647 bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
648                                         MCSymbolAttr Attribute) {
649   switch (Attribute) {
650   case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
651   case MCSA_ELF_TypeFunction:    /// .type _foo, STT_FUNC  # aka @function
652   case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
653   case MCSA_ELF_TypeObject:      /// .type _foo, STT_OBJECT  # aka @object
654   case MCSA_ELF_TypeTLS:         /// .type _foo, STT_TLS     # aka @tls_object
655   case MCSA_ELF_TypeCommon:      /// .type _foo, STT_COMMON  # aka @common
656   case MCSA_ELF_TypeNoType:      /// .type _foo, STT_NOTYPE  # aka @notype
657   case MCSA_ELF_TypeGnuUniqueObject:  /// .type _foo, @gnu_unique_object
658     if (!MAI->hasDotTypeDotSizeDirective())
659       return false; // Symbol attribute not supported
660     OS << "\t.type\t";
661     Symbol->print(OS, MAI);
662     OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
663     switch (Attribute) {
664     default: return false;
665     case MCSA_ELF_TypeFunction:    OS << "function"; break;
666     case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
667     case MCSA_ELF_TypeObject:      OS << "object"; break;
668     case MCSA_ELF_TypeTLS:         OS << "tls_object"; break;
669     case MCSA_ELF_TypeCommon:      OS << "common"; break;
670     case MCSA_ELF_TypeNoType:      OS << "notype"; break;
671     case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
672     }
673     EmitEOL();
674     return true;
675   case MCSA_Global: // .globl/.global
676     OS << MAI->getGlobalDirective();
677     break;
678   case MCSA_LGlobal:        OS << "\t.lglobl\t";          break;
679   case MCSA_Hidden:         OS << "\t.hidden\t";          break;
680   case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
681   case MCSA_Internal:       OS << "\t.internal\t";        break;
682   case MCSA_LazyReference:  OS << "\t.lazy_reference\t";  break;
683   case MCSA_Local:          OS << "\t.local\t";           break;
684   case MCSA_NoDeadStrip:
685     if (!MAI->hasNoDeadStrip())
686       return false;
687     OS << "\t.no_dead_strip\t";
688     break;
689   case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
690   case MCSA_AltEntry:       OS << "\t.alt_entry\t";       break;
691   case MCSA_PrivateExtern:
692     OS << "\t.private_extern\t";
693     break;
694   case MCSA_Protected:      OS << "\t.protected\t";       break;
695   case MCSA_Reference:      OS << "\t.reference\t";       break;
696   case MCSA_Extern:
697     OS << "\t.extern\t";
698     break;
699   case MCSA_Weak:           OS << MAI->getWeakDirective(); break;
700   case MCSA_WeakDefinition:
701     OS << "\t.weak_definition\t";
702     break;
703       // .weak_reference
704   case MCSA_WeakReference:  OS << MAI->getWeakRefDirective(); break;
705   case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
706   case MCSA_Cold:
707     // Assemblers currently do not support a .cold directive.
708     return false;
709   }
710 
711   Symbol->print(OS, MAI);
712   EmitEOL();
713 
714   return true;
715 }
716 
emitSymbolDesc(MCSymbol * Symbol,unsigned DescValue)717 void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
718   OS << ".desc" << ' ';
719   Symbol->print(OS, MAI);
720   OS << ',' << DescValue;
721   EmitEOL();
722 }
723 
emitSyntaxDirective()724 void MCAsmStreamer::emitSyntaxDirective() {
725   if (MAI->getAssemblerDialect() == 1) {
726     OS << "\t.intel_syntax noprefix";
727     EmitEOL();
728   }
729   // FIXME: Currently emit unprefix'ed registers.
730   // The intel_syntax directive has one optional argument
731   // with may have a value of prefix or noprefix.
732 }
733 
BeginCOFFSymbolDef(const MCSymbol * Symbol)734 void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
735   OS << "\t.def\t ";
736   Symbol->print(OS, MAI);
737   OS << ';';
738   EmitEOL();
739 }
740 
EmitCOFFSymbolStorageClass(int StorageClass)741 void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
742   OS << "\t.scl\t" << StorageClass << ';';
743   EmitEOL();
744 }
745 
EmitCOFFSymbolType(int Type)746 void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
747   OS << "\t.type\t" << Type << ';';
748   EmitEOL();
749 }
750 
EndCOFFSymbolDef()751 void MCAsmStreamer::EndCOFFSymbolDef() {
752   OS << "\t.endef";
753   EmitEOL();
754 }
755 
EmitCOFFSafeSEH(MCSymbol const * Symbol)756 void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
757   OS << "\t.safeseh\t";
758   Symbol->print(OS, MAI);
759   EmitEOL();
760 }
761 
EmitCOFFSymbolIndex(MCSymbol const * Symbol)762 void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
763   OS << "\t.symidx\t";
764   Symbol->print(OS, MAI);
765   EmitEOL();
766 }
767 
EmitCOFFSectionIndex(MCSymbol const * Symbol)768 void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
769   OS << "\t.secidx\t";
770   Symbol->print(OS, MAI);
771   EmitEOL();
772 }
773 
EmitCOFFSecRel32(MCSymbol const * Symbol,uint64_t Offset)774 void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
775   OS << "\t.secrel32\t";
776   Symbol->print(OS, MAI);
777   if (Offset != 0)
778     OS << '+' << Offset;
779   EmitEOL();
780 }
781 
EmitCOFFImgRel32(MCSymbol const * Symbol,int64_t Offset)782 void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
783   OS << "\t.rva\t";
784   Symbol->print(OS, MAI);
785   if (Offset > 0)
786     OS << '+' << Offset;
787   else if (Offset < 0)
788     OS << '-' << -Offset;
789   EmitEOL();
790 }
791 
792 // We need an XCOFF-specific version of this directive as the AIX syntax
793 // requires a QualName argument identifying the csect name and storage mapping
794 // class to appear before the alignment if we are specifying it.
emitXCOFFLocalCommonSymbol(MCSymbol * LabelSym,uint64_t Size,MCSymbol * CsectSym,unsigned ByteAlignment)795 void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
796                                                uint64_t Size,
797                                                MCSymbol *CsectSym,
798                                                unsigned ByteAlignment) {
799   assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
800          "We only support writing log base-2 alignment format with XCOFF.");
801   assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.");
802 
803   OS << "\t.lcomm\t";
804   LabelSym->print(OS, MAI);
805   OS << ',' << Size << ',';
806   CsectSym->print(OS, MAI);
807   OS << ',' << Log2_32(ByteAlignment);
808 
809   EmitEOL();
810 
811   // Print symbol's rename (original name contains invalid character(s)) if
812   // there is one.
813   MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym);
814   if (XSym->hasRename())
815     emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
816 }
817 
emitXCOFFSymbolLinkageWithVisibility(MCSymbol * Symbol,MCSymbolAttr Linkage,MCSymbolAttr Visibility)818 void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
819     MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
820 
821   switch (Linkage) {
822   case MCSA_Global:
823     OS << MAI->getGlobalDirective();
824     break;
825   case MCSA_Weak:
826     OS << MAI->getWeakDirective();
827     break;
828   case MCSA_Extern:
829     OS << "\t.extern\t";
830     break;
831   case MCSA_LGlobal:
832     OS << "\t.lglobl\t";
833     break;
834   default:
835     report_fatal_error("unhandled linkage type");
836   }
837 
838   Symbol->print(OS, MAI);
839 
840   switch (Visibility) {
841   case MCSA_Invalid:
842     // Nothing to do.
843     break;
844   case MCSA_Hidden:
845     OS << ",hidden";
846     break;
847   case MCSA_Protected:
848     OS << ",protected";
849     break;
850   default:
851     report_fatal_error("unexpected value for Visibility type");
852   }
853   EmitEOL();
854 
855   // Print symbol's rename (original name contains invalid character(s)) if
856   // there is one.
857   if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
858     emitXCOFFRenameDirective(Symbol,
859                              cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
860 }
861 
emitXCOFFRenameDirective(const MCSymbol * Name,StringRef Rename)862 void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
863                                              StringRef Rename) {
864   OS << "\t.rename\t";
865   Name->print(OS, MAI);
866   const char DQ = '"';
867   OS << ',' << DQ;
868   for (char C : Rename) {
869     // To escape a double quote character, the character should be doubled.
870     if (C == DQ)
871       OS << DQ;
872     OS << C;
873   }
874   OS << DQ;
875   EmitEOL();
876 }
877 
emitELFSize(MCSymbol * Symbol,const MCExpr * Value)878 void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
879   assert(MAI->hasDotTypeDotSizeDirective());
880   OS << "\t.size\t";
881   Symbol->print(OS, MAI);
882   OS << ", ";
883   Value->print(OS, MAI);
884   EmitEOL();
885 }
886 
emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)887 void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
888                                      unsigned ByteAlignment) {
889   OS << "\t.comm\t";
890   Symbol->print(OS, MAI);
891   OS << ',' << Size;
892 
893   if (ByteAlignment != 0) {
894     if (MAI->getCOMMDirectiveAlignmentIsInBytes())
895       OS << ',' << ByteAlignment;
896     else
897       OS << ',' << Log2_32(ByteAlignment);
898   }
899   EmitEOL();
900 
901   // Print symbol's rename (original name contains invalid character(s)) if
902   // there is one.
903   MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
904   if (XSym && XSym->hasRename())
905     emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
906 
907 }
908 
emitLocalCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlign)909 void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
910                                           unsigned ByteAlign) {
911   OS << "\t.lcomm\t";
912   Symbol->print(OS, MAI);
913   OS << ',' << Size;
914 
915   if (ByteAlign > 1) {
916     switch (MAI->getLCOMMDirectiveAlignmentType()) {
917     case LCOMM::NoAlignment:
918       llvm_unreachable("alignment not supported on .lcomm!");
919     case LCOMM::ByteAlignment:
920       OS << ',' << ByteAlign;
921       break;
922     case LCOMM::Log2Alignment:
923       assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
924       OS << ',' << Log2_32(ByteAlign);
925       break;
926     }
927   }
928   EmitEOL();
929 }
930 
emitZerofill(MCSection * Section,MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment,SMLoc Loc)931 void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
932                                  uint64_t Size, unsigned ByteAlignment,
933                                  SMLoc Loc) {
934   if (Symbol)
935     AssignFragment(Symbol, &Section->getDummyFragment());
936 
937   // Note: a .zerofill directive does not switch sections.
938   OS << ".zerofill ";
939 
940   assert(Section->getVariant() == MCSection::SV_MachO &&
941          ".zerofill is a Mach-O specific directive");
942   // This is a mach-o specific directive.
943 
944   const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
945   OS << MOSection->getSegmentName() << "," << MOSection->getName();
946 
947   if (Symbol) {
948     OS << ',';
949     Symbol->print(OS, MAI);
950     OS << ',' << Size;
951     if (ByteAlignment != 0)
952       OS << ',' << Log2_32(ByteAlignment);
953   }
954   EmitEOL();
955 }
956 
957 // .tbss sym, size, align
958 // This depends that the symbol has already been mangled from the original,
959 // e.g. _a.
emitTBSSSymbol(MCSection * Section,MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)960 void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
961                                    uint64_t Size, unsigned ByteAlignment) {
962   AssignFragment(Symbol, &Section->getDummyFragment());
963 
964   assert(Symbol && "Symbol shouldn't be NULL!");
965   // Instead of using the Section we'll just use the shortcut.
966 
967   assert(Section->getVariant() == MCSection::SV_MachO &&
968          ".zerofill is a Mach-O specific directive");
969   // This is a mach-o specific directive and section.
970 
971   OS << ".tbss ";
972   Symbol->print(OS, MAI);
973   OS << ", " << Size;
974 
975   // Output align if we have it.  We default to 1 so don't bother printing
976   // that.
977   if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
978 
979   EmitEOL();
980 }
981 
toOctal(int X)982 static inline char toOctal(int X) { return (X&7)+'0'; }
983 
PrintByteList(StringRef Data,raw_ostream & OS,MCAsmInfo::AsmCharLiteralSyntax ACLS)984 static void PrintByteList(StringRef Data, raw_ostream &OS,
985                           MCAsmInfo::AsmCharLiteralSyntax ACLS) {
986   assert(!Data.empty() && "Cannot generate an empty list.");
987   const auto printCharacterInOctal = [&OS](unsigned char C) {
988     OS << '0';
989     OS << toOctal(C >> 6);
990     OS << toOctal(C >> 3);
991     OS << toOctal(C >> 0);
992   };
993   const auto printOneCharacterFor = [printCharacterInOctal](
994                                         auto printOnePrintingCharacter) {
995     return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {
996       if (isPrint(C)) {
997         printOnePrintingCharacter(static_cast<char>(C));
998         return;
999       }
1000       printCharacterInOctal(C);
1001     };
1002   };
1003   const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {
1004     const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1005     for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1006       printOneCharacter(C);
1007       OS << ',';
1008     }
1009     printOneCharacter(*(EndPtr - 1));
1010   };
1011   switch (ACLS) {
1012   case MCAsmInfo::ACLS_Unknown:
1013     printCharacterList(printCharacterInOctal);
1014     return;
1015   case MCAsmInfo::ACLS_SingleQuotePrefix:
1016     printCharacterList(printOneCharacterFor([&OS](char C) {
1017       const char AsmCharLitBuf[2] = {'\'', C};
1018       OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));
1019     }));
1020     return;
1021   }
1022   llvm_unreachable("Invalid AsmCharLiteralSyntax value!");
1023 }
1024 
PrintQuotedString(StringRef Data,raw_ostream & OS)1025 static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
1026   OS << '"';
1027 
1028   for (unsigned i = 0, e = Data.size(); i != e; ++i) {
1029     unsigned char C = Data[i];
1030     if (C == '"' || C == '\\') {
1031       OS << '\\' << (char)C;
1032       continue;
1033     }
1034 
1035     if (isPrint((unsigned char)C)) {
1036       OS << (char)C;
1037       continue;
1038     }
1039 
1040     switch (C) {
1041       case '\b': OS << "\\b"; break;
1042       case '\f': OS << "\\f"; break;
1043       case '\n': OS << "\\n"; break;
1044       case '\r': OS << "\\r"; break;
1045       case '\t': OS << "\\t"; break;
1046       default:
1047         OS << '\\';
1048         OS << toOctal(C >> 6);
1049         OS << toOctal(C >> 3);
1050         OS << toOctal(C >> 0);
1051         break;
1052     }
1053   }
1054 
1055   OS << '"';
1056 }
1057 
emitBytes(StringRef Data)1058 void MCAsmStreamer::emitBytes(StringRef Data) {
1059   assert(getCurrentSectionOnly() &&
1060          "Cannot emit contents before setting section!");
1061   if (Data.empty()) return;
1062 
1063   const auto emitAsString = [this](StringRef Data) {
1064     // If the data ends with 0 and the target supports .asciz, use it, otherwise
1065     // use .ascii or a byte-list directive
1066     if (MAI->getAscizDirective() && Data.back() == 0) {
1067       OS << MAI->getAscizDirective();
1068       Data = Data.substr(0, Data.size() - 1);
1069     } else if (LLVM_LIKELY(MAI->getAsciiDirective())) {
1070       OS << MAI->getAsciiDirective();
1071     } else if (MAI->getByteListDirective()) {
1072       OS << MAI->getByteListDirective();
1073       PrintByteList(Data, OS, MAI->characterLiteralSyntax());
1074       EmitEOL();
1075       return true;
1076     } else {
1077       return false;
1078     }
1079 
1080     PrintQuotedString(Data, OS);
1081     EmitEOL();
1082     return true;
1083   };
1084 
1085   if (Data.size() != 1 && emitAsString(Data))
1086     return;
1087 
1088   // Only single byte is provided or no ascii, asciz, or byte-list directives
1089   // are applicable. Emit as vector of individual 8bits data elements.
1090   if (MCTargetStreamer *TS = getTargetStreamer()) {
1091     TS->emitRawBytes(Data);
1092     return;
1093   }
1094   const char *Directive = MAI->getData8bitsDirective();
1095   for (const unsigned char C : Data.bytes()) {
1096     OS << Directive << (unsigned)C;
1097     EmitEOL();
1098   }
1099 }
1100 
emitBinaryData(StringRef Data)1101 void MCAsmStreamer::emitBinaryData(StringRef Data) {
1102   // This is binary data. Print it in a grid of hex bytes for readability.
1103   const size_t Cols = 4;
1104   for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
1105     size_t J = I, EJ = std::min(I + Cols, Data.size());
1106     assert(EJ > 0);
1107     OS << MAI->getData8bitsDirective();
1108     for (; J < EJ - 1; ++J)
1109       OS << format("0x%02x", uint8_t(Data[J])) << ", ";
1110     OS << format("0x%02x", uint8_t(Data[J]));
1111     EmitEOL();
1112   }
1113 }
1114 
emitIntValue(uint64_t Value,unsigned Size)1115 void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
1116   emitValue(MCConstantExpr::create(Value, getContext()), Size);
1117 }
1118 
emitIntValueInHex(uint64_t Value,unsigned Size)1119 void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
1120   emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
1121 }
1122 
emitIntValueInHexWithPadding(uint64_t Value,unsigned Size)1123 void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
1124                                                  unsigned Size) {
1125   emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
1126 }
1127 
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)1128 void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
1129                                   SMLoc Loc) {
1130   assert(Size <= 8 && "Invalid size");
1131   assert(getCurrentSectionOnly() &&
1132          "Cannot emit contents before setting section!");
1133   const char *Directive = nullptr;
1134   switch (Size) {
1135   default: break;
1136   case 1: Directive = MAI->getData8bitsDirective();  break;
1137   case 2: Directive = MAI->getData16bitsDirective(); break;
1138   case 4: Directive = MAI->getData32bitsDirective(); break;
1139   case 8: Directive = MAI->getData64bitsDirective(); break;
1140   }
1141 
1142   if (!Directive) {
1143     int64_t IntValue;
1144     if (!Value->evaluateAsAbsolute(IntValue))
1145       report_fatal_error("Don't know how to emit this value.");
1146 
1147     // We couldn't handle the requested integer size so we fallback by breaking
1148     // the request down into several, smaller, integers.
1149     // Since sizes greater or equal to "Size" are invalid, we use the greatest
1150     // power of 2 that is less than "Size" as our largest piece of granularity.
1151     bool IsLittleEndian = MAI->isLittleEndian();
1152     for (unsigned Emitted = 0; Emitted != Size;) {
1153       unsigned Remaining = Size - Emitted;
1154       // The size of our partial emission must be a power of two less than
1155       // Size.
1156       unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
1157       // Calculate the byte offset of our partial emission taking into account
1158       // the endianness of the target.
1159       unsigned ByteOffset =
1160           IsLittleEndian ? Emitted : (Remaining - EmissionSize);
1161       uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
1162       // We truncate our partial emission to fit within the bounds of the
1163       // emission domain.  This produces nicer output and silences potential
1164       // truncation warnings when round tripping through another assembler.
1165       uint64_t Shift = 64 - EmissionSize * 8;
1166       assert(Shift < static_cast<uint64_t>(
1167                          std::numeric_limits<unsigned long long>::digits) &&
1168              "undefined behavior");
1169       ValueToEmit &= ~0ULL >> Shift;
1170       emitIntValue(ValueToEmit, EmissionSize);
1171       Emitted += EmissionSize;
1172     }
1173     return;
1174   }
1175 
1176   assert(Directive && "Invalid size for machine code value!");
1177   OS << Directive;
1178   if (MCTargetStreamer *TS = getTargetStreamer()) {
1179     TS->emitValue(Value);
1180   } else {
1181     Value->print(OS, MAI);
1182     EmitEOL();
1183   }
1184 }
1185 
emitULEB128Value(const MCExpr * Value)1186 void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
1187   int64_t IntValue;
1188   if (Value->evaluateAsAbsolute(IntValue)) {
1189     emitULEB128IntValue(IntValue);
1190     return;
1191   }
1192   OS << "\t.uleb128 ";
1193   Value->print(OS, MAI);
1194   EmitEOL();
1195 }
1196 
emitSLEB128Value(const MCExpr * Value)1197 void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
1198   int64_t IntValue;
1199   if (Value->evaluateAsAbsolute(IntValue)) {
1200     emitSLEB128IntValue(IntValue);
1201     return;
1202   }
1203   OS << "\t.sleb128 ";
1204   Value->print(OS, MAI);
1205   EmitEOL();
1206 }
1207 
emitDTPRel64Value(const MCExpr * Value)1208 void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {
1209   assert(MAI->getDTPRel64Directive() != nullptr);
1210   OS << MAI->getDTPRel64Directive();
1211   Value->print(OS, MAI);
1212   EmitEOL();
1213 }
1214 
emitDTPRel32Value(const MCExpr * Value)1215 void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {
1216   assert(MAI->getDTPRel32Directive() != nullptr);
1217   OS << MAI->getDTPRel32Directive();
1218   Value->print(OS, MAI);
1219   EmitEOL();
1220 }
1221 
emitTPRel64Value(const MCExpr * Value)1222 void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {
1223   assert(MAI->getTPRel64Directive() != nullptr);
1224   OS << MAI->getTPRel64Directive();
1225   Value->print(OS, MAI);
1226   EmitEOL();
1227 }
1228 
emitTPRel32Value(const MCExpr * Value)1229 void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {
1230   assert(MAI->getTPRel32Directive() != nullptr);
1231   OS << MAI->getTPRel32Directive();
1232   Value->print(OS, MAI);
1233   EmitEOL();
1234 }
1235 
emitGPRel64Value(const MCExpr * Value)1236 void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {
1237   assert(MAI->getGPRel64Directive() != nullptr);
1238   OS << MAI->getGPRel64Directive();
1239   Value->print(OS, MAI);
1240   EmitEOL();
1241 }
1242 
emitGPRel32Value(const MCExpr * Value)1243 void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {
1244   assert(MAI->getGPRel32Directive() != nullptr);
1245   OS << MAI->getGPRel32Directive();
1246   Value->print(OS, MAI);
1247   EmitEOL();
1248 }
1249 
emitFill(const MCExpr & NumBytes,uint64_t FillValue,SMLoc Loc)1250 void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
1251                              SMLoc Loc) {
1252   int64_t IntNumBytes;
1253   const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
1254   if (IsAbsolute && IntNumBytes == 0)
1255     return;
1256 
1257   if (const char *ZeroDirective = MAI->getZeroDirective()) {
1258     if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {
1259       // FIXME: Emit location directives
1260       OS << ZeroDirective;
1261       NumBytes.print(OS, MAI);
1262       if (FillValue != 0)
1263         OS << ',' << (int)FillValue;
1264       EmitEOL();
1265     } else {
1266       if (!IsAbsolute)
1267         report_fatal_error(
1268             "Cannot emit non-absolute expression lengths of fill.");
1269       for (int i = 0; i < IntNumBytes; ++i) {
1270         OS << MAI->getData8bitsDirective() << (int)FillValue;
1271         EmitEOL();
1272       }
1273     }
1274     return;
1275   }
1276 
1277   MCStreamer::emitFill(NumBytes, FillValue);
1278 }
1279 
emitFill(const MCExpr & NumValues,int64_t Size,int64_t Expr,SMLoc Loc)1280 void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
1281                              int64_t Expr, SMLoc Loc) {
1282   // FIXME: Emit location directives
1283   OS << "\t.fill\t";
1284   NumValues.print(OS, MAI);
1285   OS << ", " << Size << ", 0x";
1286   OS.write_hex(truncateToSize(Expr, 4));
1287   EmitEOL();
1288 }
1289 
emitValueToAlignment(unsigned ByteAlignment,int64_t Value,unsigned ValueSize,unsigned MaxBytesToEmit)1290 void MCAsmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
1291                                          unsigned ValueSize,
1292                                          unsigned MaxBytesToEmit) {
1293   if (MAI->useDotAlignForAlignment()) {
1294     if (!isPowerOf2_32(ByteAlignment))
1295       report_fatal_error("Only power-of-two alignments are supported "
1296                          "with .align.");
1297     OS << "\t.align\t";
1298     OS << Log2_32(ByteAlignment);
1299     EmitEOL();
1300     return;
1301   }
1302 
1303   // Some assemblers don't support non-power of two alignments, so we always
1304   // emit alignments as a power of two if possible.
1305   if (isPowerOf2_32(ByteAlignment)) {
1306     switch (ValueSize) {
1307     default:
1308       llvm_unreachable("Invalid size for machine code value!");
1309     case 1:
1310       OS << "\t.p2align\t";
1311       break;
1312     case 2:
1313       OS << ".p2alignw ";
1314       break;
1315     case 4:
1316       OS << ".p2alignl ";
1317       break;
1318     case 8:
1319       llvm_unreachable("Unsupported alignment size!");
1320     }
1321 
1322     OS << Log2_32(ByteAlignment);
1323 
1324     if (Value || MaxBytesToEmit) {
1325       OS << ", 0x";
1326       OS.write_hex(truncateToSize(Value, ValueSize));
1327 
1328       if (MaxBytesToEmit)
1329         OS << ", " << MaxBytesToEmit;
1330     }
1331     EmitEOL();
1332     return;
1333   }
1334 
1335   // Non-power of two alignment.  This is not widely supported by assemblers.
1336   // FIXME: Parameterize this based on MAI.
1337   switch (ValueSize) {
1338   default: llvm_unreachable("Invalid size for machine code value!");
1339   case 1: OS << ".balign";  break;
1340   case 2: OS << ".balignw"; break;
1341   case 4: OS << ".balignl"; break;
1342   case 8: llvm_unreachable("Unsupported alignment size!");
1343   }
1344 
1345   OS << ' ' << ByteAlignment;
1346   OS << ", " << truncateToSize(Value, ValueSize);
1347   if (MaxBytesToEmit)
1348     OS << ", " << MaxBytesToEmit;
1349   EmitEOL();
1350 }
1351 
emitCodeAlignment(unsigned ByteAlignment,unsigned MaxBytesToEmit)1352 void MCAsmStreamer::emitCodeAlignment(unsigned ByteAlignment,
1353                                       unsigned MaxBytesToEmit) {
1354   // Emit with a text fill value.
1355   emitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
1356                        1, MaxBytesToEmit);
1357 }
1358 
emitValueToOffset(const MCExpr * Offset,unsigned char Value,SMLoc Loc)1359 void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
1360                                       unsigned char Value,
1361                                       SMLoc Loc) {
1362   // FIXME: Verify that Offset is associated with the current section.
1363   OS << ".org ";
1364   Offset->print(OS, MAI);
1365   OS << ", " << (unsigned)Value;
1366   EmitEOL();
1367 }
1368 
emitFileDirective(StringRef Filename)1369 void MCAsmStreamer::emitFileDirective(StringRef Filename) {
1370   assert(MAI->hasSingleParameterDotFile());
1371   OS << "\t.file\t";
1372   PrintQuotedString(Filename, OS);
1373   EmitEOL();
1374 }
1375 
printDwarfFileDirective(unsigned FileNo,StringRef Directory,StringRef Filename,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source,bool UseDwarfDirectory,raw_svector_ostream & OS)1376 static void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
1377                                     StringRef Filename,
1378                                     Optional<MD5::MD5Result> Checksum,
1379                                     Optional<StringRef> Source,
1380                                     bool UseDwarfDirectory,
1381                                     raw_svector_ostream &OS) {
1382   SmallString<128> FullPathName;
1383 
1384   if (!UseDwarfDirectory && !Directory.empty()) {
1385     if (sys::path::is_absolute(Filename))
1386       Directory = "";
1387     else {
1388       FullPathName = Directory;
1389       sys::path::append(FullPathName, Filename);
1390       Directory = "";
1391       Filename = FullPathName;
1392     }
1393   }
1394 
1395   OS << "\t.file\t" << FileNo << ' ';
1396   if (!Directory.empty()) {
1397     PrintQuotedString(Directory, OS);
1398     OS << ' ';
1399   }
1400   PrintQuotedString(Filename, OS);
1401   if (Checksum)
1402     OS << " md5 0x" << Checksum->digest();
1403   if (Source) {
1404     OS << " source ";
1405     PrintQuotedString(*Source, OS);
1406   }
1407 }
1408 
tryEmitDwarfFileDirective(unsigned FileNo,StringRef Directory,StringRef Filename,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source,unsigned CUID)1409 Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
1410     unsigned FileNo, StringRef Directory, StringRef Filename,
1411     Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) {
1412   assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
1413 
1414   MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
1415   unsigned NumFiles = Table.getMCDwarfFiles().size();
1416   Expected<unsigned> FileNoOrErr =
1417       Table.tryGetFile(Directory, Filename, Checksum, Source,
1418                        getContext().getDwarfVersion(), FileNo);
1419   if (!FileNoOrErr)
1420     return FileNoOrErr.takeError();
1421   FileNo = FileNoOrErr.get();
1422   if (NumFiles == Table.getMCDwarfFiles().size())
1423     return FileNo;
1424 
1425   SmallString<128> Str;
1426   raw_svector_ostream OS1(Str);
1427   printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
1428                           UseDwarfDirectory, OS1);
1429 
1430   if (MCTargetStreamer *TS = getTargetStreamer())
1431     TS->emitDwarfFileDirective(OS1.str());
1432   else
1433     emitRawText(OS1.str());
1434 
1435   return FileNo;
1436 }
1437 
emitDwarfFile0Directive(StringRef Directory,StringRef Filename,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source,unsigned CUID)1438 void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
1439                                             StringRef Filename,
1440                                             Optional<MD5::MD5Result> Checksum,
1441                                             Optional<StringRef> Source,
1442                                             unsigned CUID) {
1443   assert(CUID == 0);
1444   // .file 0 is new for DWARF v5.
1445   if (getContext().getDwarfVersion() < 5)
1446     return;
1447   // Inform MCDwarf about the root file.
1448   getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
1449                                       Source);
1450 
1451   SmallString<128> Str;
1452   raw_svector_ostream OS1(Str);
1453   printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
1454                           UseDwarfDirectory, OS1);
1455 
1456   if (MCTargetStreamer *TS = getTargetStreamer())
1457     TS->emitDwarfFileDirective(OS1.str());
1458   else
1459     emitRawText(OS1.str());
1460 }
1461 
emitDwarfLocDirective(unsigned FileNo,unsigned Line,unsigned Column,unsigned Flags,unsigned Isa,unsigned Discriminator,StringRef FileName)1462 void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
1463                                           unsigned Column, unsigned Flags,
1464                                           unsigned Isa, unsigned Discriminator,
1465                                           StringRef FileName) {
1466   OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
1467   if (MAI->supportsExtendedDwarfLocDirective()) {
1468     if (Flags & DWARF2_FLAG_BASIC_BLOCK)
1469       OS << " basic_block";
1470     if (Flags & DWARF2_FLAG_PROLOGUE_END)
1471       OS << " prologue_end";
1472     if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
1473       OS << " epilogue_begin";
1474 
1475     unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
1476     if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
1477       OS << " is_stmt ";
1478 
1479       if (Flags & DWARF2_FLAG_IS_STMT)
1480         OS << "1";
1481       else
1482         OS << "0";
1483     }
1484 
1485     if (Isa)
1486       OS << " isa " << Isa;
1487     if (Discriminator)
1488       OS << " discriminator " << Discriminator;
1489   }
1490 
1491   if (IsVerboseAsm) {
1492     OS.PadToColumn(MAI->getCommentColumn());
1493     OS << MAI->getCommentString() << ' ' << FileName << ':'
1494        << Line << ':' << Column;
1495   }
1496   EmitEOL();
1497   this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1498                                           Discriminator, FileName);
1499 }
1500 
getDwarfLineTableSymbol(unsigned CUID)1501 MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
1502   // Always use the zeroth line table, since asm syntax only supports one line
1503   // table for now.
1504   return MCStreamer::getDwarfLineTableSymbol(0);
1505 }
1506 
EmitCVFileDirective(unsigned FileNo,StringRef Filename,ArrayRef<uint8_t> Checksum,unsigned ChecksumKind)1507 bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
1508                                         ArrayRef<uint8_t> Checksum,
1509                                         unsigned ChecksumKind) {
1510   if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
1511                                            ChecksumKind))
1512     return false;
1513 
1514   OS << "\t.cv_file\t" << FileNo << ' ';
1515   PrintQuotedString(Filename, OS);
1516 
1517   if (!ChecksumKind) {
1518     EmitEOL();
1519     return true;
1520   }
1521 
1522   OS << ' ';
1523   PrintQuotedString(toHex(Checksum), OS);
1524   OS << ' ' << ChecksumKind;
1525 
1526   EmitEOL();
1527   return true;
1528 }
1529 
EmitCVFuncIdDirective(unsigned FuncId)1530 bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
1531   OS << "\t.cv_func_id " << FuncId << '\n';
1532   return MCStreamer::EmitCVFuncIdDirective(FuncId);
1533 }
1534 
EmitCVInlineSiteIdDirective(unsigned FunctionId,unsigned IAFunc,unsigned IAFile,unsigned IALine,unsigned IACol,SMLoc Loc)1535 bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
1536                                                 unsigned IAFunc,
1537                                                 unsigned IAFile,
1538                                                 unsigned IALine, unsigned IACol,
1539                                                 SMLoc Loc) {
1540   OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
1541      << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
1542   return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
1543                                                  IALine, IACol, Loc);
1544 }
1545 
emitCVLocDirective(unsigned FunctionId,unsigned FileNo,unsigned Line,unsigned Column,bool PrologueEnd,bool IsStmt,StringRef FileName,SMLoc Loc)1546 void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
1547                                        unsigned Line, unsigned Column,
1548                                        bool PrologueEnd, bool IsStmt,
1549                                        StringRef FileName, SMLoc Loc) {
1550   // Validate the directive.
1551   if (!checkCVLocSection(FunctionId, FileNo, Loc))
1552     return;
1553 
1554   OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
1555      << Column;
1556   if (PrologueEnd)
1557     OS << " prologue_end";
1558 
1559   if (IsStmt)
1560     OS << " is_stmt 1";
1561 
1562   if (IsVerboseAsm) {
1563     OS.PadToColumn(MAI->getCommentColumn());
1564     OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
1565        << Column;
1566   }
1567   EmitEOL();
1568 }
1569 
emitCVLinetableDirective(unsigned FunctionId,const MCSymbol * FnStart,const MCSymbol * FnEnd)1570 void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
1571                                              const MCSymbol *FnStart,
1572                                              const MCSymbol *FnEnd) {
1573   OS << "\t.cv_linetable\t" << FunctionId << ", ";
1574   FnStart->print(OS, MAI);
1575   OS << ", ";
1576   FnEnd->print(OS, MAI);
1577   EmitEOL();
1578   this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
1579 }
1580 
emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,unsigned SourceFileId,unsigned SourceLineNum,const MCSymbol * FnStartSym,const MCSymbol * FnEndSym)1581 void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
1582                                                    unsigned SourceFileId,
1583                                                    unsigned SourceLineNum,
1584                                                    const MCSymbol *FnStartSym,
1585                                                    const MCSymbol *FnEndSym) {
1586   OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
1587      << ' ' << SourceLineNum << ' ';
1588   FnStartSym->print(OS, MAI);
1589   OS << ' ';
1590   FnEndSym->print(OS, MAI);
1591   EmitEOL();
1592   this->MCStreamer::emitCVInlineLinetableDirective(
1593       PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
1594 }
1595 
PrintCVDefRangePrefix(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges)1596 void MCAsmStreamer::PrintCVDefRangePrefix(
1597     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
1598   OS << "\t.cv_def_range\t";
1599   for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
1600     OS << ' ';
1601     Range.first->print(OS, MAI);
1602     OS << ' ';
1603     Range.second->print(OS, MAI);
1604   }
1605 }
1606 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeRegisterRelHeader DRHdr)1607 void MCAsmStreamer::emitCVDefRangeDirective(
1608     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1609     codeview::DefRangeRegisterRelHeader DRHdr) {
1610   PrintCVDefRangePrefix(Ranges);
1611   OS << ", reg_rel, ";
1612   OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
1613      << DRHdr.BasePointerOffset;
1614   EmitEOL();
1615 }
1616 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeSubfieldRegisterHeader DRHdr)1617 void MCAsmStreamer::emitCVDefRangeDirective(
1618     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1619     codeview::DefRangeSubfieldRegisterHeader DRHdr) {
1620   PrintCVDefRangePrefix(Ranges);
1621   OS << ", subfield_reg, ";
1622   OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
1623   EmitEOL();
1624 }
1625 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeRegisterHeader DRHdr)1626 void MCAsmStreamer::emitCVDefRangeDirective(
1627     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1628     codeview::DefRangeRegisterHeader DRHdr) {
1629   PrintCVDefRangePrefix(Ranges);
1630   OS << ", reg, ";
1631   OS << DRHdr.Register;
1632   EmitEOL();
1633 }
1634 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeFramePointerRelHeader DRHdr)1635 void MCAsmStreamer::emitCVDefRangeDirective(
1636     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
1637     codeview::DefRangeFramePointerRelHeader DRHdr) {
1638   PrintCVDefRangePrefix(Ranges);
1639   OS << ", frame_ptr_rel, ";
1640   OS << DRHdr.Offset;
1641   EmitEOL();
1642 }
1643 
emitCVStringTableDirective()1644 void MCAsmStreamer::emitCVStringTableDirective() {
1645   OS << "\t.cv_stringtable";
1646   EmitEOL();
1647 }
1648 
emitCVFileChecksumsDirective()1649 void MCAsmStreamer::emitCVFileChecksumsDirective() {
1650   OS << "\t.cv_filechecksums";
1651   EmitEOL();
1652 }
1653 
emitCVFileChecksumOffsetDirective(unsigned FileNo)1654 void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
1655   OS << "\t.cv_filechecksumoffset\t" << FileNo;
1656   EmitEOL();
1657 }
1658 
EmitCVFPOData(const MCSymbol * ProcSym,SMLoc L)1659 void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
1660   OS << "\t.cv_fpo_data\t";
1661   ProcSym->print(OS, MAI);
1662   EmitEOL();
1663 }
1664 
emitIdent(StringRef IdentString)1665 void MCAsmStreamer::emitIdent(StringRef IdentString) {
1666   assert(MAI->hasIdentDirective() && ".ident directive not supported");
1667   OS << "\t.ident\t";
1668   PrintQuotedString(IdentString, OS);
1669   EmitEOL();
1670 }
1671 
emitCFISections(bool EH,bool Debug)1672 void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
1673   MCStreamer::emitCFISections(EH, Debug);
1674   OS << "\t.cfi_sections ";
1675   if (EH) {
1676     OS << ".eh_frame";
1677     if (Debug)
1678       OS << ", .debug_frame";
1679   } else if (Debug) {
1680     OS << ".debug_frame";
1681   }
1682 
1683   EmitEOL();
1684 }
1685 
emitCFIStartProcImpl(MCDwarfFrameInfo & Frame)1686 void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
1687   OS << "\t.cfi_startproc";
1688   if (Frame.IsSimple)
1689     OS << " simple";
1690   EmitEOL();
1691 }
1692 
emitCFIEndProcImpl(MCDwarfFrameInfo & Frame)1693 void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
1694   MCStreamer::emitCFIEndProcImpl(Frame);
1695   OS << "\t.cfi_endproc";
1696   EmitEOL();
1697 }
1698 
EmitRegisterName(int64_t Register)1699 void MCAsmStreamer::EmitRegisterName(int64_t Register) {
1700   if (!MAI->useDwarfRegNumForCFI()) {
1701     // User .cfi_* directives can use arbitrary DWARF register numbers, not
1702     // just ones that map to LLVM register numbers and have known names.
1703     // Fall back to using the original number directly if no name is known.
1704     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
1705     if (Optional<unsigned> LLVMRegister = MRI->getLLVMRegNum(Register, true)) {
1706       InstPrinter->printRegName(OS, *LLVMRegister);
1707       return;
1708     }
1709   }
1710   OS << Register;
1711 }
1712 
emitCFIDefCfa(int64_t Register,int64_t Offset)1713 void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) {
1714   MCStreamer::emitCFIDefCfa(Register, Offset);
1715   OS << "\t.cfi_def_cfa ";
1716   EmitRegisterName(Register);
1717   OS << ", " << Offset;
1718   EmitEOL();
1719 }
1720 
emitCFIDefCfaOffset(int64_t Offset)1721 void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset) {
1722   MCStreamer::emitCFIDefCfaOffset(Offset);
1723   OS << "\t.cfi_def_cfa_offset " << Offset;
1724   EmitEOL();
1725 }
1726 
PrintCFIEscape(llvm::formatted_raw_ostream & OS,StringRef Values)1727 static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
1728   OS << "\t.cfi_escape ";
1729   if (!Values.empty()) {
1730     size_t e = Values.size() - 1;
1731     for (size_t i = 0; i < e; ++i)
1732       OS << format("0x%02x", uint8_t(Values[i])) << ", ";
1733     OS << format("0x%02x", uint8_t(Values[e]));
1734   }
1735 }
1736 
emitCFIEscape(StringRef Values)1737 void MCAsmStreamer::emitCFIEscape(StringRef Values) {
1738   MCStreamer::emitCFIEscape(Values);
1739   PrintCFIEscape(OS, Values);
1740   EmitEOL();
1741 }
1742 
emitCFIGnuArgsSize(int64_t Size)1743 void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size) {
1744   MCStreamer::emitCFIGnuArgsSize(Size);
1745 
1746   uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
1747   unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
1748 
1749   PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
1750   EmitEOL();
1751 }
1752 
emitCFIDefCfaRegister(int64_t Register)1753 void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register) {
1754   MCStreamer::emitCFIDefCfaRegister(Register);
1755   OS << "\t.cfi_def_cfa_register ";
1756   EmitRegisterName(Register);
1757   EmitEOL();
1758 }
1759 
emitCFIOffset(int64_t Register,int64_t Offset)1760 void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset) {
1761   this->MCStreamer::emitCFIOffset(Register, Offset);
1762   OS << "\t.cfi_offset ";
1763   EmitRegisterName(Register);
1764   OS << ", " << Offset;
1765   EmitEOL();
1766 }
1767 
emitCFIPersonality(const MCSymbol * Sym,unsigned Encoding)1768 void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
1769                                        unsigned Encoding) {
1770   MCStreamer::emitCFIPersonality(Sym, Encoding);
1771   OS << "\t.cfi_personality " << Encoding << ", ";
1772   Sym->print(OS, MAI);
1773   EmitEOL();
1774 }
1775 
emitCFILsda(const MCSymbol * Sym,unsigned Encoding)1776 void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
1777   MCStreamer::emitCFILsda(Sym, Encoding);
1778   OS << "\t.cfi_lsda " << Encoding << ", ";
1779   Sym->print(OS, MAI);
1780   EmitEOL();
1781 }
1782 
emitCFIRememberState()1783 void MCAsmStreamer::emitCFIRememberState() {
1784   MCStreamer::emitCFIRememberState();
1785   OS << "\t.cfi_remember_state";
1786   EmitEOL();
1787 }
1788 
emitCFIRestoreState()1789 void MCAsmStreamer::emitCFIRestoreState() {
1790   MCStreamer::emitCFIRestoreState();
1791   OS << "\t.cfi_restore_state";
1792   EmitEOL();
1793 }
1794 
emitCFIRestore(int64_t Register)1795 void MCAsmStreamer::emitCFIRestore(int64_t Register) {
1796   MCStreamer::emitCFIRestore(Register);
1797   OS << "\t.cfi_restore ";
1798   EmitRegisterName(Register);
1799   EmitEOL();
1800 }
1801 
emitCFISameValue(int64_t Register)1802 void MCAsmStreamer::emitCFISameValue(int64_t Register) {
1803   MCStreamer::emitCFISameValue(Register);
1804   OS << "\t.cfi_same_value ";
1805   EmitRegisterName(Register);
1806   EmitEOL();
1807 }
1808 
emitCFIRelOffset(int64_t Register,int64_t Offset)1809 void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) {
1810   MCStreamer::emitCFIRelOffset(Register, Offset);
1811   OS << "\t.cfi_rel_offset ";
1812   EmitRegisterName(Register);
1813   OS << ", " << Offset;
1814   EmitEOL();
1815 }
1816 
emitCFIAdjustCfaOffset(int64_t Adjustment)1817 void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) {
1818   MCStreamer::emitCFIAdjustCfaOffset(Adjustment);
1819   OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
1820   EmitEOL();
1821 }
1822 
emitCFISignalFrame()1823 void MCAsmStreamer::emitCFISignalFrame() {
1824   MCStreamer::emitCFISignalFrame();
1825   OS << "\t.cfi_signal_frame";
1826   EmitEOL();
1827 }
1828 
emitCFIUndefined(int64_t Register)1829 void MCAsmStreamer::emitCFIUndefined(int64_t Register) {
1830   MCStreamer::emitCFIUndefined(Register);
1831   OS << "\t.cfi_undefined ";
1832   EmitRegisterName(Register);
1833   EmitEOL();
1834 }
1835 
emitCFIRegister(int64_t Register1,int64_t Register2)1836 void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) {
1837   MCStreamer::emitCFIRegister(Register1, Register2);
1838   OS << "\t.cfi_register ";
1839   EmitRegisterName(Register1);
1840   OS << ", ";
1841   EmitRegisterName(Register2);
1842   EmitEOL();
1843 }
1844 
emitCFIWindowSave()1845 void MCAsmStreamer::emitCFIWindowSave() {
1846   MCStreamer::emitCFIWindowSave();
1847   OS << "\t.cfi_window_save";
1848   EmitEOL();
1849 }
1850 
emitCFINegateRAState()1851 void MCAsmStreamer::emitCFINegateRAState() {
1852   MCStreamer::emitCFINegateRAState();
1853   OS << "\t.cfi_negate_ra_state";
1854   EmitEOL();
1855 }
1856 
emitCFIReturnColumn(int64_t Register)1857 void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
1858   MCStreamer::emitCFIReturnColumn(Register);
1859   OS << "\t.cfi_return_column ";
1860   EmitRegisterName(Register);
1861   EmitEOL();
1862 }
1863 
emitCFIBKeyFrame()1864 void MCAsmStreamer::emitCFIBKeyFrame() {
1865   MCStreamer::emitCFIBKeyFrame();
1866   OS << "\t.cfi_b_key_frame";
1867   EmitEOL();
1868 }
1869 
EmitWinCFIStartProc(const MCSymbol * Symbol,SMLoc Loc)1870 void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
1871   MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
1872 
1873   OS << ".seh_proc ";
1874   Symbol->print(OS, MAI);
1875   EmitEOL();
1876 }
1877 
EmitWinCFIEndProc(SMLoc Loc)1878 void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
1879   MCStreamer::EmitWinCFIEndProc(Loc);
1880 
1881   OS << "\t.seh_endproc";
1882   EmitEOL();
1883 }
1884 
EmitWinCFIFuncletOrFuncEnd(SMLoc Loc)1885 void MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
1886   MCStreamer::EmitWinCFIFuncletOrFuncEnd(Loc);
1887 
1888   OS << "\t.seh_endfunclet";
1889   EmitEOL();
1890 }
1891 
EmitWinCFIStartChained(SMLoc Loc)1892 void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
1893   MCStreamer::EmitWinCFIStartChained(Loc);
1894 
1895   OS << "\t.seh_startchained";
1896   EmitEOL();
1897 }
1898 
EmitWinCFIEndChained(SMLoc Loc)1899 void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
1900   MCStreamer::EmitWinCFIEndChained(Loc);
1901 
1902   OS << "\t.seh_endchained";
1903   EmitEOL();
1904 }
1905 
EmitWinEHHandler(const MCSymbol * Sym,bool Unwind,bool Except,SMLoc Loc)1906 void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
1907                                      bool Except, SMLoc Loc) {
1908   MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
1909 
1910   OS << "\t.seh_handler ";
1911   Sym->print(OS, MAI);
1912   if (Unwind)
1913     OS << ", @unwind";
1914   if (Except)
1915     OS << ", @except";
1916   EmitEOL();
1917 }
1918 
EmitWinEHHandlerData(SMLoc Loc)1919 void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
1920   MCStreamer::EmitWinEHHandlerData(Loc);
1921 
1922   // Switch sections. Don't call SwitchSection directly, because that will
1923   // cause the section switch to be visible in the emitted assembly.
1924   // We only do this so the section switch that terminates the handler
1925   // data block is visible.
1926   WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
1927 
1928   // Do nothing if no frame is open. MCStreamer should've already reported an
1929   // error.
1930   if (!CurFrame)
1931     return;
1932 
1933   MCSection *TextSec = &CurFrame->Function->getSection();
1934   MCSection *XData = getAssociatedXDataSection(TextSec);
1935   SwitchSectionNoChange(XData);
1936 
1937   OS << "\t.seh_handlerdata";
1938   EmitEOL();
1939 }
1940 
EmitWinCFIPushReg(MCRegister Register,SMLoc Loc)1941 void MCAsmStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
1942   MCStreamer::EmitWinCFIPushReg(Register, Loc);
1943 
1944   OS << "\t.seh_pushreg ";
1945   InstPrinter->printRegName(OS, Register);
1946   EmitEOL();
1947 }
1948 
EmitWinCFISetFrame(MCRegister Register,unsigned Offset,SMLoc Loc)1949 void MCAsmStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
1950                                        SMLoc Loc) {
1951   MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
1952 
1953   OS << "\t.seh_setframe ";
1954   InstPrinter->printRegName(OS, Register);
1955   OS << ", " << Offset;
1956   EmitEOL();
1957 }
1958 
EmitWinCFIAllocStack(unsigned Size,SMLoc Loc)1959 void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
1960   MCStreamer::EmitWinCFIAllocStack(Size, Loc);
1961 
1962   OS << "\t.seh_stackalloc " << Size;
1963   EmitEOL();
1964 }
1965 
EmitWinCFISaveReg(MCRegister Register,unsigned Offset,SMLoc Loc)1966 void MCAsmStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
1967                                       SMLoc Loc) {
1968   MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
1969 
1970   OS << "\t.seh_savereg ";
1971   InstPrinter->printRegName(OS, Register);
1972   OS << ", " << Offset;
1973   EmitEOL();
1974 }
1975 
EmitWinCFISaveXMM(MCRegister Register,unsigned Offset,SMLoc Loc)1976 void MCAsmStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
1977                                       SMLoc Loc) {
1978   MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
1979 
1980   OS << "\t.seh_savexmm ";
1981   InstPrinter->printRegName(OS, Register);
1982   OS << ", " << Offset;
1983   EmitEOL();
1984 }
1985 
EmitWinCFIPushFrame(bool Code,SMLoc Loc)1986 void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
1987   MCStreamer::EmitWinCFIPushFrame(Code, Loc);
1988 
1989   OS << "\t.seh_pushframe";
1990   if (Code)
1991     OS << " @code";
1992   EmitEOL();
1993 }
1994 
EmitWinCFIEndProlog(SMLoc Loc)1995 void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
1996   MCStreamer::EmitWinCFIEndProlog(Loc);
1997 
1998   OS << "\t.seh_endprologue";
1999   EmitEOL();
2000 }
2001 
emitCGProfileEntry(const MCSymbolRefExpr * From,const MCSymbolRefExpr * To,uint64_t Count)2002 void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
2003                                        const MCSymbolRefExpr *To,
2004                                        uint64_t Count) {
2005   OS << "\t.cg_profile ";
2006   From->getSymbol().print(OS, MAI);
2007   OS << ", ";
2008   To->getSymbol().print(OS, MAI);
2009   OS << ", " << Count;
2010   EmitEOL();
2011 }
2012 
AddEncodingComment(const MCInst & Inst,const MCSubtargetInfo & STI)2013 void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
2014                                        const MCSubtargetInfo &STI) {
2015   raw_ostream &OS = GetCommentOS();
2016   SmallString<256> Code;
2017   SmallVector<MCFixup, 4> Fixups;
2018   raw_svector_ostream VecOS(Code);
2019 
2020   // If we have no code emitter, don't emit code.
2021   if (!getAssembler().getEmitterPtr())
2022     return;
2023 
2024   getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
2025 
2026   // If we are showing fixups, create symbolic markers in the encoded
2027   // representation. We do this by making a per-bit map to the fixup item index,
2028   // then trying to display it as nicely as possible.
2029   SmallVector<uint8_t, 64> FixupMap;
2030   FixupMap.resize(Code.size() * 8);
2031   for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
2032     FixupMap[i] = 0;
2033 
2034   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
2035     MCFixup &F = Fixups[i];
2036     const MCFixupKindInfo &Info =
2037         getAssembler().getBackend().getFixupKindInfo(F.getKind());
2038     for (unsigned j = 0; j != Info.TargetSize; ++j) {
2039       unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
2040       assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
2041       FixupMap[Index] = 1 + i;
2042     }
2043   }
2044 
2045   // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
2046   // high order halfword of a 32-bit Thumb2 instruction is emitted first.
2047   OS << "encoding: [";
2048   for (unsigned i = 0, e = Code.size(); i != e; ++i) {
2049     if (i)
2050       OS << ',';
2051 
2052     // See if all bits are the same map entry.
2053     uint8_t MapEntry = FixupMap[i * 8 + 0];
2054     for (unsigned j = 1; j != 8; ++j) {
2055       if (FixupMap[i * 8 + j] == MapEntry)
2056         continue;
2057 
2058       MapEntry = uint8_t(~0U);
2059       break;
2060     }
2061 
2062     if (MapEntry != uint8_t(~0U)) {
2063       if (MapEntry == 0) {
2064         OS << format("0x%02x", uint8_t(Code[i]));
2065       } else {
2066         if (Code[i]) {
2067           // FIXME: Some of the 8 bits require fix up.
2068           OS << format("0x%02x", uint8_t(Code[i])) << '\''
2069              << char('A' + MapEntry - 1) << '\'';
2070         } else
2071           OS << char('A' + MapEntry - 1);
2072       }
2073     } else {
2074       // Otherwise, write out in binary.
2075       OS << "0b";
2076       for (unsigned j = 8; j--;) {
2077         unsigned Bit = (Code[i] >> j) & 1;
2078 
2079         unsigned FixupBit;
2080         if (MAI->isLittleEndian())
2081           FixupBit = i * 8 + j;
2082         else
2083           FixupBit = i * 8 + (7-j);
2084 
2085         if (uint8_t MapEntry = FixupMap[FixupBit]) {
2086           assert(Bit == 0 && "Encoder wrote into fixed up bit!");
2087           OS << char('A' + MapEntry - 1);
2088         } else
2089           OS << Bit;
2090       }
2091     }
2092   }
2093   OS << "]\n";
2094 
2095   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
2096     MCFixup &F = Fixups[i];
2097     const MCFixupKindInfo &Info =
2098         getAssembler().getBackend().getFixupKindInfo(F.getKind());
2099     OS << "  fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
2100        << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
2101   }
2102 }
2103 
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)2104 void MCAsmStreamer::emitInstruction(const MCInst &Inst,
2105                                     const MCSubtargetInfo &STI) {
2106   assert(getCurrentSectionOnly() &&
2107          "Cannot emit contents before setting section!");
2108 
2109   // Show the encoding in a comment if we have a code emitter.
2110   AddEncodingComment(Inst, STI);
2111 
2112   // Show the MCInst if enabled.
2113   if (ShowInst) {
2114     Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
2115     GetCommentOS() << "\n";
2116   }
2117 
2118   if(getTargetStreamer())
2119     getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
2120   else
2121     InstPrinter->printInst(&Inst, 0, "", STI, OS);
2122 
2123   StringRef Comments = CommentToEmit;
2124   if (Comments.size() && Comments.back() != '\n')
2125     GetCommentOS() << "\n";
2126 
2127   EmitEOL();
2128 }
2129 
emitPseudoProbe(uint64_t Guid,uint64_t Index,uint64_t Type,uint64_t Attr,const MCPseudoProbeInlineStack & InlineStack)2130 void MCAsmStreamer::emitPseudoProbe(
2131     uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attr,
2132     const MCPseudoProbeInlineStack &InlineStack) {
2133   OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " "
2134      << Attr;
2135   // Emit inline stack like
2136   //  @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:11
2137   for (const auto &Site : InlineStack)
2138     OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);
2139   EmitEOL();
2140 }
2141 
emitBundleAlignMode(unsigned AlignPow2)2142 void MCAsmStreamer::emitBundleAlignMode(unsigned AlignPow2) {
2143   OS << "\t.bundle_align_mode " << AlignPow2;
2144   EmitEOL();
2145 }
2146 
emitBundleLock(bool AlignToEnd)2147 void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {
2148   OS << "\t.bundle_lock";
2149   if (AlignToEnd)
2150     OS << " align_to_end";
2151   EmitEOL();
2152 }
2153 
emitBundleUnlock()2154 void MCAsmStreamer::emitBundleUnlock() {
2155   OS << "\t.bundle_unlock";
2156   EmitEOL();
2157 }
2158 
2159 Optional<std::pair<bool, std::string>>
emitRelocDirective(const MCExpr & Offset,StringRef Name,const MCExpr * Expr,SMLoc,const MCSubtargetInfo & STI)2160 MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
2161                                   const MCExpr *Expr, SMLoc,
2162                                   const MCSubtargetInfo &STI) {
2163   OS << "\t.reloc ";
2164   Offset.print(OS, MAI);
2165   OS << ", " << Name;
2166   if (Expr) {
2167     OS << ", ";
2168     Expr->print(OS, MAI);
2169   }
2170   EmitEOL();
2171   return None;
2172 }
2173 
emitAddrsig()2174 void MCAsmStreamer::emitAddrsig() {
2175   OS << "\t.addrsig";
2176   EmitEOL();
2177 }
2178 
emitAddrsigSym(const MCSymbol * Sym)2179 void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
2180   OS << "\t.addrsig_sym ";
2181   Sym->print(OS, MAI);
2182   EmitEOL();
2183 }
2184 
2185 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
2186 /// the specified string in the output .s file.  This capability is
2187 /// indicated by the hasRawTextSupport() predicate.
emitRawTextImpl(StringRef String)2188 void MCAsmStreamer::emitRawTextImpl(StringRef String) {
2189   if (!String.empty() && String.back() == '\n')
2190     String = String.substr(0, String.size()-1);
2191   OS << String;
2192   EmitEOL();
2193 }
2194 
finishImpl()2195 void MCAsmStreamer::finishImpl() {
2196   // If we are generating dwarf for assembly source files dump out the sections.
2197   if (getContext().getGenDwarfForAssembly())
2198     MCGenDwarfInfo::Emit(this);
2199 
2200   // Emit the label for the line table, if requested - since the rest of the
2201   // line table will be defined by .loc/.file directives, and not emitted
2202   // directly, the label is the only work required here.
2203   const auto &Tables = getContext().getMCDwarfLineTables();
2204   if (!Tables.empty()) {
2205     assert(Tables.size() == 1 && "asm output only supports one line table");
2206     if (auto *Label = Tables.begin()->second.getLabel()) {
2207       SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
2208       emitLabel(Label);
2209     }
2210   }
2211 }
2212 
createAsmStreamer(MCContext & Context,std::unique_ptr<formatted_raw_ostream> OS,bool isVerboseAsm,bool useDwarfDirectory,MCInstPrinter * IP,std::unique_ptr<MCCodeEmitter> && CE,std::unique_ptr<MCAsmBackend> && MAB,bool ShowInst)2213 MCStreamer *llvm::createAsmStreamer(MCContext &Context,
2214                                     std::unique_ptr<formatted_raw_ostream> OS,
2215                                     bool isVerboseAsm, bool useDwarfDirectory,
2216                                     MCInstPrinter *IP,
2217                                     std::unique_ptr<MCCodeEmitter> &&CE,
2218                                     std::unique_ptr<MCAsmBackend> &&MAB,
2219                                     bool ShowInst) {
2220   return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
2221                            useDwarfDirectory, IP, std::move(CE), std::move(MAB),
2222                            ShowInst);
2223 }
2224