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