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