2c2fb0e8c208f09a095f4747666ac982ff9332d7
[oota-llvm.git] / lib / MC / MCAsmStreamer.cpp
1 //===- lib/MC/MCAsmStreamer.cpp - Text Assembly Output --------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/MC/MCStreamer.h"
11 #include "llvm/MC/MCAsmInfo.h"
12 #include "llvm/MC/MCCodeEmitter.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCInstPrinter.h"
17 #include "llvm/MC/MCSectionMachO.h"
18 #include "llvm/MC/MCSymbol.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/Twine.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/MathExtras.h"
23 #include "llvm/Support/Format.h"
24 #include "llvm/Support/FormattedStream.h"
25 using namespace llvm;
26
27 namespace {
28
29 class MCAsmStreamer : public MCStreamer {
30   formatted_raw_ostream &OS;
31   const MCAsmInfo &MAI;
32   bool IsLittleEndian, IsVerboseAsm;
33   MCInstPrinter *InstPrinter;
34   MCCodeEmitter *Emitter;
35   
36   SmallString<128> CommentToEmit;
37 public:
38   MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
39                 const MCAsmInfo &mai,
40                 bool isLittleEndian, bool isVerboseAsm, MCInstPrinter *printer,
41                 MCCodeEmitter *emitter)
42     : MCStreamer(Context), OS(os), MAI(mai), IsLittleEndian(isLittleEndian),
43       IsVerboseAsm(isVerboseAsm), InstPrinter(printer), Emitter(emitter) {}
44   ~MCAsmStreamer() {}
45
46   bool isLittleEndian() const { return IsLittleEndian; }
47   
48   
49   inline void EmitEOL() {
50     if (CommentToEmit.empty()) {
51       OS << '\n';
52       return;
53     }
54     EmitCommentsAndEOL();
55   }
56   void EmitCommentsAndEOL();
57   
58   /// AddComment - Add a comment that can be emitted to the generated .s
59   /// file if applicable as a QoI issue to make the output of the compiler
60   /// more readable.  This only affects the MCAsmStreamer, and only when
61   /// verbose assembly output is enabled.
62   virtual void AddComment(const Twine &T);
63   
64   /// @name MCStreamer Interface
65   /// @{
66
67   virtual void SwitchSection(const MCSection *Section);
68
69   virtual void EmitLabel(MCSymbol *Symbol);
70
71   virtual void EmitAssemblerFlag(AssemblerFlag Flag);
72
73   virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
74
75   virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
76
77   virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
78
79   virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
80                                 unsigned ByteAlignment);
81
82   virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
83                             unsigned Size = 0, unsigned ByteAlignment = 0);
84
85   virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
86
87   virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
88   virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace);
89
90   virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue,
91                         unsigned AddrSpace);
92
93   virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
94                                     unsigned ValueSize = 1,
95                                     unsigned MaxBytesToEmit = 0);
96
97   virtual void EmitValueToOffset(const MCExpr *Offset,
98                                  unsigned char Value = 0);
99   
100   virtual void EmitInstruction(const MCInst &Inst);
101
102   virtual void Finish();
103   
104   /// @}
105 };
106
107 } // end anonymous namespace.
108
109 /// AddComment - Add a comment that can be emitted to the generated .s
110 /// file if applicable as a QoI issue to make the output of the compiler
111 /// more readable.  This only affects the MCAsmStreamer, and only when
112 /// verbose assembly output is enabled.
113 void MCAsmStreamer::AddComment(const Twine &T) {
114   if (!IsVerboseAsm) return;
115   // Each comment goes on its own line.
116   if (!CommentToEmit.empty())
117     CommentToEmit.push_back('\n');
118   T.toVector(CommentToEmit);
119 }
120
121 void MCAsmStreamer::EmitCommentsAndEOL() {
122   StringRef Comments = CommentToEmit.str();
123   while (!Comments.empty()) {
124     // Emit a line of comments.
125     OS.PadToColumn(MAI.getCommentColumn());
126     size_t Position = Comments.find('\n');
127     OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n';
128     
129     if (Position == StringRef::npos) break;
130     Comments = Comments.substr(Position+1);
131   }
132   
133   CommentToEmit.clear();
134 }
135
136
137 static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
138   assert(Bytes && "Invalid size!");
139   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
140 }
141
142 static inline const MCExpr *truncateToSize(const MCExpr *Value,
143                                            unsigned Bytes) {
144   // FIXME: Do we really need this routine?
145   return Value;
146 }
147
148 void MCAsmStreamer::SwitchSection(const MCSection *Section) {
149   assert(Section && "Cannot switch to a null section!");
150   if (Section != CurSection) {
151     CurSection = Section;
152     Section->PrintSwitchToSection(MAI, OS);
153   }
154 }
155
156 void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
157   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
158   assert(CurSection && "Cannot emit before setting section!");
159
160   OS << *Symbol << ":";
161   EmitEOL();
162   Symbol->setSection(*CurSection);
163 }
164
165 void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
166   switch (Flag) {
167   default: assert(0 && "Invalid flag!");
168   case SubsectionsViaSymbols: OS << ".subsections_via_symbols"; break;
169   }
170   EmitEOL();
171 }
172
173 void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
174   // Only absolute symbols can be redefined.
175   assert((Symbol->isUndefined() || Symbol->isAbsolute()) &&
176          "Cannot define a symbol twice!");
177
178   OS << *Symbol << " = " << *Value;
179   EmitEOL();
180
181   // FIXME: Lift context changes into super class.
182   // FIXME: Set associated section.
183   Symbol->setValue(Value);
184 }
185
186 void MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
187                                         SymbolAttr Attribute) {
188   switch (Attribute) {
189   case Global:         OS << MAI.getGlobalDirective(); break; // .globl
190   case Hidden:         OS << ".hidden ";          break;
191   case IndirectSymbol: OS << ".indirect_symbol "; break;
192   case Internal:       OS << ".internal ";        break;
193   case LazyReference:  OS << ".lazy_reference ";  break;
194   case NoDeadStrip:    OS << ".no_dead_strip ";   break;
195   case PrivateExtern:  OS << ".private_extern ";  break;
196   case Protected:      OS << ".protected ";       break;
197   case Reference:      OS << ".reference ";       break;
198   case Weak:           OS << ".weak ";            break;
199   case WeakDefinition: OS << ".weak_definition "; break;
200   case WeakReference:  OS << ".weak_reference ";  break;
201   }
202
203   OS << *Symbol;
204   EmitEOL();
205 }
206
207 void MCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
208   OS << ".desc" << ' ' << *Symbol << ',' << DescValue;
209   EmitEOL();
210 }
211
212 void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
213                                      unsigned ByteAlignment) {
214   OS << MAI.getCOMMDirective() << *Symbol << ',' << Size;
215   if (ByteAlignment != 0 && MAI.getCOMMDirectiveTakesAlignment()) {
216     if (MAI.getAlignmentIsInBytes())
217       OS << ',' << ByteAlignment;
218     else
219       OS << ',' << Log2_32(ByteAlignment);
220   }
221   EmitEOL();
222 }
223
224 void MCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
225                                  unsigned Size, unsigned ByteAlignment) {
226   // Note: a .zerofill directive does not switch sections.
227   OS << ".zerofill ";
228   
229   // This is a mach-o specific directive.
230   const MCSectionMachO *MOSection = ((const MCSectionMachO*)Section);
231   OS << MOSection->getSegmentName() << "," << MOSection->getSectionName();
232   
233   if (Symbol != NULL) {
234     OS << ',' << *Symbol << ',' << Size;
235     if (ByteAlignment != 0)
236       OS << ',' << Log2_32(ByteAlignment);
237   }
238   EmitEOL();
239 }
240
241 void MCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
242   assert(CurSection && "Cannot emit contents before setting section!");
243   const char *Directive = MAI.getData8bitsDirective(AddrSpace);
244   for (unsigned i = 0, e = Data.size(); i != e; ++i) {
245     OS << Directive << (unsigned)(unsigned char)Data[i];
246     EmitEOL();
247   }
248 }
249
250 /// EmitIntValue - Special case of EmitValue that avoids the client having
251 /// to pass in a MCExpr for constant integers.
252 void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size,
253                                  unsigned AddrSpace) {
254   assert(CurSection && "Cannot emit contents before setting section!");
255   const char *Directive = 0;
256   switch (Size) {
257   default: break;
258   case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break;
259   case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break;
260   case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break;
261   case 8:
262     Directive = MAI.getData64bitsDirective(AddrSpace);
263     // If the target doesn't support 64-bit data, emit as two 32-bit halves.
264     if (Directive) break;
265     if (isLittleEndian()) {
266       EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace);
267       EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace);
268     } else {
269       EmitIntValue((uint32_t)(Value >> 32), 4, AddrSpace);
270       EmitIntValue((uint32_t)(Value >> 0 ), 4, AddrSpace);
271     }
272     return;
273   }
274   
275   assert(Directive && "Invalid size for machine code value!");
276   OS << Directive << truncateToSize(Value, Size);
277   EmitEOL();
278 }
279
280 void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size,
281                               unsigned AddrSpace) {
282   assert(CurSection && "Cannot emit contents before setting section!");
283   const char *Directive = 0;
284   switch (Size) {
285   default: break;
286   case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break;
287   case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break;
288   case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break;
289   case 8: Directive = MAI.getData64bitsDirective(AddrSpace); break;
290   }
291   
292   assert(Directive && "Invalid size for machine code value!");
293   OS << Directive << *truncateToSize(Value, Size);
294   EmitEOL();
295 }
296
297 /// EmitFill - Emit NumBytes bytes worth of the value specified by
298 /// FillValue.  This implements directives such as '.space'.
299 void MCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
300                              unsigned AddrSpace) {
301   if (NumBytes == 0) return;
302   
303   if (AddrSpace == 0)
304     if (const char *ZeroDirective = MAI.getZeroDirective()) {
305       OS << ZeroDirective << NumBytes;
306       if (FillValue != 0)
307         OS << ',' << (int)FillValue;
308       EmitEOL();
309       return;
310     }
311
312   // Emit a byte at a time.
313   MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace);
314 }
315
316 void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
317                                          unsigned ValueSize,
318                                          unsigned MaxBytesToEmit) {
319   // Some assemblers don't support non-power of two alignments, so we always
320   // emit alignments as a power of two if possible.
321   if (isPowerOf2_32(ByteAlignment)) {
322     switch (ValueSize) {
323     default: llvm_unreachable("Invalid size for machine code value!");
324     case 1: OS << MAI.getAlignDirective(); break;
325     // FIXME: use MAI for this!
326     case 2: OS << ".p2alignw "; break;
327     case 4: OS << ".p2alignl "; break;
328     case 8: llvm_unreachable("Unsupported alignment size!");
329     }
330     
331     if (MAI.getAlignmentIsInBytes())
332       OS << ByteAlignment;
333     else
334       OS << Log2_32(ByteAlignment);
335
336     if (Value || MaxBytesToEmit) {
337       OS << ", 0x";
338       OS.write_hex(truncateToSize(Value, ValueSize));
339
340       if (MaxBytesToEmit) 
341         OS << ", " << MaxBytesToEmit;
342     }
343     EmitEOL();
344     return;
345   }
346   
347   // Non-power of two alignment.  This is not widely supported by assemblers.
348   // FIXME: Parameterize this based on MAI.
349   switch (ValueSize) {
350   default: llvm_unreachable("Invalid size for machine code value!");
351   case 1: OS << ".balign";  break;
352   case 2: OS << ".balignw"; break;
353   case 4: OS << ".balignl"; break;
354   case 8: llvm_unreachable("Unsupported alignment size!");
355   }
356
357   OS << ' ' << ByteAlignment;
358   OS << ", " << truncateToSize(Value, ValueSize);
359   if (MaxBytesToEmit) 
360     OS << ", " << MaxBytesToEmit;
361   EmitEOL();
362 }
363
364 void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,
365                                       unsigned char Value) {
366   // FIXME: Verify that Offset is associated with the current section.
367   OS << ".org " << *Offset << ", " << (unsigned) Value;
368   EmitEOL();
369 }
370
371 void MCAsmStreamer::EmitInstruction(const MCInst &Inst) {
372   assert(CurSection && "Cannot emit contents before setting section!");
373
374   // If we have an AsmPrinter, use that to print.
375   if (InstPrinter) {
376     InstPrinter->printInst(&Inst);
377     EmitEOL();
378
379     // Show the encoding if we have a code emitter.
380     if (Emitter) {
381       SmallString<256> Code;
382       raw_svector_ostream VecOS(Code);
383       Emitter->EncodeInstruction(Inst, VecOS);
384       VecOS.flush();
385   
386       OS.indent(20);
387       OS << " # encoding: [";
388       for (unsigned i = 0, e = Code.size(); i != e; ++i) {
389         if (i)
390           OS << ',';
391         OS << format("%#04x", uint8_t(Code[i]));
392       }
393       OS << "]\n";
394     }
395
396     return;
397   }
398
399   // Otherwise fall back to a structural printing for now. Eventually we should
400   // always have access to the target specific printer.
401   Inst.print(OS, &MAI);
402   EmitEOL();
403 }
404
405 void MCAsmStreamer::Finish() {
406   OS.flush();
407 }
408     
409 MCStreamer *llvm::createAsmStreamer(MCContext &Context,
410                                     formatted_raw_ostream &OS,
411                                     const MCAsmInfo &MAI, bool isLittleEndian,
412                                     bool isVerboseAsm, MCInstPrinter *IP,
413                                     MCCodeEmitter *CE) {
414   return new MCAsmStreamer(Context, OS, MAI, isLittleEndian, isVerboseAsm,
415                            IP, CE);
416 }