xref: /minix3/external/bsd/llvm/dist/llvm/lib/MC/MCAsmStreamer.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc 
10f4a2713aSLionel Sambuc #include "llvm/MC/MCStreamer.h"
11*0a6a1f1dSLionel Sambuc #include "llvm/ADT/STLExtras.h"
12f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
13f4a2713aSLionel Sambuc #include "llvm/ADT/StringExtras.h"
14f4a2713aSLionel Sambuc #include "llvm/ADT/Twine.h"
15f4a2713aSLionel Sambuc #include "llvm/MC/MCAsmBackend.h"
16f4a2713aSLionel Sambuc #include "llvm/MC/MCAsmInfo.h"
17f4a2713aSLionel Sambuc #include "llvm/MC/MCCodeEmitter.h"
18f4a2713aSLionel Sambuc #include "llvm/MC/MCContext.h"
19f4a2713aSLionel Sambuc #include "llvm/MC/MCExpr.h"
20f4a2713aSLionel Sambuc #include "llvm/MC/MCFixupKindInfo.h"
21f4a2713aSLionel Sambuc #include "llvm/MC/MCInst.h"
22f4a2713aSLionel Sambuc #include "llvm/MC/MCInstPrinter.h"
23f4a2713aSLionel Sambuc #include "llvm/MC/MCObjectFileInfo.h"
24f4a2713aSLionel Sambuc #include "llvm/MC/MCRegisterInfo.h"
25f4a2713aSLionel Sambuc #include "llvm/MC/MCSectionCOFF.h"
26f4a2713aSLionel Sambuc #include "llvm/MC/MCSectionMachO.h"
27f4a2713aSLionel Sambuc #include "llvm/MC/MCSymbol.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
30f4a2713aSLionel Sambuc #include "llvm/Support/Format.h"
31f4a2713aSLionel Sambuc #include "llvm/Support/FormattedStream.h"
32f4a2713aSLionel Sambuc #include "llvm/Support/MathExtras.h"
33f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
34f4a2713aSLionel Sambuc #include <cctype>
35f4a2713aSLionel Sambuc using namespace llvm;
36f4a2713aSLionel Sambuc 
37f4a2713aSLionel Sambuc namespace {
38f4a2713aSLionel Sambuc 
39f4a2713aSLionel Sambuc class MCAsmStreamer : public MCStreamer {
40f4a2713aSLionel Sambuc protected:
41f4a2713aSLionel Sambuc   formatted_raw_ostream &OS;
42f4a2713aSLionel Sambuc   const MCAsmInfo *MAI;
43f4a2713aSLionel Sambuc private:
44*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCInstPrinter> InstPrinter;
45*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCCodeEmitter> Emitter;
46*0a6a1f1dSLionel Sambuc   std::unique_ptr<MCAsmBackend> AsmBackend;
47f4a2713aSLionel Sambuc 
48f4a2713aSLionel Sambuc   SmallString<128> CommentToEmit;
49f4a2713aSLionel Sambuc   raw_svector_ostream CommentStream;
50f4a2713aSLionel Sambuc 
51f4a2713aSLionel Sambuc   unsigned IsVerboseAsm : 1;
52f4a2713aSLionel Sambuc   unsigned ShowInst : 1;
53f4a2713aSLionel Sambuc   unsigned UseDwarfDirectory : 1;
54f4a2713aSLionel Sambuc 
55f4a2713aSLionel Sambuc   void EmitRegisterName(int64_t Register);
56*0a6a1f1dSLionel Sambuc   void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
57*0a6a1f1dSLionel Sambuc   void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
58f4a2713aSLionel Sambuc 
59f4a2713aSLionel Sambuc public:
MCAsmStreamer(MCContext & Context,formatted_raw_ostream & os,bool isVerboseAsm,bool useDwarfDirectory,MCInstPrinter * printer,MCCodeEmitter * emitter,MCAsmBackend * asmbackend,bool showInst)60*0a6a1f1dSLionel Sambuc   MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
61*0a6a1f1dSLionel Sambuc                 bool isVerboseAsm, bool useDwarfDirectory,
62*0a6a1f1dSLionel Sambuc                 MCInstPrinter *printer, MCCodeEmitter *emitter,
63*0a6a1f1dSLionel Sambuc                 MCAsmBackend *asmbackend, bool showInst)
64*0a6a1f1dSLionel Sambuc       : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()),
65f4a2713aSLionel Sambuc         InstPrinter(printer), Emitter(emitter), AsmBackend(asmbackend),
66f4a2713aSLionel Sambuc         CommentStream(CommentToEmit), IsVerboseAsm(isVerboseAsm),
67*0a6a1f1dSLionel Sambuc         ShowInst(showInst), UseDwarfDirectory(useDwarfDirectory) {
68f4a2713aSLionel Sambuc     if (InstPrinter && IsVerboseAsm)
69f4a2713aSLionel Sambuc       InstPrinter->setCommentStream(CommentStream);
70f4a2713aSLionel Sambuc   }
71f4a2713aSLionel Sambuc 
EmitEOL()72f4a2713aSLionel Sambuc   inline void EmitEOL() {
73f4a2713aSLionel Sambuc     // If we don't have any comments, just emit a \n.
74f4a2713aSLionel Sambuc     if (!IsVerboseAsm) {
75f4a2713aSLionel Sambuc       OS << '\n';
76f4a2713aSLionel Sambuc       return;
77f4a2713aSLionel Sambuc     }
78f4a2713aSLionel Sambuc     EmitCommentsAndEOL();
79f4a2713aSLionel Sambuc   }
80f4a2713aSLionel Sambuc   void EmitCommentsAndEOL();
81f4a2713aSLionel Sambuc 
82f4a2713aSLionel Sambuc   /// isVerboseAsm - Return true if this streamer supports verbose assembly at
83f4a2713aSLionel Sambuc   /// all.
isVerboseAsm() const84*0a6a1f1dSLionel Sambuc   bool isVerboseAsm() const override { return IsVerboseAsm; }
85f4a2713aSLionel Sambuc 
86f4a2713aSLionel Sambuc   /// hasRawTextSupport - We support EmitRawText.
hasRawTextSupport() const87*0a6a1f1dSLionel Sambuc   bool hasRawTextSupport() const override { return true; }
88f4a2713aSLionel Sambuc 
89f4a2713aSLionel Sambuc   /// AddComment - Add a comment that can be emitted to the generated .s
90f4a2713aSLionel Sambuc   /// file if applicable as a QoI issue to make the output of the compiler
91f4a2713aSLionel Sambuc   /// more readable.  This only affects the MCAsmStreamer, and only when
92f4a2713aSLionel Sambuc   /// verbose assembly output is enabled.
93*0a6a1f1dSLionel Sambuc   void AddComment(const Twine &T) override;
94f4a2713aSLionel Sambuc 
95f4a2713aSLionel Sambuc   /// AddEncodingComment - Add a comment showing the encoding of an instruction.
96*0a6a1f1dSLionel Sambuc   void AddEncodingComment(const MCInst &Inst, const MCSubtargetInfo &);
97f4a2713aSLionel Sambuc 
98f4a2713aSLionel Sambuc   /// GetCommentOS - Return a raw_ostream that comments can be written to.
99f4a2713aSLionel Sambuc   /// Unlike AddComment, you are required to terminate comments with \n if you
100f4a2713aSLionel Sambuc   /// use this method.
GetCommentOS()101*0a6a1f1dSLionel Sambuc   raw_ostream &GetCommentOS() override {
102f4a2713aSLionel Sambuc     if (!IsVerboseAsm)
103f4a2713aSLionel Sambuc       return nulls();  // Discard comments unless in verbose asm mode.
104f4a2713aSLionel Sambuc     return CommentStream;
105f4a2713aSLionel Sambuc   }
106f4a2713aSLionel Sambuc 
107*0a6a1f1dSLionel Sambuc   void emitRawComment(const Twine &T, bool TabPrefix = true) override;
108*0a6a1f1dSLionel Sambuc 
109f4a2713aSLionel Sambuc   /// AddBlankLine - Emit a blank line to a .s file to pretty it up.
AddBlankLine()110*0a6a1f1dSLionel Sambuc   void AddBlankLine() override {
111f4a2713aSLionel Sambuc     EmitEOL();
112f4a2713aSLionel Sambuc   }
113f4a2713aSLionel Sambuc 
114f4a2713aSLionel Sambuc   /// @name MCStreamer Interface
115f4a2713aSLionel Sambuc   /// @{
116f4a2713aSLionel Sambuc 
117*0a6a1f1dSLionel Sambuc   void ChangeSection(const MCSection *Section,
118*0a6a1f1dSLionel Sambuc                      const MCExpr *Subsection) override;
119f4a2713aSLionel Sambuc 
120*0a6a1f1dSLionel Sambuc   void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override;
121*0a6a1f1dSLionel Sambuc   void EmitLabel(MCSymbol *Symbol) override;
122f4a2713aSLionel Sambuc 
123*0a6a1f1dSLionel Sambuc   void EmitAssemblerFlag(MCAssemblerFlag Flag) override;
124*0a6a1f1dSLionel Sambuc   void EmitLinkerOptions(ArrayRef<std::string> Options) override;
125*0a6a1f1dSLionel Sambuc   void EmitDataRegion(MCDataRegionType Kind) override;
126*0a6a1f1dSLionel Sambuc   void EmitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
127*0a6a1f1dSLionel Sambuc                       unsigned Update) override;
128*0a6a1f1dSLionel Sambuc   void EmitThumbFunc(MCSymbol *Func) override;
129f4a2713aSLionel Sambuc 
130*0a6a1f1dSLionel Sambuc   void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
131*0a6a1f1dSLionel Sambuc   void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
132*0a6a1f1dSLionel Sambuc   bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
133f4a2713aSLionel Sambuc 
134*0a6a1f1dSLionel Sambuc   void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
135*0a6a1f1dSLionel Sambuc   void BeginCOFFSymbolDef(const MCSymbol *Symbol) override;
136*0a6a1f1dSLionel Sambuc   void EmitCOFFSymbolStorageClass(int StorageClass) override;
137*0a6a1f1dSLionel Sambuc   void EmitCOFFSymbolType(int Type) override;
138*0a6a1f1dSLionel Sambuc   void EndCOFFSymbolDef() override;
139*0a6a1f1dSLionel Sambuc   void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
140*0a6a1f1dSLionel Sambuc   void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
141*0a6a1f1dSLionel Sambuc   void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
142*0a6a1f1dSLionel Sambuc   void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
143*0a6a1f1dSLionel Sambuc                         unsigned ByteAlignment) override;
144f4a2713aSLionel Sambuc 
145f4a2713aSLionel Sambuc   /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
146f4a2713aSLionel Sambuc   ///
147f4a2713aSLionel Sambuc   /// @param Symbol - The common symbol to emit.
148f4a2713aSLionel Sambuc   /// @param Size - The size of the common symbol.
149f4a2713aSLionel Sambuc   /// @param ByteAlignment - The alignment of the common symbol in bytes.
150*0a6a1f1dSLionel Sambuc   void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
151*0a6a1f1dSLionel Sambuc                              unsigned ByteAlignment) override;
152f4a2713aSLionel Sambuc 
153*0a6a1f1dSLionel Sambuc   void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr,
154*0a6a1f1dSLionel Sambuc                     uint64_t Size = 0, unsigned ByteAlignment = 0) override;
155f4a2713aSLionel Sambuc 
156*0a6a1f1dSLionel Sambuc   void EmitTBSSSymbol (const MCSection *Section, MCSymbol *Symbol,
157*0a6a1f1dSLionel Sambuc                        uint64_t Size, unsigned ByteAlignment = 0) override;
158f4a2713aSLionel Sambuc 
159*0a6a1f1dSLionel Sambuc   void EmitBytes(StringRef Data) override;
160f4a2713aSLionel Sambuc 
161*0a6a1f1dSLionel Sambuc   void EmitValueImpl(const MCExpr *Value, unsigned Size,
162*0a6a1f1dSLionel Sambuc                      const SMLoc &Loc = SMLoc()) override;
163*0a6a1f1dSLionel Sambuc   void EmitIntValue(uint64_t Value, unsigned Size) override;
164f4a2713aSLionel Sambuc 
165*0a6a1f1dSLionel Sambuc   void EmitULEB128Value(const MCExpr *Value) override;
166f4a2713aSLionel Sambuc 
167*0a6a1f1dSLionel Sambuc   void EmitSLEB128Value(const MCExpr *Value) override;
168f4a2713aSLionel Sambuc 
169*0a6a1f1dSLionel Sambuc   void EmitGPRel64Value(const MCExpr *Value) override;
170f4a2713aSLionel Sambuc 
171*0a6a1f1dSLionel Sambuc   void EmitGPRel32Value(const MCExpr *Value) override;
172f4a2713aSLionel Sambuc 
173f4a2713aSLionel Sambuc 
174*0a6a1f1dSLionel Sambuc   void EmitFill(uint64_t NumBytes, uint8_t FillValue) override;
175f4a2713aSLionel Sambuc 
176*0a6a1f1dSLionel Sambuc   void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
177f4a2713aSLionel Sambuc                             unsigned ValueSize = 1,
178*0a6a1f1dSLionel Sambuc                             unsigned MaxBytesToEmit = 0) override;
179f4a2713aSLionel Sambuc 
180*0a6a1f1dSLionel Sambuc   void EmitCodeAlignment(unsigned ByteAlignment,
181*0a6a1f1dSLionel Sambuc                          unsigned MaxBytesToEmit = 0) override;
182f4a2713aSLionel Sambuc 
183*0a6a1f1dSLionel Sambuc   bool EmitValueToOffset(const MCExpr *Offset,
184*0a6a1f1dSLionel Sambuc                          unsigned char Value = 0) override;
185f4a2713aSLionel Sambuc 
186*0a6a1f1dSLionel Sambuc   void EmitFileDirective(StringRef Filename) override;
187*0a6a1f1dSLionel Sambuc   unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory,
188*0a6a1f1dSLionel Sambuc                                   StringRef Filename,
189*0a6a1f1dSLionel Sambuc                                   unsigned CUID = 0) override;
190*0a6a1f1dSLionel Sambuc   void EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
191f4a2713aSLionel Sambuc                              unsigned Column, unsigned Flags,
192f4a2713aSLionel Sambuc                              unsigned Isa, unsigned Discriminator,
193*0a6a1f1dSLionel Sambuc                              StringRef FileName) override;
194*0a6a1f1dSLionel Sambuc   MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override;
195f4a2713aSLionel Sambuc 
196*0a6a1f1dSLionel Sambuc   void EmitIdent(StringRef IdentString) override;
197*0a6a1f1dSLionel Sambuc   void EmitCFISections(bool EH, bool Debug) override;
198*0a6a1f1dSLionel Sambuc   void EmitCFIDefCfa(int64_t Register, int64_t Offset) override;
199*0a6a1f1dSLionel Sambuc   void EmitCFIDefCfaOffset(int64_t Offset) override;
200*0a6a1f1dSLionel Sambuc   void EmitCFIDefCfaRegister(int64_t Register) override;
201*0a6a1f1dSLionel Sambuc   void EmitCFIOffset(int64_t Register, int64_t Offset) override;
202*0a6a1f1dSLionel Sambuc   void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) override;
203*0a6a1f1dSLionel Sambuc   void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) override;
204*0a6a1f1dSLionel Sambuc   void EmitCFIRememberState() override;
205*0a6a1f1dSLionel Sambuc   void EmitCFIRestoreState() override;
206*0a6a1f1dSLionel Sambuc   void EmitCFISameValue(int64_t Register) override;
207*0a6a1f1dSLionel Sambuc   void EmitCFIRelOffset(int64_t Register, int64_t Offset) override;
208*0a6a1f1dSLionel Sambuc   void EmitCFIAdjustCfaOffset(int64_t Adjustment) override;
209*0a6a1f1dSLionel Sambuc   void EmitCFISignalFrame() override;
210*0a6a1f1dSLionel Sambuc   void EmitCFIUndefined(int64_t Register) override;
211*0a6a1f1dSLionel Sambuc   void EmitCFIRegister(int64_t Register1, int64_t Register2) override;
212*0a6a1f1dSLionel Sambuc   void EmitCFIWindowSave() override;
213f4a2713aSLionel Sambuc 
214*0a6a1f1dSLionel Sambuc   void EmitWinCFIStartProc(const MCSymbol *Symbol) override;
215*0a6a1f1dSLionel Sambuc   void EmitWinCFIEndProc() override;
216*0a6a1f1dSLionel Sambuc   void EmitWinCFIStartChained() override;
217*0a6a1f1dSLionel Sambuc   void EmitWinCFIEndChained() override;
218*0a6a1f1dSLionel Sambuc   void EmitWinCFIPushReg(unsigned Register) override;
219*0a6a1f1dSLionel Sambuc   void EmitWinCFISetFrame(unsigned Register, unsigned Offset) override;
220*0a6a1f1dSLionel Sambuc   void EmitWinCFIAllocStack(unsigned Size) override;
221*0a6a1f1dSLionel Sambuc   void EmitWinCFISaveReg(unsigned Register, unsigned Offset) override;
222*0a6a1f1dSLionel Sambuc   void EmitWinCFISaveXMM(unsigned Register, unsigned Offset) override;
223*0a6a1f1dSLionel Sambuc   void EmitWinCFIPushFrame(bool Code) override;
224*0a6a1f1dSLionel Sambuc   void EmitWinCFIEndProlog() override;
225f4a2713aSLionel Sambuc 
226*0a6a1f1dSLionel Sambuc   void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except) override;
227*0a6a1f1dSLionel Sambuc   void EmitWinEHHandlerData() override;
228f4a2713aSLionel Sambuc 
229*0a6a1f1dSLionel Sambuc   void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
230*0a6a1f1dSLionel Sambuc 
231*0a6a1f1dSLionel Sambuc   void EmitBundleAlignMode(unsigned AlignPow2) override;
232*0a6a1f1dSLionel Sambuc   void EmitBundleLock(bool AlignToEnd) override;
233*0a6a1f1dSLionel Sambuc   void EmitBundleUnlock() override;
234f4a2713aSLionel Sambuc 
235f4a2713aSLionel Sambuc   /// EmitRawText - If this file is backed by an assembly streamer, this dumps
236f4a2713aSLionel Sambuc   /// the specified string in the output .s file.  This capability is
237f4a2713aSLionel Sambuc   /// indicated by the hasRawTextSupport() predicate.
238*0a6a1f1dSLionel Sambuc   void EmitRawTextImpl(StringRef String) override;
239f4a2713aSLionel Sambuc 
240*0a6a1f1dSLionel Sambuc   void FinishImpl() override;
241f4a2713aSLionel Sambuc };
242f4a2713aSLionel Sambuc 
243f4a2713aSLionel Sambuc } // end anonymous namespace.
244f4a2713aSLionel Sambuc 
245f4a2713aSLionel Sambuc /// AddComment - Add a comment that can be emitted to the generated .s
246f4a2713aSLionel Sambuc /// file if applicable as a QoI issue to make the output of the compiler
247f4a2713aSLionel Sambuc /// more readable.  This only affects the MCAsmStreamer, and only when
248f4a2713aSLionel Sambuc /// verbose assembly output is enabled.
AddComment(const Twine & T)249f4a2713aSLionel Sambuc void MCAsmStreamer::AddComment(const Twine &T) {
250f4a2713aSLionel Sambuc   if (!IsVerboseAsm) return;
251f4a2713aSLionel Sambuc 
252f4a2713aSLionel Sambuc   // Make sure that CommentStream is flushed.
253f4a2713aSLionel Sambuc   CommentStream.flush();
254f4a2713aSLionel Sambuc 
255f4a2713aSLionel Sambuc   T.toVector(CommentToEmit);
256f4a2713aSLionel Sambuc   // Each comment goes on its own line.
257f4a2713aSLionel Sambuc   CommentToEmit.push_back('\n');
258f4a2713aSLionel Sambuc 
259f4a2713aSLionel Sambuc   // Tell the comment stream that the vector changed underneath it.
260f4a2713aSLionel Sambuc   CommentStream.resync();
261f4a2713aSLionel Sambuc }
262f4a2713aSLionel Sambuc 
EmitCommentsAndEOL()263f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCommentsAndEOL() {
264f4a2713aSLionel Sambuc   if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
265f4a2713aSLionel Sambuc     OS << '\n';
266f4a2713aSLionel Sambuc     return;
267f4a2713aSLionel Sambuc   }
268f4a2713aSLionel Sambuc 
269f4a2713aSLionel Sambuc   CommentStream.flush();
270f4a2713aSLionel Sambuc   StringRef Comments = CommentToEmit.str();
271f4a2713aSLionel Sambuc 
272f4a2713aSLionel Sambuc   assert(Comments.back() == '\n' &&
273f4a2713aSLionel Sambuc          "Comment array not newline terminated");
274f4a2713aSLionel Sambuc   do {
275f4a2713aSLionel Sambuc     // Emit a line of comments.
276f4a2713aSLionel Sambuc     OS.PadToColumn(MAI->getCommentColumn());
277f4a2713aSLionel Sambuc     size_t Position = Comments.find('\n');
278f4a2713aSLionel Sambuc     OS << MAI->getCommentString() << ' ' << Comments.substr(0, Position) <<'\n';
279f4a2713aSLionel Sambuc 
280f4a2713aSLionel Sambuc     Comments = Comments.substr(Position+1);
281f4a2713aSLionel Sambuc   } while (!Comments.empty());
282f4a2713aSLionel Sambuc 
283f4a2713aSLionel Sambuc   CommentToEmit.clear();
284f4a2713aSLionel Sambuc   // Tell the comment stream that the vector changed underneath it.
285f4a2713aSLionel Sambuc   CommentStream.resync();
286f4a2713aSLionel Sambuc }
287f4a2713aSLionel Sambuc 
truncateToSize(int64_t Value,unsigned Bytes)288f4a2713aSLionel Sambuc static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
289f4a2713aSLionel Sambuc   assert(Bytes && "Invalid size!");
290f4a2713aSLionel Sambuc   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
291f4a2713aSLionel Sambuc }
292f4a2713aSLionel Sambuc 
emitRawComment(const Twine & T,bool TabPrefix)293*0a6a1f1dSLionel Sambuc void MCAsmStreamer::emitRawComment(const Twine &T, bool TabPrefix) {
294*0a6a1f1dSLionel Sambuc   if (TabPrefix)
295*0a6a1f1dSLionel Sambuc     OS << '\t';
296*0a6a1f1dSLionel Sambuc   OS << MAI->getCommentString() << T;
297*0a6a1f1dSLionel Sambuc   EmitEOL();
298*0a6a1f1dSLionel Sambuc }
299*0a6a1f1dSLionel Sambuc 
ChangeSection(const MCSection * Section,const MCExpr * Subsection)300f4a2713aSLionel Sambuc void MCAsmStreamer::ChangeSection(const MCSection *Section,
301f4a2713aSLionel Sambuc                                   const MCExpr *Subsection) {
302f4a2713aSLionel Sambuc   assert(Section && "Cannot switch to a null section!");
303f4a2713aSLionel Sambuc   Section->PrintSwitchToSection(*MAI, OS, Subsection);
304f4a2713aSLionel Sambuc }
305f4a2713aSLionel Sambuc 
EmitLabel(MCSymbol * Symbol)306f4a2713aSLionel Sambuc void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
307f4a2713aSLionel Sambuc   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
308f4a2713aSLionel Sambuc   MCStreamer::EmitLabel(Symbol);
309f4a2713aSLionel Sambuc 
310f4a2713aSLionel Sambuc   OS << *Symbol << MAI->getLabelSuffix();
311f4a2713aSLionel Sambuc   EmitEOL();
312f4a2713aSLionel Sambuc }
313f4a2713aSLionel Sambuc 
EmitLOHDirective(MCLOHType Kind,const MCLOHArgs & Args)314*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {
315*0a6a1f1dSLionel Sambuc   StringRef str = MCLOHIdToName(Kind);
316f4a2713aSLionel Sambuc 
317*0a6a1f1dSLionel Sambuc #ifndef NDEBUG
318*0a6a1f1dSLionel Sambuc   int NbArgs = MCLOHIdToNbArgs(Kind);
319*0a6a1f1dSLionel Sambuc   assert(NbArgs != -1 && ((size_t)NbArgs) == Args.size() && "Malformed LOH!");
320*0a6a1f1dSLionel Sambuc   assert(str != "" && "Invalid LOH name");
321*0a6a1f1dSLionel Sambuc #endif
322*0a6a1f1dSLionel Sambuc 
323*0a6a1f1dSLionel Sambuc   OS << "\t" << MCLOHDirectiveName() << " " << str << "\t";
324*0a6a1f1dSLionel Sambuc   bool IsFirst = true;
325*0a6a1f1dSLionel Sambuc   for (MCLOHArgs::const_iterator It = Args.begin(), EndIt = Args.end();
326*0a6a1f1dSLionel Sambuc        It != EndIt; ++It) {
327*0a6a1f1dSLionel Sambuc     if (!IsFirst)
328*0a6a1f1dSLionel Sambuc       OS << ", ";
329*0a6a1f1dSLionel Sambuc     IsFirst = false;
330*0a6a1f1dSLionel Sambuc     OS << **It;
331*0a6a1f1dSLionel Sambuc   }
332f4a2713aSLionel Sambuc   EmitEOL();
333f4a2713aSLionel Sambuc }
334f4a2713aSLionel Sambuc 
EmitAssemblerFlag(MCAssemblerFlag Flag)335f4a2713aSLionel Sambuc void MCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
336f4a2713aSLionel Sambuc   switch (Flag) {
337f4a2713aSLionel Sambuc   case MCAF_SyntaxUnified:         OS << "\t.syntax unified"; break;
338f4a2713aSLionel Sambuc   case MCAF_SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
339f4a2713aSLionel Sambuc   case MCAF_Code16:                OS << '\t'<< MAI->getCode16Directive();break;
340f4a2713aSLionel Sambuc   case MCAF_Code32:                OS << '\t'<< MAI->getCode32Directive();break;
341f4a2713aSLionel Sambuc   case MCAF_Code64:                OS << '\t'<< MAI->getCode64Directive();break;
342f4a2713aSLionel Sambuc   }
343f4a2713aSLionel Sambuc   EmitEOL();
344f4a2713aSLionel Sambuc }
345f4a2713aSLionel Sambuc 
EmitLinkerOptions(ArrayRef<std::string> Options)346f4a2713aSLionel Sambuc void MCAsmStreamer::EmitLinkerOptions(ArrayRef<std::string> Options) {
347f4a2713aSLionel Sambuc   assert(!Options.empty() && "At least one option is required!");
348f4a2713aSLionel Sambuc   OS << "\t.linker_option \"" << Options[0] << '"';
349f4a2713aSLionel Sambuc   for (ArrayRef<std::string>::iterator it = Options.begin() + 1,
350f4a2713aSLionel Sambuc          ie = Options.end(); it != ie; ++it) {
351f4a2713aSLionel Sambuc     OS << ", " << '"' << *it << '"';
352f4a2713aSLionel Sambuc   }
353f4a2713aSLionel Sambuc   OS << "\n";
354f4a2713aSLionel Sambuc }
355f4a2713aSLionel Sambuc 
EmitDataRegion(MCDataRegionType Kind)356f4a2713aSLionel Sambuc void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
357f4a2713aSLionel Sambuc   if (!MAI->doesSupportDataRegionDirectives())
358f4a2713aSLionel Sambuc     return;
359f4a2713aSLionel Sambuc   switch (Kind) {
360f4a2713aSLionel Sambuc   case MCDR_DataRegion:            OS << "\t.data_region"; break;
361f4a2713aSLionel Sambuc   case MCDR_DataRegionJT8:         OS << "\t.data_region jt8"; break;
362f4a2713aSLionel Sambuc   case MCDR_DataRegionJT16:        OS << "\t.data_region jt16"; break;
363f4a2713aSLionel Sambuc   case MCDR_DataRegionJT32:        OS << "\t.data_region jt32"; break;
364f4a2713aSLionel Sambuc   case MCDR_DataRegionEnd:         OS << "\t.end_data_region"; break;
365f4a2713aSLionel Sambuc   }
366f4a2713aSLionel Sambuc   EmitEOL();
367f4a2713aSLionel Sambuc }
368f4a2713aSLionel Sambuc 
EmitVersionMin(MCVersionMinType Kind,unsigned Major,unsigned Minor,unsigned Update)369*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitVersionMin(MCVersionMinType Kind, unsigned Major,
370*0a6a1f1dSLionel Sambuc                                    unsigned Minor, unsigned Update) {
371*0a6a1f1dSLionel Sambuc   switch (Kind) {
372*0a6a1f1dSLionel Sambuc   case MCVM_IOSVersionMin:        OS << "\t.ios_version_min"; break;
373*0a6a1f1dSLionel Sambuc   case MCVM_OSXVersionMin:        OS << "\t.macosx_version_min"; break;
374*0a6a1f1dSLionel Sambuc   }
375*0a6a1f1dSLionel Sambuc   OS << " " << Major << ", " << Minor;
376*0a6a1f1dSLionel Sambuc   if (Update)
377*0a6a1f1dSLionel Sambuc     OS << ", " << Update;
378*0a6a1f1dSLionel Sambuc   EmitEOL();
379*0a6a1f1dSLionel Sambuc }
380*0a6a1f1dSLionel Sambuc 
EmitThumbFunc(MCSymbol * Func)381f4a2713aSLionel Sambuc void MCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {
382f4a2713aSLionel Sambuc   // This needs to emit to a temporary string to get properly quoted
383f4a2713aSLionel Sambuc   // MCSymbols when they have spaces in them.
384f4a2713aSLionel Sambuc   OS << "\t.thumb_func";
385f4a2713aSLionel Sambuc   // Only Mach-O hasSubsectionsViaSymbols()
386f4a2713aSLionel Sambuc   if (MAI->hasSubsectionsViaSymbols())
387f4a2713aSLionel Sambuc     OS << '\t' << *Func;
388f4a2713aSLionel Sambuc   EmitEOL();
389f4a2713aSLionel Sambuc }
390f4a2713aSLionel Sambuc 
EmitAssignment(MCSymbol * Symbol,const MCExpr * Value)391f4a2713aSLionel Sambuc void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
392f4a2713aSLionel Sambuc   OS << *Symbol << " = " << *Value;
393f4a2713aSLionel Sambuc   EmitEOL();
394f4a2713aSLionel Sambuc 
395*0a6a1f1dSLionel Sambuc   MCStreamer::EmitAssignment(Symbol, Value);
396f4a2713aSLionel Sambuc }
397f4a2713aSLionel Sambuc 
EmitWeakReference(MCSymbol * Alias,const MCSymbol * Symbol)398f4a2713aSLionel Sambuc void MCAsmStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
399f4a2713aSLionel Sambuc   OS << ".weakref " << *Alias << ", " << *Symbol;
400f4a2713aSLionel Sambuc   EmitEOL();
401f4a2713aSLionel Sambuc }
402f4a2713aSLionel Sambuc 
EmitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)403f4a2713aSLionel Sambuc bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
404f4a2713aSLionel Sambuc                                         MCSymbolAttr Attribute) {
405f4a2713aSLionel Sambuc   switch (Attribute) {
406f4a2713aSLionel Sambuc   case MCSA_Invalid: llvm_unreachable("Invalid symbol attribute");
407f4a2713aSLionel Sambuc   case MCSA_ELF_TypeFunction:    /// .type _foo, STT_FUNC  # aka @function
408f4a2713aSLionel Sambuc   case MCSA_ELF_TypeIndFunction: /// .type _foo, STT_GNU_IFUNC
409f4a2713aSLionel Sambuc   case MCSA_ELF_TypeObject:      /// .type _foo, STT_OBJECT  # aka @object
410f4a2713aSLionel Sambuc   case MCSA_ELF_TypeTLS:         /// .type _foo, STT_TLS     # aka @tls_object
411f4a2713aSLionel Sambuc   case MCSA_ELF_TypeCommon:      /// .type _foo, STT_COMMON  # aka @common
412f4a2713aSLionel Sambuc   case MCSA_ELF_TypeNoType:      /// .type _foo, STT_NOTYPE  # aka @notype
413f4a2713aSLionel Sambuc   case MCSA_ELF_TypeGnuUniqueObject:  /// .type _foo, @gnu_unique_object
414f4a2713aSLionel Sambuc     if (!MAI->hasDotTypeDotSizeDirective())
415f4a2713aSLionel Sambuc       return false; // Symbol attribute not supported
416f4a2713aSLionel Sambuc     OS << "\t.type\t" << *Symbol << ','
417f4a2713aSLionel Sambuc        << ((MAI->getCommentString()[0] != '@') ? '@' : '%');
418f4a2713aSLionel Sambuc     switch (Attribute) {
419f4a2713aSLionel Sambuc     default: return false;
420f4a2713aSLionel Sambuc     case MCSA_ELF_TypeFunction:    OS << "function"; break;
421f4a2713aSLionel Sambuc     case MCSA_ELF_TypeIndFunction: OS << "gnu_indirect_function"; break;
422f4a2713aSLionel Sambuc     case MCSA_ELF_TypeObject:      OS << "object"; break;
423f4a2713aSLionel Sambuc     case MCSA_ELF_TypeTLS:         OS << "tls_object"; break;
424f4a2713aSLionel Sambuc     case MCSA_ELF_TypeCommon:      OS << "common"; break;
425f4a2713aSLionel Sambuc     case MCSA_ELF_TypeNoType:      OS << "no_type"; break;
426f4a2713aSLionel Sambuc     case MCSA_ELF_TypeGnuUniqueObject: OS << "gnu_unique_object"; break;
427f4a2713aSLionel Sambuc     }
428f4a2713aSLionel Sambuc     EmitEOL();
429f4a2713aSLionel Sambuc     return true;
430f4a2713aSLionel Sambuc   case MCSA_Global: // .globl/.global
431f4a2713aSLionel Sambuc     OS << MAI->getGlobalDirective();
432f4a2713aSLionel Sambuc     break;
433f4a2713aSLionel Sambuc   case MCSA_Hidden:         OS << "\t.hidden\t";          break;
434f4a2713aSLionel Sambuc   case MCSA_IndirectSymbol: OS << "\t.indirect_symbol\t"; break;
435f4a2713aSLionel Sambuc   case MCSA_Internal:       OS << "\t.internal\t";        break;
436f4a2713aSLionel Sambuc   case MCSA_LazyReference:  OS << "\t.lazy_reference\t";  break;
437f4a2713aSLionel Sambuc   case MCSA_Local:          OS << "\t.local\t";           break;
438*0a6a1f1dSLionel Sambuc   case MCSA_NoDeadStrip:
439*0a6a1f1dSLionel Sambuc     if (!MAI->hasNoDeadStrip())
440*0a6a1f1dSLionel Sambuc       return false;
441*0a6a1f1dSLionel Sambuc     OS << "\t.no_dead_strip\t";
442*0a6a1f1dSLionel Sambuc     break;
443f4a2713aSLionel Sambuc   case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break;
444f4a2713aSLionel Sambuc   case MCSA_PrivateExtern:
445f4a2713aSLionel Sambuc     OS << "\t.private_extern\t";
446f4a2713aSLionel Sambuc     break;
447f4a2713aSLionel Sambuc   case MCSA_Protected:      OS << "\t.protected\t";       break;
448f4a2713aSLionel Sambuc   case MCSA_Reference:      OS << "\t.reference\t";       break;
449*0a6a1f1dSLionel Sambuc   case MCSA_Weak:           OS << MAI->getWeakDirective(); break;
450f4a2713aSLionel Sambuc   case MCSA_WeakDefinition:
451f4a2713aSLionel Sambuc     OS << "\t.weak_definition\t";
452f4a2713aSLionel Sambuc     break;
453f4a2713aSLionel Sambuc       // .weak_reference
454f4a2713aSLionel Sambuc   case MCSA_WeakReference:  OS << MAI->getWeakRefDirective(); break;
455f4a2713aSLionel Sambuc   case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
456f4a2713aSLionel Sambuc   }
457f4a2713aSLionel Sambuc 
458f4a2713aSLionel Sambuc   OS << *Symbol;
459f4a2713aSLionel Sambuc   EmitEOL();
460f4a2713aSLionel Sambuc 
461f4a2713aSLionel Sambuc   return true;
462f4a2713aSLionel Sambuc }
463f4a2713aSLionel Sambuc 
EmitSymbolDesc(MCSymbol * Symbol,unsigned DescValue)464f4a2713aSLionel Sambuc void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
465f4a2713aSLionel Sambuc   OS << ".desc" << ' ' << *Symbol << ',' << DescValue;
466f4a2713aSLionel Sambuc   EmitEOL();
467f4a2713aSLionel Sambuc }
468f4a2713aSLionel Sambuc 
BeginCOFFSymbolDef(const MCSymbol * Symbol)469f4a2713aSLionel Sambuc void MCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {
470f4a2713aSLionel Sambuc   OS << "\t.def\t " << *Symbol << ';';
471f4a2713aSLionel Sambuc   EmitEOL();
472f4a2713aSLionel Sambuc }
473f4a2713aSLionel Sambuc 
EmitCOFFSymbolStorageClass(int StorageClass)474f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {
475f4a2713aSLionel Sambuc   OS << "\t.scl\t" << StorageClass << ';';
476f4a2713aSLionel Sambuc   EmitEOL();
477f4a2713aSLionel Sambuc }
478f4a2713aSLionel Sambuc 
EmitCOFFSymbolType(int Type)479f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCOFFSymbolType (int Type) {
480f4a2713aSLionel Sambuc   OS << "\t.type\t" << Type << ';';
481f4a2713aSLionel Sambuc   EmitEOL();
482f4a2713aSLionel Sambuc }
483f4a2713aSLionel Sambuc 
EndCOFFSymbolDef()484f4a2713aSLionel Sambuc void MCAsmStreamer::EndCOFFSymbolDef() {
485f4a2713aSLionel Sambuc   OS << "\t.endef";
486f4a2713aSLionel Sambuc   EmitEOL();
487f4a2713aSLionel Sambuc }
488f4a2713aSLionel Sambuc 
EmitCOFFSectionIndex(MCSymbol const * Symbol)489*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
490*0a6a1f1dSLionel Sambuc   OS << "\t.secidx\t" << *Symbol;
491*0a6a1f1dSLionel Sambuc   EmitEOL();
492*0a6a1f1dSLionel Sambuc }
493*0a6a1f1dSLionel Sambuc 
EmitCOFFSecRel32(MCSymbol const * Symbol)494f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
495*0a6a1f1dSLionel Sambuc   OS << "\t.secrel32\t" << *Symbol;
496f4a2713aSLionel Sambuc   EmitEOL();
497f4a2713aSLionel Sambuc }
498f4a2713aSLionel Sambuc 
EmitELFSize(MCSymbol * Symbol,const MCExpr * Value)499f4a2713aSLionel Sambuc void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
500f4a2713aSLionel Sambuc   assert(MAI->hasDotTypeDotSizeDirective());
501f4a2713aSLionel Sambuc   OS << "\t.size\t" << *Symbol << ", " << *Value << '\n';
502f4a2713aSLionel Sambuc }
503f4a2713aSLionel Sambuc 
EmitCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)504f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
505f4a2713aSLionel Sambuc                                      unsigned ByteAlignment) {
506f4a2713aSLionel Sambuc   // Common symbols do not belong to any actual section.
507*0a6a1f1dSLionel Sambuc   AssignSection(Symbol, nullptr);
508f4a2713aSLionel Sambuc 
509f4a2713aSLionel Sambuc   OS << "\t.comm\t" << *Symbol << ',' << Size;
510f4a2713aSLionel Sambuc   if (ByteAlignment != 0) {
511f4a2713aSLionel Sambuc     if (MAI->getCOMMDirectiveAlignmentIsInBytes())
512f4a2713aSLionel Sambuc       OS << ',' << ByteAlignment;
513f4a2713aSLionel Sambuc     else
514f4a2713aSLionel Sambuc       OS << ',' << Log2_32(ByteAlignment);
515f4a2713aSLionel Sambuc   }
516f4a2713aSLionel Sambuc   EmitEOL();
517f4a2713aSLionel Sambuc }
518f4a2713aSLionel Sambuc 
519f4a2713aSLionel Sambuc /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
520f4a2713aSLionel Sambuc ///
521f4a2713aSLionel Sambuc /// @param Symbol - The common symbol to emit.
522f4a2713aSLionel Sambuc /// @param Size - The size of the common symbol.
EmitLocalCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlign)523f4a2713aSLionel Sambuc void MCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
524f4a2713aSLionel Sambuc                                           unsigned ByteAlign) {
525f4a2713aSLionel Sambuc   // Common symbols do not belong to any actual section.
526*0a6a1f1dSLionel Sambuc   AssignSection(Symbol, nullptr);
527f4a2713aSLionel Sambuc 
528f4a2713aSLionel Sambuc   OS << "\t.lcomm\t" << *Symbol << ',' << Size;
529f4a2713aSLionel Sambuc   if (ByteAlign > 1) {
530f4a2713aSLionel Sambuc     switch (MAI->getLCOMMDirectiveAlignmentType()) {
531f4a2713aSLionel Sambuc     case LCOMM::NoAlignment:
532f4a2713aSLionel Sambuc       llvm_unreachable("alignment not supported on .lcomm!");
533f4a2713aSLionel Sambuc     case LCOMM::ByteAlignment:
534f4a2713aSLionel Sambuc       OS << ',' << ByteAlign;
535f4a2713aSLionel Sambuc       break;
536f4a2713aSLionel Sambuc     case LCOMM::Log2Alignment:
537f4a2713aSLionel Sambuc       assert(isPowerOf2_32(ByteAlign) && "alignment must be a power of 2");
538f4a2713aSLionel Sambuc       OS << ',' << Log2_32(ByteAlign);
539f4a2713aSLionel Sambuc       break;
540f4a2713aSLionel Sambuc     }
541f4a2713aSLionel Sambuc   }
542f4a2713aSLionel Sambuc   EmitEOL();
543f4a2713aSLionel Sambuc }
544f4a2713aSLionel Sambuc 
EmitZerofill(const MCSection * Section,MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)545f4a2713aSLionel Sambuc void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
546f4a2713aSLionel Sambuc                                  uint64_t Size, unsigned ByteAlignment) {
547f4a2713aSLionel Sambuc   if (Symbol)
548f4a2713aSLionel Sambuc     AssignSection(Symbol, Section);
549f4a2713aSLionel Sambuc 
550f4a2713aSLionel Sambuc   // Note: a .zerofill directive does not switch sections.
551f4a2713aSLionel Sambuc   OS << ".zerofill ";
552f4a2713aSLionel Sambuc 
553f4a2713aSLionel Sambuc   // This is a mach-o specific directive.
554f4a2713aSLionel Sambuc   const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
555f4a2713aSLionel Sambuc   OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
556f4a2713aSLionel Sambuc 
557*0a6a1f1dSLionel Sambuc   if (Symbol) {
558f4a2713aSLionel Sambuc     OS << ',' << *Symbol << ',' << Size;
559f4a2713aSLionel Sambuc     if (ByteAlignment != 0)
560f4a2713aSLionel Sambuc       OS << ',' << Log2_32(ByteAlignment);
561f4a2713aSLionel Sambuc   }
562f4a2713aSLionel Sambuc   EmitEOL();
563f4a2713aSLionel Sambuc }
564f4a2713aSLionel Sambuc 
565f4a2713aSLionel Sambuc // .tbss sym, size, align
566f4a2713aSLionel Sambuc // This depends that the symbol has already been mangled from the original,
567f4a2713aSLionel Sambuc // e.g. _a.
EmitTBSSSymbol(const MCSection * Section,MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)568f4a2713aSLionel Sambuc void MCAsmStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
569f4a2713aSLionel Sambuc                                    uint64_t Size, unsigned ByteAlignment) {
570f4a2713aSLionel Sambuc   AssignSection(Symbol, Section);
571f4a2713aSLionel Sambuc 
572*0a6a1f1dSLionel Sambuc   assert(Symbol && "Symbol shouldn't be NULL!");
573f4a2713aSLionel Sambuc   // Instead of using the Section we'll just use the shortcut.
574f4a2713aSLionel Sambuc   // This is a mach-o specific directive and section.
575f4a2713aSLionel Sambuc   OS << ".tbss " << *Symbol << ", " << Size;
576f4a2713aSLionel Sambuc 
577f4a2713aSLionel Sambuc   // Output align if we have it.  We default to 1 so don't bother printing
578f4a2713aSLionel Sambuc   // that.
579f4a2713aSLionel Sambuc   if (ByteAlignment > 1) OS << ", " << Log2_32(ByteAlignment);
580f4a2713aSLionel Sambuc 
581f4a2713aSLionel Sambuc   EmitEOL();
582f4a2713aSLionel Sambuc }
583f4a2713aSLionel Sambuc 
toOctal(int X)584f4a2713aSLionel Sambuc static inline char toOctal(int X) { return (X&7)+'0'; }
585f4a2713aSLionel Sambuc 
PrintQuotedString(StringRef Data,raw_ostream & OS)586f4a2713aSLionel Sambuc static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
587f4a2713aSLionel Sambuc   OS << '"';
588f4a2713aSLionel Sambuc 
589f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Data.size(); i != e; ++i) {
590f4a2713aSLionel Sambuc     unsigned char C = Data[i];
591f4a2713aSLionel Sambuc     if (C == '"' || C == '\\') {
592f4a2713aSLionel Sambuc       OS << '\\' << (char)C;
593f4a2713aSLionel Sambuc       continue;
594f4a2713aSLionel Sambuc     }
595f4a2713aSLionel Sambuc 
596f4a2713aSLionel Sambuc     if (isprint((unsigned char)C)) {
597f4a2713aSLionel Sambuc       OS << (char)C;
598f4a2713aSLionel Sambuc       continue;
599f4a2713aSLionel Sambuc     }
600f4a2713aSLionel Sambuc 
601f4a2713aSLionel Sambuc     switch (C) {
602f4a2713aSLionel Sambuc       case '\b': OS << "\\b"; break;
603f4a2713aSLionel Sambuc       case '\f': OS << "\\f"; break;
604f4a2713aSLionel Sambuc       case '\n': OS << "\\n"; break;
605f4a2713aSLionel Sambuc       case '\r': OS << "\\r"; break;
606f4a2713aSLionel Sambuc       case '\t': OS << "\\t"; break;
607f4a2713aSLionel Sambuc       default:
608f4a2713aSLionel Sambuc         OS << '\\';
609f4a2713aSLionel Sambuc         OS << toOctal(C >> 6);
610f4a2713aSLionel Sambuc         OS << toOctal(C >> 3);
611f4a2713aSLionel Sambuc         OS << toOctal(C >> 0);
612f4a2713aSLionel Sambuc         break;
613f4a2713aSLionel Sambuc     }
614f4a2713aSLionel Sambuc   }
615f4a2713aSLionel Sambuc 
616f4a2713aSLionel Sambuc   OS << '"';
617f4a2713aSLionel Sambuc }
618f4a2713aSLionel Sambuc 
619f4a2713aSLionel Sambuc 
EmitBytes(StringRef Data)620f4a2713aSLionel Sambuc void MCAsmStreamer::EmitBytes(StringRef Data) {
621f4a2713aSLionel Sambuc   assert(getCurrentSection().first &&
622f4a2713aSLionel Sambuc          "Cannot emit contents before setting section!");
623f4a2713aSLionel Sambuc   if (Data.empty()) return;
624f4a2713aSLionel Sambuc 
625f4a2713aSLionel Sambuc   if (Data.size() == 1) {
626f4a2713aSLionel Sambuc     OS << MAI->getData8bitsDirective();
627f4a2713aSLionel Sambuc     OS << (unsigned)(unsigned char)Data[0];
628f4a2713aSLionel Sambuc     EmitEOL();
629f4a2713aSLionel Sambuc     return;
630f4a2713aSLionel Sambuc   }
631f4a2713aSLionel Sambuc 
632f4a2713aSLionel Sambuc   // If the data ends with 0 and the target supports .asciz, use it, otherwise
633f4a2713aSLionel Sambuc   // use .ascii
634f4a2713aSLionel Sambuc   if (MAI->getAscizDirective() && Data.back() == 0) {
635f4a2713aSLionel Sambuc     OS << MAI->getAscizDirective();
636f4a2713aSLionel Sambuc     Data = Data.substr(0, Data.size()-1);
637f4a2713aSLionel Sambuc   } else {
638f4a2713aSLionel Sambuc     OS << MAI->getAsciiDirective();
639f4a2713aSLionel Sambuc   }
640f4a2713aSLionel Sambuc 
641f4a2713aSLionel Sambuc   PrintQuotedString(Data, OS);
642f4a2713aSLionel Sambuc   EmitEOL();
643f4a2713aSLionel Sambuc }
644f4a2713aSLionel Sambuc 
EmitIntValue(uint64_t Value,unsigned Size)645f4a2713aSLionel Sambuc void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size) {
646f4a2713aSLionel Sambuc   EmitValue(MCConstantExpr::Create(Value, getContext()), Size);
647f4a2713aSLionel Sambuc }
648f4a2713aSLionel Sambuc 
EmitValueImpl(const MCExpr * Value,unsigned Size,const SMLoc & Loc)649*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
650*0a6a1f1dSLionel Sambuc                                   const SMLoc &Loc) {
651*0a6a1f1dSLionel Sambuc   assert(Size <= 8 && "Invalid size");
652f4a2713aSLionel Sambuc   assert(getCurrentSection().first &&
653f4a2713aSLionel Sambuc          "Cannot emit contents before setting section!");
654*0a6a1f1dSLionel Sambuc   const char *Directive = nullptr;
655f4a2713aSLionel Sambuc   switch (Size) {
656f4a2713aSLionel Sambuc   default: break;
657f4a2713aSLionel Sambuc   case 1: Directive = MAI->getData8bitsDirective();  break;
658f4a2713aSLionel Sambuc   case 2: Directive = MAI->getData16bitsDirective(); break;
659f4a2713aSLionel Sambuc   case 4: Directive = MAI->getData32bitsDirective(); break;
660*0a6a1f1dSLionel Sambuc   case 8: Directive = MAI->getData64bitsDirective(); break;
661*0a6a1f1dSLionel Sambuc   }
662*0a6a1f1dSLionel Sambuc 
663*0a6a1f1dSLionel Sambuc   if (!Directive) {
664f4a2713aSLionel Sambuc     int64_t IntValue;
665f4a2713aSLionel Sambuc     if (!Value->EvaluateAsAbsolute(IntValue))
666f4a2713aSLionel Sambuc       report_fatal_error("Don't know how to emit this value.");
667*0a6a1f1dSLionel Sambuc 
668*0a6a1f1dSLionel Sambuc     // We couldn't handle the requested integer size so we fallback by breaking
669*0a6a1f1dSLionel Sambuc     // the request down into several, smaller, integers.  Since sizes greater
670*0a6a1f1dSLionel Sambuc     // than eight are invalid and size equivalent to eight should have been
671*0a6a1f1dSLionel Sambuc     // handled earlier, we use four bytes as our largest piece of granularity.
672*0a6a1f1dSLionel Sambuc     bool IsLittleEndian = MAI->isLittleEndian();
673*0a6a1f1dSLionel Sambuc     for (unsigned Emitted = 0; Emitted != Size;) {
674*0a6a1f1dSLionel Sambuc       unsigned Remaining = Size - Emitted;
675*0a6a1f1dSLionel Sambuc       // The size of our partial emission must be a power of two less than
676*0a6a1f1dSLionel Sambuc       // eight.
677*0a6a1f1dSLionel Sambuc       unsigned EmissionSize = PowerOf2Floor(Remaining);
678*0a6a1f1dSLionel Sambuc       if (EmissionSize > 4)
679*0a6a1f1dSLionel Sambuc         EmissionSize = 4;
680*0a6a1f1dSLionel Sambuc       // Calculate the byte offset of our partial emission taking into account
681*0a6a1f1dSLionel Sambuc       // the endianness of the target.
682*0a6a1f1dSLionel Sambuc       unsigned ByteOffset =
683*0a6a1f1dSLionel Sambuc           IsLittleEndian ? Emitted : (Remaining - EmissionSize);
684*0a6a1f1dSLionel Sambuc       uint64_t ValueToEmit = IntValue >> (ByteOffset * 8);
685*0a6a1f1dSLionel Sambuc       // We truncate our partial emission to fit within the bounds of the
686*0a6a1f1dSLionel Sambuc       // emission domain.  This produces nicer output and silences potential
687*0a6a1f1dSLionel Sambuc       // truncation warnings when round tripping through another assembler.
688*0a6a1f1dSLionel Sambuc       uint64_t Shift = 64 - EmissionSize * 8;
689*0a6a1f1dSLionel Sambuc       assert(Shift < static_cast<uint64_t>(
690*0a6a1f1dSLionel Sambuc                          std::numeric_limits<unsigned long long>::digits) &&
691*0a6a1f1dSLionel Sambuc              "undefined behavior");
692*0a6a1f1dSLionel Sambuc       ValueToEmit &= ~0ULL >> Shift;
693*0a6a1f1dSLionel Sambuc       EmitIntValue(ValueToEmit, EmissionSize);
694*0a6a1f1dSLionel Sambuc       Emitted += EmissionSize;
695f4a2713aSLionel Sambuc     }
696f4a2713aSLionel Sambuc     return;
697f4a2713aSLionel Sambuc   }
698f4a2713aSLionel Sambuc 
699f4a2713aSLionel Sambuc   assert(Directive && "Invalid size for machine code value!");
700f4a2713aSLionel Sambuc   OS << Directive << *Value;
701f4a2713aSLionel Sambuc   EmitEOL();
702f4a2713aSLionel Sambuc }
703f4a2713aSLionel Sambuc 
EmitULEB128Value(const MCExpr * Value)704f4a2713aSLionel Sambuc void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) {
705f4a2713aSLionel Sambuc   int64_t IntValue;
706f4a2713aSLionel Sambuc   if (Value->EvaluateAsAbsolute(IntValue)) {
707f4a2713aSLionel Sambuc     EmitULEB128IntValue(IntValue);
708f4a2713aSLionel Sambuc     return;
709f4a2713aSLionel Sambuc   }
710f4a2713aSLionel Sambuc   OS << ".uleb128 " << *Value;
711f4a2713aSLionel Sambuc   EmitEOL();
712f4a2713aSLionel Sambuc }
713f4a2713aSLionel Sambuc 
EmitSLEB128Value(const MCExpr * Value)714f4a2713aSLionel Sambuc void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
715f4a2713aSLionel Sambuc   int64_t IntValue;
716f4a2713aSLionel Sambuc   if (Value->EvaluateAsAbsolute(IntValue)) {
717f4a2713aSLionel Sambuc     EmitSLEB128IntValue(IntValue);
718f4a2713aSLionel Sambuc     return;
719f4a2713aSLionel Sambuc   }
720f4a2713aSLionel Sambuc   OS << ".sleb128 " << *Value;
721f4a2713aSLionel Sambuc   EmitEOL();
722f4a2713aSLionel Sambuc }
723f4a2713aSLionel Sambuc 
EmitGPRel64Value(const MCExpr * Value)724f4a2713aSLionel Sambuc void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
725*0a6a1f1dSLionel Sambuc   assert(MAI->getGPRel64Directive() != nullptr);
726f4a2713aSLionel Sambuc   OS << MAI->getGPRel64Directive() << *Value;
727f4a2713aSLionel Sambuc   EmitEOL();
728f4a2713aSLionel Sambuc }
729f4a2713aSLionel Sambuc 
EmitGPRel32Value(const MCExpr * Value)730f4a2713aSLionel Sambuc void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
731*0a6a1f1dSLionel Sambuc   assert(MAI->getGPRel32Directive() != nullptr);
732f4a2713aSLionel Sambuc   OS << MAI->getGPRel32Directive() << *Value;
733f4a2713aSLionel Sambuc   EmitEOL();
734f4a2713aSLionel Sambuc }
735f4a2713aSLionel Sambuc 
736f4a2713aSLionel Sambuc 
737f4a2713aSLionel Sambuc /// EmitFill - Emit NumBytes bytes worth of the value specified by
738f4a2713aSLionel Sambuc /// FillValue.  This implements directives such as '.space'.
EmitFill(uint64_t NumBytes,uint8_t FillValue)739f4a2713aSLionel Sambuc void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) {
740f4a2713aSLionel Sambuc   if (NumBytes == 0) return;
741f4a2713aSLionel Sambuc 
742f4a2713aSLionel Sambuc   if (const char *ZeroDirective = MAI->getZeroDirective()) {
743f4a2713aSLionel Sambuc     OS << ZeroDirective << NumBytes;
744f4a2713aSLionel Sambuc     if (FillValue != 0)
745f4a2713aSLionel Sambuc       OS << ',' << (int)FillValue;
746f4a2713aSLionel Sambuc     EmitEOL();
747f4a2713aSLionel Sambuc     return;
748f4a2713aSLionel Sambuc   }
749f4a2713aSLionel Sambuc 
750f4a2713aSLionel Sambuc   // Emit a byte at a time.
751f4a2713aSLionel Sambuc   MCStreamer::EmitFill(NumBytes, FillValue);
752f4a2713aSLionel Sambuc }
753f4a2713aSLionel Sambuc 
EmitValueToAlignment(unsigned ByteAlignment,int64_t Value,unsigned ValueSize,unsigned MaxBytesToEmit)754f4a2713aSLionel Sambuc void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
755f4a2713aSLionel Sambuc                                          unsigned ValueSize,
756f4a2713aSLionel Sambuc                                          unsigned MaxBytesToEmit) {
757f4a2713aSLionel Sambuc   // Some assemblers don't support non-power of two alignments, so we always
758f4a2713aSLionel Sambuc   // emit alignments as a power of two if possible.
759f4a2713aSLionel Sambuc   if (isPowerOf2_32(ByteAlignment)) {
760f4a2713aSLionel Sambuc     switch (ValueSize) {
761*0a6a1f1dSLionel Sambuc     default:
762*0a6a1f1dSLionel Sambuc       llvm_unreachable("Invalid size for machine code value!");
763*0a6a1f1dSLionel Sambuc     case 1:
764*0a6a1f1dSLionel Sambuc       OS << "\t.align\t";
765*0a6a1f1dSLionel Sambuc       break;
766*0a6a1f1dSLionel Sambuc     case 2:
767*0a6a1f1dSLionel Sambuc       OS << ".p2alignw ";
768*0a6a1f1dSLionel Sambuc       break;
769*0a6a1f1dSLionel Sambuc     case 4:
770*0a6a1f1dSLionel Sambuc       OS << ".p2alignl ";
771*0a6a1f1dSLionel Sambuc       break;
772*0a6a1f1dSLionel Sambuc     case 8:
773*0a6a1f1dSLionel Sambuc       llvm_unreachable("Unsupported alignment size!");
774f4a2713aSLionel Sambuc     }
775f4a2713aSLionel Sambuc 
776f4a2713aSLionel Sambuc     if (MAI->getAlignmentIsInBytes())
777f4a2713aSLionel Sambuc       OS << ByteAlignment;
778f4a2713aSLionel Sambuc     else
779f4a2713aSLionel Sambuc       OS << Log2_32(ByteAlignment);
780f4a2713aSLionel Sambuc 
781f4a2713aSLionel Sambuc     if (Value || MaxBytesToEmit) {
782f4a2713aSLionel Sambuc       OS << ", 0x";
783f4a2713aSLionel Sambuc       OS.write_hex(truncateToSize(Value, ValueSize));
784f4a2713aSLionel Sambuc 
785f4a2713aSLionel Sambuc       if (MaxBytesToEmit)
786f4a2713aSLionel Sambuc         OS << ", " << MaxBytesToEmit;
787f4a2713aSLionel Sambuc     }
788f4a2713aSLionel Sambuc     EmitEOL();
789f4a2713aSLionel Sambuc     return;
790f4a2713aSLionel Sambuc   }
791f4a2713aSLionel Sambuc 
792f4a2713aSLionel Sambuc   // Non-power of two alignment.  This is not widely supported by assemblers.
793f4a2713aSLionel Sambuc   // FIXME: Parameterize this based on MAI.
794f4a2713aSLionel Sambuc   switch (ValueSize) {
795f4a2713aSLionel Sambuc   default: llvm_unreachable("Invalid size for machine code value!");
796f4a2713aSLionel Sambuc   case 1: OS << ".balign";  break;
797f4a2713aSLionel Sambuc   case 2: OS << ".balignw"; break;
798f4a2713aSLionel Sambuc   case 4: OS << ".balignl"; break;
799f4a2713aSLionel Sambuc   case 8: llvm_unreachable("Unsupported alignment size!");
800f4a2713aSLionel Sambuc   }
801f4a2713aSLionel Sambuc 
802f4a2713aSLionel Sambuc   OS << ' ' << ByteAlignment;
803f4a2713aSLionel Sambuc   OS << ", " << truncateToSize(Value, ValueSize);
804f4a2713aSLionel Sambuc   if (MaxBytesToEmit)
805f4a2713aSLionel Sambuc     OS << ", " << MaxBytesToEmit;
806f4a2713aSLionel Sambuc   EmitEOL();
807f4a2713aSLionel Sambuc }
808f4a2713aSLionel Sambuc 
EmitCodeAlignment(unsigned ByteAlignment,unsigned MaxBytesToEmit)809f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
810f4a2713aSLionel Sambuc                                       unsigned MaxBytesToEmit) {
811f4a2713aSLionel Sambuc   // Emit with a text fill value.
812f4a2713aSLionel Sambuc   EmitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
813f4a2713aSLionel Sambuc                        1, MaxBytesToEmit);
814f4a2713aSLionel Sambuc }
815f4a2713aSLionel Sambuc 
EmitValueToOffset(const MCExpr * Offset,unsigned char Value)816f4a2713aSLionel Sambuc bool MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,
817f4a2713aSLionel Sambuc                                       unsigned char Value) {
818f4a2713aSLionel Sambuc   // FIXME: Verify that Offset is associated with the current section.
819f4a2713aSLionel Sambuc   OS << ".org " << *Offset << ", " << (unsigned) Value;
820f4a2713aSLionel Sambuc   EmitEOL();
821f4a2713aSLionel Sambuc   return false;
822f4a2713aSLionel Sambuc }
823f4a2713aSLionel Sambuc 
824f4a2713aSLionel Sambuc 
EmitFileDirective(StringRef Filename)825f4a2713aSLionel Sambuc void MCAsmStreamer::EmitFileDirective(StringRef Filename) {
826f4a2713aSLionel Sambuc   assert(MAI->hasSingleParameterDotFile());
827f4a2713aSLionel Sambuc   OS << "\t.file\t";
828f4a2713aSLionel Sambuc   PrintQuotedString(Filename, OS);
829f4a2713aSLionel Sambuc   EmitEOL();
830f4a2713aSLionel Sambuc }
831f4a2713aSLionel Sambuc 
EmitDwarfFileDirective(unsigned FileNo,StringRef Directory,StringRef Filename,unsigned CUID)832*0a6a1f1dSLionel Sambuc unsigned MCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
833*0a6a1f1dSLionel Sambuc                                                StringRef Directory,
834*0a6a1f1dSLionel Sambuc                                                StringRef Filename,
835*0a6a1f1dSLionel Sambuc                                                unsigned CUID) {
836*0a6a1f1dSLionel Sambuc   assert(CUID == 0);
837*0a6a1f1dSLionel Sambuc 
838*0a6a1f1dSLionel Sambuc   MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID);
839*0a6a1f1dSLionel Sambuc   unsigned NumFiles = Table.getMCDwarfFiles().size();
840*0a6a1f1dSLionel Sambuc   FileNo = Table.getFile(Directory, Filename, FileNo);
841*0a6a1f1dSLionel Sambuc   if (FileNo == 0)
842*0a6a1f1dSLionel Sambuc     return 0;
843*0a6a1f1dSLionel Sambuc   if (NumFiles == Table.getMCDwarfFiles().size())
844*0a6a1f1dSLionel Sambuc     return FileNo;
845*0a6a1f1dSLionel Sambuc 
846*0a6a1f1dSLionel Sambuc   SmallString<128> FullPathName;
847*0a6a1f1dSLionel Sambuc 
848f4a2713aSLionel Sambuc   if (!UseDwarfDirectory && !Directory.empty()) {
849f4a2713aSLionel Sambuc     if (sys::path::is_absolute(Filename))
850*0a6a1f1dSLionel Sambuc       Directory = "";
851*0a6a1f1dSLionel Sambuc     else {
852*0a6a1f1dSLionel Sambuc       FullPathName = Directory;
853f4a2713aSLionel Sambuc       sys::path::append(FullPathName, Filename);
854*0a6a1f1dSLionel Sambuc       Directory = "";
855*0a6a1f1dSLionel Sambuc       Filename = FullPathName;
856*0a6a1f1dSLionel Sambuc     }
857f4a2713aSLionel Sambuc   }
858f4a2713aSLionel Sambuc 
859f4a2713aSLionel Sambuc   OS << "\t.file\t" << FileNo << ' ';
860f4a2713aSLionel Sambuc   if (!Directory.empty()) {
861f4a2713aSLionel Sambuc     PrintQuotedString(Directory, OS);
862f4a2713aSLionel Sambuc     OS << ' ';
863f4a2713aSLionel Sambuc   }
864f4a2713aSLionel Sambuc   PrintQuotedString(Filename, OS);
865f4a2713aSLionel Sambuc   EmitEOL();
866*0a6a1f1dSLionel Sambuc 
867*0a6a1f1dSLionel Sambuc   return FileNo;
868f4a2713aSLionel Sambuc }
869f4a2713aSLionel Sambuc 
EmitDwarfLocDirective(unsigned FileNo,unsigned Line,unsigned Column,unsigned Flags,unsigned Isa,unsigned Discriminator,StringRef FileName)870f4a2713aSLionel Sambuc void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
871f4a2713aSLionel Sambuc                                           unsigned Column, unsigned Flags,
872f4a2713aSLionel Sambuc                                           unsigned Isa,
873f4a2713aSLionel Sambuc                                           unsigned Discriminator,
874f4a2713aSLionel Sambuc                                           StringRef FileName) {
875f4a2713aSLionel Sambuc   OS << "\t.loc\t" << FileNo << " " << Line << " " << Column;
876f4a2713aSLionel Sambuc   if (Flags & DWARF2_FLAG_BASIC_BLOCK)
877f4a2713aSLionel Sambuc     OS << " basic_block";
878f4a2713aSLionel Sambuc   if (Flags & DWARF2_FLAG_PROLOGUE_END)
879f4a2713aSLionel Sambuc     OS << " prologue_end";
880f4a2713aSLionel Sambuc   if (Flags & DWARF2_FLAG_EPILOGUE_BEGIN)
881f4a2713aSLionel Sambuc     OS << " epilogue_begin";
882f4a2713aSLionel Sambuc 
883f4a2713aSLionel Sambuc   unsigned OldFlags = getContext().getCurrentDwarfLoc().getFlags();
884f4a2713aSLionel Sambuc   if ((Flags & DWARF2_FLAG_IS_STMT) != (OldFlags & DWARF2_FLAG_IS_STMT)) {
885f4a2713aSLionel Sambuc     OS << " is_stmt ";
886f4a2713aSLionel Sambuc 
887f4a2713aSLionel Sambuc     if (Flags & DWARF2_FLAG_IS_STMT)
888f4a2713aSLionel Sambuc       OS << "1";
889f4a2713aSLionel Sambuc     else
890f4a2713aSLionel Sambuc       OS << "0";
891f4a2713aSLionel Sambuc   }
892f4a2713aSLionel Sambuc 
893f4a2713aSLionel Sambuc   if (Isa)
894f4a2713aSLionel Sambuc     OS << " isa " << Isa;
895f4a2713aSLionel Sambuc   if (Discriminator)
896f4a2713aSLionel Sambuc     OS << " discriminator " << Discriminator;
897f4a2713aSLionel Sambuc 
898f4a2713aSLionel Sambuc   if (IsVerboseAsm) {
899f4a2713aSLionel Sambuc     OS.PadToColumn(MAI->getCommentColumn());
900f4a2713aSLionel Sambuc     OS << MAI->getCommentString() << ' ' << FileName << ':'
901f4a2713aSLionel Sambuc        << Line << ':' << Column;
902f4a2713aSLionel Sambuc   }
903f4a2713aSLionel Sambuc   EmitEOL();
904*0a6a1f1dSLionel Sambuc   this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
905*0a6a1f1dSLionel Sambuc                                           Isa, Discriminator, FileName);
906*0a6a1f1dSLionel Sambuc }
907*0a6a1f1dSLionel Sambuc 
getDwarfLineTableSymbol(unsigned CUID)908*0a6a1f1dSLionel Sambuc MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) {
909*0a6a1f1dSLionel Sambuc   // Always use the zeroth line table, since asm syntax only supports one line
910*0a6a1f1dSLionel Sambuc   // table for now.
911*0a6a1f1dSLionel Sambuc   return MCStreamer::getDwarfLineTableSymbol(0);
912f4a2713aSLionel Sambuc }
913f4a2713aSLionel Sambuc 
EmitIdent(StringRef IdentString)914f4a2713aSLionel Sambuc void MCAsmStreamer::EmitIdent(StringRef IdentString) {
915f4a2713aSLionel Sambuc   assert(MAI->hasIdentDirective() && ".ident directive not supported");
916f4a2713aSLionel Sambuc   OS << "\t.ident\t";
917f4a2713aSLionel Sambuc   PrintQuotedString(IdentString, OS);
918f4a2713aSLionel Sambuc   EmitEOL();
919f4a2713aSLionel Sambuc }
920f4a2713aSLionel Sambuc 
EmitCFISections(bool EH,bool Debug)921f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFISections(bool EH, bool Debug) {
922f4a2713aSLionel Sambuc   MCStreamer::EmitCFISections(EH, Debug);
923f4a2713aSLionel Sambuc   OS << "\t.cfi_sections ";
924f4a2713aSLionel Sambuc   if (EH) {
925f4a2713aSLionel Sambuc     OS << ".eh_frame";
926f4a2713aSLionel Sambuc     if (Debug)
927f4a2713aSLionel Sambuc       OS << ", .debug_frame";
928f4a2713aSLionel Sambuc   } else if (Debug) {
929f4a2713aSLionel Sambuc     OS << ".debug_frame";
930f4a2713aSLionel Sambuc   }
931f4a2713aSLionel Sambuc 
932f4a2713aSLionel Sambuc   EmitEOL();
933f4a2713aSLionel Sambuc }
934f4a2713aSLionel Sambuc 
EmitCFIStartProcImpl(MCDwarfFrameInfo & Frame)935f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
936f4a2713aSLionel Sambuc   OS << "\t.cfi_startproc";
937*0a6a1f1dSLionel Sambuc   if (Frame.IsSimple)
938*0a6a1f1dSLionel Sambuc     OS << " simple";
939f4a2713aSLionel Sambuc   EmitEOL();
940f4a2713aSLionel Sambuc }
941f4a2713aSLionel Sambuc 
EmitCFIEndProcImpl(MCDwarfFrameInfo & Frame)942f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
943*0a6a1f1dSLionel Sambuc   MCStreamer::EmitCFIEndProcImpl(Frame);
944f4a2713aSLionel Sambuc   OS << "\t.cfi_endproc";
945f4a2713aSLionel Sambuc   EmitEOL();
946f4a2713aSLionel Sambuc }
947f4a2713aSLionel Sambuc 
EmitRegisterName(int64_t Register)948f4a2713aSLionel Sambuc void MCAsmStreamer::EmitRegisterName(int64_t Register) {
949f4a2713aSLionel Sambuc   if (InstPrinter && !MAI->useDwarfRegNumForCFI()) {
950f4a2713aSLionel Sambuc     const MCRegisterInfo *MRI = getContext().getRegisterInfo();
951f4a2713aSLionel Sambuc     unsigned LLVMRegister = MRI->getLLVMRegNum(Register, true);
952f4a2713aSLionel Sambuc     InstPrinter->printRegName(OS, LLVMRegister);
953f4a2713aSLionel Sambuc   } else {
954f4a2713aSLionel Sambuc     OS << Register;
955f4a2713aSLionel Sambuc   }
956f4a2713aSLionel Sambuc }
957f4a2713aSLionel Sambuc 
EmitCFIDefCfa(int64_t Register,int64_t Offset)958f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) {
959f4a2713aSLionel Sambuc   MCStreamer::EmitCFIDefCfa(Register, Offset);
960f4a2713aSLionel Sambuc   OS << "\t.cfi_def_cfa ";
961f4a2713aSLionel Sambuc   EmitRegisterName(Register);
962f4a2713aSLionel Sambuc   OS << ", " << Offset;
963f4a2713aSLionel Sambuc   EmitEOL();
964f4a2713aSLionel Sambuc }
965f4a2713aSLionel Sambuc 
EmitCFIDefCfaOffset(int64_t Offset)966f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) {
967f4a2713aSLionel Sambuc   MCStreamer::EmitCFIDefCfaOffset(Offset);
968f4a2713aSLionel Sambuc   OS << "\t.cfi_def_cfa_offset " << Offset;
969f4a2713aSLionel Sambuc   EmitEOL();
970f4a2713aSLionel Sambuc }
971f4a2713aSLionel Sambuc 
EmitCFIDefCfaRegister(int64_t Register)972f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) {
973f4a2713aSLionel Sambuc   MCStreamer::EmitCFIDefCfaRegister(Register);
974f4a2713aSLionel Sambuc   OS << "\t.cfi_def_cfa_register ";
975f4a2713aSLionel Sambuc   EmitRegisterName(Register);
976f4a2713aSLionel Sambuc   EmitEOL();
977f4a2713aSLionel Sambuc }
978f4a2713aSLionel Sambuc 
EmitCFIOffset(int64_t Register,int64_t Offset)979f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) {
980f4a2713aSLionel Sambuc   this->MCStreamer::EmitCFIOffset(Register, Offset);
981f4a2713aSLionel Sambuc   OS << "\t.cfi_offset ";
982f4a2713aSLionel Sambuc   EmitRegisterName(Register);
983f4a2713aSLionel Sambuc   OS << ", " << Offset;
984f4a2713aSLionel Sambuc   EmitEOL();
985f4a2713aSLionel Sambuc }
986f4a2713aSLionel Sambuc 
EmitCFIPersonality(const MCSymbol * Sym,unsigned Encoding)987f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym,
988f4a2713aSLionel Sambuc                                        unsigned Encoding) {
989f4a2713aSLionel Sambuc   MCStreamer::EmitCFIPersonality(Sym, Encoding);
990f4a2713aSLionel Sambuc   OS << "\t.cfi_personality " << Encoding << ", " << *Sym;
991f4a2713aSLionel Sambuc   EmitEOL();
992f4a2713aSLionel Sambuc }
993f4a2713aSLionel Sambuc 
EmitCFILsda(const MCSymbol * Sym,unsigned Encoding)994f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) {
995f4a2713aSLionel Sambuc   MCStreamer::EmitCFILsda(Sym, Encoding);
996f4a2713aSLionel Sambuc   OS << "\t.cfi_lsda " << Encoding << ", " << *Sym;
997f4a2713aSLionel Sambuc   EmitEOL();
998f4a2713aSLionel Sambuc }
999f4a2713aSLionel Sambuc 
EmitCFIRememberState()1000f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIRememberState() {
1001f4a2713aSLionel Sambuc   MCStreamer::EmitCFIRememberState();
1002f4a2713aSLionel Sambuc   OS << "\t.cfi_remember_state";
1003f4a2713aSLionel Sambuc   EmitEOL();
1004f4a2713aSLionel Sambuc }
1005f4a2713aSLionel Sambuc 
EmitCFIRestoreState()1006f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIRestoreState() {
1007f4a2713aSLionel Sambuc   MCStreamer::EmitCFIRestoreState();
1008f4a2713aSLionel Sambuc   OS << "\t.cfi_restore_state";
1009f4a2713aSLionel Sambuc   EmitEOL();
1010f4a2713aSLionel Sambuc }
1011f4a2713aSLionel Sambuc 
EmitCFISameValue(int64_t Register)1012f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFISameValue(int64_t Register) {
1013f4a2713aSLionel Sambuc   MCStreamer::EmitCFISameValue(Register);
1014f4a2713aSLionel Sambuc   OS << "\t.cfi_same_value ";
1015f4a2713aSLionel Sambuc   EmitRegisterName(Register);
1016f4a2713aSLionel Sambuc   EmitEOL();
1017f4a2713aSLionel Sambuc }
1018f4a2713aSLionel Sambuc 
EmitCFIRelOffset(int64_t Register,int64_t Offset)1019f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) {
1020f4a2713aSLionel Sambuc   MCStreamer::EmitCFIRelOffset(Register, Offset);
1021f4a2713aSLionel Sambuc   OS << "\t.cfi_rel_offset ";
1022f4a2713aSLionel Sambuc   EmitRegisterName(Register);
1023f4a2713aSLionel Sambuc   OS << ", " << Offset;
1024f4a2713aSLionel Sambuc   EmitEOL();
1025f4a2713aSLionel Sambuc }
1026f4a2713aSLionel Sambuc 
EmitCFIAdjustCfaOffset(int64_t Adjustment)1027f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) {
1028f4a2713aSLionel Sambuc   MCStreamer::EmitCFIAdjustCfaOffset(Adjustment);
1029f4a2713aSLionel Sambuc   OS << "\t.cfi_adjust_cfa_offset " << Adjustment;
1030f4a2713aSLionel Sambuc   EmitEOL();
1031f4a2713aSLionel Sambuc }
1032f4a2713aSLionel Sambuc 
EmitCFISignalFrame()1033f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFISignalFrame() {
1034f4a2713aSLionel Sambuc   MCStreamer::EmitCFISignalFrame();
1035f4a2713aSLionel Sambuc   OS << "\t.cfi_signal_frame";
1036f4a2713aSLionel Sambuc   EmitEOL();
1037f4a2713aSLionel Sambuc }
1038f4a2713aSLionel Sambuc 
EmitCFIUndefined(int64_t Register)1039f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIUndefined(int64_t Register) {
1040f4a2713aSLionel Sambuc   MCStreamer::EmitCFIUndefined(Register);
1041f4a2713aSLionel Sambuc   OS << "\t.cfi_undefined " << Register;
1042f4a2713aSLionel Sambuc   EmitEOL();
1043f4a2713aSLionel Sambuc }
1044f4a2713aSLionel Sambuc 
EmitCFIRegister(int64_t Register1,int64_t Register2)1045f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIRegister(int64_t Register1, int64_t Register2) {
1046f4a2713aSLionel Sambuc   MCStreamer::EmitCFIRegister(Register1, Register2);
1047f4a2713aSLionel Sambuc   OS << "\t.cfi_register " << Register1 << ", " << Register2;
1048f4a2713aSLionel Sambuc   EmitEOL();
1049f4a2713aSLionel Sambuc }
1050f4a2713aSLionel Sambuc 
EmitCFIWindowSave()1051f4a2713aSLionel Sambuc void MCAsmStreamer::EmitCFIWindowSave() {
1052f4a2713aSLionel Sambuc   MCStreamer::EmitCFIWindowSave();
1053f4a2713aSLionel Sambuc   OS << "\t.cfi_window_save";
1054f4a2713aSLionel Sambuc   EmitEOL();
1055f4a2713aSLionel Sambuc }
1056f4a2713aSLionel Sambuc 
EmitWinCFIStartProc(const MCSymbol * Symbol)1057*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) {
1058*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIStartProc(Symbol);
1059f4a2713aSLionel Sambuc 
1060f4a2713aSLionel Sambuc   OS << ".seh_proc " << *Symbol;
1061f4a2713aSLionel Sambuc   EmitEOL();
1062f4a2713aSLionel Sambuc }
1063f4a2713aSLionel Sambuc 
EmitWinCFIEndProc()1064*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIEndProc() {
1065*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIEndProc();
1066f4a2713aSLionel Sambuc 
1067f4a2713aSLionel Sambuc   OS << "\t.seh_endproc";
1068f4a2713aSLionel Sambuc   EmitEOL();
1069f4a2713aSLionel Sambuc }
1070f4a2713aSLionel Sambuc 
EmitWinCFIStartChained()1071*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIStartChained() {
1072*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIStartChained();
1073f4a2713aSLionel Sambuc 
1074f4a2713aSLionel Sambuc   OS << "\t.seh_startchained";
1075f4a2713aSLionel Sambuc   EmitEOL();
1076f4a2713aSLionel Sambuc }
1077f4a2713aSLionel Sambuc 
EmitWinCFIEndChained()1078*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIEndChained() {
1079*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIEndChained();
1080f4a2713aSLionel Sambuc 
1081f4a2713aSLionel Sambuc   OS << "\t.seh_endchained";
1082f4a2713aSLionel Sambuc   EmitEOL();
1083f4a2713aSLionel Sambuc }
1084f4a2713aSLionel Sambuc 
EmitWinEHHandler(const MCSymbol * Sym,bool Unwind,bool Except)1085*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind,
1086f4a2713aSLionel Sambuc                                       bool Except) {
1087*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinEHHandler(Sym, Unwind, Except);
1088f4a2713aSLionel Sambuc 
1089f4a2713aSLionel Sambuc   OS << "\t.seh_handler " << *Sym;
1090f4a2713aSLionel Sambuc   if (Unwind)
1091f4a2713aSLionel Sambuc     OS << ", @unwind";
1092f4a2713aSLionel Sambuc   if (Except)
1093f4a2713aSLionel Sambuc     OS << ", @except";
1094f4a2713aSLionel Sambuc   EmitEOL();
1095f4a2713aSLionel Sambuc }
1096f4a2713aSLionel Sambuc 
EmitWinEHHandlerData()1097*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinEHHandlerData() {
1098*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinEHHandlerData();
1099f4a2713aSLionel Sambuc 
1100f4a2713aSLionel Sambuc   // Switch sections. Don't call SwitchSection directly, because that will
1101f4a2713aSLionel Sambuc   // cause the section switch to be visible in the emitted assembly.
1102f4a2713aSLionel Sambuc   // We only do this so the section switch that terminates the handler
1103f4a2713aSLionel Sambuc   // data block is visible.
1104*0a6a1f1dSLionel Sambuc   WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
1105*0a6a1f1dSLionel Sambuc   if (const MCSection *XData = WinEH::UnwindEmitter::getXDataSection(
1106*0a6a1f1dSLionel Sambuc           CurFrame->Function, getContext()))
1107*0a6a1f1dSLionel Sambuc     SwitchSectionNoChange(XData);
1108f4a2713aSLionel Sambuc 
1109f4a2713aSLionel Sambuc   OS << "\t.seh_handlerdata";
1110f4a2713aSLionel Sambuc   EmitEOL();
1111f4a2713aSLionel Sambuc }
1112f4a2713aSLionel Sambuc 
EmitWinCFIPushReg(unsigned Register)1113*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIPushReg(unsigned Register) {
1114*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIPushReg(Register);
1115f4a2713aSLionel Sambuc 
1116f4a2713aSLionel Sambuc   OS << "\t.seh_pushreg " << Register;
1117f4a2713aSLionel Sambuc   EmitEOL();
1118f4a2713aSLionel Sambuc }
1119f4a2713aSLionel Sambuc 
EmitWinCFISetFrame(unsigned Register,unsigned Offset)1120*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFISetFrame(unsigned Register, unsigned Offset) {
1121*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFISetFrame(Register, Offset);
1122f4a2713aSLionel Sambuc 
1123f4a2713aSLionel Sambuc   OS << "\t.seh_setframe " << Register << ", " << Offset;
1124f4a2713aSLionel Sambuc   EmitEOL();
1125f4a2713aSLionel Sambuc }
1126f4a2713aSLionel Sambuc 
EmitWinCFIAllocStack(unsigned Size)1127*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIAllocStack(unsigned Size) {
1128*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIAllocStack(Size);
1129f4a2713aSLionel Sambuc 
1130f4a2713aSLionel Sambuc   OS << "\t.seh_stackalloc " << Size;
1131f4a2713aSLionel Sambuc   EmitEOL();
1132f4a2713aSLionel Sambuc }
1133f4a2713aSLionel Sambuc 
EmitWinCFISaveReg(unsigned Register,unsigned Offset)1134*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFISaveReg(unsigned Register, unsigned Offset) {
1135*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFISaveReg(Register, Offset);
1136f4a2713aSLionel Sambuc 
1137f4a2713aSLionel Sambuc   OS << "\t.seh_savereg " << Register << ", " << Offset;
1138f4a2713aSLionel Sambuc   EmitEOL();
1139f4a2713aSLionel Sambuc }
1140f4a2713aSLionel Sambuc 
EmitWinCFISaveXMM(unsigned Register,unsigned Offset)1141*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFISaveXMM(unsigned Register, unsigned Offset) {
1142*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFISaveXMM(Register, Offset);
1143f4a2713aSLionel Sambuc 
1144f4a2713aSLionel Sambuc   OS << "\t.seh_savexmm " << Register << ", " << Offset;
1145f4a2713aSLionel Sambuc   EmitEOL();
1146f4a2713aSLionel Sambuc }
1147f4a2713aSLionel Sambuc 
EmitWinCFIPushFrame(bool Code)1148*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIPushFrame(bool Code) {
1149*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIPushFrame(Code);
1150f4a2713aSLionel Sambuc 
1151f4a2713aSLionel Sambuc   OS << "\t.seh_pushframe";
1152f4a2713aSLionel Sambuc   if (Code)
1153f4a2713aSLionel Sambuc     OS << " @code";
1154f4a2713aSLionel Sambuc   EmitEOL();
1155f4a2713aSLionel Sambuc }
1156f4a2713aSLionel Sambuc 
EmitWinCFIEndProlog(void)1157*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitWinCFIEndProlog(void) {
1158*0a6a1f1dSLionel Sambuc   MCStreamer::EmitWinCFIEndProlog();
1159f4a2713aSLionel Sambuc 
1160f4a2713aSLionel Sambuc   OS << "\t.seh_endprologue";
1161f4a2713aSLionel Sambuc   EmitEOL();
1162f4a2713aSLionel Sambuc }
1163f4a2713aSLionel Sambuc 
AddEncodingComment(const MCInst & Inst,const MCSubtargetInfo & STI)1164*0a6a1f1dSLionel Sambuc void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
1165*0a6a1f1dSLionel Sambuc                                        const MCSubtargetInfo &STI) {
1166f4a2713aSLionel Sambuc   raw_ostream &OS = GetCommentOS();
1167f4a2713aSLionel Sambuc   SmallString<256> Code;
1168f4a2713aSLionel Sambuc   SmallVector<MCFixup, 4> Fixups;
1169f4a2713aSLionel Sambuc   raw_svector_ostream VecOS(Code);
1170*0a6a1f1dSLionel Sambuc   Emitter->EncodeInstruction(Inst, VecOS, Fixups, STI);
1171f4a2713aSLionel Sambuc   VecOS.flush();
1172f4a2713aSLionel Sambuc 
1173f4a2713aSLionel Sambuc   // If we are showing fixups, create symbolic markers in the encoded
1174f4a2713aSLionel Sambuc   // representation. We do this by making a per-bit map to the fixup item index,
1175f4a2713aSLionel Sambuc   // then trying to display it as nicely as possible.
1176f4a2713aSLionel Sambuc   SmallVector<uint8_t, 64> FixupMap;
1177f4a2713aSLionel Sambuc   FixupMap.resize(Code.size() * 8);
1178f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Code.size() * 8; i != e; ++i)
1179f4a2713aSLionel Sambuc     FixupMap[i] = 0;
1180f4a2713aSLionel Sambuc 
1181f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
1182f4a2713aSLionel Sambuc     MCFixup &F = Fixups[i];
1183f4a2713aSLionel Sambuc     const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
1184f4a2713aSLionel Sambuc     for (unsigned j = 0; j != Info.TargetSize; ++j) {
1185f4a2713aSLionel Sambuc       unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
1186f4a2713aSLionel Sambuc       assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
1187f4a2713aSLionel Sambuc       FixupMap[Index] = 1 + i;
1188f4a2713aSLionel Sambuc     }
1189f4a2713aSLionel Sambuc   }
1190f4a2713aSLionel Sambuc 
1191f4a2713aSLionel Sambuc   // FIXME: Note the fixup comments for Thumb2 are completely bogus since the
1192f4a2713aSLionel Sambuc   // high order halfword of a 32-bit Thumb2 instruction is emitted first.
1193f4a2713aSLionel Sambuc   OS << "encoding: [";
1194f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Code.size(); i != e; ++i) {
1195f4a2713aSLionel Sambuc     if (i)
1196f4a2713aSLionel Sambuc       OS << ',';
1197f4a2713aSLionel Sambuc 
1198f4a2713aSLionel Sambuc     // See if all bits are the same map entry.
1199f4a2713aSLionel Sambuc     uint8_t MapEntry = FixupMap[i * 8 + 0];
1200f4a2713aSLionel Sambuc     for (unsigned j = 1; j != 8; ++j) {
1201f4a2713aSLionel Sambuc       if (FixupMap[i * 8 + j] == MapEntry)
1202f4a2713aSLionel Sambuc         continue;
1203f4a2713aSLionel Sambuc 
1204f4a2713aSLionel Sambuc       MapEntry = uint8_t(~0U);
1205f4a2713aSLionel Sambuc       break;
1206f4a2713aSLionel Sambuc     }
1207f4a2713aSLionel Sambuc 
1208f4a2713aSLionel Sambuc     if (MapEntry != uint8_t(~0U)) {
1209f4a2713aSLionel Sambuc       if (MapEntry == 0) {
1210f4a2713aSLionel Sambuc         OS << format("0x%02x", uint8_t(Code[i]));
1211f4a2713aSLionel Sambuc       } else {
1212f4a2713aSLionel Sambuc         if (Code[i]) {
1213f4a2713aSLionel Sambuc           // FIXME: Some of the 8 bits require fix up.
1214f4a2713aSLionel Sambuc           OS << format("0x%02x", uint8_t(Code[i])) << '\''
1215f4a2713aSLionel Sambuc              << char('A' + MapEntry - 1) << '\'';
1216f4a2713aSLionel Sambuc         } else
1217f4a2713aSLionel Sambuc           OS << char('A' + MapEntry - 1);
1218f4a2713aSLionel Sambuc       }
1219f4a2713aSLionel Sambuc     } else {
1220f4a2713aSLionel Sambuc       // Otherwise, write out in binary.
1221f4a2713aSLionel Sambuc       OS << "0b";
1222f4a2713aSLionel Sambuc       for (unsigned j = 8; j--;) {
1223f4a2713aSLionel Sambuc         unsigned Bit = (Code[i] >> j) & 1;
1224f4a2713aSLionel Sambuc 
1225f4a2713aSLionel Sambuc         unsigned FixupBit;
1226f4a2713aSLionel Sambuc         if (MAI->isLittleEndian())
1227f4a2713aSLionel Sambuc           FixupBit = i * 8 + j;
1228f4a2713aSLionel Sambuc         else
1229f4a2713aSLionel Sambuc           FixupBit = i * 8 + (7-j);
1230f4a2713aSLionel Sambuc 
1231f4a2713aSLionel Sambuc         if (uint8_t MapEntry = FixupMap[FixupBit]) {
1232f4a2713aSLionel Sambuc           assert(Bit == 0 && "Encoder wrote into fixed up bit!");
1233f4a2713aSLionel Sambuc           OS << char('A' + MapEntry - 1);
1234f4a2713aSLionel Sambuc         } else
1235f4a2713aSLionel Sambuc           OS << Bit;
1236f4a2713aSLionel Sambuc       }
1237f4a2713aSLionel Sambuc     }
1238f4a2713aSLionel Sambuc   }
1239f4a2713aSLionel Sambuc   OS << "]\n";
1240f4a2713aSLionel Sambuc 
1241f4a2713aSLionel Sambuc   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
1242f4a2713aSLionel Sambuc     MCFixup &F = Fixups[i];
1243f4a2713aSLionel Sambuc     const MCFixupKindInfo &Info = AsmBackend->getFixupKindInfo(F.getKind());
1244f4a2713aSLionel Sambuc     OS << "  fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
1245f4a2713aSLionel Sambuc        << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
1246f4a2713aSLionel Sambuc   }
1247f4a2713aSLionel Sambuc }
1248f4a2713aSLionel Sambuc 
EmitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)1249*0a6a1f1dSLionel Sambuc void MCAsmStreamer::EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) {
1250f4a2713aSLionel Sambuc   assert(getCurrentSection().first &&
1251f4a2713aSLionel Sambuc          "Cannot emit contents before setting section!");
1252f4a2713aSLionel Sambuc 
1253f4a2713aSLionel Sambuc   // Show the encoding in a comment if we have a code emitter.
1254f4a2713aSLionel Sambuc   if (Emitter)
1255*0a6a1f1dSLionel Sambuc     AddEncodingComment(Inst, STI);
1256f4a2713aSLionel Sambuc 
1257f4a2713aSLionel Sambuc   // Show the MCInst if enabled.
1258f4a2713aSLionel Sambuc   if (ShowInst) {
1259f4a2713aSLionel Sambuc     Inst.dump_pretty(GetCommentOS(), MAI, InstPrinter.get(), "\n ");
1260f4a2713aSLionel Sambuc     GetCommentOS() << "\n";
1261f4a2713aSLionel Sambuc   }
1262f4a2713aSLionel Sambuc 
1263f4a2713aSLionel Sambuc   // If we have an AsmPrinter, use that to print, otherwise print the MCInst.
1264f4a2713aSLionel Sambuc   if (InstPrinter)
1265f4a2713aSLionel Sambuc     InstPrinter->printInst(&Inst, OS, "");
1266f4a2713aSLionel Sambuc   else
1267f4a2713aSLionel Sambuc     Inst.print(OS, MAI);
1268f4a2713aSLionel Sambuc   EmitEOL();
1269f4a2713aSLionel Sambuc }
1270f4a2713aSLionel Sambuc 
EmitBundleAlignMode(unsigned AlignPow2)1271f4a2713aSLionel Sambuc void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
1272f4a2713aSLionel Sambuc   OS << "\t.bundle_align_mode " << AlignPow2;
1273f4a2713aSLionel Sambuc   EmitEOL();
1274f4a2713aSLionel Sambuc }
1275f4a2713aSLionel Sambuc 
EmitBundleLock(bool AlignToEnd)1276f4a2713aSLionel Sambuc void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
1277f4a2713aSLionel Sambuc   OS << "\t.bundle_lock";
1278f4a2713aSLionel Sambuc   if (AlignToEnd)
1279f4a2713aSLionel Sambuc     OS << " align_to_end";
1280f4a2713aSLionel Sambuc   EmitEOL();
1281f4a2713aSLionel Sambuc }
1282f4a2713aSLionel Sambuc 
EmitBundleUnlock()1283f4a2713aSLionel Sambuc void MCAsmStreamer::EmitBundleUnlock() {
1284f4a2713aSLionel Sambuc   OS << "\t.bundle_unlock";
1285f4a2713aSLionel Sambuc   EmitEOL();
1286f4a2713aSLionel Sambuc }
1287f4a2713aSLionel Sambuc 
1288f4a2713aSLionel Sambuc /// EmitRawText - If this file is backed by an assembly streamer, this dumps
1289f4a2713aSLionel Sambuc /// the specified string in the output .s file.  This capability is
1290f4a2713aSLionel Sambuc /// indicated by the hasRawTextSupport() predicate.
EmitRawTextImpl(StringRef String)1291f4a2713aSLionel Sambuc void MCAsmStreamer::EmitRawTextImpl(StringRef String) {
1292f4a2713aSLionel Sambuc   if (!String.empty() && String.back() == '\n')
1293f4a2713aSLionel Sambuc     String = String.substr(0, String.size()-1);
1294f4a2713aSLionel Sambuc   OS << String;
1295f4a2713aSLionel Sambuc   EmitEOL();
1296f4a2713aSLionel Sambuc }
1297f4a2713aSLionel Sambuc 
FinishImpl()1298f4a2713aSLionel Sambuc void MCAsmStreamer::FinishImpl() {
1299f4a2713aSLionel Sambuc   // If we are generating dwarf for assembly source files dump out the sections.
1300f4a2713aSLionel Sambuc   if (getContext().getGenDwarfForAssembly())
1301*0a6a1f1dSLionel Sambuc     MCGenDwarfInfo::Emit(this);
1302f4a2713aSLionel Sambuc 
1303*0a6a1f1dSLionel Sambuc   // Emit the label for the line table, if requested - since the rest of the
1304*0a6a1f1dSLionel Sambuc   // line table will be defined by .loc/.file directives, and not emitted
1305*0a6a1f1dSLionel Sambuc   // directly, the label is the only work required here.
1306*0a6a1f1dSLionel Sambuc   auto &Tables = getContext().getMCDwarfLineTables();
1307*0a6a1f1dSLionel Sambuc   if (!Tables.empty()) {
1308*0a6a1f1dSLionel Sambuc     assert(Tables.size() == 1 && "asm output only supports one line table");
1309*0a6a1f1dSLionel Sambuc     if (auto *Label = Tables.begin()->second.getLabel()) {
1310*0a6a1f1dSLionel Sambuc       SwitchSection(getContext().getObjectFileInfo()->getDwarfLineSection());
1311*0a6a1f1dSLionel Sambuc       EmitLabel(Label);
1312*0a6a1f1dSLionel Sambuc     }
1313*0a6a1f1dSLionel Sambuc   }
1314f4a2713aSLionel Sambuc }
1315f4a2713aSLionel Sambuc 
createAsmStreamer(MCContext & Context,formatted_raw_ostream & OS,bool isVerboseAsm,bool useDwarfDirectory,MCInstPrinter * IP,MCCodeEmitter * CE,MCAsmBackend * MAB,bool ShowInst)1316f4a2713aSLionel Sambuc MCStreamer *llvm::createAsmStreamer(MCContext &Context,
1317f4a2713aSLionel Sambuc                                     formatted_raw_ostream &OS,
1318*0a6a1f1dSLionel Sambuc                                     bool isVerboseAsm, bool useDwarfDirectory,
1319*0a6a1f1dSLionel Sambuc                                     MCInstPrinter *IP, MCCodeEmitter *CE,
1320*0a6a1f1dSLionel Sambuc                                     MCAsmBackend *MAB, bool ShowInst) {
1321*0a6a1f1dSLionel Sambuc   return new MCAsmStreamer(Context, OS, isVerboseAsm, useDwarfDirectory, IP, CE,
1322*0a6a1f1dSLionel Sambuc                            MAB, ShowInst);
1323f4a2713aSLionel Sambuc }
1324