NVPTXAsmPrinter.h revision 239462
1//===-- NVPTXAsmPrinter.h - NVPTX LLVM assembly writer --------------------===//
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// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to NVPTX assembly language.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef NVPTXASMPRINTER_H
16#define NVPTXASMPRINTER_H
17
18#include "NVPTX.h"
19#include "NVPTXTargetMachine.h"
20#include "NVPTXSubtarget.h"
21#include "llvm/Function.h"
22#include "llvm/CodeGen/AsmPrinter.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/MC/MCAsmInfo.h"
25#include "llvm/MC/MCExpr.h"
26#include "llvm/Target/TargetMachine.h"
27#include "llvm/MC/MCSymbol.h"
28#include "llvm/Support/FormattedStream.h"
29#include "llvm/Target/Mangler.h"
30#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/StringExtras.h"
32#include <fstream>
33
34// The ptx syntax and format is very different from that usually seem in a .s
35// file,
36// therefore we are not able to use the MCAsmStreamer interface here.
37//
38// We are handcrafting the output method here.
39//
40// A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer
41// (subclass of MCStreamer).
42
43// This is defined in AsmPrinter.cpp.
44// Used to process the constant expressions in initializers.
45namespace nvptx {
46const llvm::MCExpr *LowerConstant(const llvm::Constant *CV,
47                                  llvm::AsmPrinter &AP) ;
48}
49
50namespace llvm {
51
52class LineReader {
53private:
54  unsigned theCurLine ;
55  std::ifstream fstr;
56  char buff[512];
57  std::string theFileName;
58  SmallVector<unsigned, 32> lineOffset;
59public:
60  LineReader(std::string filename) {
61    theCurLine = 0;
62    fstr.open(filename.c_str());
63    theFileName = filename;
64  }
65  std::string fileName() { return theFileName; }
66  ~LineReader() {
67    fstr.close();
68  }
69  std::string readLine(unsigned line);
70};
71
72
73
74class LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter : public AsmPrinter {
75
76
77  class AggBuffer {
78    // Used to buffer the emitted string for initializing global
79    // aggregates.
80    //
81    // Normally an aggregate (array, vector or structure) is emitted
82    // as a u8[]. However, if one element/field of the aggregate
83    // is a non-NULL address, then the aggregate is emitted as u32[]
84    // or u64[].
85    //
86    // We first layout the aggregate in 'buffer' in bytes, except for
87    // those symbol addresses. For the i-th symbol address in the
88    //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer'
89    // are filled with 0s. symbolPosInBuffer[i-1] records its position
90    // in 'buffer', and Symbols[i-1] records the Value*.
91    //
92    // Once we have this AggBuffer setup, we can choose how to print
93    // it out.
94  public:
95    unsigned size;   // size of the buffer in bytes
96    unsigned char *buffer; // the buffer
97    unsigned numSymbols;   // number of symbol addresses
98    SmallVector<unsigned, 4> symbolPosInBuffer;
99    SmallVector<Value *, 4> Symbols;
100
101  private:
102    unsigned curpos;
103    raw_ostream &O;
104    NVPTXAsmPrinter &AP;
105
106  public:
107    AggBuffer(unsigned _size, raw_ostream &_O, NVPTXAsmPrinter &_AP)
108    :O(_O),AP(_AP) {
109      buffer = new unsigned char[_size];
110      size = _size;
111      curpos = 0;
112      numSymbols = 0;
113    }
114    ~AggBuffer() {
115      delete [] buffer;
116    }
117    unsigned addBytes(unsigned char *Ptr, int Num, int Bytes) {
118      assert((curpos+Num) <= size);
119      assert((curpos+Bytes) <= size);
120      for ( int i= 0; i < Num; ++i) {
121        buffer[curpos] = Ptr[i];
122        curpos ++;
123      }
124      for ( int i=Num; i < Bytes ; ++i) {
125        buffer[curpos] = 0;
126        curpos ++;
127      }
128      return curpos;
129    }
130    unsigned addZeros(int Num) {
131      assert((curpos+Num) <= size);
132      for ( int i= 0; i < Num; ++i) {
133        buffer[curpos] = 0;
134        curpos ++;
135      }
136      return curpos;
137    }
138    void addSymbol(Value *GVar) {
139      symbolPosInBuffer.push_back(curpos);
140      Symbols.push_back(GVar);
141      numSymbols++;
142    }
143    void print() {
144      if (numSymbols == 0) {
145        // print out in bytes
146        for (unsigned i=0; i<size; i++) {
147          if (i)
148            O << ", ";
149          O << (unsigned int)buffer[i];
150        }
151      } else {
152        // print out in 4-bytes or 8-bytes
153        unsigned int pos = 0;
154        unsigned int nSym = 0;
155        unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
156        unsigned int nBytes = 4;
157        if (AP.nvptxSubtarget.is64Bit())
158          nBytes = 8;
159        for (pos=0; pos<size; pos+=nBytes) {
160          if (pos)
161            O << ", ";
162          if (pos == nextSymbolPos) {
163            Value *v = Symbols[nSym];
164            if (GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
165              MCSymbol *Name = AP.Mang->getSymbol(GVar);
166              O << *Name;
167            }
168            else if (ConstantExpr *Cexpr =
169                dyn_cast<ConstantExpr>(v)) {
170              O << *nvptx::LowerConstant(Cexpr, AP);
171            } else
172              llvm_unreachable("symbol type unknown");
173            nSym++;
174            if (nSym >= numSymbols)
175              nextSymbolPos = size+1;
176            else
177              nextSymbolPos = symbolPosInBuffer[nSym];
178          } else
179            if (nBytes == 4)
180              O << *(unsigned int*)(buffer+pos);
181            else
182              O << *(unsigned long long*)(buffer+pos);
183        }
184      }
185    }
186  };
187
188  friend class AggBuffer;
189
190  virtual void emitSrcInText(StringRef filename, unsigned line);
191
192private :
193  virtual const char *getPassName() const {
194    return "NVPTX Assembly Printer";
195  }
196
197  const Function *F;
198  std::string CurrentFnName;
199
200  void EmitFunctionEntryLabel();
201  void EmitFunctionBodyStart();
202  void EmitFunctionBodyEnd();
203
204  void EmitInstruction(const MachineInstr *);
205
206  void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const {}
207
208  void printGlobalVariable(const GlobalVariable *GVar);
209  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
210                    const char *Modifier=0);
211  void printLdStCode(const MachineInstr *MI, int opNum, raw_ostream &O,
212                     const char *Modifier=0);
213  void printVecModifiedImmediate(const MachineOperand &MO,
214                                 const char *Modifier, raw_ostream &O);
215  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
216                       const char *Modifier=0);
217  void printImplicitDef(const MachineInstr *MI, raw_ostream &O) const;
218  // definition autogenerated.
219  void printInstruction(const MachineInstr *MI, raw_ostream &O);
220  void printModuleLevelGV(GlobalVariable* GVar, raw_ostream &O,
221                          bool=false);
222  void printParamName(int paramIndex, raw_ostream &O);
223  void printParamName(Function::const_arg_iterator I, int paramIndex,
224                      raw_ostream &O);
225  void emitHeader(Module &M, raw_ostream &O);
226  void emitKernelFunctionDirectives(const Function& F,
227                                    raw_ostream &O) const;
228  void emitVirtualRegister(unsigned int vr, bool isVec, raw_ostream &O);
229  void emitFunctionExternParamList(const MachineFunction &MF);
230  void emitFunctionParamList(const Function *, raw_ostream &O);
231  void emitFunctionParamList(const MachineFunction &MF, raw_ostream &O);
232  void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
233  void emitFunctionTempData(const MachineFunction &MF,
234                            unsigned &FrameSize);
235  bool isImageType(const Type *Ty);
236  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
237                       unsigned AsmVariant, const char *ExtraCode,
238                       raw_ostream &);
239  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
240                             unsigned AsmVariant, const char *ExtraCode,
241                             raw_ostream &);
242  void printReturnValStr(const Function *, raw_ostream &O);
243  void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
244
245protected:
246  bool doInitialization(Module &M);
247  bool doFinalization(Module &M);
248
249private:
250  std::string CurrentBankselLabelInBasicBlock;
251
252  // This is specific per MachineFunction.
253  const MachineRegisterInfo *MRI;
254  // The contents are specific for each
255  // MachineFunction. But the size of the
256  // array is not.
257  std::map<unsigned, unsigned> *VRidGlobal2LocalMap;
258  // cache the subtarget here.
259  const NVPTXSubtarget &nvptxSubtarget;
260  // Build the map between type name and ID based on module's type
261  // symbol table.
262  std::map<const Type *, std::string> TypeNameMap;
263
264  // List of variables demoted to a function scope.
265  std::map<const Function *, std::vector<GlobalVariable *> > localDecls;
266
267  // To record filename to ID mapping
268  std::map<std::string, unsigned> filenameMap;
269  void recordAndEmitFilenames(Module &);
270
271  void emitPTXGlobalVariable(const GlobalVariable *GVar, raw_ostream &O);
272  void emitPTXAddressSpace(unsigned int AddressSpace,
273                           raw_ostream &O) const;
274  std::string getPTXFundamentalTypeStr(const Type *Ty, bool=true) const ;
275  void printScalarConstant(Constant *CPV, raw_ostream &O) ;
276  void printFPConstant(const ConstantFP *Fp, raw_ostream &O) ;
277  void bufferLEByte(Constant *CPV, int Bytes, AggBuffer *aggBuffer) ;
278  void bufferAggregateConstant(Constant *CV, AggBuffer *aggBuffer) ;
279
280  void printOperandProper(const MachineOperand &MO);
281
282  void emitLinkageDirective(const GlobalValue* V, raw_ostream &O);
283  void emitDeclarations(Module &, raw_ostream &O);
284  void emitDeclaration(const Function *, raw_ostream &O);
285
286  static const char *getRegisterName(unsigned RegNo);
287  void emitDemotedVars(const Function *, raw_ostream &);
288
289  LineReader *reader;
290  LineReader *getReader(std::string);
291public:
292  NVPTXAsmPrinter(TargetMachine &TM,
293                  MCStreamer &Streamer)
294  : AsmPrinter(TM, Streamer),
295    nvptxSubtarget(TM.getSubtarget<NVPTXSubtarget>()) {
296    CurrentBankselLabelInBasicBlock = "";
297    VRidGlobal2LocalMap = NULL;
298    reader = NULL;
299  }
300
301  ~NVPTXAsmPrinter() {
302    if (!reader)
303      delete reader;
304  }
305
306  bool ignoreLoc(const MachineInstr &);
307
308  virtual void getVirtualRegisterName(unsigned, bool, raw_ostream &);
309
310  DebugLoc prevDebugLoc;
311  void emitLineNumberAsDotLoc(const MachineInstr &);
312};
313} // end of namespace
314
315#endif
316