ARM Pseudo-ize tBR_JTr.
[oota-llvm.git] / lib / Target / PTX / PTXMCAsmStreamer.cpp
1 //===- lib/Target/PTX/PTXMCAsmStreamer.cpp - PTX 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/ADT/OwningPtr.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/Twine.h"
13 #include "llvm/MC/MCAsmInfo.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCCodeEmitter.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/MC/MCInstPrinter.h"
19 #include "llvm/MC/MCStreamer.h"
20 #include "llvm/MC/MCSymbol.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 #include "llvm/Support/raw_ostream.h"
26
27 using namespace llvm;
28
29 namespace {
30 class PTXMCAsmStreamer : public MCStreamer {
31   formatted_raw_ostream &OS;
32   const MCAsmInfo &MAI;
33   OwningPtr<MCInstPrinter> InstPrinter;
34   OwningPtr<MCCodeEmitter> Emitter;
35
36   SmallString<128> CommentToEmit;
37   raw_svector_ostream CommentStream;
38
39   unsigned IsLittleEndian : 1;
40   unsigned IsVerboseAsm : 1;
41   unsigned ShowInst : 1;
42
43 public:
44   PTXMCAsmStreamer(MCContext &Context,
45                    formatted_raw_ostream &os,
46                    bool isLittleEndian,
47                    bool isVerboseAsm,
48                    MCInstPrinter *printer,
49                    MCCodeEmitter *emitter,
50                    bool showInst)
51     : MCStreamer(Context), OS(os), MAI(Context.getAsmInfo()),
52       InstPrinter(printer), Emitter(emitter), CommentStream(CommentToEmit),
53       IsLittleEndian(isLittleEndian), IsVerboseAsm(isVerboseAsm),
54       ShowInst(showInst) {
55     if (InstPrinter && IsVerboseAsm)
56       InstPrinter->setCommentStream(CommentStream);
57   }
58
59   ~PTXMCAsmStreamer() {}
60
61   bool isLittleEndian() const { return IsLittleEndian; }
62
63   inline void EmitEOL() {
64     // If we don't have any comments, just emit a \n.
65     if (!IsVerboseAsm) {
66       OS << '\n';
67       return;
68     }
69     EmitCommentsAndEOL();
70   }
71   void EmitCommentsAndEOL();
72
73   /// isVerboseAsm - Return true if this streamer supports verbose assembly at
74   /// all.
75   virtual bool isVerboseAsm() const { return IsVerboseAsm; }
76
77   /// hasRawTextSupport - We support EmitRawText.
78   virtual bool hasRawTextSupport() const { return true; }
79
80   /// AddComment - Add a comment that can be emitted to the generated .s
81   /// file if applicable as a QoI issue to make the output of the compiler
82   /// more readable.  This only affects the MCAsmStreamer, and only when
83   /// verbose assembly output is enabled.
84   virtual void AddComment(const Twine &T);
85
86   /// AddEncodingComment - Add a comment showing the encoding of an instruction.
87   virtual void AddEncodingComment(const MCInst &Inst);
88
89   /// GetCommentOS - Return a raw_ostream that comments can be written to.
90   /// Unlike AddComment, you are required to terminate comments with \n if you
91   /// use this method.
92   virtual raw_ostream &GetCommentOS() {
93     if (!IsVerboseAsm)
94       return nulls();  // Discard comments unless in verbose asm mode.
95     return CommentStream;
96   }
97
98   /// AddBlankLine - Emit a blank line to a .s file to pretty it up.
99   virtual void AddBlankLine() {
100     EmitEOL();
101   }
102
103   /// @name MCStreamer Interface
104   /// @{
105
106   virtual void SwitchSection(const MCSection *Section);
107
108   virtual void InitSections() {
109   }
110
111   virtual void EmitLabel(MCSymbol *Symbol);
112
113   virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
114
115   virtual void EmitThumbFunc(MCSymbol *Func);
116
117   virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
118
119   virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol);
120
121   virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
122
123   virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
124   virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol);
125   virtual void EmitCOFFSymbolStorageClass(int StorageClass);
126   virtual void EmitCOFFSymbolType(int Type);
127   virtual void EndCOFFSymbolDef();
128   virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value);
129   virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
130                                 unsigned ByteAlignment);
131
132   /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol.
133   ///
134   /// @param Symbol - The common symbol to emit.
135   /// @param Size - The size of the common symbol.
136   virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size);
137
138   virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0,
139                             unsigned Size = 0, unsigned ByteAlignment = 0);
140
141   virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol,
142                               uint64_t Size, unsigned ByteAlignment = 0);
143
144   virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
145
146   virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
147   virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
148   virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
149   virtual void EmitGPRel32Value(const MCExpr *Value);
150
151
152   virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue,
153                         unsigned AddrSpace);
154
155   virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
156                                     unsigned ValueSize = 1,
157                                     unsigned MaxBytesToEmit = 0);
158
159   virtual void EmitCodeAlignment(unsigned ByteAlignment,
160                                  unsigned MaxBytesToEmit = 0);
161
162   virtual void EmitValueToOffset(const MCExpr *Offset,
163                                  unsigned char Value = 0);
164
165   virtual void EmitFileDirective(StringRef Filename);
166   virtual bool EmitDwarfFileDirective(unsigned FileNo, StringRef Filename);
167
168   virtual void EmitInstruction(const MCInst &Inst);
169
170   /// EmitRawText - If this file is backed by an assembly streamer, this dumps
171   /// the specified string in the output .s file.  This capability is
172   /// indicated by the hasRawTextSupport() predicate.
173   virtual void EmitRawText(StringRef String);
174
175   virtual void Finish();
176
177   /// @}
178
179 }; // class PTXMCAsmStreamer
180
181 }
182
183 /// TODO: Add appropriate implementation of Emit*() methods when needed
184
185 void PTXMCAsmStreamer::AddComment(const Twine &T) {
186   if (!IsVerboseAsm) return;
187
188   // Make sure that CommentStream is flushed.
189   CommentStream.flush();
190
191   T.toVector(CommentToEmit);
192   // Each comment goes on its own line.
193   CommentToEmit.push_back('\n');
194
195   // Tell the comment stream that the vector changed underneath it.
196   CommentStream.resync();
197 }
198
199 void PTXMCAsmStreamer::EmitCommentsAndEOL() {
200   if (CommentToEmit.empty() && CommentStream.GetNumBytesInBuffer() == 0) {
201     OS << '\n';
202     return;
203   }
204
205   CommentStream.flush();
206   StringRef Comments = CommentToEmit.str();
207
208   assert(Comments.back() == '\n' &&
209          "Comment array not newline terminated");
210   do {
211     // Emit a line of comments.
212     OS.PadToColumn(MAI.getCommentColumn());
213     size_t Position = Comments.find('\n');
214     OS << MAI.getCommentString() << ' ' << Comments.substr(0, Position) << '\n';
215
216     Comments = Comments.substr(Position+1);
217   } while (!Comments.empty());
218
219   CommentToEmit.clear();
220   // Tell the comment stream that the vector changed underneath it.
221   CommentStream.resync();
222 }
223
224 static inline int64_t truncateToSize(int64_t Value, unsigned Bytes) {
225   assert(Bytes && "Invalid size!");
226   return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
227 }
228
229 void PTXMCAsmStreamer::SwitchSection(const MCSection *Section) {
230   assert(Section && "Cannot switch to a null section!");
231   if (Section != CurSection) {
232     PrevSection = CurSection;
233     CurSection = Section;
234   }
235 }
236
237 void PTXMCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
238   assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
239   assert(!Symbol->isVariable() && "Cannot emit a variable symbol!");
240   assert(CurSection && "Cannot emit before setting section!");
241
242   OS << *Symbol << MAI.getLabelSuffix();
243   EmitEOL();
244   Symbol->setSection(*CurSection);
245 }
246
247 void PTXMCAsmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {}
248
249 void PTXMCAsmStreamer::EmitThumbFunc(MCSymbol *Func) {}
250
251 void PTXMCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
252   OS << *Symbol << " = " << *Value;
253   EmitEOL();
254
255   // FIXME: Lift context changes into super class.
256   Symbol->setVariableValue(Value);
257 }
258
259 void PTXMCAsmStreamer::EmitWeakReference(MCSymbol *Alias,
260                                          const MCSymbol *Symbol) {
261   OS << ".weakref " << *Alias << ", " << *Symbol;
262   EmitEOL();
263 }
264
265 void PTXMCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
266                                            MCSymbolAttr Attribute) {}
267
268 void PTXMCAsmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {}
269
270 void PTXMCAsmStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) {}
271
272 void PTXMCAsmStreamer::EmitCOFFSymbolStorageClass (int StorageClass) {}
273
274 void PTXMCAsmStreamer::EmitCOFFSymbolType (int Type) {}
275
276 void PTXMCAsmStreamer::EndCOFFSymbolDef() {}
277
278 void PTXMCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {}
279
280 void PTXMCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
281                                         unsigned ByteAlignment) {}
282
283 void PTXMCAsmStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) {}
284
285 void PTXMCAsmStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
286                                     unsigned Size, unsigned ByteAlignment) {}
287
288 void PTXMCAsmStreamer::EmitTBSSSymbol(const MCSection *Section,
289                                       MCSymbol *Symbol,
290                                       uint64_t Size, unsigned ByteAlignment) {}
291
292 static inline char toOctal(int X) { return (X&7)+'0'; }
293
294 static void PrintQuotedString(StringRef Data, raw_ostream &OS) {
295   OS << '"';
296
297   for (unsigned i = 0, e = Data.size(); i != e; ++i) {
298     unsigned char C = Data[i];
299     if (C == '"' || C == '\\') {
300       OS << '\\' << (char)C;
301       continue;
302     }
303
304     if (isprint((unsigned char)C)) {
305       OS << (char)C;
306       continue;
307     }
308
309     switch (C) {
310       case '\b': OS << "\\b"; break;
311       case '\f': OS << "\\f"; break;
312       case '\n': OS << "\\n"; break;
313       case '\r': OS << "\\r"; break;
314       case '\t': OS << "\\t"; break;
315       default:
316         OS << '\\';
317         OS << toOctal(C >> 6);
318         OS << toOctal(C >> 3);
319         OS << toOctal(C >> 0);
320         break;
321     }
322   }
323
324   OS << '"';
325 }
326
327 void PTXMCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) {
328   assert(CurSection && "Cannot emit contents before setting section!");
329   if (Data.empty()) return;
330
331   if (Data.size() == 1) {
332     OS << MAI.getData8bitsDirective(AddrSpace);
333     OS << (unsigned)(unsigned char)Data[0];
334     EmitEOL();
335     return;
336   }
337
338   // If the data ends with 0 and the target supports .asciz, use it, otherwise
339   // use .ascii
340   if (MAI.getAscizDirective() && Data.back() == 0) {
341     OS << MAI.getAscizDirective();
342     Data = Data.substr(0, Data.size()-1);
343   } else {
344     OS << MAI.getAsciiDirective();
345   }
346
347   OS << ' ';
348   PrintQuotedString(Data, OS);
349   EmitEOL();
350 }
351
352 void PTXMCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size,
353                                  unsigned AddrSpace) {
354   assert(CurSection && "Cannot emit contents before setting section!");
355   const char *Directive = 0;
356   switch (Size) {
357   default: break;
358   case 1: Directive = MAI.getData8bitsDirective(AddrSpace); break;
359   case 2: Directive = MAI.getData16bitsDirective(AddrSpace); break;
360   case 4: Directive = MAI.getData32bitsDirective(AddrSpace); break;
361   case 8:
362     Directive = MAI.getData64bitsDirective(AddrSpace);
363     // If the target doesn't support 64-bit data, emit as two 32-bit halves.
364     if (Directive) break;
365     int64_t IntValue;
366     if (!Value->EvaluateAsAbsolute(IntValue))
367       report_fatal_error("Don't know how to emit this value.");
368     if (isLittleEndian()) {
369       EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace);
370       EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace);
371     } else {
372       EmitIntValue((uint32_t)(IntValue >> 32), 4, AddrSpace);
373       EmitIntValue((uint32_t)(IntValue >> 0 ), 4, AddrSpace);
374     }
375     return;
376   }
377
378   assert(Directive && "Invalid size for machine code value!");
379   OS << Directive << *Value;
380   EmitEOL();
381 }
382
383 void PTXMCAsmStreamer::EmitULEB128Value(const MCExpr *Value,
384                                         unsigned AddrSpace) {
385   assert(MAI.hasLEB128() && "Cannot print a .uleb");
386   OS << ".uleb128 " << *Value;
387   EmitEOL();
388 }
389
390 void PTXMCAsmStreamer::EmitSLEB128Value(const MCExpr *Value,
391                                         unsigned AddrSpace) {
392   assert(MAI.hasLEB128() && "Cannot print a .sleb");
393   OS << ".sleb128 " << *Value;
394   EmitEOL();
395 }
396
397 void PTXMCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
398   assert(MAI.getGPRel32Directive() != 0);
399   OS << MAI.getGPRel32Directive() << *Value;
400   EmitEOL();
401 }
402
403
404 /// EmitFill - Emit NumBytes bytes worth of the value specified by
405 /// FillValue.  This implements directives such as '.space'.
406 void PTXMCAsmStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue,
407                                 unsigned AddrSpace) {
408   if (NumBytes == 0) return;
409
410   if (AddrSpace == 0)
411     if (const char *ZeroDirective = MAI.getZeroDirective()) {
412       OS << ZeroDirective << NumBytes;
413       if (FillValue != 0)
414         OS << ',' << (int)FillValue;
415       EmitEOL();
416       return;
417     }
418
419   // Emit a byte at a time.
420   MCStreamer::EmitFill(NumBytes, FillValue, AddrSpace);
421 }
422
423 void PTXMCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
424                                             unsigned ValueSize,
425                                             unsigned MaxBytesToEmit) {
426   // Some assemblers don't support non-power of two alignments, so we always
427   // emit alignments as a power of two if possible.
428   if (isPowerOf2_32(ByteAlignment)) {
429     switch (ValueSize) {
430     default: llvm_unreachable("Invalid size for machine code value!");
431     case 1: OS << MAI.getAlignDirective(); break;
432     // FIXME: use MAI for this!
433     case 2: OS << ".p2alignw "; break;
434     case 4: OS << ".p2alignl "; break;
435     case 8: llvm_unreachable("Unsupported alignment size!");
436     }
437
438     if (MAI.getAlignmentIsInBytes())
439       OS << ByteAlignment;
440     else
441       OS << Log2_32(ByteAlignment);
442
443     if (Value || MaxBytesToEmit) {
444       OS << ", 0x";
445       OS.write_hex(truncateToSize(Value, ValueSize));
446
447       if (MaxBytesToEmit)
448         OS << ", " << MaxBytesToEmit;
449     }
450     EmitEOL();
451     return;
452   }
453
454   // Non-power of two alignment.  This is not widely supported by assemblers.
455   // FIXME: Parameterize this based on MAI.
456   switch (ValueSize) {
457   default: llvm_unreachable("Invalid size for machine code value!");
458   case 1: OS << ".balign";  break;
459   case 2: OS << ".balignw"; break;
460   case 4: OS << ".balignl"; break;
461   case 8: llvm_unreachable("Unsupported alignment size!");
462   }
463
464   OS << ' ' << ByteAlignment;
465   OS << ", " << truncateToSize(Value, ValueSize);
466   if (MaxBytesToEmit)
467     OS << ", " << MaxBytesToEmit;
468   EmitEOL();
469 }
470
471 void PTXMCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
472                                          unsigned MaxBytesToEmit) {}
473
474 void PTXMCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,
475                                          unsigned char Value) {}
476
477
478 void PTXMCAsmStreamer::EmitFileDirective(StringRef Filename) {
479   assert(MAI.hasSingleParameterDotFile());
480   OS << "\t.file\t";
481   PrintQuotedString(Filename, OS);
482   EmitEOL();
483 }
484
485 // FIXME: should we inherit from MCAsmStreamer?
486 bool PTXMCAsmStreamer::EmitDwarfFileDirective(unsigned FileNo,
487                                               StringRef Filename){
488   OS << "\t.file\t" << FileNo << ' ';
489   PrintQuotedString(Filename, OS);
490   EmitEOL();
491   return this->MCStreamer::EmitDwarfFileDirective(FileNo, Filename);
492 }
493
494 void PTXMCAsmStreamer::AddEncodingComment(const MCInst &Inst) {}
495
496 void PTXMCAsmStreamer::EmitInstruction(const MCInst &Inst) {
497   assert(CurSection && "Cannot emit contents before setting section!");
498
499   // Show the encoding in a comment if we have a code emitter.
500   if (Emitter)
501     AddEncodingComment(Inst);
502
503   // Show the MCInst if enabled.
504   if (ShowInst) {
505     Inst.dump_pretty(GetCommentOS(), &MAI, InstPrinter.get(), "\n ");
506     GetCommentOS() << "\n";
507   }
508
509   // If we have an AsmPrinter, use that to print, otherwise print the MCInst.
510   if (InstPrinter)
511     InstPrinter->printInst(&Inst, OS);
512   else
513     Inst.print(OS, &MAI);
514   EmitEOL();
515 }
516
517 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
518 /// the specified string in the output .s file.  This capability is
519 /// indicated by the hasRawTextSupport() predicate.
520 void PTXMCAsmStreamer::EmitRawText(StringRef String) {
521   if (!String.empty() && String.back() == '\n')
522     String = String.substr(0, String.size()-1);
523   OS << String;
524   EmitEOL();
525 }
526
527 void PTXMCAsmStreamer::Finish() {}
528
529 namespace llvm {
530   MCStreamer *createPTXAsmStreamer(MCContext &Context,
531                                    formatted_raw_ostream &OS,
532                                    bool isLittleEndian,
533                                    bool isVerboseAsm, MCInstPrinter *IP,
534                                    MCCodeEmitter *CE, bool ShowInst) {
535     return new PTXMCAsmStreamer(Context, OS, isLittleEndian, isVerboseAsm,
536                                 IP, CE, ShowInst);
537   }
538 }