106f32e7eSjoerg //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output ----------*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg 
906f32e7eSjoerg #include "llvm/ADT/Optional.h"
1006f32e7eSjoerg #include "llvm/ADT/STLExtras.h"
1106f32e7eSjoerg #include "llvm/ADT/SmallString.h"
1206f32e7eSjoerg #include "llvm/ADT/StringExtras.h"
1306f32e7eSjoerg #include "llvm/ADT/Twine.h"
1406f32e7eSjoerg #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
1506f32e7eSjoerg #include "llvm/MC/MCAsmBackend.h"
1606f32e7eSjoerg #include "llvm/MC/MCAsmInfo.h"
1706f32e7eSjoerg #include "llvm/MC/MCAssembler.h"
1806f32e7eSjoerg #include "llvm/MC/MCCodeEmitter.h"
1906f32e7eSjoerg #include "llvm/MC/MCCodeView.h"
2006f32e7eSjoerg #include "llvm/MC/MCContext.h"
2106f32e7eSjoerg #include "llvm/MC/MCExpr.h"
2206f32e7eSjoerg #include "llvm/MC/MCFixupKindInfo.h"
2306f32e7eSjoerg #include "llvm/MC/MCInst.h"
2406f32e7eSjoerg #include "llvm/MC/MCInstPrinter.h"
2506f32e7eSjoerg #include "llvm/MC/MCObjectFileInfo.h"
2606f32e7eSjoerg #include "llvm/MC/MCObjectWriter.h"
27*da58b97aSjoerg #include "llvm/MC/MCPseudoProbe.h"
2806f32e7eSjoerg #include "llvm/MC/MCRegister.h"
2906f32e7eSjoerg #include "llvm/MC/MCRegisterInfo.h"
3006f32e7eSjoerg #include "llvm/MC/MCSectionMachO.h"
3106f32e7eSjoerg #include "llvm/MC/MCStreamer.h"
32*da58b97aSjoerg #include "llvm/MC/MCSymbolXCOFF.h"
3306f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
3406f32e7eSjoerg #include "llvm/Support/Format.h"
3506f32e7eSjoerg #include "llvm/Support/FormattedStream.h"
3606f32e7eSjoerg #include "llvm/Support/LEB128.h"
3706f32e7eSjoerg #include "llvm/Support/MathExtras.h"
3806f32e7eSjoerg #include "llvm/Support/Path.h"
3906f32e7eSjoerg #include "llvm/Support/TargetRegistry.h"
4006f32e7eSjoerg #include <cctype>
4106f32e7eSjoerg 
4206f32e7eSjoerg using namespace llvm;
4306f32e7eSjoerg 
4406f32e7eSjoerg namespace {
4506f32e7eSjoerg 
4606f32e7eSjoerg class MCAsmStreamer final : public MCStreamer {
4706f32e7eSjoerg   std::unique_ptr<formatted_raw_ostream> OSOwner;
4806f32e7eSjoerg   formatted_raw_ostream &OS;
4906f32e7eSjoerg   const MCAsmInfo *MAI;
5006f32e7eSjoerg   std::unique_ptr<MCInstPrinter> InstPrinter;
5106f32e7eSjoerg   std::unique_ptr<MCAssembler> Assembler;
5206f32e7eSjoerg 
5306f32e7eSjoerg   SmallString<128> ExplicitCommentToEmit;
5406f32e7eSjoerg   SmallString<128> CommentToEmit;
5506f32e7eSjoerg   raw_svector_ostream CommentStream;
5606f32e7eSjoerg   raw_null_ostream NullStream;
5706f32e7eSjoerg 
5806f32e7eSjoerg   unsigned IsVerboseAsm : 1;
5906f32e7eSjoerg   unsigned ShowInst : 1;
6006f32e7eSjoerg   unsigned UseDwarfDirectory : 1;
6106f32e7eSjoerg 
6206f32e7eSjoerg   void EmitRegisterName(int64_t Register);
63*da58b97aSjoerg   void PrintQuotedString(StringRef Data, raw_ostream &OS) const;
64*da58b97aSjoerg   void printDwarfFileDirective(unsigned FileNo, StringRef Directory,
65*da58b97aSjoerg                                StringRef Filename,
66*da58b97aSjoerg                                Optional<MD5::MD5Result> Checksum,
67*da58b97aSjoerg                                Optional<StringRef> Source,
68*da58b97aSjoerg                                bool UseDwarfDirectory,
69*da58b97aSjoerg                                raw_svector_ostream &OS) const;
70*da58b97aSjoerg   void emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
71*da58b97aSjoerg   void emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
7206f32e7eSjoerg 
7306f32e7eSjoerg public:
MCAsmStreamer(MCContext & Context,std::unique_ptr<formatted_raw_ostream> os,bool isVerboseAsm,bool useDwarfDirectory,MCInstPrinter * printer,std::unique_ptr<MCCodeEmitter> emitter,std::unique_ptr<MCAsmBackend> asmbackend,bool showInst)7406f32e7eSjoerg   MCAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> os,
7506f32e7eSjoerg                 bool isVerboseAsm, bool useDwarfDirectory,
7606f32e7eSjoerg                 MCInstPrinter *printer, std::unique_ptr<MCCodeEmitter> emitter,
7706f32e7eSjoerg                 std::unique_ptr<MCAsmBackend> asmbackend, bool showInst)
7806f32e7eSjoerg       : MCStreamer(Context), OSOwner(std::move(os)), OS(*OSOwner),
7906f32e7eSjoerg         MAI(Context.getAsmInfo()), InstPrinter(printer),
8006f32e7eSjoerg         Assembler(std::make_unique<MCAssembler>(
8106f32e7eSjoerg             Context, std::move(asmbackend), std::move(emitter),
8206f32e7eSjoerg             (asmbackend) ? asmbackend->createObjectWriter(NullStream)
8306f32e7eSjoerg                          : nullptr)),
8406f32e7eSjoerg         CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
8506f32e7eSjoerg         ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
8606f32e7eSjoerg     assert(InstPrinter);
8706f32e7eSjoerg     if (IsVerboseAsm)
8806f32e7eSjoerg         InstPrinter->setCommentStream(CommentStream);
89*da58b97aSjoerg     if (Assembler->getBackendPtr())
90*da58b97aSjoerg       setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
91*da58b97aSjoerg 
92*da58b97aSjoerg     Context.setUseNamesOnTempLabels(true);
9306f32e7eSjoerg   }
9406f32e7eSjoerg 
getAssembler()9506f32e7eSjoerg   MCAssembler &getAssembler() { return *Assembler; }
getAssemblerPtr()9606f32e7eSjoerg   MCAssembler *getAssemblerPtr() override { return nullptr; }
9706f32e7eSjoerg 
EmitEOL()9806f32e7eSjoerg   inline void EmitEOL() {
9906f32e7eSjoerg     // Dump Explicit Comments here.
10006f32e7eSjoerg     emitExplicitComments();
10106f32e7eSjoerg     // If we don't have any comments, just emit a \n.
10206f32e7eSjoerg     if (!IsVerboseAsm) {
10306f32e7eSjoerg       OS << '\n';
10406f32e7eSjoerg       return;
10506f32e7eSjoerg     }
10606f32e7eSjoerg     EmitCommentsAndEOL();
10706f32e7eSjoerg   }
10806f32e7eSjoerg 
109*da58b97aSjoerg   void emitSyntaxDirective() override;
11006f32e7eSjoerg 
11106f32e7eSjoerg   void EmitCommentsAndEOL();
11206f32e7eSjoerg 
11306f32e7eSjoerg   /// Return true if this streamer supports verbose assembly at all.
isVerboseAsm() const11406f32e7eSjoerg   bool isVerboseAsm() const override { return IsVerboseAsm; }
11506f32e7eSjoerg 
11606f32e7eSjoerg   /// Do we support EmitRawText?
hasRawTextSupport() const11706f32e7eSjoerg   bool hasRawTextSupport() const override { return true; }
11806f32e7eSjoerg 
11906f32e7eSjoerg   /// Add a comment that can be emitted to the generated .s file to make the
12006f32e7eSjoerg   /// output of the compiler more readable. This only affects the MCAsmStreamer
12106f32e7eSjoerg   /// and only when verbose assembly output is enabled.
12206f32e7eSjoerg   void AddComment(const Twine &T, bool EOL = true) override;
12306f32e7eSjoerg 
12406f32e7eSjoerg   /// Add a comment showing the encoding of an instruction.
12506f32e7eSjoerg   void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
12606f32e7eSjoerg 
12706f32e7eSjoerg   /// Return a raw_ostream that comments can be written to.
12806f32e7eSjoerg   /// Unlike AddComment, you are required to terminate comments with \n if you
12906f32e7eSjoerg   /// use this method.
GetCommentOS()13006f32e7eSjoerg   raw_ostream &GetCommentOS() override {
13106f32e7eSjoerg     if (!IsVerboseAsm)
13206f32e7eSjoerg       return nulls();  // Discard comments unless in verbose asm mode.
13306f32e7eSjoerg     return CommentStream;
13406f32e7eSjoerg   }
13506f32e7eSjoerg 
13606f32e7eSjoerg   void emitRawComment(const Twine &T, bool TabPrefix = true) override;
13706f32e7eSjoerg 
13806f32e7eSjoerg   void addExplicitComment(const Twine &T) override;
13906f32e7eSjoerg   void emitExplicitComments() override;
14006f32e7eSjoerg 
14106f32e7eSjoerg   /// Emit a blank line to a .s file to pretty it up.
AddBlankLine()14206f32e7eSjoerg   void AddBlankLine() override {
14306f32e7eSjoerg     EmitEOL();
14406f32e7eSjoerg   }
14506f32e7eSjoerg 
14606f32e7eSjoerg   /// @name MCStreamer Interface
14706f32e7eSjoerg   /// @{
14806f32e7eSjoerg 
149*da58b97aSjoerg   void changeSection(MCSection *Section, const MCExpr *Subsection) override;
15006f32e7eSjoerg 
151*da58b97aSjoerg   void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name,
152*da58b97aSjoerg                               bool KeepOriginalSym) override;
15306f32e7eSjoerg 
154*da58b97aSjoerg   void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
15506f32e7eSjoerg 
getMnemonic(MCInst & MI)156*da58b97aSjoerg   StringRef getMnemonic(MCInst &MI) override {
157*da58b97aSjoerg     return InstPrinter->getMnemonic(&MI).first;
158*da58b97aSjoerg   }
159*da58b97aSjoerg 
160*da58b97aSjoerg   void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
161*da58b97aSjoerg 
162*da58b97aSjoerg   void emitAssemblerFlag(MCAssemblerFlag Flag) override;
163*da58b97aSjoerg   void emitLinkerOptions(ArrayRef<std::string> Options) override;
164*da58b97aSjoerg   void emitDataRegion(MCDataRegionType Kind) override;
165*da58b97aSjoerg   void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
16606f32e7eSjoerg                       unsigned Update, VersionTuple SDKVersion) override;
167*da58b97aSjoerg   void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
16806f32e7eSjoerg                         unsigned Update, VersionTuple SDKVersion) override;
169*da58b97aSjoerg   void emitThumbFunc(MCSymbol *Func) override;
17006f32e7eSjoerg 
171*da58b97aSjoerg   void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
172*da58b97aSjoerg   void emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
173*da58b97aSjoerg   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
17406f32e7eSjoerg 
175*da58b97aSjoerg   void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
17606f32e7eSjoerg   void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
17706f32e7eSjoerg   void EmitCOFFSymbolStorageClass(int StorageClass) override;
17806f32e7eSjoerg   void EmitCOFFSymbolType(int Type) override;
17906f32e7eSjoerg   void EndCOFFSymbolDef() override;
18006f32e7eSjoerg   void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
18106f32e7eSjoerg   void EmitCOFFSymbolIndex(MCSymbol const *Symbol) override;
18206f32e7eSjoerg   void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
18306f32e7eSjoerg   void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
18406f32e7eSjoerg   void EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override;
185*da58b97aSjoerg   void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size,
186*da58b97aSjoerg                                   MCSymbol *CsectSym,
18706f32e7eSjoerg                                   unsigned ByteAlign) override;
188*da58b97aSjoerg   void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol,
189*da58b97aSjoerg                                             MCSymbolAttr Linakge,
190*da58b97aSjoerg                                             MCSymbolAttr Visibility) override;
191*da58b97aSjoerg   void emitXCOFFRenameDirective(const MCSymbol *Name,
192*da58b97aSjoerg                                 StringRef Rename) override;
193*da58b97aSjoerg 
19406f32e7eSjoerg   void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
195*da58b97aSjoerg   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
19606f32e7eSjoerg                         unsigned ByteAlignment) override;
19706f32e7eSjoerg 
19806f32e7eSjoerg   /// Emit a local common (.lcomm) symbol.
19906f32e7eSjoerg   ///
20006f32e7eSjoerg   /// @param Symbol - The common symbol to emit.
20106f32e7eSjoerg   /// @param Size - The size of the common symbol.
20206f32e7eSjoerg   /// @param ByteAlignment - The alignment of the common symbol in bytes.
203*da58b97aSjoerg   void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
20406f32e7eSjoerg                              unsigned ByteAlignment) override;
20506f32e7eSjoerg 
206*da58b97aSjoerg   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
20706f32e7eSjoerg                     uint64_t Size = 0, unsigned ByteAlignment = 0,
20806f32e7eSjoerg                     SMLoc Loc = SMLoc()) override;
20906f32e7eSjoerg 
210*da58b97aSjoerg   void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
21106f32e7eSjoerg                       unsigned ByteAlignment = 0) override;
21206f32e7eSjoerg 
213*da58b97aSjoerg   void emitBinaryData(StringRef Data) override;
21406f32e7eSjoerg 
215*da58b97aSjoerg   void emitBytes(StringRef Data) override;
21606f32e7eSjoerg 
217*da58b97aSjoerg   void emitValueImpl(const MCExpr *Value, unsigned Size,
21806f32e7eSjoerg                      SMLoc Loc = SMLoc()) override;
219*da58b97aSjoerg   void emitIntValue(uint64_t Value, unsigned Size) override;
220*da58b97aSjoerg   void emitIntValueInHex(uint64_t Value, unsigned Size) override;
221*da58b97aSjoerg   void emitIntValueInHexWithPadding(uint64_t Value, unsigned Size) override;
22206f32e7eSjoerg 
223*da58b97aSjoerg   void emitULEB128Value(const MCExpr *Value) override;
22406f32e7eSjoerg 
225*da58b97aSjoerg   void emitSLEB128Value(const MCExpr *Value) override;
22606f32e7eSjoerg 
227*da58b97aSjoerg   void emitDTPRel32Value(const MCExpr *Value) override;
228*da58b97aSjoerg   void emitDTPRel64Value(const MCExpr *Value) override;
229*da58b97aSjoerg   void emitTPRel32Value(const MCExpr *Value) override;
230*da58b97aSjoerg   void emitTPRel64Value(const MCExpr *Value) override;
23106f32e7eSjoerg 
232*da58b97aSjoerg   void emitGPRel64Value(const MCExpr *Value) override;
23306f32e7eSjoerg 
234*da58b97aSjoerg   void emitGPRel32Value(const MCExpr *Value) override;
23506f32e7eSjoerg 
23606f32e7eSjoerg   void emitFill(const MCExpr &NumBytes, uint64_t FillValue,
23706f32e7eSjoerg                 SMLoc Loc = SMLoc()) override;
23806f32e7eSjoerg 
23906f32e7eSjoerg   void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr,
24006f32e7eSjoerg                 SMLoc Loc = SMLoc()) override;
24106f32e7eSjoerg 
242*da58b97aSjoerg   void emitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
24306f32e7eSjoerg                             unsigned ValueSize = 1,
24406f32e7eSjoerg                             unsigned MaxBytesToEmit = 0) override;
24506f32e7eSjoerg 
246*da58b97aSjoerg   void emitCodeAlignment(unsigned ByteAlignment,
24706f32e7eSjoerg                          unsigned MaxBytesToEmit = 0) override;
24806f32e7eSjoerg 
24906f32e7eSjoerg   void emitValueToOffset(const MCExpr *Offset,
25006f32e7eSjoerg                          unsigned char Value,
25106f32e7eSjoerg                          SMLoc Loc) override;
25206f32e7eSjoerg 
253*da58b97aSjoerg   void emitFileDirective(StringRef Filename) override;
25406f32e7eSjoerg   Expected<unsigned> tryEmitDwarfFileDirective(unsigned FileNo,
25506f32e7eSjoerg                                                StringRef Directory,
25606f32e7eSjoerg                                                StringRef Filename,
25706f32e7eSjoerg                                                Optional<MD5::MD5Result> Checksum = None,
25806f32e7eSjoerg                                                Optional<StringRef> Source = None,
25906f32e7eSjoerg                                                unsigned CUID = 0) override;
26006f32e7eSjoerg   void emitDwarfFile0Directive(StringRef Directory, StringRef Filename,
26106f32e7eSjoerg                                Optional<MD5::MD5Result> Checksum,
26206f32e7eSjoerg                                Optional<StringRef> Source,
26306f32e7eSjoerg                                unsigned CUID = 0) override;
264*da58b97aSjoerg   void emitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column,
265*da58b97aSjoerg                              unsigned Flags, unsigned Isa,
266*da58b97aSjoerg                              unsigned Discriminator,
26706f32e7eSjoerg                              StringRef FileName) override;
26806f32e7eSjoerg   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
26906f32e7eSjoerg 
27006f32e7eSjoerg   bool EmitCVFileDirective(unsigned FileNo, StringRef Filename,
27106f32e7eSjoerg                            ArrayRef<uint8_t> Checksum,
27206f32e7eSjoerg                            unsigned ChecksumKind) override;
27306f32e7eSjoerg   bool EmitCVFuncIdDirective(unsigned FuncId) override;
27406f32e7eSjoerg   bool EmitCVInlineSiteIdDirective(unsigned FunctionId, unsigned IAFunc,
27506f32e7eSjoerg                                    unsigned IAFile, unsigned IALine,
27606f32e7eSjoerg                                    unsigned IACol, SMLoc Loc) override;
277*da58b97aSjoerg   void emitCVLocDirective(unsigned FunctionId, unsigned FileNo, unsigned Line,
27806f32e7eSjoerg                           unsigned Column, bool PrologueEnd, bool IsStmt,
27906f32e7eSjoerg                           StringRef FileName, SMLoc Loc) override;
280*da58b97aSjoerg   void emitCVLinetableDirective(unsigned FunctionId, const MCSymbol *FnStart,
28106f32e7eSjoerg                                 const MCSymbol *FnEnd) override;
282*da58b97aSjoerg   void emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
28306f32e7eSjoerg                                       unsigned SourceFileId,
28406f32e7eSjoerg                                       unsigned SourceLineNum,
28506f32e7eSjoerg                                       const MCSymbol *FnStartSym,
28606f32e7eSjoerg                                       const MCSymbol *FnEndSym) override;
28706f32e7eSjoerg 
28806f32e7eSjoerg   void PrintCVDefRangePrefix(
28906f32e7eSjoerg       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges);
29006f32e7eSjoerg 
291*da58b97aSjoerg   void emitCVDefRangeDirective(
29206f32e7eSjoerg       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
29306f32e7eSjoerg       codeview::DefRangeRegisterRelHeader DRHdr) override;
29406f32e7eSjoerg 
295*da58b97aSjoerg   void emitCVDefRangeDirective(
29606f32e7eSjoerg       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
29706f32e7eSjoerg       codeview::DefRangeSubfieldRegisterHeader DRHdr) override;
29806f32e7eSjoerg 
299*da58b97aSjoerg   void emitCVDefRangeDirective(
30006f32e7eSjoerg       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
30106f32e7eSjoerg       codeview::DefRangeRegisterHeader DRHdr) override;
30206f32e7eSjoerg 
303*da58b97aSjoerg   void emitCVDefRangeDirective(
30406f32e7eSjoerg       ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
30506f32e7eSjoerg       codeview::DefRangeFramePointerRelHeader DRHdr) override;
30606f32e7eSjoerg 
307*da58b97aSjoerg   void emitCVStringTableDirective() override;
308*da58b97aSjoerg   void emitCVFileChecksumsDirective() override;
309*da58b97aSjoerg   void emitCVFileChecksumOffsetDirective(unsigned FileNo) override;
31006f32e7eSjoerg   void EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) override;
31106f32e7eSjoerg 
312*da58b97aSjoerg   void emitIdent(StringRef IdentString) override;
313*da58b97aSjoerg   void emitCFIBKeyFrame() override;
314*da58b97aSjoerg   void emitCFISections(bool EH, bool Debug) override;
315*da58b97aSjoerg   void emitCFIDefCfa(int64_t Register, int64_t Offset) override;
316*da58b97aSjoerg   void emitCFIDefCfaOffset(int64_t Offset) override;
317*da58b97aSjoerg   void emitCFIDefCfaRegister(int64_t Register) override;
318*da58b97aSjoerg   void emitCFIOffset(int64_t Register, int64_t Offset) override;
319*da58b97aSjoerg   void emitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
320*da58b97aSjoerg   void emitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
321*da58b97aSjoerg   void emitCFIRememberState() override;
322*da58b97aSjoerg   void emitCFIRestoreState() override;
323*da58b97aSjoerg   void emitCFIRestore(int64_t Register) override;
324*da58b97aSjoerg   void emitCFISameValue(int64_t Register) override;
325*da58b97aSjoerg   void emitCFIRelOffset(int64_t Register, int64_t Offset) override;
326*da58b97aSjoerg   void emitCFIAdjustCfaOffset(int64_t Adjustment) override;
327*da58b97aSjoerg   void emitCFIEscape(StringRef Values) override;
328*da58b97aSjoerg   void emitCFIGnuArgsSize(int64_t Size) override;
329*da58b97aSjoerg   void emitCFISignalFrame() override;
330*da58b97aSjoerg   void emitCFIUndefined(int64_t Register) override;
331*da58b97aSjoerg   void emitCFIRegister(int64_t Register1, int64_t Register2) override;
332*da58b97aSjoerg   void emitCFIWindowSave() override;
333*da58b97aSjoerg   void emitCFINegateRAState() override;
334*da58b97aSjoerg   void emitCFIReturnColumn(int64_t Register) override;
33506f32e7eSjoerg 
33606f32e7eSjoerg   void EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override;
33706f32e7eSjoerg   void EmitWinCFIEndProc(SMLoc Loc) override;
33806f32e7eSjoerg   void EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) override;
33906f32e7eSjoerg   void EmitWinCFIStartChained(SMLoc Loc) override;
34006f32e7eSjoerg   void EmitWinCFIEndChained(SMLoc Loc) override;
34106f32e7eSjoerg   void EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) override;
34206f32e7eSjoerg   void EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
34306f32e7eSjoerg                           SMLoc Loc) override;
34406f32e7eSjoerg   void EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) override;
34506f32e7eSjoerg   void EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
34606f32e7eSjoerg                          SMLoc Loc) override;
34706f32e7eSjoerg   void EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
34806f32e7eSjoerg                          SMLoc Loc) override;
34906f32e7eSjoerg   void EmitWinCFIPushFrame(bool Code, SMLoc Loc) override;
35006f32e7eSjoerg   void EmitWinCFIEndProlog(SMLoc Loc) override;
35106f32e7eSjoerg 
35206f32e7eSjoerg   void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except,
35306f32e7eSjoerg                         SMLoc Loc) override;
35406f32e7eSjoerg   void EmitWinEHHandlerData(SMLoc Loc) override;
35506f32e7eSjoerg 
35606f32e7eSjoerg   void emitCGProfileEntry(const MCSymbolRefExpr *From,
35706f32e7eSjoerg                           const MCSymbolRefExpr *To, uint64_t Count) override;
35806f32e7eSjoerg 
359*da58b97aSjoerg   void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
36006f32e7eSjoerg 
361*da58b97aSjoerg   void emitPseudoProbe(uint64_t Guid, uint64_t Index, uint64_t Type,
362*da58b97aSjoerg                        uint64_t Attr,
363*da58b97aSjoerg                        const MCPseudoProbeInlineStack &InlineStack) override;
36406f32e7eSjoerg 
365*da58b97aSjoerg   void emitBundleAlignMode(unsigned AlignPow2) override;
366*da58b97aSjoerg   void emitBundleLock(bool AlignToEnd) override;
367*da58b97aSjoerg   void emitBundleUnlock() override;
36806f32e7eSjoerg 
369*da58b97aSjoerg   Optional<std::pair<bool, std::string>>
370*da58b97aSjoerg   emitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr,
371*da58b97aSjoerg                      SMLoc Loc, const MCSubtargetInfo &STI) override;
372*da58b97aSjoerg 
373*da58b97aSjoerg   void emitAddrsig() override;
374*da58b97aSjoerg   void emitAddrsigSym(const MCSymbol *Sym) override;
37506f32e7eSjoerg 
37606f32e7eSjoerg   /// If this file is backed by an assembly streamer, this dumps the specified
37706f32e7eSjoerg   /// string in the output .s file. This capability is indicated by the
37806f32e7eSjoerg   /// hasRawTextSupport() predicate.
379*da58b97aSjoerg   void emitRawTextImpl(StringRef String) override;
38006f32e7eSjoerg 
381*da58b97aSjoerg   void finishImpl() override;
382*da58b97aSjoerg 
383*da58b97aSjoerg   void emitDwarfUnitLength(uint64_t Length, const Twine &Comment) override;
384*da58b97aSjoerg 
385*da58b97aSjoerg   MCSymbol *emitDwarfUnitLength(const Twine &Prefix,
386*da58b97aSjoerg                                 const Twine &Comment) override;
387*da58b97aSjoerg 
388*da58b97aSjoerg   void emitDwarfLineStartLabel(MCSymbol *StartSym) override;
389*da58b97aSjoerg 
390*da58b97aSjoerg   void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override;
391*da58b97aSjoerg 
392*da58b97aSjoerg   void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel,
393*da58b97aSjoerg                                 const MCSymbol *Label,
394*da58b97aSjoerg                                 unsigned PointerSize) override;
395*da58b97aSjoerg 
396*da58b97aSjoerg   void doFinalizationAtSectionEnd(MCSection *Section) override;
39706f32e7eSjoerg };
39806f32e7eSjoerg 
39906f32e7eSjoerg } // end anonymous namespace.
40006f32e7eSjoerg 
AddComment(const Twine & T,bool EOL)40106f32e7eSjoerg void MCAsmStreamer::AddComment(const Twine &T, bool EOL) {
40206f32e7eSjoerg   if (!IsVerboseAsm) return;
40306f32e7eSjoerg 
40406f32e7eSjoerg   T.toVector(CommentToEmit);
40506f32e7eSjoerg 
40606f32e7eSjoerg   if (EOL)
40706f32e7eSjoerg     CommentToEmit.push_back('\n'); // Place comment in a new line.
40806f32e7eSjoerg }
40906f32e7eSjoerg 
EmitCommentsAndEOL()41006f32e7eSjoerg void MCAsmStreamer::EmitCommentsAndEOL() {
41106f32e7eSjoerg   if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
41206f32e7eSjoerg     OS << '\n';
41306f32e7eSjoerg     return;
41406f32e7eSjoerg   }
41506f32e7eSjoerg 
41606f32e7eSjoerg   StringRef Comments = CommentToEmit;
41706f32e7eSjoerg 
41806f32e7eSjoerg   assert(Comments.back() == '\n' &&
41906f32e7eSjoerg          "Comment array not newline terminated");
42006f32e7eSjoerg   do {
42106f32e7eSjoerg     // Emit a line of comments.
42206f32e7eSjoerg     OS.PadToColumn(MAI->getCommentColumn());
42306f32e7eSjoerg     size_t Position = Comments.find('\n');
42406f32e7eSjoerg     OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
42506f32e7eSjoerg 
42606f32e7eSjoerg     Comments = Comments.substr(Position+1);
42706f32e7eSjoerg   } while (!Comments.empty());
42806f32e7eSjoerg 
42906f32e7eSjoerg   CommentToEmit.clear();
43006f32e7eSjoerg }
43106f32e7eSjoerg 
truncateToSize(int64_t Value,unsigned Bytes)43206f32e7eSjoerg static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
43306f32e7eSjoerg   assert(Bytes > 0 && Bytes <= 8 && "Invalid size!");
43406f32e7eSjoerg   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
43506f32e7eSjoerg }
43606f32e7eSjoerg 
emitRawComment(const Twine & T,bool TabPrefix)43706f32e7eSjoerg void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
43806f32e7eSjoerg   if (TabPrefix)
43906f32e7eSjoerg     OS << '\t';
44006f32e7eSjoerg   OS << MAI->getCommentString() << T;
44106f32e7eSjoerg   EmitEOL();
44206f32e7eSjoerg }
44306f32e7eSjoerg 
addExplicitComment(const Twine & T)44406f32e7eSjoerg void MCAsmStreamer::addExplicitComment(const Twine &T) {
44506f32e7eSjoerg   StringRef c = T.getSingleStringRef();
44606f32e7eSjoerg   if (c.equals(StringRef(MAI->getSeparatorString())))
44706f32e7eSjoerg     return;
44806f32e7eSjoerg   if (c.startswith(StringRef("//"))) {
44906f32e7eSjoerg     ExplicitCommentToEmit.append("\t");
45006f32e7eSjoerg     ExplicitCommentToEmit.append(MAI->getCommentString());
45106f32e7eSjoerg     // drop //
45206f32e7eSjoerg     ExplicitCommentToEmit.append(c.slice(2, c.size()).str());
45306f32e7eSjoerg   } else if (c.startswith(StringRef("/*"))) {
45406f32e7eSjoerg     size_t p = 2, len = c.size() - 2;
45506f32e7eSjoerg     // emit each line in comment as separate newline.
45606f32e7eSjoerg     do {
45706f32e7eSjoerg       size_t newp = std::min(len, c.find_first_of("\r\n", p));
45806f32e7eSjoerg       ExplicitCommentToEmit.append("\t");
45906f32e7eSjoerg       ExplicitCommentToEmit.append(MAI->getCommentString());
46006f32e7eSjoerg       ExplicitCommentToEmit.append(c.slice(p, newp).str());
46106f32e7eSjoerg       // If we have another line in this comment add line
46206f32e7eSjoerg       if (newp < len)
46306f32e7eSjoerg         ExplicitCommentToEmit.append("\n");
46406f32e7eSjoerg       p = newp + 1;
46506f32e7eSjoerg     } while (p < len);
46606f32e7eSjoerg   } else if (c.startswith(StringRef(MAI->getCommentString()))) {
46706f32e7eSjoerg     ExplicitCommentToEmit.append("\t");
46806f32e7eSjoerg     ExplicitCommentToEmit.append(c.str());
46906f32e7eSjoerg   } else if (c.front() == '#') {
47006f32e7eSjoerg 
47106f32e7eSjoerg     ExplicitCommentToEmit.append("\t");
47206f32e7eSjoerg     ExplicitCommentToEmit.append(MAI->getCommentString());
47306f32e7eSjoerg     ExplicitCommentToEmit.append(c.slice(1, c.size()).str());
47406f32e7eSjoerg   } else
47506f32e7eSjoerg     assert(false && "Unexpected Assembly Comment");
47606f32e7eSjoerg   // full line comments immediately output
47706f32e7eSjoerg   if (c.back() == '\n')
47806f32e7eSjoerg     emitExplicitComments();
47906f32e7eSjoerg }
48006f32e7eSjoerg 
emitExplicitComments()48106f32e7eSjoerg void MCAsmStreamer::emitExplicitComments() {
48206f32e7eSjoerg   StringRef Comments = ExplicitCommentToEmit;
48306f32e7eSjoerg   if (!Comments.empty())
48406f32e7eSjoerg     OS << Comments;
48506f32e7eSjoerg   ExplicitCommentToEmit.clear();
48606f32e7eSjoerg }
48706f32e7eSjoerg 
changeSection(MCSection * Section,const MCExpr * Subsection)488*da58b97aSjoerg void MCAsmStreamer::changeSection(MCSection *Section,
48906f32e7eSjoerg                                   const MCExpr *Subsection) {
49006f32e7eSjoerg   assert(Section && "Cannot switch to a null section!");
49106f32e7eSjoerg   if (MCTargetStreamer *TS = getTargetStreamer()) {
49206f32e7eSjoerg     TS->changeSection(getCurrentSectionOnly(), Section, Subsection, OS);
49306f32e7eSjoerg   } else {
494*da58b97aSjoerg     Section->PrintSwitchToSection(*MAI, getContext().getTargetTriple(), OS,
49506f32e7eSjoerg                                   Subsection);
49606f32e7eSjoerg   }
49706f32e7eSjoerg }
49806f32e7eSjoerg 
emitELFSymverDirective(const MCSymbol * OriginalSym,StringRef Name,bool KeepOriginalSym)499*da58b97aSjoerg void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym,
500*da58b97aSjoerg                                            StringRef Name,
501*da58b97aSjoerg                                            bool KeepOriginalSym) {
50206f32e7eSjoerg   OS << ".symver ";
503*da58b97aSjoerg   OriginalSym->print(OS, MAI);
504*da58b97aSjoerg   OS << ", " << Name;
505*da58b97aSjoerg   if (!KeepOriginalSym && !Name.contains("@@@"))
506*da58b97aSjoerg     OS << ", remove";
50706f32e7eSjoerg   EmitEOL();
50806f32e7eSjoerg }
50906f32e7eSjoerg 
emitLabel(MCSymbol * Symbol,SMLoc Loc)510*da58b97aSjoerg void MCAsmStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
511*da58b97aSjoerg   MCStreamer::emitLabel(Symbol, Loc);
51206f32e7eSjoerg 
51306f32e7eSjoerg   Symbol->print(OS, MAI);
51406f32e7eSjoerg   OS << MAI->getLabelSuffix();
51506f32e7eSjoerg 
51606f32e7eSjoerg   EmitEOL();
51706f32e7eSjoerg }
51806f32e7eSjoerg 
emitLOHDirective(MCLOHType Kind,const MCLOHArgs & Args)519*da58b97aSjoerg void MCAsmStreamer::emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
52006f32e7eSjoerg   StringRef str = MCLOHIdToName(Kind);
52106f32e7eSjoerg 
52206f32e7eSjoerg #ifndef NDEBUG
52306f32e7eSjoerg   int NbArgs = MCLOHIdToNbArgs(Kind);
52406f32e7eSjoerg   assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
52506f32e7eSjoerg   assert(str != "" && "Invalid LOH name");
52606f32e7eSjoerg #endif
52706f32e7eSjoerg 
52806f32e7eSjoerg   OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
52906f32e7eSjoerg   bool IsFirst = true;
53006f32e7eSjoerg   for (const MCSymbol *Arg : Args) {
53106f32e7eSjoerg     if (!IsFirst)
53206f32e7eSjoerg       OS << ", ";
53306f32e7eSjoerg     IsFirst = false;
53406f32e7eSjoerg     Arg->print(OS, MAI);
53506f32e7eSjoerg   }
53606f32e7eSjoerg   EmitEOL();
53706f32e7eSjoerg }
53806f32e7eSjoerg 
emitAssemblerFlag(MCAssemblerFlag Flag)539*da58b97aSjoerg void MCAsmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
54006f32e7eSjoerg   switch (Flag) {
54106f32e7eSjoerg   case MCAF_SyntaxUnified:         OS << "\t.syntax unified"; break;
54206f32e7eSjoerg   case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
54306f32e7eSjoerg   case MCAF_Code16:                OS << '\t'<< MAI->getCode16Directive();break;
54406f32e7eSjoerg   case MCAF_Code32:                OS << '\t'<< MAI->getCode32Directive();break;
54506f32e7eSjoerg   case MCAF_Code64:                OS << '\t'<< MAI->getCode64Directive();break;
54606f32e7eSjoerg   }
54706f32e7eSjoerg   EmitEOL();
54806f32e7eSjoerg }
54906f32e7eSjoerg 
emitLinkerOptions(ArrayRef<std::string> Options)550*da58b97aSjoerg void MCAsmStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
55106f32e7eSjoerg   assert(!Options.empty() && "At least one option is required!");
55206f32e7eSjoerg   OS << "\t.linker_option \"" << Options[0] << '"';
55306f32e7eSjoerg   for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
55406f32e7eSjoerg          ie = Options.end(); it != ie; ++it) {
55506f32e7eSjoerg     OS << ", " << '"' << *it << '"';
55606f32e7eSjoerg   }
55706f32e7eSjoerg   EmitEOL();
55806f32e7eSjoerg }
55906f32e7eSjoerg 
emitDataRegion(MCDataRegionType Kind)560*da58b97aSjoerg void MCAsmStreamer::emitDataRegion(MCDataRegionType Kind) {
56106f32e7eSjoerg   if (!MAI->doesSupportDataRegionDirectives())
56206f32e7eSjoerg     return;
56306f32e7eSjoerg   switch (Kind) {
56406f32e7eSjoerg   case MCDR_DataRegion:            OS << "\t.data_region"; break;
56506f32e7eSjoerg   case MCDR_DataRegionJT8:         OS << "\t.data_region jt8"; break;
56606f32e7eSjoerg   case MCDR_DataRegionJT16:        OS << "\t.data_region jt16"; break;
56706f32e7eSjoerg   case MCDR_DataRegionJT32:        OS << "\t.data_region jt32"; break;
56806f32e7eSjoerg   case MCDR_DataRegionEnd:         OS << "\t.end_data_region"; break;
56906f32e7eSjoerg   }
57006f32e7eSjoerg   EmitEOL();
57106f32e7eSjoerg }
57206f32e7eSjoerg 
getVersionMinDirective(MCVersionMinType Type)57306f32e7eSjoerg static const char *getVersionMinDirective(MCVersionMinType Type) {
57406f32e7eSjoerg   switch (Type) {
57506f32e7eSjoerg   case MCVM_WatchOSVersionMin: return ".watchos_version_min";
57606f32e7eSjoerg   case MCVM_TvOSVersionMin:    return ".tvos_version_min";
57706f32e7eSjoerg   case MCVM_IOSVersionMin:     return ".ios_version_min";
57806f32e7eSjoerg   case MCVM_OSXVersionMin:     return ".macosx_version_min";
57906f32e7eSjoerg   }
58006f32e7eSjoerg   llvm_unreachable("Invalid MC version min type");
58106f32e7eSjoerg }
58206f32e7eSjoerg 
EmitSDKVersionSuffix(raw_ostream & OS,const VersionTuple & SDKVersion)58306f32e7eSjoerg static void EmitSDKVersionSuffix(raw_ostream &OS,
58406f32e7eSjoerg                                  const VersionTuple &SDKVersion) {
58506f32e7eSjoerg   if (SDKVersion.empty())
58606f32e7eSjoerg     return;
58706f32e7eSjoerg   OS << '\t' << "sdk_version " << SDKVersion.getMajor();
58806f32e7eSjoerg   if (auto Minor = SDKVersion.getMinor()) {
58906f32e7eSjoerg     OS << ", " << *Minor;
59006f32e7eSjoerg     if (auto Subminor = SDKVersion.getSubminor()) {
59106f32e7eSjoerg       OS << ", " << *Subminor;
59206f32e7eSjoerg     }
59306f32e7eSjoerg   }
59406f32e7eSjoerg }
59506f32e7eSjoerg 
emitVersionMin(MCVersionMinType Type,unsigned Major,unsigned Minor,unsigned Update,VersionTuple SDKVersion)596*da58b97aSjoerg void MCAsmStreamer::emitVersionMin(MCVersionMinType Type, unsigned Major,
59706f32e7eSjoerg                                    unsigned Minor, unsigned Update,
59806f32e7eSjoerg                                    VersionTuple SDKVersion) {
59906f32e7eSjoerg   OS << '\t' << getVersionMinDirective(Type) << ' ' << Major << ", " << Minor;
60006f32e7eSjoerg   if (Update)
60106f32e7eSjoerg     OS << ", " << Update;
60206f32e7eSjoerg   EmitSDKVersionSuffix(OS, SDKVersion);
60306f32e7eSjoerg   EmitEOL();
60406f32e7eSjoerg }
60506f32e7eSjoerg 
getPlatformName(MachO::PlatformType Type)60606f32e7eSjoerg static const char *getPlatformName(MachO::PlatformType Type) {
60706f32e7eSjoerg   switch (Type) {
60806f32e7eSjoerg   case MachO::PLATFORM_MACOS:            return "macos";
60906f32e7eSjoerg   case MachO::PLATFORM_IOS:              return "ios";
61006f32e7eSjoerg   case MachO::PLATFORM_TVOS:             return "tvos";
61106f32e7eSjoerg   case MachO::PLATFORM_WATCHOS:          return "watchos";
61206f32e7eSjoerg   case MachO::PLATFORM_BRIDGEOS:         return "bridgeos";
61306f32e7eSjoerg   case MachO::PLATFORM_MACCATALYST:      return "macCatalyst";
61406f32e7eSjoerg   case MachO::PLATFORM_IOSSIMULATOR:     return "iossimulator";
61506f32e7eSjoerg   case MachO::PLATFORM_TVOSSIMULATOR:    return "tvossimulator";
61606f32e7eSjoerg   case MachO::PLATFORM_WATCHOSSIMULATOR: return "watchossimulator";
617*da58b97aSjoerg   case MachO::PLATFORM_DRIVERKIT:        return "driverkit";
61806f32e7eSjoerg   }
61906f32e7eSjoerg   llvm_unreachable("Invalid Mach-O platform type");
62006f32e7eSjoerg }
62106f32e7eSjoerg 
emitBuildVersion(unsigned Platform,unsigned Major,unsigned Minor,unsigned Update,VersionTuple SDKVersion)622*da58b97aSjoerg void MCAsmStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
62306f32e7eSjoerg                                      unsigned Minor, unsigned Update,
62406f32e7eSjoerg                                      VersionTuple SDKVersion) {
62506f32e7eSjoerg   const char *PlatformName = getPlatformName((MachO::PlatformType)Platform);
62606f32e7eSjoerg   OS << "\t.build_version " << PlatformName << ", " << Major << ", " << Minor;
62706f32e7eSjoerg   if (Update)
62806f32e7eSjoerg     OS << ", " << Update;
62906f32e7eSjoerg   EmitSDKVersionSuffix(OS, SDKVersion);
63006f32e7eSjoerg   EmitEOL();
63106f32e7eSjoerg }
63206f32e7eSjoerg 
emitThumbFunc(MCSymbol * Func)633*da58b97aSjoerg void MCAsmStreamer::emitThumbFunc(MCSymbol *Func) {
63406f32e7eSjoerg   // This needs to emit to a temporary string to get properly quoted
63506f32e7eSjoerg   // MCSymbols when they have spaces in them.
63606f32e7eSjoerg   OS << "\t.thumb_func";
63706f32e7eSjoerg   // Only Mach-O hasSubsectionsViaSymbols()
63806f32e7eSjoerg   if (MAI->hasSubsectionsViaSymbols()) {
63906f32e7eSjoerg     OS << '\t';
64006f32e7eSjoerg     Func->print(OS, MAI);
64106f32e7eSjoerg   }
64206f32e7eSjoerg   EmitEOL();
64306f32e7eSjoerg }
64406f32e7eSjoerg 
emitAssignment(MCSymbol * Symbol,const MCExpr * Value)645*da58b97aSjoerg void MCAsmStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
64606f32e7eSjoerg   // Do not emit a .set on inlined target assignments.
64706f32e7eSjoerg   bool EmitSet = true;
64806f32e7eSjoerg   if (auto *E = dyn_cast<MCTargetExpr>(Value))
64906f32e7eSjoerg     if (E->inlineAssignedExpr())
65006f32e7eSjoerg       EmitSet = false;
65106f32e7eSjoerg   if (EmitSet) {
65206f32e7eSjoerg     OS << ".set ";
65306f32e7eSjoerg     Symbol->print(OS, MAI);
65406f32e7eSjoerg     OS << ", ";
65506f32e7eSjoerg     Value->print(OS, MAI);
65606f32e7eSjoerg 
65706f32e7eSjoerg     EmitEOL();
65806f32e7eSjoerg   }
65906f32e7eSjoerg 
660*da58b97aSjoerg   MCStreamer::emitAssignment(Symbol, Value);
66106f32e7eSjoerg }
66206f32e7eSjoerg 
emitWeakReference(MCSymbol * Alias,const MCSymbol * Symbol)663*da58b97aSjoerg void MCAsmStreamer::emitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
66406f32e7eSjoerg   OS << ".weakref ";
66506f32e7eSjoerg   Alias->print(OS, MAI);
66606f32e7eSjoerg   OS << ", ";
66706f32e7eSjoerg   Symbol->print(OS, MAI);
66806f32e7eSjoerg   EmitEOL();
66906f32e7eSjoerg }
67006f32e7eSjoerg 
emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)671*da58b97aSjoerg bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
67206f32e7eSjoerg                                         MCSymbolAttr Attribute) {
67306f32e7eSjoerg   switch (Attribute) {
67406f32e7eSjoerg   case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
67506f32e7eSjoerg   case MCSA_ELF_TypeFunction:    /// .type _foo, STT_FUNC  # aka @function
67606f32e7eSjoerg   case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
67706f32e7eSjoerg   case MCSA_ELF_TypeObject:      /// .type _foo, STT_OBJECT  # aka @object
67806f32e7eSjoerg   case MCSA_ELF_TypeTLS:         /// .type _foo, STT_TLS     # aka @tls_object
67906f32e7eSjoerg   case MCSA_ELF_TypeCommon:      /// .type _foo, STT_COMMON  # aka @common
68006f32e7eSjoerg   case MCSA_ELF_TypeNoType:      /// .type _foo, STT_NOTYPE  # aka @notype
68106f32e7eSjoerg   case MCSA_ELF_TypeGnuUniqueObject:  /// .type _foo, @gnu_unique_object
68206f32e7eSjoerg     if (!MAI->hasDotTypeDotSizeDirective())
68306f32e7eSjoerg       return false; // Symbol attribute not supported
68406f32e7eSjoerg     OS << "\t.type\t";
68506f32e7eSjoerg     Symbol->print(OS, MAI);
68606f32e7eSjoerg     OS << ',' << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
68706f32e7eSjoerg     switch (Attribute) {
68806f32e7eSjoerg     default: return false;
68906f32e7eSjoerg     case MCSA_ELF_TypeFunction:    OS << "function"; break;
69006f32e7eSjoerg     case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
69106f32e7eSjoerg     case MCSA_ELF_TypeObject:      OS << "object"; break;
69206f32e7eSjoerg     case MCSA_ELF_TypeTLS:         OS << "tls_object"; break;
69306f32e7eSjoerg     case MCSA_ELF_TypeCommon:      OS << "common"; break;
69406f32e7eSjoerg     case MCSA_ELF_TypeNoType:      OS << "notype"; break;
69506f32e7eSjoerg     case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
69606f32e7eSjoerg     }
69706f32e7eSjoerg     EmitEOL();
69806f32e7eSjoerg     return true;
69906f32e7eSjoerg   case MCSA_Global: // .globl/.global
70006f32e7eSjoerg     OS << MAI->getGlobalDirective();
70106f32e7eSjoerg     break;
70206f32e7eSjoerg   case MCSA_LGlobal:        OS << "\t.lglobl\t";          break;
70306f32e7eSjoerg   case MCSA_Hidden:         OS << "\t.hidden\t";          break;
70406f32e7eSjoerg   case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
70506f32e7eSjoerg   case MCSA_Internal:       OS << "\t.internal\t";        break;
70606f32e7eSjoerg   case MCSA_LazyReference:  OS << "\t.lazy_reference\t";  break;
70706f32e7eSjoerg   case MCSA_Local:          OS << "\t.local\t";           break;
70806f32e7eSjoerg   case MCSA_NoDeadStrip:
70906f32e7eSjoerg     if (!MAI->hasNoDeadStrip())
71006f32e7eSjoerg       return false;
71106f32e7eSjoerg     OS << "\t.no_dead_strip\t";
71206f32e7eSjoerg     break;
71306f32e7eSjoerg   case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
71406f32e7eSjoerg   case MCSA_AltEntry:       OS << "\t.alt_entry\t";       break;
71506f32e7eSjoerg   case MCSA_PrivateExtern:
71606f32e7eSjoerg     OS << "\t.private_extern\t";
71706f32e7eSjoerg     break;
71806f32e7eSjoerg   case MCSA_Protected:      OS << "\t.protected\t";       break;
71906f32e7eSjoerg   case MCSA_Reference:      OS << "\t.reference\t";       break;
720*da58b97aSjoerg   case MCSA_Extern:
721*da58b97aSjoerg     OS << "\t.extern\t";
722*da58b97aSjoerg     break;
72306f32e7eSjoerg   case MCSA_Weak:           OS << MAI->getWeakDirective(); break;
72406f32e7eSjoerg   case MCSA_WeakDefinition:
72506f32e7eSjoerg     OS << "\t.weak_definition\t";
72606f32e7eSjoerg     break;
72706f32e7eSjoerg       // .weak_reference
72806f32e7eSjoerg   case MCSA_WeakReference:  OS << MAI->getWeakRefDirective(); break;
72906f32e7eSjoerg   case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
73006f32e7eSjoerg   case MCSA_Cold:
73106f32e7eSjoerg     // Assemblers currently do not support a .cold directive.
73206f32e7eSjoerg     return false;
73306f32e7eSjoerg   }
73406f32e7eSjoerg 
73506f32e7eSjoerg   Symbol->print(OS, MAI);
73606f32e7eSjoerg   EmitEOL();
73706f32e7eSjoerg 
73806f32e7eSjoerg   return true;
73906f32e7eSjoerg }
74006f32e7eSjoerg 
emitSymbolDesc(MCSymbol * Symbol,unsigned DescValue)741*da58b97aSjoerg void MCAsmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
74206f32e7eSjoerg   OS << ".desc" << ' ';
74306f32e7eSjoerg   Symbol->print(OS, MAI);
74406f32e7eSjoerg   OS << ',' << DescValue;
74506f32e7eSjoerg   EmitEOL();
74606f32e7eSjoerg }
74706f32e7eSjoerg 
emitSyntaxDirective()748*da58b97aSjoerg void MCAsmStreamer::emitSyntaxDirective() {
74906f32e7eSjoerg   if (MAI->getAssemblerDialect() == 1) {
75006f32e7eSjoerg     OS << "\t.intel_syntax noprefix";
75106f32e7eSjoerg     EmitEOL();
75206f32e7eSjoerg   }
75306f32e7eSjoerg   // FIXME: Currently emit unprefix'ed registers.
75406f32e7eSjoerg   // The intel_syntax directive has one optional argument
75506f32e7eSjoerg   // with may have a value of prefix or noprefix.
75606f32e7eSjoerg }
75706f32e7eSjoerg 
BeginCOFFSymbolDef(const MCSymbol * Symbol)75806f32e7eSjoerg void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
75906f32e7eSjoerg   OS << "\t.def\t ";
76006f32e7eSjoerg   Symbol->print(OS, MAI);
76106f32e7eSjoerg   OS << ';';
76206f32e7eSjoerg   EmitEOL();
76306f32e7eSjoerg }
76406f32e7eSjoerg 
EmitCOFFSymbolStorageClass(int StorageClass)76506f32e7eSjoerg void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
76606f32e7eSjoerg   OS << "\t.scl\t" << StorageClass << ';';
76706f32e7eSjoerg   EmitEOL();
76806f32e7eSjoerg }
76906f32e7eSjoerg 
EmitCOFFSymbolType(int Type)77006f32e7eSjoerg void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
77106f32e7eSjoerg   OS << "\t.type\t" << Type << ';';
77206f32e7eSjoerg   EmitEOL();
77306f32e7eSjoerg }
77406f32e7eSjoerg 
EndCOFFSymbolDef()77506f32e7eSjoerg void MCAsmStreamer::EndCOFFSymbolDef() {
77606f32e7eSjoerg   OS << "\t.endef";
77706f32e7eSjoerg   EmitEOL();
77806f32e7eSjoerg }
77906f32e7eSjoerg 
EmitCOFFSafeSEH(MCSymbol const * Symbol)78006f32e7eSjoerg void MCAsmStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
78106f32e7eSjoerg   OS << "\t.safeseh\t";
78206f32e7eSjoerg   Symbol->print(OS, MAI);
78306f32e7eSjoerg   EmitEOL();
78406f32e7eSjoerg }
78506f32e7eSjoerg 
EmitCOFFSymbolIndex(MCSymbol const * Symbol)78606f32e7eSjoerg void MCAsmStreamer::EmitCOFFSymbolIndex(MCSymbol const *Symbol) {
78706f32e7eSjoerg   OS << "\t.symidx\t";
78806f32e7eSjoerg   Symbol->print(OS, MAI);
78906f32e7eSjoerg   EmitEOL();
79006f32e7eSjoerg }
79106f32e7eSjoerg 
EmitCOFFSectionIndex(MCSymbol const * Symbol)79206f32e7eSjoerg void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
79306f32e7eSjoerg   OS << "\t.secidx\t";
79406f32e7eSjoerg   Symbol->print(OS, MAI);
79506f32e7eSjoerg   EmitEOL();
79606f32e7eSjoerg }
79706f32e7eSjoerg 
EmitCOFFSecRel32(MCSymbol const * Symbol,uint64_t Offset)79806f32e7eSjoerg void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
79906f32e7eSjoerg   OS << "\t.secrel32\t";
80006f32e7eSjoerg   Symbol->print(OS, MAI);
80106f32e7eSjoerg   if (Offset != 0)
80206f32e7eSjoerg     OS << '+' << Offset;
80306f32e7eSjoerg   EmitEOL();
80406f32e7eSjoerg }
80506f32e7eSjoerg 
EmitCOFFImgRel32(MCSymbol const * Symbol,int64_t Offset)80606f32e7eSjoerg void MCAsmStreamer::EmitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) {
80706f32e7eSjoerg   OS << "\t.rva\t";
80806f32e7eSjoerg   Symbol->print(OS, MAI);
80906f32e7eSjoerg   if (Offset > 0)
81006f32e7eSjoerg     OS << '+' << Offset;
81106f32e7eSjoerg   else if (Offset < 0)
81206f32e7eSjoerg     OS << '-' << -Offset;
81306f32e7eSjoerg   EmitEOL();
81406f32e7eSjoerg }
81506f32e7eSjoerg 
81606f32e7eSjoerg // We need an XCOFF-specific version of this directive as the AIX syntax
81706f32e7eSjoerg // requires a QualName argument identifying the csect name and storage mapping
81806f32e7eSjoerg // class to appear before the alignment if we are specifying it.
emitXCOFFLocalCommonSymbol(MCSymbol * LabelSym,uint64_t Size,MCSymbol * CsectSym,unsigned ByteAlignment)819*da58b97aSjoerg void MCAsmStreamer::emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym,
820*da58b97aSjoerg                                                uint64_t Size,
821*da58b97aSjoerg                                                MCSymbol *CsectSym,
82206f32e7eSjoerg                                                unsigned ByteAlignment) {
82306f32e7eSjoerg   assert(MAI->getLCOMMDirectiveAlignmentType() == LCOMM::Log2Alignment &&
82406f32e7eSjoerg          "We only support writing log base-2 alignment format with XCOFF.");
82506f32e7eSjoerg   assert(isPowerOf2_32(ByteAlignment) && "Alignment must be a power of 2.");
82606f32e7eSjoerg 
82706f32e7eSjoerg   OS << "\t.lcomm\t";
828*da58b97aSjoerg   LabelSym->print(OS, MAI);
829*da58b97aSjoerg   OS << ',' << Size << ',';
830*da58b97aSjoerg   CsectSym->print(OS, MAI);
83106f32e7eSjoerg   OS << ',' << Log2_32(ByteAlignment);
83206f32e7eSjoerg 
83306f32e7eSjoerg   EmitEOL();
834*da58b97aSjoerg 
835*da58b97aSjoerg   // Print symbol's rename (original name contains invalid character(s)) if
836*da58b97aSjoerg   // there is one.
837*da58b97aSjoerg   MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(CsectSym);
838*da58b97aSjoerg   if (XSym->hasRename())
839*da58b97aSjoerg     emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
840*da58b97aSjoerg }
841*da58b97aSjoerg 
emitXCOFFSymbolLinkageWithVisibility(MCSymbol * Symbol,MCSymbolAttr Linkage,MCSymbolAttr Visibility)842*da58b97aSjoerg void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
843*da58b97aSjoerg     MCSymbol *Symbol, MCSymbolAttr Linkage, MCSymbolAttr Visibility) {
844*da58b97aSjoerg 
845*da58b97aSjoerg   switch (Linkage) {
846*da58b97aSjoerg   case MCSA_Global:
847*da58b97aSjoerg     OS << MAI->getGlobalDirective();
848*da58b97aSjoerg     break;
849*da58b97aSjoerg   case MCSA_Weak:
850*da58b97aSjoerg     OS << MAI->getWeakDirective();
851*da58b97aSjoerg     break;
852*da58b97aSjoerg   case MCSA_Extern:
853*da58b97aSjoerg     OS << "\t.extern\t";
854*da58b97aSjoerg     break;
855*da58b97aSjoerg   case MCSA_LGlobal:
856*da58b97aSjoerg     OS << "\t.lglobl\t";
857*da58b97aSjoerg     break;
858*da58b97aSjoerg   default:
859*da58b97aSjoerg     report_fatal_error("unhandled linkage type");
860*da58b97aSjoerg   }
861*da58b97aSjoerg 
862*da58b97aSjoerg   Symbol->print(OS, MAI);
863*da58b97aSjoerg 
864*da58b97aSjoerg   switch (Visibility) {
865*da58b97aSjoerg   case MCSA_Invalid:
866*da58b97aSjoerg     // Nothing to do.
867*da58b97aSjoerg     break;
868*da58b97aSjoerg   case MCSA_Hidden:
869*da58b97aSjoerg     OS << ",hidden";
870*da58b97aSjoerg     break;
871*da58b97aSjoerg   case MCSA_Protected:
872*da58b97aSjoerg     OS << ",protected";
873*da58b97aSjoerg     break;
874*da58b97aSjoerg   default:
875*da58b97aSjoerg     report_fatal_error("unexpected value for Visibility type");
876*da58b97aSjoerg   }
877*da58b97aSjoerg   EmitEOL();
878*da58b97aSjoerg 
879*da58b97aSjoerg   // Print symbol's rename (original name contains invalid character(s)) if
880*da58b97aSjoerg   // there is one.
881*da58b97aSjoerg   if (cast<MCSymbolXCOFF>(Symbol)->hasRename())
882*da58b97aSjoerg     emitXCOFFRenameDirective(Symbol,
883*da58b97aSjoerg                              cast<MCSymbolXCOFF>(Symbol)->getSymbolTableName());
884*da58b97aSjoerg }
885*da58b97aSjoerg 
emitXCOFFRenameDirective(const MCSymbol * Name,StringRef Rename)886*da58b97aSjoerg void MCAsmStreamer::emitXCOFFRenameDirective(const MCSymbol *Name,
887*da58b97aSjoerg                                              StringRef Rename) {
888*da58b97aSjoerg   OS << "\t.rename\t";
889*da58b97aSjoerg   Name->print(OS, MAI);
890*da58b97aSjoerg   const char DQ = '"';
891*da58b97aSjoerg   OS << ',' << DQ;
892*da58b97aSjoerg   for (char C : Rename) {
893*da58b97aSjoerg     // To escape a double quote character, the character should be doubled.
894*da58b97aSjoerg     if (C == DQ)
895*da58b97aSjoerg       OS << DQ;
896*da58b97aSjoerg     OS << C;
897*da58b97aSjoerg   }
898*da58b97aSjoerg   OS << DQ;
899*da58b97aSjoerg   EmitEOL();
90006f32e7eSjoerg }
90106f32e7eSjoerg 
emitELFSize(MCSymbol * Symbol,const MCExpr * Value)90206f32e7eSjoerg void MCAsmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
90306f32e7eSjoerg   assert(MAI->hasDotTypeDotSizeDirective());
90406f32e7eSjoerg   OS << "\t.size\t";
90506f32e7eSjoerg   Symbol->print(OS, MAI);
90606f32e7eSjoerg   OS << ", ";
90706f32e7eSjoerg   Value->print(OS, MAI);
90806f32e7eSjoerg   EmitEOL();
90906f32e7eSjoerg }
91006f32e7eSjoerg 
emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)911*da58b97aSjoerg void MCAsmStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
91206f32e7eSjoerg                                      unsigned ByteAlignment) {
91306f32e7eSjoerg   OS << "\t.comm\t";
91406f32e7eSjoerg   Symbol->print(OS, MAI);
91506f32e7eSjoerg   OS << ',' << Size;
91606f32e7eSjoerg 
91706f32e7eSjoerg   if (ByteAlignment != 0) {
91806f32e7eSjoerg     if (MAI->getCOMMDirectiveAlignmentIsInBytes())
91906f32e7eSjoerg       OS << ',' << ByteAlignment;
92006f32e7eSjoerg     else
92106f32e7eSjoerg       OS << ',' << Log2_32(ByteAlignment);
92206f32e7eSjoerg   }
92306f32e7eSjoerg   EmitEOL();
924*da58b97aSjoerg 
925*da58b97aSjoerg   // Print symbol's rename (original name contains invalid character(s)) if
926*da58b97aSjoerg   // there is one.
927*da58b97aSjoerg   MCSymbolXCOFF *XSym = dyn_cast<MCSymbolXCOFF>(Symbol);
928*da58b97aSjoerg   if (XSym && XSym->hasRename())
929*da58b97aSjoerg     emitXCOFFRenameDirective(XSym, XSym->getSymbolTableName());
930*da58b97aSjoerg 
93106f32e7eSjoerg }
93206f32e7eSjoerg 
emitLocalCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlign)933*da58b97aSjoerg void MCAsmStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
93406f32e7eSjoerg                                           unsigned ByteAlign) {
93506f32e7eSjoerg   OS << "\t.lcomm\t";
93606f32e7eSjoerg   Symbol->print(OS, MAI);
93706f32e7eSjoerg   OS << ',' << Size;
93806f32e7eSjoerg 
93906f32e7eSjoerg   if (ByteAlign > 1) {
94006f32e7eSjoerg     switch (MAI->getLCOMMDirectiveAlignmentType()) {
94106f32e7eSjoerg     case LCOMM::NoAlignment:
94206f32e7eSjoerg       llvm_unreachable("alignment not supported on .lcomm!");
94306f32e7eSjoerg     case LCOMM::ByteAlignment:
94406f32e7eSjoerg       OS << ',' << ByteAlign;
94506f32e7eSjoerg       break;
94606f32e7eSjoerg     case LCOMM::Log2Alignment:
94706f32e7eSjoerg       assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
94806f32e7eSjoerg       OS << ',' << Log2_32(ByteAlign);
94906f32e7eSjoerg       break;
95006f32e7eSjoerg     }
95106f32e7eSjoerg   }
95206f32e7eSjoerg   EmitEOL();
95306f32e7eSjoerg }
95406f32e7eSjoerg 
emitZerofill(MCSection * Section,MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment,SMLoc Loc)955*da58b97aSjoerg void MCAsmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
95606f32e7eSjoerg                                  uint64_t Size, unsigned ByteAlignment,
95706f32e7eSjoerg                                  SMLoc Loc) {
95806f32e7eSjoerg   if (Symbol)
95906f32e7eSjoerg     AssignFragment(Symbol, &Section->getDummyFragment());
96006f32e7eSjoerg 
96106f32e7eSjoerg   // Note: a .zerofill directive does not switch sections.
96206f32e7eSjoerg   OS << ".zerofill ";
96306f32e7eSjoerg 
96406f32e7eSjoerg   assert(Section->getVariant() == MCSection::SV_MachO &&
96506f32e7eSjoerg          ".zerofill is a Mach-O specific directive");
96606f32e7eSjoerg   // This is a mach-o specific directive.
96706f32e7eSjoerg 
96806f32e7eSjoerg   const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
969*da58b97aSjoerg   OS << MOSection->getSegmentName() << "," << MOSection->getName();
97006f32e7eSjoerg 
97106f32e7eSjoerg   if (Symbol) {
97206f32e7eSjoerg     OS << ',';
97306f32e7eSjoerg     Symbol->print(OS, MAI);
97406f32e7eSjoerg     OS << ',' << Size;
97506f32e7eSjoerg     if (ByteAlignment != 0)
97606f32e7eSjoerg       OS << ',' << Log2_32(ByteAlignment);
97706f32e7eSjoerg   }
97806f32e7eSjoerg   EmitEOL();
97906f32e7eSjoerg }
98006f32e7eSjoerg 
98106f32e7eSjoerg // .tbss sym, size, align
98206f32e7eSjoerg // This depends that the symbol has already been mangled from the original,
98306f32e7eSjoerg // e.g. _a.
emitTBSSSymbol(MCSection * Section,MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)984*da58b97aSjoerg void MCAsmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
98506f32e7eSjoerg                                    uint64_t Size, unsigned ByteAlignment) {
98606f32e7eSjoerg   AssignFragment(Symbol, &Section->getDummyFragment());
98706f32e7eSjoerg 
98806f32e7eSjoerg   assert(Symbol && "Symbol shouldn't be NULL!");
98906f32e7eSjoerg   // Instead of using the Section we'll just use the shortcut.
99006f32e7eSjoerg 
99106f32e7eSjoerg   assert(Section->getVariant() == MCSection::SV_MachO &&
99206f32e7eSjoerg          ".zerofill is a Mach-O specific directive");
99306f32e7eSjoerg   // This is a mach-o specific directive and section.
99406f32e7eSjoerg 
99506f32e7eSjoerg   OS << ".tbss ";
99606f32e7eSjoerg   Symbol->print(OS, MAI);
99706f32e7eSjoerg   OS << ", " << Size;
99806f32e7eSjoerg 
99906f32e7eSjoerg   // Output align if we have it.  We default to 1 so don't bother printing
100006f32e7eSjoerg   // that.
100106f32e7eSjoerg   if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
100206f32e7eSjoerg 
100306f32e7eSjoerg   EmitEOL();
100406f32e7eSjoerg }
100506f32e7eSjoerg 
isPrintableString(StringRef Data)1006*da58b97aSjoerg static inline bool isPrintableString(StringRef Data) {
1007*da58b97aSjoerg   const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1008*da58b97aSjoerg   for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1009*da58b97aSjoerg     if (!isPrint(C))
1010*da58b97aSjoerg       return false;
1011*da58b97aSjoerg   }
1012*da58b97aSjoerg   return isPrint(Data.back()) || Data.back() == 0;
1013*da58b97aSjoerg }
1014*da58b97aSjoerg 
toOctal(int X)101506f32e7eSjoerg static inline char toOctal(int X) { return (X&7)+'0'; }
101606f32e7eSjoerg 
PrintByteList(StringRef Data,raw_ostream & OS,MCAsmInfo::AsmCharLiteralSyntax ACLS)1017*da58b97aSjoerg static void PrintByteList(StringRef Data, raw_ostream &OS,
1018*da58b97aSjoerg                           MCAsmInfo::AsmCharLiteralSyntax ACLS) {
1019*da58b97aSjoerg   assert(!Data.empty() && "Cannot generate an empty list.");
1020*da58b97aSjoerg   const auto printCharacterInOctal = [&OS](unsigned char C) {
1021*da58b97aSjoerg     OS << '0';
1022*da58b97aSjoerg     OS << toOctal(C >> 6);
1023*da58b97aSjoerg     OS << toOctal(C >> 3);
1024*da58b97aSjoerg     OS << toOctal(C >> 0);
1025*da58b97aSjoerg   };
1026*da58b97aSjoerg   const auto printOneCharacterFor = [printCharacterInOctal](
1027*da58b97aSjoerg                                         auto printOnePrintingCharacter) {
1028*da58b97aSjoerg     return [printCharacterInOctal, printOnePrintingCharacter](unsigned char C) {
1029*da58b97aSjoerg       if (isPrint(C)) {
1030*da58b97aSjoerg         printOnePrintingCharacter(static_cast<char>(C));
1031*da58b97aSjoerg         return;
1032*da58b97aSjoerg       }
1033*da58b97aSjoerg       printCharacterInOctal(C);
1034*da58b97aSjoerg     };
1035*da58b97aSjoerg   };
1036*da58b97aSjoerg   const auto printCharacterList = [Data, &OS](const auto &printOneCharacter) {
1037*da58b97aSjoerg     const auto BeginPtr = Data.begin(), EndPtr = Data.end();
1038*da58b97aSjoerg     for (const unsigned char C : make_range(BeginPtr, EndPtr - 1)) {
1039*da58b97aSjoerg       printOneCharacter(C);
1040*da58b97aSjoerg       OS << ',';
1041*da58b97aSjoerg     }
1042*da58b97aSjoerg     printOneCharacter(*(EndPtr - 1));
1043*da58b97aSjoerg   };
1044*da58b97aSjoerg   switch (ACLS) {
1045*da58b97aSjoerg   case MCAsmInfo::ACLS_Unknown:
1046*da58b97aSjoerg     printCharacterList(printCharacterInOctal);
1047*da58b97aSjoerg     return;
1048*da58b97aSjoerg   case MCAsmInfo::ACLS_SingleQuotePrefix:
1049*da58b97aSjoerg     printCharacterList(printOneCharacterFor([&OS](char C) {
1050*da58b97aSjoerg       const char AsmCharLitBuf[2] = {'\'', C};
1051*da58b97aSjoerg       OS << StringRef(AsmCharLitBuf, sizeof(AsmCharLitBuf));
1052*da58b97aSjoerg     }));
1053*da58b97aSjoerg     return;
1054*da58b97aSjoerg   }
1055*da58b97aSjoerg   llvm_unreachable("Invalid AsmCharLiteralSyntax value!");
1056*da58b97aSjoerg }
1057*da58b97aSjoerg 
PrintQuotedString(StringRef Data,raw_ostream & OS) const1058*da58b97aSjoerg void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const {
105906f32e7eSjoerg   OS << '"';
106006f32e7eSjoerg 
1061*da58b97aSjoerg   if (MAI->hasPairedDoubleQuoteStringConstants()) {
1062*da58b97aSjoerg     for (unsigned i = 0, e = Data.size(); i != e; ++i) {
1063*da58b97aSjoerg       unsigned char C = Data[i];
1064*da58b97aSjoerg       if (C == '"')
1065*da58b97aSjoerg         OS << "\"\"";
1066*da58b97aSjoerg       else
1067*da58b97aSjoerg         OS << (char)C;
1068*da58b97aSjoerg     }
1069*da58b97aSjoerg   } else {
107006f32e7eSjoerg     for (unsigned i = 0, e = Data.size(); i != e; ++i) {
107106f32e7eSjoerg       unsigned char C = Data[i];
107206f32e7eSjoerg       if (C == '"' || C == '\\') {
107306f32e7eSjoerg         OS << '\\' << (char)C;
107406f32e7eSjoerg         continue;
107506f32e7eSjoerg       }
107606f32e7eSjoerg 
107706f32e7eSjoerg       if (isPrint((unsigned char)C)) {
107806f32e7eSjoerg         OS << (char)C;
107906f32e7eSjoerg         continue;
108006f32e7eSjoerg       }
108106f32e7eSjoerg 
108206f32e7eSjoerg       switch (C) {
1083*da58b97aSjoerg       case '\b':
1084*da58b97aSjoerg         OS << "\\b";
1085*da58b97aSjoerg         break;
1086*da58b97aSjoerg       case '\f':
1087*da58b97aSjoerg         OS << "\\f";
1088*da58b97aSjoerg         break;
1089*da58b97aSjoerg       case '\n':
1090*da58b97aSjoerg         OS << "\\n";
1091*da58b97aSjoerg         break;
1092*da58b97aSjoerg       case '\r':
1093*da58b97aSjoerg         OS << "\\r";
1094*da58b97aSjoerg         break;
1095*da58b97aSjoerg       case '\t':
1096*da58b97aSjoerg         OS << "\\t";
1097*da58b97aSjoerg         break;
109806f32e7eSjoerg       default:
109906f32e7eSjoerg         OS << '\\';
110006f32e7eSjoerg         OS << toOctal(C >> 6);
110106f32e7eSjoerg         OS << toOctal(C >> 3);
110206f32e7eSjoerg         OS << toOctal(C >> 0);
110306f32e7eSjoerg         break;
110406f32e7eSjoerg       }
110506f32e7eSjoerg     }
1106*da58b97aSjoerg   }
110706f32e7eSjoerg 
110806f32e7eSjoerg   OS << '"';
110906f32e7eSjoerg }
111006f32e7eSjoerg 
emitBytes(StringRef Data)1111*da58b97aSjoerg void MCAsmStreamer::emitBytes(StringRef Data) {
111206f32e7eSjoerg   assert(getCurrentSectionOnly() &&
111306f32e7eSjoerg          "Cannot emit contents before setting section!");
111406f32e7eSjoerg   if (Data.empty()) return;
111506f32e7eSjoerg 
1116*da58b97aSjoerg   const auto emitAsString = [this](StringRef Data) {
1117*da58b97aSjoerg     // If the data ends with 0 and the target supports .asciz, use it, otherwise
1118*da58b97aSjoerg     // use .ascii or a byte-list directive
1119*da58b97aSjoerg     if (MAI->getAscizDirective() && Data.back() == 0) {
1120*da58b97aSjoerg       OS << MAI->getAscizDirective();
1121*da58b97aSjoerg       Data = Data.substr(0, Data.size() - 1);
1122*da58b97aSjoerg     } else if (LLVM_LIKELY(MAI->getAsciiDirective())) {
1123*da58b97aSjoerg       OS << MAI->getAsciiDirective();
1124*da58b97aSjoerg     } else if (MAI->hasPairedDoubleQuoteStringConstants() &&
1125*da58b97aSjoerg                isPrintableString(Data)) {
1126*da58b97aSjoerg       // For target with DoubleQuoteString constants, .string and .byte are used
1127*da58b97aSjoerg       // as replacement of .asciz and .ascii.
1128*da58b97aSjoerg       assert(MAI->getPlainStringDirective() &&
1129*da58b97aSjoerg              "hasPairedDoubleQuoteStringConstants target must support "
1130*da58b97aSjoerg              "PlainString Directive");
1131*da58b97aSjoerg       assert(MAI->getByteListDirective() &&
1132*da58b97aSjoerg              "hasPairedDoubleQuoteStringConstants target must support ByteList "
1133*da58b97aSjoerg              "Directive");
1134*da58b97aSjoerg       if (Data.back() == 0) {
1135*da58b97aSjoerg         OS << MAI->getPlainStringDirective();
1136*da58b97aSjoerg         Data = Data.substr(0, Data.size() - 1);
1137*da58b97aSjoerg       } else {
1138*da58b97aSjoerg         OS << MAI->getByteListDirective();
1139*da58b97aSjoerg       }
1140*da58b97aSjoerg     } else if (MAI->getByteListDirective()) {
1141*da58b97aSjoerg       OS << MAI->getByteListDirective();
1142*da58b97aSjoerg       PrintByteList(Data, OS, MAI->characterLiteralSyntax());
1143*da58b97aSjoerg       EmitEOL();
1144*da58b97aSjoerg       return true;
1145*da58b97aSjoerg     } else {
1146*da58b97aSjoerg       return false;
1147*da58b97aSjoerg     }
1148*da58b97aSjoerg 
1149*da58b97aSjoerg     PrintQuotedString(Data, OS);
1150*da58b97aSjoerg     EmitEOL();
1151*da58b97aSjoerg     return true;
1152*da58b97aSjoerg   };
1153*da58b97aSjoerg 
1154*da58b97aSjoerg   if (Data.size() != 1 && emitAsString(Data))
1155*da58b97aSjoerg     return;
1156*da58b97aSjoerg 
1157*da58b97aSjoerg   // Only single byte is provided or no ascii, asciz, or byte-list directives
1158*da58b97aSjoerg   // are applicable. Emit as vector of individual 8bits data elements.
115906f32e7eSjoerg   if (MCTargetStreamer *TS = getTargetStreamer()) {
116006f32e7eSjoerg     TS->emitRawBytes(Data);
1161*da58b97aSjoerg     return;
1162*da58b97aSjoerg   }
116306f32e7eSjoerg   const char *Directive = MAI->getData8bitsDirective();
116406f32e7eSjoerg   for (const unsigned char C : Data.bytes()) {
116506f32e7eSjoerg     OS << Directive << (unsigned)C;
116606f32e7eSjoerg     EmitEOL();
116706f32e7eSjoerg   }
116806f32e7eSjoerg }
116906f32e7eSjoerg 
emitBinaryData(StringRef Data)1170*da58b97aSjoerg void MCAsmStreamer::emitBinaryData(StringRef Data) {
117106f32e7eSjoerg   // This is binary data. Print it in a grid of hex bytes for readability.
117206f32e7eSjoerg   const size_t Cols = 4;
117306f32e7eSjoerg   for (size_t I = 0, EI = alignTo(Data.size(), Cols); I < EI; I += Cols) {
117406f32e7eSjoerg     size_t J = I, EJ = std::min(I + Cols, Data.size());
117506f32e7eSjoerg     assert(EJ > 0);
117606f32e7eSjoerg     OS << MAI->getData8bitsDirective();
117706f32e7eSjoerg     for (; J < EJ - 1; ++J)
117806f32e7eSjoerg       OS << format("0x%02x", uint8_t(Data[J])) << ", ";
117906f32e7eSjoerg     OS << format("0x%02x", uint8_t(Data[J]));
118006f32e7eSjoerg     EmitEOL();
118106f32e7eSjoerg   }
118206f32e7eSjoerg }
118306f32e7eSjoerg 
emitIntValue(uint64_t Value,unsigned Size)1184*da58b97aSjoerg void MCAsmStreamer::emitIntValue(uint64_t Value, unsigned Size) {
1185*da58b97aSjoerg   emitValue(MCConstantExpr::create(Value, getContext()), Size);
118606f32e7eSjoerg }
118706f32e7eSjoerg 
emitIntValueInHex(uint64_t Value,unsigned Size)1188*da58b97aSjoerg void MCAsmStreamer::emitIntValueInHex(uint64_t Value, unsigned Size) {
1189*da58b97aSjoerg   emitValue(MCConstantExpr::create(Value, getContext(), true), Size);
119006f32e7eSjoerg }
119106f32e7eSjoerg 
emitIntValueInHexWithPadding(uint64_t Value,unsigned Size)1192*da58b97aSjoerg void MCAsmStreamer::emitIntValueInHexWithPadding(uint64_t Value,
1193*da58b97aSjoerg                                                  unsigned Size) {
1194*da58b97aSjoerg   emitValue(MCConstantExpr::create(Value, getContext(), true, Size), Size);
1195*da58b97aSjoerg }
1196*da58b97aSjoerg 
emitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)1197*da58b97aSjoerg void MCAsmStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
119806f32e7eSjoerg                                   SMLoc Loc) {
119906f32e7eSjoerg   assert(Size <= 8 && "Invalid size");
120006f32e7eSjoerg   assert(getCurrentSectionOnly() &&
120106f32e7eSjoerg          "Cannot emit contents before setting section!");
120206f32e7eSjoerg   const char *Directive = nullptr;
120306f32e7eSjoerg   switch (Size) {
120406f32e7eSjoerg   default: break;
120506f32e7eSjoerg   case 1: Directive = MAI->getData8bitsDirective();  break;
120606f32e7eSjoerg   case 2: Directive = MAI->getData16bitsDirective(); break;
120706f32e7eSjoerg   case 4: Directive = MAI->getData32bitsDirective(); break;
120806f32e7eSjoerg   case 8: Directive = MAI->getData64bitsDirective(); break;
120906f32e7eSjoerg   }
121006f32e7eSjoerg 
121106f32e7eSjoerg   if (!Directive) {
121206f32e7eSjoerg     int64_t IntValue;
121306f32e7eSjoerg     if (!Value->evaluateAsAbsolute(IntValue))
121406f32e7eSjoerg       report_fatal_error("Don't know how to emit this value.");
121506f32e7eSjoerg 
121606f32e7eSjoerg     // We couldn't handle the requested integer size so we fallback by breaking
121706f32e7eSjoerg     // the request down into several, smaller, integers.
121806f32e7eSjoerg     // Since sizes greater or equal to "Size" are invalid, we use the greatest
121906f32e7eSjoerg     // power of 2 that is less than "Size" as our largest piece of granularity.
122006f32e7eSjoerg     bool IsLittleEndian = MAI->isLittleEndian();
122106f32e7eSjoerg     for (unsigned Emitted = 0; Emitted != Size;) {
122206f32e7eSjoerg       unsigned Remaining = Size - Emitted;
122306f32e7eSjoerg       // The size of our partial emission must be a power of two less than
122406f32e7eSjoerg       // Size.
122506f32e7eSjoerg       unsigned EmissionSize = PowerOf2Floor(std::min(Remaining, Size - 1));
122606f32e7eSjoerg       // Calculate the byte offset of our partial emission taking into account
122706f32e7eSjoerg       // the endianness of the target.
122806f32e7eSjoerg       unsigned ByteOffset =
122906f32e7eSjoerg           IsLittleEndian ? Emitted : (Remaining - EmissionSize);
123006f32e7eSjoerg       uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
123106f32e7eSjoerg       // We truncate our partial emission to fit within the bounds of the
123206f32e7eSjoerg       // emission domain.  This produces nicer output and silences potential
123306f32e7eSjoerg       // truncation warnings when round tripping through another assembler.
123406f32e7eSjoerg       uint64_t Shift = 64 - EmissionSize * 8;
123506f32e7eSjoerg       assert(Shift < static_cast<uint64_t>(
123606f32e7eSjoerg                          std::numeric_limits<unsigned long long>::digits) &&
123706f32e7eSjoerg              "undefined behavior");
123806f32e7eSjoerg       ValueToEmit &= ~0ULL >> Shift;
1239*da58b97aSjoerg       emitIntValue(ValueToEmit, EmissionSize);
124006f32e7eSjoerg       Emitted += EmissionSize;
124106f32e7eSjoerg     }
124206f32e7eSjoerg     return;
124306f32e7eSjoerg   }
124406f32e7eSjoerg 
124506f32e7eSjoerg   assert(Directive && "Invalid size for machine code value!");
124606f32e7eSjoerg   OS << Directive;
124706f32e7eSjoerg   if (MCTargetStreamer *TS = getTargetStreamer()) {
124806f32e7eSjoerg     TS->emitValue(Value);
124906f32e7eSjoerg   } else {
125006f32e7eSjoerg     Value->print(OS, MAI);
125106f32e7eSjoerg     EmitEOL();
125206f32e7eSjoerg   }
125306f32e7eSjoerg }
125406f32e7eSjoerg 
emitULEB128Value(const MCExpr * Value)1255*da58b97aSjoerg void MCAsmStreamer::emitULEB128Value(const MCExpr *Value) {
125606f32e7eSjoerg   int64_t IntValue;
125706f32e7eSjoerg   if (Value->evaluateAsAbsolute(IntValue)) {
1258*da58b97aSjoerg     emitULEB128IntValue(IntValue);
125906f32e7eSjoerg     return;
126006f32e7eSjoerg   }
126106f32e7eSjoerg   OS << "\t.uleb128 ";
126206f32e7eSjoerg   Value->print(OS, MAI);
126306f32e7eSjoerg   EmitEOL();
126406f32e7eSjoerg }
126506f32e7eSjoerg 
emitSLEB128Value(const MCExpr * Value)1266*da58b97aSjoerg void MCAsmStreamer::emitSLEB128Value(const MCExpr *Value) {
126706f32e7eSjoerg   int64_t IntValue;
126806f32e7eSjoerg   if (Value->evaluateAsAbsolute(IntValue)) {
1269*da58b97aSjoerg     emitSLEB128IntValue(IntValue);
127006f32e7eSjoerg     return;
127106f32e7eSjoerg   }
127206f32e7eSjoerg   OS << "\t.sleb128 ";
127306f32e7eSjoerg   Value->print(OS, MAI);
127406f32e7eSjoerg   EmitEOL();
127506f32e7eSjoerg }
127606f32e7eSjoerg 
emitDTPRel64Value(const MCExpr * Value)1277*da58b97aSjoerg void MCAsmStreamer::emitDTPRel64Value(const MCExpr *Value) {
127806f32e7eSjoerg   assert(MAI->getDTPRel64Directive() != nullptr);
127906f32e7eSjoerg   OS << MAI->getDTPRel64Directive();
128006f32e7eSjoerg   Value->print(OS, MAI);
128106f32e7eSjoerg   EmitEOL();
128206f32e7eSjoerg }
128306f32e7eSjoerg 
emitDTPRel32Value(const MCExpr * Value)1284*da58b97aSjoerg void MCAsmStreamer::emitDTPRel32Value(const MCExpr *Value) {
128506f32e7eSjoerg   assert(MAI->getDTPRel32Directive() != nullptr);
128606f32e7eSjoerg   OS << MAI->getDTPRel32Directive();
128706f32e7eSjoerg   Value->print(OS, MAI);
128806f32e7eSjoerg   EmitEOL();
128906f32e7eSjoerg }
129006f32e7eSjoerg 
emitTPRel64Value(const MCExpr * Value)1291*da58b97aSjoerg void MCAsmStreamer::emitTPRel64Value(const MCExpr *Value) {
129206f32e7eSjoerg   assert(MAI->getTPRel64Directive() != nullptr);
129306f32e7eSjoerg   OS << MAI->getTPRel64Directive();
129406f32e7eSjoerg   Value->print(OS, MAI);
129506f32e7eSjoerg   EmitEOL();
129606f32e7eSjoerg }
129706f32e7eSjoerg 
emitTPRel32Value(const MCExpr * Value)1298*da58b97aSjoerg void MCAsmStreamer::emitTPRel32Value(const MCExpr *Value) {
129906f32e7eSjoerg   assert(MAI->getTPRel32Directive() != nullptr);
130006f32e7eSjoerg   OS << MAI->getTPRel32Directive();
130106f32e7eSjoerg   Value->print(OS, MAI);
130206f32e7eSjoerg   EmitEOL();
130306f32e7eSjoerg }
130406f32e7eSjoerg 
emitGPRel64Value(const MCExpr * Value)1305*da58b97aSjoerg void MCAsmStreamer::emitGPRel64Value(const MCExpr *Value) {
130606f32e7eSjoerg   assert(MAI->getGPRel64Directive() != nullptr);
130706f32e7eSjoerg   OS << MAI->getGPRel64Directive();
130806f32e7eSjoerg   Value->print(OS, MAI);
130906f32e7eSjoerg   EmitEOL();
131006f32e7eSjoerg }
131106f32e7eSjoerg 
emitGPRel32Value(const MCExpr * Value)1312*da58b97aSjoerg void MCAsmStreamer::emitGPRel32Value(const MCExpr *Value) {
131306f32e7eSjoerg   assert(MAI->getGPRel32Directive() != nullptr);
131406f32e7eSjoerg   OS << MAI->getGPRel32Directive();
131506f32e7eSjoerg   Value->print(OS, MAI);
131606f32e7eSjoerg   EmitEOL();
131706f32e7eSjoerg }
131806f32e7eSjoerg 
emitFill(const MCExpr & NumBytes,uint64_t FillValue,SMLoc Loc)131906f32e7eSjoerg void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
132006f32e7eSjoerg                              SMLoc Loc) {
132106f32e7eSjoerg   int64_t IntNumBytes;
1322*da58b97aSjoerg   const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes);
1323*da58b97aSjoerg   if (IsAbsolute && IntNumBytes == 0)
132406f32e7eSjoerg     return;
132506f32e7eSjoerg 
132606f32e7eSjoerg   if (const char *ZeroDirective = MAI->getZeroDirective()) {
1327*da58b97aSjoerg     if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) {
132806f32e7eSjoerg       // FIXME: Emit location directives
132906f32e7eSjoerg       OS << ZeroDirective;
133006f32e7eSjoerg       NumBytes.print(OS, MAI);
133106f32e7eSjoerg       if (FillValue != 0)
133206f32e7eSjoerg         OS << ',' << (int)FillValue;
133306f32e7eSjoerg       EmitEOL();
1334*da58b97aSjoerg     } else {
1335*da58b97aSjoerg       if (!IsAbsolute)
1336*da58b97aSjoerg         report_fatal_error(
1337*da58b97aSjoerg             "Cannot emit non-absolute expression lengths of fill.");
1338*da58b97aSjoerg       for (int i = 0; i < IntNumBytes; ++i) {
1339*da58b97aSjoerg         OS << MAI->getData8bitsDirective() << (int)FillValue;
1340*da58b97aSjoerg         EmitEOL();
1341*da58b97aSjoerg       }
1342*da58b97aSjoerg     }
134306f32e7eSjoerg     return;
134406f32e7eSjoerg   }
134506f32e7eSjoerg 
134606f32e7eSjoerg   MCStreamer::emitFill(NumBytes, FillValue);
134706f32e7eSjoerg }
134806f32e7eSjoerg 
emitFill(const MCExpr & NumValues,int64_t Size,int64_t Expr,SMLoc Loc)134906f32e7eSjoerg void MCAsmStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
135006f32e7eSjoerg                              int64_t Expr, SMLoc Loc) {
135106f32e7eSjoerg   // FIXME: Emit location directives
135206f32e7eSjoerg   OS << "\t.fill\t";
135306f32e7eSjoerg   NumValues.print(OS, MAI);
135406f32e7eSjoerg   OS << ", " << Size << ", 0x";
135506f32e7eSjoerg   OS.write_hex(truncateToSize(Expr, 4));
135606f32e7eSjoerg   EmitEOL();
135706f32e7eSjoerg }
135806f32e7eSjoerg 
emitValueToAlignment(unsigned ByteAlignment,int64_t Value,unsigned ValueSize,unsigned MaxBytesToEmit)1359*da58b97aSjoerg void MCAsmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
136006f32e7eSjoerg                                          unsigned ValueSize,
136106f32e7eSjoerg                                          unsigned MaxBytesToEmit) {
136206f32e7eSjoerg   if (MAI->useDotAlignForAlignment()) {
136306f32e7eSjoerg     if (!isPowerOf2_32(ByteAlignment))
136406f32e7eSjoerg       report_fatal_error("Only power-of-two alignments are supported "
136506f32e7eSjoerg                          "with .align.");
136606f32e7eSjoerg     OS << "\t.align\t";
136706f32e7eSjoerg     OS << Log2_32(ByteAlignment);
136806f32e7eSjoerg     EmitEOL();
136906f32e7eSjoerg     return;
137006f32e7eSjoerg   }
137106f32e7eSjoerg 
137206f32e7eSjoerg   // Some assemblers don't support non-power of two alignments, so we always
137306f32e7eSjoerg   // emit alignments as a power of two if possible.
137406f32e7eSjoerg   if (isPowerOf2_32(ByteAlignment)) {
137506f32e7eSjoerg     switch (ValueSize) {
137606f32e7eSjoerg     default:
137706f32e7eSjoerg       llvm_unreachable("Invalid size for machine code value!");
137806f32e7eSjoerg     case 1:
137906f32e7eSjoerg       OS << "\t.p2align\t";
138006f32e7eSjoerg       break;
138106f32e7eSjoerg     case 2:
138206f32e7eSjoerg       OS << ".p2alignw ";
138306f32e7eSjoerg       break;
138406f32e7eSjoerg     case 4:
138506f32e7eSjoerg       OS << ".p2alignl ";
138606f32e7eSjoerg       break;
138706f32e7eSjoerg     case 8:
138806f32e7eSjoerg       llvm_unreachable("Unsupported alignment size!");
138906f32e7eSjoerg     }
139006f32e7eSjoerg 
139106f32e7eSjoerg     OS << Log2_32(ByteAlignment);
139206f32e7eSjoerg 
139306f32e7eSjoerg     if (Value || MaxBytesToEmit) {
139406f32e7eSjoerg       OS << ", 0x";
139506f32e7eSjoerg       OS.write_hex(truncateToSize(Value, ValueSize));
139606f32e7eSjoerg 
139706f32e7eSjoerg       if (MaxBytesToEmit)
139806f32e7eSjoerg         OS << ", " << MaxBytesToEmit;
139906f32e7eSjoerg     }
140006f32e7eSjoerg     EmitEOL();
140106f32e7eSjoerg     return;
140206f32e7eSjoerg   }
140306f32e7eSjoerg 
140406f32e7eSjoerg   // Non-power of two alignment.  This is not widely supported by assemblers.
140506f32e7eSjoerg   // FIXME: Parameterize this based on MAI.
140606f32e7eSjoerg   switch (ValueSize) {
140706f32e7eSjoerg   default: llvm_unreachable("Invalid size for machine code value!");
140806f32e7eSjoerg   case 1: OS << ".balign";  break;
140906f32e7eSjoerg   case 2: OS << ".balignw"; break;
141006f32e7eSjoerg   case 4: OS << ".balignl"; break;
141106f32e7eSjoerg   case 8: llvm_unreachable("Unsupported alignment size!");
141206f32e7eSjoerg   }
141306f32e7eSjoerg 
141406f32e7eSjoerg   OS << ' ' << ByteAlignment;
141506f32e7eSjoerg   OS << ", " << truncateToSize(Value, ValueSize);
141606f32e7eSjoerg   if (MaxBytesToEmit)
141706f32e7eSjoerg     OS << ", " << MaxBytesToEmit;
141806f32e7eSjoerg   EmitEOL();
141906f32e7eSjoerg }
142006f32e7eSjoerg 
emitCodeAlignment(unsigned ByteAlignment,unsigned MaxBytesToEmit)1421*da58b97aSjoerg void MCAsmStreamer::emitCodeAlignment(unsigned ByteAlignment,
142206f32e7eSjoerg                                       unsigned MaxBytesToEmit) {
142306f32e7eSjoerg   // Emit with a text fill value.
1424*da58b97aSjoerg   emitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
142506f32e7eSjoerg                        1, MaxBytesToEmit);
142606f32e7eSjoerg }
142706f32e7eSjoerg 
emitValueToOffset(const MCExpr * Offset,unsigned char Value,SMLoc Loc)142806f32e7eSjoerg void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset,
142906f32e7eSjoerg                                       unsigned char Value,
143006f32e7eSjoerg                                       SMLoc Loc) {
143106f32e7eSjoerg   // FIXME: Verify that Offset is associated with the current section.
143206f32e7eSjoerg   OS << ".org ";
143306f32e7eSjoerg   Offset->print(OS, MAI);
143406f32e7eSjoerg   OS << ", " << (unsigned)Value;
143506f32e7eSjoerg   EmitEOL();
143606f32e7eSjoerg }
143706f32e7eSjoerg 
emitFileDirective(StringRef Filename)1438*da58b97aSjoerg void MCAsmStreamer::emitFileDirective(StringRef Filename) {
143906f32e7eSjoerg   assert(MAI->hasSingleParameterDotFile());
144006f32e7eSjoerg   OS << "\t.file\t";
144106f32e7eSjoerg   PrintQuotedString(Filename, OS);
144206f32e7eSjoerg   EmitEOL();
144306f32e7eSjoerg }
144406f32e7eSjoerg 
printDwarfFileDirective(unsigned FileNo,StringRef Directory,StringRef Filename,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source,bool UseDwarfDirectory,raw_svector_ostream & OS) const1445*da58b97aSjoerg void MCAsmStreamer::printDwarfFileDirective(
1446*da58b97aSjoerg     unsigned FileNo, StringRef Directory, StringRef Filename,
1447*da58b97aSjoerg     Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source,
1448*da58b97aSjoerg     bool UseDwarfDirectory, raw_svector_ostream &OS) const {
144906f32e7eSjoerg   SmallString<128> FullPathName;
145006f32e7eSjoerg 
145106f32e7eSjoerg   if (!UseDwarfDirectory && !Directory.empty()) {
145206f32e7eSjoerg     if (sys::path::is_absolute(Filename))
145306f32e7eSjoerg       Directory = "";
145406f32e7eSjoerg     else {
145506f32e7eSjoerg       FullPathName = Directory;
145606f32e7eSjoerg       sys::path::append(FullPathName, Filename);
145706f32e7eSjoerg       Directory = "";
145806f32e7eSjoerg       Filename = FullPathName;
145906f32e7eSjoerg     }
146006f32e7eSjoerg   }
146106f32e7eSjoerg 
146206f32e7eSjoerg   OS << "\t.file\t" << FileNo << ' ';
146306f32e7eSjoerg   if (!Directory.empty()) {
146406f32e7eSjoerg     PrintQuotedString(Directory, OS);
146506f32e7eSjoerg     OS << ' ';
146606f32e7eSjoerg   }
146706f32e7eSjoerg   PrintQuotedString(Filename, OS);
146806f32e7eSjoerg   if (Checksum)
146906f32e7eSjoerg     OS << " md5 0x" << Checksum->digest();
147006f32e7eSjoerg   if (Source) {
147106f32e7eSjoerg     OS << " source ";
147206f32e7eSjoerg     PrintQuotedString(*Source, OS);
147306f32e7eSjoerg   }
147406f32e7eSjoerg }
147506f32e7eSjoerg 
tryEmitDwarfFileDirective(unsigned FileNo,StringRef Directory,StringRef Filename,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source,unsigned CUID)147606f32e7eSjoerg Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective(
147706f32e7eSjoerg     unsigned FileNo, StringRef Directory, StringRef Filename,
147806f32e7eSjoerg     Optional<MD5::MD5Result> Checksum, Optional<StringRef> Source, unsigned CUID) {
147906f32e7eSjoerg   assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer");
148006f32e7eSjoerg 
148106f32e7eSjoerg   MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
148206f32e7eSjoerg   unsigned NumFiles = Table.getMCDwarfFiles().size();
148306f32e7eSjoerg   Expected<unsigned> FileNoOrErr =
148406f32e7eSjoerg       Table.tryGetFile(Directory, Filename, Checksum, Source,
148506f32e7eSjoerg                        getContext().getDwarfVersion(), FileNo);
148606f32e7eSjoerg   if (!FileNoOrErr)
148706f32e7eSjoerg     return FileNoOrErr.takeError();
148806f32e7eSjoerg   FileNo = FileNoOrErr.get();
1489*da58b97aSjoerg 
1490*da58b97aSjoerg   // Return early if this file is already emitted before or if target doesn't
1491*da58b97aSjoerg   // support .file directive.
1492*da58b97aSjoerg   if (NumFiles == Table.getMCDwarfFiles().size() ||
1493*da58b97aSjoerg       !MAI->usesDwarfFileAndLocDirectives())
149406f32e7eSjoerg     return FileNo;
149506f32e7eSjoerg 
149606f32e7eSjoerg   SmallString<128> Str;
149706f32e7eSjoerg   raw_svector_ostream OS1(Str);
149806f32e7eSjoerg   printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source,
149906f32e7eSjoerg                           UseDwarfDirectory, OS1);
150006f32e7eSjoerg 
150106f32e7eSjoerg   if (MCTargetStreamer *TS = getTargetStreamer())
150206f32e7eSjoerg     TS->emitDwarfFileDirective(OS1.str());
150306f32e7eSjoerg   else
1504*da58b97aSjoerg     emitRawText(OS1.str());
150506f32e7eSjoerg 
150606f32e7eSjoerg   return FileNo;
150706f32e7eSjoerg }
150806f32e7eSjoerg 
emitDwarfFile0Directive(StringRef Directory,StringRef Filename,Optional<MD5::MD5Result> Checksum,Optional<StringRef> Source,unsigned CUID)150906f32e7eSjoerg void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory,
151006f32e7eSjoerg                                             StringRef Filename,
151106f32e7eSjoerg                                             Optional<MD5::MD5Result> Checksum,
151206f32e7eSjoerg                                             Optional<StringRef> Source,
151306f32e7eSjoerg                                             unsigned CUID) {
151406f32e7eSjoerg   assert(CUID == 0);
151506f32e7eSjoerg   // .file 0 is new for DWARF v5.
151606f32e7eSjoerg   if (getContext().getDwarfVersion() < 5)
151706f32e7eSjoerg     return;
151806f32e7eSjoerg   // Inform MCDwarf about the root file.
151906f32e7eSjoerg   getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
152006f32e7eSjoerg                                       Source);
152106f32e7eSjoerg 
1522*da58b97aSjoerg   // Target doesn't support .loc/.file directives, return early.
1523*da58b97aSjoerg   if (!MAI->usesDwarfFileAndLocDirectives())
1524*da58b97aSjoerg     return;
1525*da58b97aSjoerg 
152606f32e7eSjoerg   SmallString<128> Str;
152706f32e7eSjoerg   raw_svector_ostream OS1(Str);
152806f32e7eSjoerg   printDwarfFileDirective(0, Directory, Filename, Checksum, Source,
152906f32e7eSjoerg                           UseDwarfDirectory, OS1);
153006f32e7eSjoerg 
153106f32e7eSjoerg   if (MCTargetStreamer *TS = getTargetStreamer())
153206f32e7eSjoerg     TS->emitDwarfFileDirective(OS1.str());
153306f32e7eSjoerg   else
1534*da58b97aSjoerg     emitRawText(OS1.str());
153506f32e7eSjoerg }
153606f32e7eSjoerg 
emitDwarfLocDirective(unsigned FileNo,unsigned Line,unsigned Column,unsigned Flags,unsigned Isa,unsigned Discriminator,StringRef FileName)1537*da58b97aSjoerg void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
153806f32e7eSjoerg                                           unsigned Column, unsigned Flags,
1539*da58b97aSjoerg                                           unsigned Isa, unsigned Discriminator,
154006f32e7eSjoerg                                           StringRef FileName) {
1541*da58b97aSjoerg   // If target doesn't support .loc/.file directive, we need to record the lines
1542*da58b97aSjoerg   // same way like we do in object mode.
1543*da58b97aSjoerg   if (!MAI->usesDwarfFileAndLocDirectives()) {
1544*da58b97aSjoerg     // In case we see two .loc directives in a row, make sure the
1545*da58b97aSjoerg     // first one gets a line entry.
1546*da58b97aSjoerg     MCDwarfLineEntry::make(this, getCurrentSectionOnly());
1547*da58b97aSjoerg     this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1548*da58b97aSjoerg                                             Discriminator, FileName);
1549*da58b97aSjoerg     return;
1550*da58b97aSjoerg   }
1551*da58b97aSjoerg 
155206f32e7eSjoerg   OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
155306f32e7eSjoerg   if (MAI->supportsExtendedDwarfLocDirective()) {
155406f32e7eSjoerg     if (Flags & DWARF2_FLAG_BASIC_BLOCK)
155506f32e7eSjoerg       OS << " basic_block";
155606f32e7eSjoerg     if (Flags & DWARF2_FLAG_PROLOGUE_END)
155706f32e7eSjoerg       OS << " prologue_end";
155806f32e7eSjoerg     if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
155906f32e7eSjoerg       OS << " epilogue_begin";
156006f32e7eSjoerg 
156106f32e7eSjoerg     unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
156206f32e7eSjoerg     if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
156306f32e7eSjoerg       OS << " is_stmt ";
156406f32e7eSjoerg 
156506f32e7eSjoerg       if (Flags & DWARF2_FLAG_IS_STMT)
156606f32e7eSjoerg         OS << "1";
156706f32e7eSjoerg       else
156806f32e7eSjoerg         OS << "0";
156906f32e7eSjoerg     }
157006f32e7eSjoerg 
157106f32e7eSjoerg     if (Isa)
157206f32e7eSjoerg       OS << " isa " << Isa;
157306f32e7eSjoerg     if (Discriminator)
157406f32e7eSjoerg       OS << " discriminator " << Discriminator;
157506f32e7eSjoerg   }
157606f32e7eSjoerg 
157706f32e7eSjoerg   if (IsVerboseAsm) {
157806f32e7eSjoerg     OS.PadToColumn(MAI->getCommentColumn());
157906f32e7eSjoerg     OS << MAI->getCommentString() << ' ' << FileName << ':'
158006f32e7eSjoerg        << Line << ':' << Column;
158106f32e7eSjoerg   }
158206f32e7eSjoerg   EmitEOL();
1583*da58b97aSjoerg   this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
1584*da58b97aSjoerg                                           Discriminator, FileName);
158506f32e7eSjoerg }
158606f32e7eSjoerg 
getDwarfLineTableSymbol(unsigned CUID)158706f32e7eSjoerg MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
158806f32e7eSjoerg   // Always use the zeroth line table, since asm syntax only supports one line
158906f32e7eSjoerg   // table for now.
159006f32e7eSjoerg   return MCStreamer::getDwarfLineTableSymbol(0);
159106f32e7eSjoerg }
159206f32e7eSjoerg 
EmitCVFileDirective(unsigned FileNo,StringRef Filename,ArrayRef<uint8_t> Checksum,unsigned ChecksumKind)159306f32e7eSjoerg bool MCAsmStreamer::EmitCVFileDirective(unsigned FileNo, StringRef Filename,
159406f32e7eSjoerg                                         ArrayRef<uint8_t> Checksum,
159506f32e7eSjoerg                                         unsigned ChecksumKind) {
159606f32e7eSjoerg   if (!getContext().getCVContext().addFile(*this, FileNo, Filename, Checksum,
159706f32e7eSjoerg                                            ChecksumKind))
159806f32e7eSjoerg     return false;
159906f32e7eSjoerg 
160006f32e7eSjoerg   OS << "\t.cv_file\t" << FileNo << ' ';
160106f32e7eSjoerg   PrintQuotedString(Filename, OS);
160206f32e7eSjoerg 
160306f32e7eSjoerg   if (!ChecksumKind) {
160406f32e7eSjoerg     EmitEOL();
160506f32e7eSjoerg     return true;
160606f32e7eSjoerg   }
160706f32e7eSjoerg 
160806f32e7eSjoerg   OS << ' ';
160906f32e7eSjoerg   PrintQuotedString(toHex(Checksum), OS);
161006f32e7eSjoerg   OS << ' ' << ChecksumKind;
161106f32e7eSjoerg 
161206f32e7eSjoerg   EmitEOL();
161306f32e7eSjoerg   return true;
161406f32e7eSjoerg }
161506f32e7eSjoerg 
EmitCVFuncIdDirective(unsigned FuncId)161606f32e7eSjoerg bool MCAsmStreamer::EmitCVFuncIdDirective(unsigned FuncId) {
161706f32e7eSjoerg   OS << "\t.cv_func_id " << FuncId << '\n';
161806f32e7eSjoerg   return MCStreamer::EmitCVFuncIdDirective(FuncId);
161906f32e7eSjoerg }
162006f32e7eSjoerg 
EmitCVInlineSiteIdDirective(unsigned FunctionId,unsigned IAFunc,unsigned IAFile,unsigned IALine,unsigned IACol,SMLoc Loc)162106f32e7eSjoerg bool MCAsmStreamer::EmitCVInlineSiteIdDirective(unsigned FunctionId,
162206f32e7eSjoerg                                                 unsigned IAFunc,
162306f32e7eSjoerg                                                 unsigned IAFile,
162406f32e7eSjoerg                                                 unsigned IALine, unsigned IACol,
162506f32e7eSjoerg                                                 SMLoc Loc) {
162606f32e7eSjoerg   OS << "\t.cv_inline_site_id " << FunctionId << " within " << IAFunc
162706f32e7eSjoerg      << " inlined_at " << IAFile << ' ' << IALine << ' ' << IACol << '\n';
162806f32e7eSjoerg   return MCStreamer::EmitCVInlineSiteIdDirective(FunctionId, IAFunc, IAFile,
162906f32e7eSjoerg                                                  IALine, IACol, Loc);
163006f32e7eSjoerg }
163106f32e7eSjoerg 
emitCVLocDirective(unsigned FunctionId,unsigned FileNo,unsigned Line,unsigned Column,bool PrologueEnd,bool IsStmt,StringRef FileName,SMLoc Loc)1632*da58b97aSjoerg void MCAsmStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
163306f32e7eSjoerg                                        unsigned Line, unsigned Column,
163406f32e7eSjoerg                                        bool PrologueEnd, bool IsStmt,
163506f32e7eSjoerg                                        StringRef FileName, SMLoc Loc) {
163606f32e7eSjoerg   // Validate the directive.
163706f32e7eSjoerg   if (!checkCVLocSection(FunctionId, FileNo, Loc))
163806f32e7eSjoerg     return;
163906f32e7eSjoerg 
164006f32e7eSjoerg   OS << "\t.cv_loc\t" << FunctionId << " " << FileNo << " " << Line << " "
164106f32e7eSjoerg      << Column;
164206f32e7eSjoerg   if (PrologueEnd)
164306f32e7eSjoerg     OS << " prologue_end";
164406f32e7eSjoerg 
164506f32e7eSjoerg   if (IsStmt)
164606f32e7eSjoerg     OS << " is_stmt 1";
164706f32e7eSjoerg 
164806f32e7eSjoerg   if (IsVerboseAsm) {
164906f32e7eSjoerg     OS.PadToColumn(MAI->getCommentColumn());
165006f32e7eSjoerg     OS << MAI->getCommentString() << ' ' << FileName << ':' << Line << ':'
165106f32e7eSjoerg        << Column;
165206f32e7eSjoerg   }
165306f32e7eSjoerg   EmitEOL();
165406f32e7eSjoerg }
165506f32e7eSjoerg 
emitCVLinetableDirective(unsigned FunctionId,const MCSymbol * FnStart,const MCSymbol * FnEnd)1656*da58b97aSjoerg void MCAsmStreamer::emitCVLinetableDirective(unsigned FunctionId,
165706f32e7eSjoerg                                              const MCSymbol *FnStart,
165806f32e7eSjoerg                                              const MCSymbol *FnEnd) {
165906f32e7eSjoerg   OS << "\t.cv_linetable\t" << FunctionId << ", ";
166006f32e7eSjoerg   FnStart->print(OS, MAI);
166106f32e7eSjoerg   OS << ", ";
166206f32e7eSjoerg   FnEnd->print(OS, MAI);
166306f32e7eSjoerg   EmitEOL();
1664*da58b97aSjoerg   this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart, FnEnd);
166506f32e7eSjoerg }
166606f32e7eSjoerg 
emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,unsigned SourceFileId,unsigned SourceLineNum,const MCSymbol * FnStartSym,const MCSymbol * FnEndSym)1667*da58b97aSjoerg void MCAsmStreamer::emitCVInlineLinetableDirective(unsigned PrimaryFunctionId,
166806f32e7eSjoerg                                                    unsigned SourceFileId,
166906f32e7eSjoerg                                                    unsigned SourceLineNum,
167006f32e7eSjoerg                                                    const MCSymbol *FnStartSym,
167106f32e7eSjoerg                                                    const MCSymbol *FnEndSym) {
167206f32e7eSjoerg   OS << "\t.cv_inline_linetable\t" << PrimaryFunctionId << ' ' << SourceFileId
167306f32e7eSjoerg      << ' ' << SourceLineNum << ' ';
167406f32e7eSjoerg   FnStartSym->print(OS, MAI);
167506f32e7eSjoerg   OS << ' ';
167606f32e7eSjoerg   FnEndSym->print(OS, MAI);
167706f32e7eSjoerg   EmitEOL();
1678*da58b97aSjoerg   this->MCStreamer::emitCVInlineLinetableDirective(
167906f32e7eSjoerg       PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
168006f32e7eSjoerg }
168106f32e7eSjoerg 
PrintCVDefRangePrefix(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges)168206f32e7eSjoerg void MCAsmStreamer::PrintCVDefRangePrefix(
168306f32e7eSjoerg     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges) {
168406f32e7eSjoerg   OS << "\t.cv_def_range\t";
168506f32e7eSjoerg   for (std::pair<const MCSymbol *, const MCSymbol *> Range : Ranges) {
168606f32e7eSjoerg     OS << ' ';
168706f32e7eSjoerg     Range.first->print(OS, MAI);
168806f32e7eSjoerg     OS << ' ';
168906f32e7eSjoerg     Range.second->print(OS, MAI);
169006f32e7eSjoerg   }
169106f32e7eSjoerg }
169206f32e7eSjoerg 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeRegisterRelHeader DRHdr)1693*da58b97aSjoerg void MCAsmStreamer::emitCVDefRangeDirective(
169406f32e7eSjoerg     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
169506f32e7eSjoerg     codeview::DefRangeRegisterRelHeader DRHdr) {
169606f32e7eSjoerg   PrintCVDefRangePrefix(Ranges);
169706f32e7eSjoerg   OS << ", reg_rel, ";
169806f32e7eSjoerg   OS << DRHdr.Register << ", " << DRHdr.Flags << ", "
169906f32e7eSjoerg      << DRHdr.BasePointerOffset;
170006f32e7eSjoerg   EmitEOL();
170106f32e7eSjoerg }
170206f32e7eSjoerg 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeSubfieldRegisterHeader DRHdr)1703*da58b97aSjoerg void MCAsmStreamer::emitCVDefRangeDirective(
170406f32e7eSjoerg     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
170506f32e7eSjoerg     codeview::DefRangeSubfieldRegisterHeader DRHdr) {
170606f32e7eSjoerg   PrintCVDefRangePrefix(Ranges);
170706f32e7eSjoerg   OS << ", subfield_reg, ";
170806f32e7eSjoerg   OS << DRHdr.Register << ", " << DRHdr.OffsetInParent;
170906f32e7eSjoerg   EmitEOL();
171006f32e7eSjoerg }
171106f32e7eSjoerg 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeRegisterHeader DRHdr)1712*da58b97aSjoerg void MCAsmStreamer::emitCVDefRangeDirective(
171306f32e7eSjoerg     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
171406f32e7eSjoerg     codeview::DefRangeRegisterHeader DRHdr) {
171506f32e7eSjoerg   PrintCVDefRangePrefix(Ranges);
171606f32e7eSjoerg   OS << ", reg, ";
171706f32e7eSjoerg   OS << DRHdr.Register;
171806f32e7eSjoerg   EmitEOL();
171906f32e7eSjoerg }
172006f32e7eSjoerg 
emitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,codeview::DefRangeFramePointerRelHeader DRHdr)1721*da58b97aSjoerg void MCAsmStreamer::emitCVDefRangeDirective(
172206f32e7eSjoerg     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
172306f32e7eSjoerg     codeview::DefRangeFramePointerRelHeader DRHdr) {
172406f32e7eSjoerg   PrintCVDefRangePrefix(Ranges);
172506f32e7eSjoerg   OS << ", frame_ptr_rel, ";
172606f32e7eSjoerg   OS << DRHdr.Offset;
172706f32e7eSjoerg   EmitEOL();
172806f32e7eSjoerg }
172906f32e7eSjoerg 
emitCVStringTableDirective()1730*da58b97aSjoerg void MCAsmStreamer::emitCVStringTableDirective() {
173106f32e7eSjoerg   OS << "\t.cv_stringtable";
173206f32e7eSjoerg   EmitEOL();
173306f32e7eSjoerg }
173406f32e7eSjoerg 
emitCVFileChecksumsDirective()1735*da58b97aSjoerg void MCAsmStreamer::emitCVFileChecksumsDirective() {
173606f32e7eSjoerg   OS << "\t.cv_filechecksums";
173706f32e7eSjoerg   EmitEOL();
173806f32e7eSjoerg }
173906f32e7eSjoerg 
emitCVFileChecksumOffsetDirective(unsigned FileNo)1740*da58b97aSjoerg void MCAsmStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
174106f32e7eSjoerg   OS << "\t.cv_filechecksumoffset\t" << FileNo;
174206f32e7eSjoerg   EmitEOL();
174306f32e7eSjoerg }
174406f32e7eSjoerg 
EmitCVFPOData(const MCSymbol * ProcSym,SMLoc L)174506f32e7eSjoerg void MCAsmStreamer::EmitCVFPOData(const MCSymbol *ProcSym, SMLoc L) {
174606f32e7eSjoerg   OS << "\t.cv_fpo_data\t";
174706f32e7eSjoerg   ProcSym->print(OS, MAI);
174806f32e7eSjoerg   EmitEOL();
174906f32e7eSjoerg }
175006f32e7eSjoerg 
emitIdent(StringRef IdentString)1751*da58b97aSjoerg void MCAsmStreamer::emitIdent(StringRef IdentString) {
175206f32e7eSjoerg   assert(MAI->hasIdentDirective() && ".ident directive not supported");
175306f32e7eSjoerg   OS << "\t.ident\t";
175406f32e7eSjoerg   PrintQuotedString(IdentString, OS);
175506f32e7eSjoerg   EmitEOL();
175606f32e7eSjoerg }
175706f32e7eSjoerg 
emitCFISections(bool EH,bool Debug)1758*da58b97aSjoerg void MCAsmStreamer::emitCFISections(bool EH, bool Debug) {
1759*da58b97aSjoerg   MCStreamer::emitCFISections(EH, Debug);
176006f32e7eSjoerg   OS << "\t.cfi_sections ";
176106f32e7eSjoerg   if (EH) {
176206f32e7eSjoerg     OS << ".eh_frame";
176306f32e7eSjoerg     if (Debug)
176406f32e7eSjoerg       OS << ", .debug_frame";
176506f32e7eSjoerg   } else if (Debug) {
176606f32e7eSjoerg     OS << ".debug_frame";
176706f32e7eSjoerg   }
176806f32e7eSjoerg 
176906f32e7eSjoerg   EmitEOL();
177006f32e7eSjoerg }
177106f32e7eSjoerg 
emitCFIStartProcImpl(MCDwarfFrameInfo & Frame)1772*da58b97aSjoerg void MCAsmStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
177306f32e7eSjoerg   OS << "\t.cfi_startproc";
177406f32e7eSjoerg   if (Frame.IsSimple)
177506f32e7eSjoerg     OS << " simple";
177606f32e7eSjoerg   EmitEOL();
177706f32e7eSjoerg }
177806f32e7eSjoerg 
emitCFIEndProcImpl(MCDwarfFrameInfo & Frame)1779*da58b97aSjoerg void MCAsmStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
1780*da58b97aSjoerg   MCStreamer::emitCFIEndProcImpl(Frame);
178106f32e7eSjoerg   OS << "\t.cfi_endproc";
178206f32e7eSjoerg   EmitEOL();
178306f32e7eSjoerg }
178406f32e7eSjoerg 
EmitRegisterName(int64_t Register)178506f32e7eSjoerg void MCAsmStreamer::EmitRegisterName(int64_t Register) {
178606f32e7eSjoerg   if (!MAI->useDwarfRegNumForCFI()) {
178706f32e7eSjoerg     // User .cfi_* directives can use arbitrary DWARF register numbers, not
178806f32e7eSjoerg     // just ones that map to LLVM register numbers and have known names.
178906f32e7eSjoerg     // Fall back to using the original number directly if no name is known.
179006f32e7eSjoerg     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
179106f32e7eSjoerg     if (Optional<unsigned> LLVMRegister = MRI->getLLVMRegNum(Register, true)) {
179206f32e7eSjoerg       InstPrinter->printRegName(OS, *LLVMRegister);
179306f32e7eSjoerg       return;
179406f32e7eSjoerg     }
179506f32e7eSjoerg   }
179606f32e7eSjoerg   OS << Register;
179706f32e7eSjoerg }
179806f32e7eSjoerg 
emitCFIDefCfa(int64_t Register,int64_t Offset)1799*da58b97aSjoerg void MCAsmStreamer::emitCFIDefCfa(int64_t Register, int64_t Offset) {
1800*da58b97aSjoerg   MCStreamer::emitCFIDefCfa(Register, Offset);
180106f32e7eSjoerg   OS << "\t.cfi_def_cfa ";
180206f32e7eSjoerg   EmitRegisterName(Register);
180306f32e7eSjoerg   OS << ", " << Offset;
180406f32e7eSjoerg   EmitEOL();
180506f32e7eSjoerg }
180606f32e7eSjoerg 
emitCFIDefCfaOffset(int64_t Offset)1807*da58b97aSjoerg void MCAsmStreamer::emitCFIDefCfaOffset(int64_t Offset) {
1808*da58b97aSjoerg   MCStreamer::emitCFIDefCfaOffset(Offset);
180906f32e7eSjoerg   OS << "\t.cfi_def_cfa_offset " << Offset;
181006f32e7eSjoerg   EmitEOL();
181106f32e7eSjoerg }
181206f32e7eSjoerg 
PrintCFIEscape(llvm::formatted_raw_ostream & OS,StringRef Values)181306f32e7eSjoerg static void PrintCFIEscape(llvm::formatted_raw_ostream &OS, StringRef Values) {
181406f32e7eSjoerg   OS << "\t.cfi_escape ";
181506f32e7eSjoerg   if (!Values.empty()) {
181606f32e7eSjoerg     size_t e = Values.size() - 1;
181706f32e7eSjoerg     for (size_t i = 0; i < e; ++i)
181806f32e7eSjoerg       OS << format("0x%02x", uint8_t(Values[i])) << ", ";
181906f32e7eSjoerg     OS << format("0x%02x", uint8_t(Values[e]));
182006f32e7eSjoerg   }
182106f32e7eSjoerg }
182206f32e7eSjoerg 
emitCFIEscape(StringRef Values)1823*da58b97aSjoerg void MCAsmStreamer::emitCFIEscape(StringRef Values) {
1824*da58b97aSjoerg   MCStreamer::emitCFIEscape(Values);
182506f32e7eSjoerg   PrintCFIEscape(OS, Values);
182606f32e7eSjoerg   EmitEOL();
182706f32e7eSjoerg }
182806f32e7eSjoerg 
emitCFIGnuArgsSize(int64_t Size)1829*da58b97aSjoerg void MCAsmStreamer::emitCFIGnuArgsSize(int64_t Size) {
1830*da58b97aSjoerg   MCStreamer::emitCFIGnuArgsSize(Size);
183106f32e7eSjoerg 
183206f32e7eSjoerg   uint8_t Buffer[16] = { dwarf::DW_CFA_GNU_args_size };
183306f32e7eSjoerg   unsigned Len = encodeULEB128(Size, Buffer + 1) + 1;
183406f32e7eSjoerg 
183506f32e7eSjoerg   PrintCFIEscape(OS, StringRef((const char *)&Buffer[0], Len));
183606f32e7eSjoerg   EmitEOL();
183706f32e7eSjoerg }
183806f32e7eSjoerg 
emitCFIDefCfaRegister(int64_t Register)1839*da58b97aSjoerg void MCAsmStreamer::emitCFIDefCfaRegister(int64_t Register) {
1840*da58b97aSjoerg   MCStreamer::emitCFIDefCfaRegister(Register);
184106f32e7eSjoerg   OS << "\t.cfi_def_cfa_register ";
184206f32e7eSjoerg   EmitRegisterName(Register);
184306f32e7eSjoerg   EmitEOL();
184406f32e7eSjoerg }
184506f32e7eSjoerg 
emitCFIOffset(int64_t Register,int64_t Offset)1846*da58b97aSjoerg void MCAsmStreamer::emitCFIOffset(int64_t Register, int64_t Offset) {
1847*da58b97aSjoerg   this->MCStreamer::emitCFIOffset(Register, Offset);
184806f32e7eSjoerg   OS << "\t.cfi_offset ";
184906f32e7eSjoerg   EmitRegisterName(Register);
185006f32e7eSjoerg   OS << ", " << Offset;
185106f32e7eSjoerg   EmitEOL();
185206f32e7eSjoerg }
185306f32e7eSjoerg 
emitCFIPersonality(const MCSymbol * Sym,unsigned Encoding)1854*da58b97aSjoerg void MCAsmStreamer::emitCFIPersonality(const MCSymbol *Sym,
185506f32e7eSjoerg                                        unsigned Encoding) {
1856*da58b97aSjoerg   MCStreamer::emitCFIPersonality(Sym, Encoding);
185706f32e7eSjoerg   OS << "\t.cfi_personality " << Encoding << ", ";
185806f32e7eSjoerg   Sym->print(OS, MAI);
185906f32e7eSjoerg   EmitEOL();
186006f32e7eSjoerg }
186106f32e7eSjoerg 
emitCFILsda(const MCSymbol * Sym,unsigned Encoding)1862*da58b97aSjoerg void MCAsmStreamer::emitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
1863*da58b97aSjoerg   MCStreamer::emitCFILsda(Sym, Encoding);
186406f32e7eSjoerg   OS << "\t.cfi_lsda " << Encoding << ", ";
186506f32e7eSjoerg   Sym->print(OS, MAI);
186606f32e7eSjoerg   EmitEOL();
186706f32e7eSjoerg }
186806f32e7eSjoerg 
emitCFIRememberState()1869*da58b97aSjoerg void MCAsmStreamer::emitCFIRememberState() {
1870*da58b97aSjoerg   MCStreamer::emitCFIRememberState();
187106f32e7eSjoerg   OS << "\t.cfi_remember_state";
187206f32e7eSjoerg   EmitEOL();
187306f32e7eSjoerg }
187406f32e7eSjoerg 
emitCFIRestoreState()1875*da58b97aSjoerg void MCAsmStreamer::emitCFIRestoreState() {
1876*da58b97aSjoerg   MCStreamer::emitCFIRestoreState();
187706f32e7eSjoerg   OS << "\t.cfi_restore_state";
187806f32e7eSjoerg   EmitEOL();
187906f32e7eSjoerg }
188006f32e7eSjoerg 
emitCFIRestore(int64_t Register)1881*da58b97aSjoerg void MCAsmStreamer::emitCFIRestore(int64_t Register) {
1882*da58b97aSjoerg   MCStreamer::emitCFIRestore(Register);
188306f32e7eSjoerg   OS << "\t.cfi_restore ";
188406f32e7eSjoerg   EmitRegisterName(Register);
188506f32e7eSjoerg   EmitEOL();
188606f32e7eSjoerg }
188706f32e7eSjoerg 
emitCFISameValue(int64_t Register)1888*da58b97aSjoerg void MCAsmStreamer::emitCFISameValue(int64_t Register) {
1889*da58b97aSjoerg   MCStreamer::emitCFISameValue(Register);
189006f32e7eSjoerg   OS << "\t.cfi_same_value ";
189106f32e7eSjoerg   EmitRegisterName(Register);
189206f32e7eSjoerg   EmitEOL();
189306f32e7eSjoerg }
189406f32e7eSjoerg 
emitCFIRelOffset(int64_t Register,int64_t Offset)1895*da58b97aSjoerg void MCAsmStreamer::emitCFIRelOffset(int64_t Register, int64_t Offset) {
1896*da58b97aSjoerg   MCStreamer::emitCFIRelOffset(Register, Offset);
189706f32e7eSjoerg   OS << "\t.cfi_rel_offset ";
189806f32e7eSjoerg   EmitRegisterName(Register);
189906f32e7eSjoerg   OS << ", " << Offset;
190006f32e7eSjoerg   EmitEOL();
190106f32e7eSjoerg }
190206f32e7eSjoerg 
emitCFIAdjustCfaOffset(int64_t Adjustment)1903*da58b97aSjoerg void MCAsmStreamer::emitCFIAdjustCfaOffset(int64_t Adjustment) {
1904*da58b97aSjoerg   MCStreamer::emitCFIAdjustCfaOffset(Adjustment);
190506f32e7eSjoerg   OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
190606f32e7eSjoerg   EmitEOL();
190706f32e7eSjoerg }
190806f32e7eSjoerg 
emitCFISignalFrame()1909*da58b97aSjoerg void MCAsmStreamer::emitCFISignalFrame() {
1910*da58b97aSjoerg   MCStreamer::emitCFISignalFrame();
191106f32e7eSjoerg   OS << "\t.cfi_signal_frame";
191206f32e7eSjoerg   EmitEOL();
191306f32e7eSjoerg }
191406f32e7eSjoerg 
emitCFIUndefined(int64_t Register)1915*da58b97aSjoerg void MCAsmStreamer::emitCFIUndefined(int64_t Register) {
1916*da58b97aSjoerg   MCStreamer::emitCFIUndefined(Register);
1917*da58b97aSjoerg   OS << "\t.cfi_undefined ";
1918*da58b97aSjoerg   EmitRegisterName(Register);
191906f32e7eSjoerg   EmitEOL();
192006f32e7eSjoerg }
192106f32e7eSjoerg 
emitCFIRegister(int64_t Register1,int64_t Register2)1922*da58b97aSjoerg void MCAsmStreamer::emitCFIRegister(int64_t Register1, int64_t Register2) {
1923*da58b97aSjoerg   MCStreamer::emitCFIRegister(Register1, Register2);
1924*da58b97aSjoerg   OS << "\t.cfi_register ";
1925*da58b97aSjoerg   EmitRegisterName(Register1);
1926*da58b97aSjoerg   OS << ", ";
1927*da58b97aSjoerg   EmitRegisterName(Register2);
192806f32e7eSjoerg   EmitEOL();
192906f32e7eSjoerg }
193006f32e7eSjoerg 
emitCFIWindowSave()1931*da58b97aSjoerg void MCAsmStreamer::emitCFIWindowSave() {
1932*da58b97aSjoerg   MCStreamer::emitCFIWindowSave();
193306f32e7eSjoerg   OS << "\t.cfi_window_save";
193406f32e7eSjoerg   EmitEOL();
193506f32e7eSjoerg }
193606f32e7eSjoerg 
emitCFINegateRAState()1937*da58b97aSjoerg void MCAsmStreamer::emitCFINegateRAState() {
1938*da58b97aSjoerg   MCStreamer::emitCFINegateRAState();
193906f32e7eSjoerg   OS << "\t.cfi_negate_ra_state";
194006f32e7eSjoerg   EmitEOL();
194106f32e7eSjoerg }
194206f32e7eSjoerg 
emitCFIReturnColumn(int64_t Register)1943*da58b97aSjoerg void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) {
1944*da58b97aSjoerg   MCStreamer::emitCFIReturnColumn(Register);
1945*da58b97aSjoerg   OS << "\t.cfi_return_column ";
1946*da58b97aSjoerg   EmitRegisterName(Register);
194706f32e7eSjoerg   EmitEOL();
194806f32e7eSjoerg }
194906f32e7eSjoerg 
emitCFIBKeyFrame()1950*da58b97aSjoerg void MCAsmStreamer::emitCFIBKeyFrame() {
1951*da58b97aSjoerg   MCStreamer::emitCFIBKeyFrame();
195206f32e7eSjoerg   OS << "\t.cfi_b_key_frame";
195306f32e7eSjoerg   EmitEOL();
195406f32e7eSjoerg }
195506f32e7eSjoerg 
EmitWinCFIStartProc(const MCSymbol * Symbol,SMLoc Loc)195606f32e7eSjoerg void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) {
195706f32e7eSjoerg   MCStreamer::EmitWinCFIStartProc(Symbol, Loc);
195806f32e7eSjoerg 
195906f32e7eSjoerg   OS << ".seh_proc ";
196006f32e7eSjoerg   Symbol->print(OS, MAI);
196106f32e7eSjoerg   EmitEOL();
196206f32e7eSjoerg }
196306f32e7eSjoerg 
EmitWinCFIEndProc(SMLoc Loc)196406f32e7eSjoerg void MCAsmStreamer::EmitWinCFIEndProc(SMLoc Loc) {
196506f32e7eSjoerg   MCStreamer::EmitWinCFIEndProc(Loc);
196606f32e7eSjoerg 
196706f32e7eSjoerg   OS << "\t.seh_endproc";
196806f32e7eSjoerg   EmitEOL();
196906f32e7eSjoerg }
197006f32e7eSjoerg 
EmitWinCFIFuncletOrFuncEnd(SMLoc Loc)197106f32e7eSjoerg void MCAsmStreamer::EmitWinCFIFuncletOrFuncEnd(SMLoc Loc) {
1972*da58b97aSjoerg   MCStreamer::EmitWinCFIFuncletOrFuncEnd(Loc);
1973*da58b97aSjoerg 
1974*da58b97aSjoerg   OS << "\t.seh_endfunclet";
1975*da58b97aSjoerg   EmitEOL();
197606f32e7eSjoerg }
197706f32e7eSjoerg 
EmitWinCFIStartChained(SMLoc Loc)197806f32e7eSjoerg void MCAsmStreamer::EmitWinCFIStartChained(SMLoc Loc) {
197906f32e7eSjoerg   MCStreamer::EmitWinCFIStartChained(Loc);
198006f32e7eSjoerg 
198106f32e7eSjoerg   OS << "\t.seh_startchained";
198206f32e7eSjoerg   EmitEOL();
198306f32e7eSjoerg }
198406f32e7eSjoerg 
EmitWinCFIEndChained(SMLoc Loc)198506f32e7eSjoerg void MCAsmStreamer::EmitWinCFIEndChained(SMLoc Loc) {
198606f32e7eSjoerg   MCStreamer::EmitWinCFIEndChained(Loc);
198706f32e7eSjoerg 
198806f32e7eSjoerg   OS << "\t.seh_endchained";
198906f32e7eSjoerg   EmitEOL();
199006f32e7eSjoerg }
199106f32e7eSjoerg 
EmitWinEHHandler(const MCSymbol * Sym,bool Unwind,bool Except,SMLoc Loc)199206f32e7eSjoerg void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
199306f32e7eSjoerg                                      bool Except, SMLoc Loc) {
199406f32e7eSjoerg   MCStreamer::EmitWinEHHandler(Sym, Unwind, Except, Loc);
199506f32e7eSjoerg 
199606f32e7eSjoerg   OS << "\t.seh_handler ";
199706f32e7eSjoerg   Sym->print(OS, MAI);
199806f32e7eSjoerg   if (Unwind)
199906f32e7eSjoerg     OS << ", @unwind";
200006f32e7eSjoerg   if (Except)
200106f32e7eSjoerg     OS << ", @except";
200206f32e7eSjoerg   EmitEOL();
200306f32e7eSjoerg }
200406f32e7eSjoerg 
EmitWinEHHandlerData(SMLoc Loc)200506f32e7eSjoerg void MCAsmStreamer::EmitWinEHHandlerData(SMLoc Loc) {
200606f32e7eSjoerg   MCStreamer::EmitWinEHHandlerData(Loc);
200706f32e7eSjoerg 
200806f32e7eSjoerg   // Switch sections. Don't call SwitchSection directly, because that will
200906f32e7eSjoerg   // cause the section switch to be visible in the emitted assembly.
201006f32e7eSjoerg   // We only do this so the section switch that terminates the handler
201106f32e7eSjoerg   // data block is visible.
201206f32e7eSjoerg   WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
201306f32e7eSjoerg 
201406f32e7eSjoerg   // Do nothing if no frame is open. MCStreamer should've already reported an
201506f32e7eSjoerg   // error.
201606f32e7eSjoerg   if (!CurFrame)
201706f32e7eSjoerg     return;
201806f32e7eSjoerg 
201906f32e7eSjoerg   MCSection *TextSec = &CurFrame->Function->getSection();
202006f32e7eSjoerg   MCSection *XData = getAssociatedXDataSection(TextSec);
202106f32e7eSjoerg   SwitchSectionNoChange(XData);
202206f32e7eSjoerg 
202306f32e7eSjoerg   OS << "\t.seh_handlerdata";
202406f32e7eSjoerg   EmitEOL();
202506f32e7eSjoerg }
202606f32e7eSjoerg 
EmitWinCFIPushReg(MCRegister Register,SMLoc Loc)202706f32e7eSjoerg void MCAsmStreamer::EmitWinCFIPushReg(MCRegister Register, SMLoc Loc) {
202806f32e7eSjoerg   MCStreamer::EmitWinCFIPushReg(Register, Loc);
202906f32e7eSjoerg 
203006f32e7eSjoerg   OS << "\t.seh_pushreg ";
203106f32e7eSjoerg   InstPrinter->printRegName(OS, Register);
203206f32e7eSjoerg   EmitEOL();
203306f32e7eSjoerg }
203406f32e7eSjoerg 
EmitWinCFISetFrame(MCRegister Register,unsigned Offset,SMLoc Loc)203506f32e7eSjoerg void MCAsmStreamer::EmitWinCFISetFrame(MCRegister Register, unsigned Offset,
203606f32e7eSjoerg                                        SMLoc Loc) {
203706f32e7eSjoerg   MCStreamer::EmitWinCFISetFrame(Register, Offset, Loc);
203806f32e7eSjoerg 
203906f32e7eSjoerg   OS << "\t.seh_setframe ";
204006f32e7eSjoerg   InstPrinter->printRegName(OS, Register);
204106f32e7eSjoerg   OS << ", " << Offset;
204206f32e7eSjoerg   EmitEOL();
204306f32e7eSjoerg }
204406f32e7eSjoerg 
EmitWinCFIAllocStack(unsigned Size,SMLoc Loc)204506f32e7eSjoerg void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size, SMLoc Loc) {
204606f32e7eSjoerg   MCStreamer::EmitWinCFIAllocStack(Size, Loc);
204706f32e7eSjoerg 
204806f32e7eSjoerg   OS << "\t.seh_stackalloc " << Size;
204906f32e7eSjoerg   EmitEOL();
205006f32e7eSjoerg }
205106f32e7eSjoerg 
EmitWinCFISaveReg(MCRegister Register,unsigned Offset,SMLoc Loc)205206f32e7eSjoerg void MCAsmStreamer::EmitWinCFISaveReg(MCRegister Register, unsigned Offset,
205306f32e7eSjoerg                                       SMLoc Loc) {
205406f32e7eSjoerg   MCStreamer::EmitWinCFISaveReg(Register, Offset, Loc);
205506f32e7eSjoerg 
205606f32e7eSjoerg   OS << "\t.seh_savereg ";
205706f32e7eSjoerg   InstPrinter->printRegName(OS, Register);
205806f32e7eSjoerg   OS << ", " << Offset;
205906f32e7eSjoerg   EmitEOL();
206006f32e7eSjoerg }
206106f32e7eSjoerg 
EmitWinCFISaveXMM(MCRegister Register,unsigned Offset,SMLoc Loc)206206f32e7eSjoerg void MCAsmStreamer::EmitWinCFISaveXMM(MCRegister Register, unsigned Offset,
206306f32e7eSjoerg                                       SMLoc Loc) {
206406f32e7eSjoerg   MCStreamer::EmitWinCFISaveXMM(Register, Offset, Loc);
206506f32e7eSjoerg 
206606f32e7eSjoerg   OS << "\t.seh_savexmm ";
206706f32e7eSjoerg   InstPrinter->printRegName(OS, Register);
206806f32e7eSjoerg   OS << ", " << Offset;
206906f32e7eSjoerg   EmitEOL();
207006f32e7eSjoerg }
207106f32e7eSjoerg 
EmitWinCFIPushFrame(bool Code,SMLoc Loc)207206f32e7eSjoerg void MCAsmStreamer::EmitWinCFIPushFrame(bool Code, SMLoc Loc) {
207306f32e7eSjoerg   MCStreamer::EmitWinCFIPushFrame(Code, Loc);
207406f32e7eSjoerg 
207506f32e7eSjoerg   OS << "\t.seh_pushframe";
207606f32e7eSjoerg   if (Code)
207706f32e7eSjoerg     OS << " @code";
207806f32e7eSjoerg   EmitEOL();
207906f32e7eSjoerg }
208006f32e7eSjoerg 
EmitWinCFIEndProlog(SMLoc Loc)208106f32e7eSjoerg void MCAsmStreamer::EmitWinCFIEndProlog(SMLoc Loc) {
208206f32e7eSjoerg   MCStreamer::EmitWinCFIEndProlog(Loc);
208306f32e7eSjoerg 
208406f32e7eSjoerg   OS << "\t.seh_endprologue";
208506f32e7eSjoerg   EmitEOL();
208606f32e7eSjoerg }
208706f32e7eSjoerg 
emitCGProfileEntry(const MCSymbolRefExpr * From,const MCSymbolRefExpr * To,uint64_t Count)208806f32e7eSjoerg void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
208906f32e7eSjoerg                                        const MCSymbolRefExpr *To,
209006f32e7eSjoerg                                        uint64_t Count) {
209106f32e7eSjoerg   OS << "\t.cg_profile ";
209206f32e7eSjoerg   From->getSymbol().print(OS, MAI);
209306f32e7eSjoerg   OS << ", ";
209406f32e7eSjoerg   To->getSymbol().print(OS, MAI);
209506f32e7eSjoerg   OS << ", " << Count;
209606f32e7eSjoerg   EmitEOL();
209706f32e7eSjoerg }
209806f32e7eSjoerg 
AddEncodingComment(const MCInst & Inst,const MCSubtargetInfo & STI)209906f32e7eSjoerg void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
210006f32e7eSjoerg                                        const MCSubtargetInfo &STI) {
210106f32e7eSjoerg   raw_ostream &OS = GetCommentOS();
210206f32e7eSjoerg   SmallString<256> Code;
210306f32e7eSjoerg   SmallVector<MCFixup, 4> Fixups;
210406f32e7eSjoerg   raw_svector_ostream VecOS(Code);
210506f32e7eSjoerg 
210606f32e7eSjoerg   // If we have no code emitter, don't emit code.
210706f32e7eSjoerg   if (!getAssembler().getEmitterPtr())
210806f32e7eSjoerg     return;
210906f32e7eSjoerg 
211006f32e7eSjoerg   getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
211106f32e7eSjoerg 
211206f32e7eSjoerg   // If we are showing fixups, create symbolic markers in the encoded
211306f32e7eSjoerg   // representation. We do this by making a per-bit map to the fixup item index,
211406f32e7eSjoerg   // then trying to display it as nicely as possible.
211506f32e7eSjoerg   SmallVector<uint8_t, 64> FixupMap;
211606f32e7eSjoerg   FixupMap.resize(Code.size() * 8);
211706f32e7eSjoerg   for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
211806f32e7eSjoerg     FixupMap[i] = 0;
211906f32e7eSjoerg 
212006f32e7eSjoerg   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
212106f32e7eSjoerg     MCFixup &F = Fixups[i];
212206f32e7eSjoerg     const MCFixupKindInfo &Info =
212306f32e7eSjoerg         getAssembler().getBackend().getFixupKindInfo(F.getKind());
212406f32e7eSjoerg     for (unsigned j = 0; j != Info.TargetSize; ++j) {
212506f32e7eSjoerg       unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
212606f32e7eSjoerg       assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
212706f32e7eSjoerg       FixupMap[Index] = 1 + i;
212806f32e7eSjoerg     }
212906f32e7eSjoerg   }
213006f32e7eSjoerg 
213106f32e7eSjoerg   // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
213206f32e7eSjoerg   // high order halfword of a 32-bit Thumb2 instruction is emitted first.
213306f32e7eSjoerg   OS << "encoding: [";
213406f32e7eSjoerg   for (unsigned i = 0, e = Code.size(); i != e; ++i) {
213506f32e7eSjoerg     if (i)
213606f32e7eSjoerg       OS << ',';
213706f32e7eSjoerg 
213806f32e7eSjoerg     // See if all bits are the same map entry.
213906f32e7eSjoerg     uint8_t MapEntry = FixupMap[i * 8 + 0];
214006f32e7eSjoerg     for (unsigned j = 1; j != 8; ++j) {
214106f32e7eSjoerg       if (FixupMap[i * 8 + j] == MapEntry)
214206f32e7eSjoerg         continue;
214306f32e7eSjoerg 
214406f32e7eSjoerg       MapEntry = uint8_t(~0U);
214506f32e7eSjoerg       break;
214606f32e7eSjoerg     }
214706f32e7eSjoerg 
214806f32e7eSjoerg     if (MapEntry != uint8_t(~0U)) {
214906f32e7eSjoerg       if (MapEntry == 0) {
215006f32e7eSjoerg         OS << format("0x%02x", uint8_t(Code[i]));
215106f32e7eSjoerg       } else {
215206f32e7eSjoerg         if (Code[i]) {
215306f32e7eSjoerg           // FIXME: Some of the 8 bits require fix up.
215406f32e7eSjoerg           OS << format("0x%02x", uint8_t(Code[i])) << '\''
215506f32e7eSjoerg              << char('A' + MapEntry - 1) << '\'';
215606f32e7eSjoerg         } else
215706f32e7eSjoerg           OS << char('A' + MapEntry - 1);
215806f32e7eSjoerg       }
215906f32e7eSjoerg     } else {
216006f32e7eSjoerg       // Otherwise, write out in binary.
216106f32e7eSjoerg       OS << "0b";
216206f32e7eSjoerg       for (unsigned j = 8; j--;) {
216306f32e7eSjoerg         unsigned Bit = (Code[i] >> j) & 1;
216406f32e7eSjoerg 
216506f32e7eSjoerg         unsigned FixupBit;
216606f32e7eSjoerg         if (MAI->isLittleEndian())
216706f32e7eSjoerg           FixupBit = i * 8 + j;
216806f32e7eSjoerg         else
216906f32e7eSjoerg           FixupBit = i * 8 + (7-j);
217006f32e7eSjoerg 
217106f32e7eSjoerg         if (uint8_t MapEntry = FixupMap[FixupBit]) {
217206f32e7eSjoerg           assert(Bit == 0 && "Encoder wrote into fixed up bit!");
217306f32e7eSjoerg           OS << char('A' + MapEntry - 1);
217406f32e7eSjoerg         } else
217506f32e7eSjoerg           OS << Bit;
217606f32e7eSjoerg       }
217706f32e7eSjoerg     }
217806f32e7eSjoerg   }
217906f32e7eSjoerg   OS << "]\n";
218006f32e7eSjoerg 
218106f32e7eSjoerg   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
218206f32e7eSjoerg     MCFixup &F = Fixups[i];
218306f32e7eSjoerg     const MCFixupKindInfo &Info =
218406f32e7eSjoerg         getAssembler().getBackend().getFixupKindInfo(F.getKind());
218506f32e7eSjoerg     OS << "  fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
218606f32e7eSjoerg        << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
218706f32e7eSjoerg   }
218806f32e7eSjoerg }
218906f32e7eSjoerg 
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)2190*da58b97aSjoerg void MCAsmStreamer::emitInstruction(const MCInst &Inst,
219106f32e7eSjoerg                                     const MCSubtargetInfo &STI) {
219206f32e7eSjoerg   assert(getCurrentSectionOnly() &&
219306f32e7eSjoerg          "Cannot emit contents before setting section!");
219406f32e7eSjoerg 
2195*da58b97aSjoerg   if (!MAI->usesDwarfFileAndLocDirectives())
2196*da58b97aSjoerg     // Now that a machine instruction has been assembled into this section, make
2197*da58b97aSjoerg     // a line entry for any .loc directive that has been seen.
2198*da58b97aSjoerg     MCDwarfLineEntry::make(this, getCurrentSectionOnly());
2199*da58b97aSjoerg 
220006f32e7eSjoerg   // Show the encoding in a comment if we have a code emitter.
220106f32e7eSjoerg   AddEncodingComment(Inst, STI);
220206f32e7eSjoerg 
220306f32e7eSjoerg   // Show the MCInst if enabled.
220406f32e7eSjoerg   if (ShowInst) {
220506f32e7eSjoerg     Inst.dump_pretty(GetCommentOS(), InstPrinter.get(), "\n ");
220606f32e7eSjoerg     GetCommentOS() << "\n";
220706f32e7eSjoerg   }
220806f32e7eSjoerg 
220906f32e7eSjoerg   if(getTargetStreamer())
2210*da58b97aSjoerg     getTargetStreamer()->prettyPrintAsm(*InstPrinter, 0, Inst, STI, OS);
221106f32e7eSjoerg   else
2212*da58b97aSjoerg     InstPrinter->printInst(&Inst, 0, "", STI, OS);
221306f32e7eSjoerg 
221406f32e7eSjoerg   StringRef Comments = CommentToEmit;
221506f32e7eSjoerg   if (Comments.size() && Comments.back() != '\n')
221606f32e7eSjoerg     GetCommentOS() << "\n";
221706f32e7eSjoerg 
221806f32e7eSjoerg   EmitEOL();
221906f32e7eSjoerg }
222006f32e7eSjoerg 
emitPseudoProbe(uint64_t Guid,uint64_t Index,uint64_t Type,uint64_t Attr,const MCPseudoProbeInlineStack & InlineStack)2221*da58b97aSjoerg void MCAsmStreamer::emitPseudoProbe(
2222*da58b97aSjoerg     uint64_t Guid, uint64_t Index, uint64_t Type, uint64_t Attr,
2223*da58b97aSjoerg     const MCPseudoProbeInlineStack &InlineStack) {
2224*da58b97aSjoerg   OS << "\t.pseudoprobe\t" << Guid << " " << Index << " " << Type << " "
2225*da58b97aSjoerg      << Attr;
2226*da58b97aSjoerg   // Emit inline stack like
2227*da58b97aSjoerg   //  @ GUIDmain:3 @ GUIDCaller:1 @ GUIDDirectCaller:11
2228*da58b97aSjoerg   for (const auto &Site : InlineStack)
2229*da58b97aSjoerg     OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);
2230*da58b97aSjoerg   EmitEOL();
2231*da58b97aSjoerg }
2232*da58b97aSjoerg 
emitBundleAlignMode(unsigned AlignPow2)2233*da58b97aSjoerg void MCAsmStreamer::emitBundleAlignMode(unsigned AlignPow2) {
223406f32e7eSjoerg   OS << "\t.bundle_align_mode " << AlignPow2;
223506f32e7eSjoerg   EmitEOL();
223606f32e7eSjoerg }
223706f32e7eSjoerg 
emitBundleLock(bool AlignToEnd)2238*da58b97aSjoerg void MCAsmStreamer::emitBundleLock(bool AlignToEnd) {
223906f32e7eSjoerg   OS << "\t.bundle_lock";
224006f32e7eSjoerg   if (AlignToEnd)
224106f32e7eSjoerg     OS << " align_to_end";
224206f32e7eSjoerg   EmitEOL();
224306f32e7eSjoerg }
224406f32e7eSjoerg 
emitBundleUnlock()2245*da58b97aSjoerg void MCAsmStreamer::emitBundleUnlock() {
224606f32e7eSjoerg   OS << "\t.bundle_unlock";
224706f32e7eSjoerg   EmitEOL();
224806f32e7eSjoerg }
224906f32e7eSjoerg 
2250*da58b97aSjoerg Optional<std::pair<bool, std::string>>
emitRelocDirective(const MCExpr & Offset,StringRef Name,const MCExpr * Expr,SMLoc,const MCSubtargetInfo & STI)2251*da58b97aSjoerg MCAsmStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
225206f32e7eSjoerg                                   const MCExpr *Expr, SMLoc,
225306f32e7eSjoerg                                   const MCSubtargetInfo &STI) {
225406f32e7eSjoerg   OS << "\t.reloc ";
225506f32e7eSjoerg   Offset.print(OS, MAI);
225606f32e7eSjoerg   OS << ", " << Name;
225706f32e7eSjoerg   if (Expr) {
225806f32e7eSjoerg     OS << ", ";
225906f32e7eSjoerg     Expr->print(OS, MAI);
226006f32e7eSjoerg   }
226106f32e7eSjoerg   EmitEOL();
2262*da58b97aSjoerg   return None;
226306f32e7eSjoerg }
226406f32e7eSjoerg 
emitAddrsig()2265*da58b97aSjoerg void MCAsmStreamer::emitAddrsig() {
226606f32e7eSjoerg   OS << "\t.addrsig";
226706f32e7eSjoerg   EmitEOL();
226806f32e7eSjoerg }
226906f32e7eSjoerg 
emitAddrsigSym(const MCSymbol * Sym)2270*da58b97aSjoerg void MCAsmStreamer::emitAddrsigSym(const MCSymbol *Sym) {
227106f32e7eSjoerg   OS << "\t.addrsig_sym ";
227206f32e7eSjoerg   Sym->print(OS, MAI);
227306f32e7eSjoerg   EmitEOL();
227406f32e7eSjoerg }
227506f32e7eSjoerg 
227606f32e7eSjoerg /// EmitRawText - If this file is backed by an assembly streamer, this dumps
227706f32e7eSjoerg /// the specified string in the output .s file.  This capability is
227806f32e7eSjoerg /// indicated by the hasRawTextSupport() predicate.
emitRawTextImpl(StringRef String)2279*da58b97aSjoerg void MCAsmStreamer::emitRawTextImpl(StringRef String) {
228006f32e7eSjoerg   if (!String.empty() && String.back() == '\n')
228106f32e7eSjoerg     String = String.substr(0, String.size()-1);
228206f32e7eSjoerg   OS << String;
228306f32e7eSjoerg   EmitEOL();
228406f32e7eSjoerg }
228506f32e7eSjoerg 
finishImpl()2286*da58b97aSjoerg void MCAsmStreamer::finishImpl() {
228706f32e7eSjoerg   // If we are generating dwarf for assembly source files dump out the sections.
228806f32e7eSjoerg   if (getContext().getGenDwarfForAssembly())
228906f32e7eSjoerg     MCGenDwarfInfo::Emit(this);
229006f32e7eSjoerg 
2291*da58b97aSjoerg   // Now it is time to emit debug line sections if target doesn't support .loc
2292*da58b97aSjoerg   // and .line directives.
2293*da58b97aSjoerg   if (!MAI->usesDwarfFileAndLocDirectives()) {
2294*da58b97aSjoerg     MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
2295*da58b97aSjoerg     return;
2296*da58b97aSjoerg   }
2297*da58b97aSjoerg 
229806f32e7eSjoerg   // Emit the label for the line table, if requested - since the rest of the
229906f32e7eSjoerg   // line table will be defined by .loc/.file directives, and not emitted
230006f32e7eSjoerg   // directly, the label is the only work required here.
230106f32e7eSjoerg   const auto &Tables = getContext().getMCDwarfLineTables();
230206f32e7eSjoerg   if (!Tables.empty()) {
230306f32e7eSjoerg     assert(Tables.size() == 1 && "asm output only supports one line table");
230406f32e7eSjoerg     if (auto *Label = Tables.begin()->second.getLabel()) {
230506f32e7eSjoerg       SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
2306*da58b97aSjoerg       emitLabel(Label);
230706f32e7eSjoerg     }
230806f32e7eSjoerg   }
230906f32e7eSjoerg }
231006f32e7eSjoerg 
emitDwarfUnitLength(uint64_t Length,const Twine & Comment)2311*da58b97aSjoerg void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) {
2312*da58b97aSjoerg   // If the assembler on some target fills in the DWARF unit length, we
2313*da58b97aSjoerg   // don't want to emit the length in the compiler. For example, the AIX
2314*da58b97aSjoerg   // assembler requires the assembly file with the unit length omitted from
2315*da58b97aSjoerg   // the debug section headers. In such cases, any label we placed occurs
2316*da58b97aSjoerg   // after the implied length field. We need to adjust the reference here
2317*da58b97aSjoerg   // to account for the offset introduced by the inserted length field.
2318*da58b97aSjoerg   if (!MAI->needsDwarfSectionSizeInHeader())
2319*da58b97aSjoerg     return;
2320*da58b97aSjoerg   MCStreamer::emitDwarfUnitLength(Length, Comment);
2321*da58b97aSjoerg }
2322*da58b97aSjoerg 
emitDwarfUnitLength(const Twine & Prefix,const Twine & Comment)2323*da58b97aSjoerg MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix,
2324*da58b97aSjoerg                                              const Twine &Comment) {
2325*da58b97aSjoerg   // If the assembler on some target fills in the DWARF unit length, we
2326*da58b97aSjoerg   // don't want to emit the length in the compiler. For example, the AIX
2327*da58b97aSjoerg   // assembler requires the assembly file with the unit length omitted from
2328*da58b97aSjoerg   // the debug section headers. In such cases, any label we placed occurs
2329*da58b97aSjoerg   // after the implied length field. We need to adjust the reference here
2330*da58b97aSjoerg   // to account for the offset introduced by the inserted length field.
2331*da58b97aSjoerg   if (!MAI->needsDwarfSectionSizeInHeader())
2332*da58b97aSjoerg     return getContext().createTempSymbol(Prefix + "_end");
2333*da58b97aSjoerg   return MCStreamer::emitDwarfUnitLength(Prefix, Comment);
2334*da58b97aSjoerg }
2335*da58b97aSjoerg 
emitDwarfLineStartLabel(MCSymbol * StartSym)2336*da58b97aSjoerg void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) {
2337*da58b97aSjoerg   // If the assembler on some target fills in the DWARF unit length, we
2338*da58b97aSjoerg   // don't want to emit the length in the compiler. For example, the AIX
2339*da58b97aSjoerg   // assembler requires the assembly file with the unit length omitted from
2340*da58b97aSjoerg   // the debug section headers. In such cases, any label we placed occurs
2341*da58b97aSjoerg   // after the implied length field. We need to adjust the reference here
2342*da58b97aSjoerg   // to account for the offset introduced by the inserted length field.
2343*da58b97aSjoerg   MCContext &Ctx = getContext();
2344*da58b97aSjoerg   if (!MAI->needsDwarfSectionSizeInHeader()) {
2345*da58b97aSjoerg     MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_");
2346*da58b97aSjoerg     // Emit the symbol which does not contain the unit length field.
2347*da58b97aSjoerg     emitLabel(DebugLineSymTmp);
2348*da58b97aSjoerg 
2349*da58b97aSjoerg     // Adjust the outer reference to account for the offset introduced by the
2350*da58b97aSjoerg     // inserted length field.
2351*da58b97aSjoerg     unsigned LengthFieldSize =
2352*da58b97aSjoerg         dwarf::getUnitLengthFieldByteSize(Ctx.getDwarfFormat());
2353*da58b97aSjoerg     const MCExpr *EntrySize = MCConstantExpr::create(LengthFieldSize, Ctx);
2354*da58b97aSjoerg     const MCExpr *OuterSym = MCBinaryExpr::createSub(
2355*da58b97aSjoerg         MCSymbolRefExpr::create(DebugLineSymTmp, Ctx), EntrySize, Ctx);
2356*da58b97aSjoerg 
2357*da58b97aSjoerg     emitAssignment(StartSym, OuterSym);
2358*da58b97aSjoerg     return;
2359*da58b97aSjoerg   }
2360*da58b97aSjoerg   MCStreamer::emitDwarfLineStartLabel(StartSym);
2361*da58b97aSjoerg }
2362*da58b97aSjoerg 
emitDwarfLineEndEntry(MCSection * Section,MCSymbol * LastLabel)2363*da58b97aSjoerg void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section,
2364*da58b97aSjoerg                                           MCSymbol *LastLabel) {
2365*da58b97aSjoerg   // If the targets write the raw debug line data for assembly output (We can
2366*da58b97aSjoerg   // not switch to Section and add the end symbol there for assembly output)
2367*da58b97aSjoerg   // we currently use the .text end label as any section end. This will not
2368*da58b97aSjoerg   // impact the debugability as we will jump to the caller of the last function
2369*da58b97aSjoerg   // in the section before we come into the .text end address.
2370*da58b97aSjoerg   assert(!MAI->usesDwarfFileAndLocDirectives() &&
2371*da58b97aSjoerg          ".loc should not be generated together with raw data!");
2372*da58b97aSjoerg 
2373*da58b97aSjoerg   MCContext &Ctx = getContext();
2374*da58b97aSjoerg 
2375*da58b97aSjoerg   // FIXME: use section end symbol as end of the Section. We need to consider
2376*da58b97aSjoerg   // the explicit sections and -ffunction-sections when we try to generate or
2377*da58b97aSjoerg   // find section end symbol for the Section.
2378*da58b97aSjoerg   MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection();
2379*da58b97aSjoerg   assert(TextSection->hasEnded() && ".text section is not end!");
2380*da58b97aSjoerg 
2381*da58b97aSjoerg   MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx);
2382*da58b97aSjoerg   const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
2383*da58b97aSjoerg   emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
2384*da58b97aSjoerg                            AsmInfo->getCodePointerSize());
2385*da58b97aSjoerg }
2386*da58b97aSjoerg 
2387*da58b97aSjoerg // Generate DWARF line sections for assembly mode without .loc/.file
emitDwarfAdvanceLineAddr(int64_t LineDelta,const MCSymbol * LastLabel,const MCSymbol * Label,unsigned PointerSize)2388*da58b97aSjoerg void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
2389*da58b97aSjoerg                                              const MCSymbol *LastLabel,
2390*da58b97aSjoerg                                              const MCSymbol *Label,
2391*da58b97aSjoerg                                              unsigned PointerSize) {
2392*da58b97aSjoerg   assert(!MAI->usesDwarfFileAndLocDirectives() &&
2393*da58b97aSjoerg          ".loc/.file don't need raw data in debug line section!");
2394*da58b97aSjoerg 
2395*da58b97aSjoerg   // Set to new address.
2396*da58b97aSjoerg   AddComment("Set address to " + Label->getName());
2397*da58b97aSjoerg   emitIntValue(dwarf::DW_LNS_extended_op, 1);
2398*da58b97aSjoerg   emitULEB128IntValue(PointerSize + 1);
2399*da58b97aSjoerg   emitIntValue(dwarf::DW_LNE_set_address, 1);
2400*da58b97aSjoerg   emitSymbolValue(Label, PointerSize);
2401*da58b97aSjoerg 
2402*da58b97aSjoerg   if (!LastLabel) {
2403*da58b97aSjoerg     // Emit the sequence for the LineDelta (from 1) and a zero address delta.
2404*da58b97aSjoerg     AddComment("Start sequence");
2405*da58b97aSjoerg     MCDwarfLineAddr::Emit(this, MCDwarfLineTableParams(), LineDelta, 0);
2406*da58b97aSjoerg     return;
2407*da58b97aSjoerg   }
2408*da58b97aSjoerg 
2409*da58b97aSjoerg   // INT64_MAX is a signal of the end of the section. Emit DW_LNE_end_sequence
2410*da58b97aSjoerg   // for the end of the section.
2411*da58b97aSjoerg   if (LineDelta == INT64_MAX) {
2412*da58b97aSjoerg     AddComment("End sequence");
2413*da58b97aSjoerg     emitIntValue(dwarf::DW_LNS_extended_op, 1);
2414*da58b97aSjoerg     emitULEB128IntValue(1);
2415*da58b97aSjoerg     emitIntValue(dwarf::DW_LNE_end_sequence, 1);
2416*da58b97aSjoerg     return;
2417*da58b97aSjoerg   }
2418*da58b97aSjoerg 
2419*da58b97aSjoerg   // Advance line.
2420*da58b97aSjoerg   AddComment("Advance line " + Twine(LineDelta));
2421*da58b97aSjoerg   emitIntValue(dwarf::DW_LNS_advance_line, 1);
2422*da58b97aSjoerg   emitSLEB128IntValue(LineDelta);
2423*da58b97aSjoerg   emitIntValue(dwarf::DW_LNS_copy, 1);
2424*da58b97aSjoerg }
2425*da58b97aSjoerg 
doFinalizationAtSectionEnd(MCSection * Section)2426*da58b97aSjoerg void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) {
2427*da58b97aSjoerg   // Emit section end. This is used to tell the debug line section where the end
2428*da58b97aSjoerg   // is for a text section if we don't use .loc to represent the debug line.
2429*da58b97aSjoerg   if (MAI->usesDwarfFileAndLocDirectives())
2430*da58b97aSjoerg     return;
2431*da58b97aSjoerg 
2432*da58b97aSjoerg   SwitchSectionNoChange(Section);
2433*da58b97aSjoerg 
2434*da58b97aSjoerg   MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext());
2435*da58b97aSjoerg 
2436*da58b97aSjoerg   if (!Sym->isInSection())
2437*da58b97aSjoerg     emitLabel(Sym);
2438*da58b97aSjoerg }
2439*da58b97aSjoerg 
createAsmStreamer(MCContext & Context,std::unique_ptr<formatted_raw_ostream> OS,bool isVerboseAsm,bool useDwarfDirectory,MCInstPrinter * IP,std::unique_ptr<MCCodeEmitter> && CE,std::unique_ptr<MCAsmBackend> && MAB,bool ShowInst)244006f32e7eSjoerg MCStreamer *llvm::createAsmStreamer(MCContext &Context,
244106f32e7eSjoerg                                     std::unique_ptr<formatted_raw_ostream> OS,
244206f32e7eSjoerg                                     bool isVerboseAsm, bool useDwarfDirectory,
244306f32e7eSjoerg                                     MCInstPrinter *IP,
244406f32e7eSjoerg                                     std::unique_ptr<MCCodeEmitter> &&CE,
244506f32e7eSjoerg                                     std::unique_ptr<MCAsmBackend> &&MAB,
244606f32e7eSjoerg                                     bool ShowInst) {
244706f32e7eSjoerg   return new MCAsmStreamer(Context, std::move(OS), isVerboseAsm,
244806f32e7eSjoerg                            useDwarfDirectory, IP, std::move(CE), std::move(MAB),
244906f32e7eSjoerg                            ShowInst);
245006f32e7eSjoerg }
2451