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