LLVM  6.0.0svn
NVPTXAsmPrinter.h
Go to the documentation of this file.
1 //===-- NVPTXAsmPrinter.h - NVPTX LLVM assembly writer ----------*- C++ -*-===//
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 LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
16 #define LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
17 
18 #include "NVPTX.h"
19 #include "NVPTXSubtarget.h"
20 #include "NVPTXTargetMachine.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringRef.h"
27 #include "llvm/IR/Constants.h"
28 #include "llvm/IR/DebugLoc.h"
29 #include "llvm/IR/DerivedTypes.h"
30 #include "llvm/IR/Function.h"
31 #include "llvm/IR/GlobalValue.h"
32 #include "llvm/IR/Value.h"
33 #include "llvm/MC/MCExpr.h"
34 #include "llvm/MC/MCStreamer.h"
35 #include "llvm/MC/MCSymbol.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/Compiler.h"
42 #include <algorithm>
43 #include <cassert>
44 #include <fstream>
45 #include <map>
46 #include <memory>
47 #include <string>
48 #include <vector>
49 
50 // The ptx syntax and format is very different from that usually seem in a .s
51 // file,
52 // therefore we are not able to use the MCAsmStreamer interface here.
53 //
54 // We are handcrafting the output method here.
55 //
56 // A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer
57 // (subclass of MCStreamer).
58 
59 namespace llvm {
60 
61 class MCOperand;
62 
63 class LineReader {
64 private:
65  unsigned theCurLine;
66  std::ifstream fstr;
67  char buff[512];
68  std::string theFileName;
69  SmallVector<unsigned, 32> lineOffset;
70 
71 public:
72  LineReader(std::string filename) {
73  theCurLine = 0;
74  fstr.open(filename.c_str());
75  theFileName = filename;
76  }
77 
78  ~LineReader() { fstr.close(); }
79 
80  std::string fileName() { return theFileName; }
81  std::string readLine(unsigned line);
82 };
83 
85 
86  class AggBuffer {
87  // Used to buffer the emitted string for initializing global
88  // aggregates.
89  //
90  // Normally an aggregate (array, vector or structure) is emitted
91  // as a u8[]. However, if one element/field of the aggregate
92  // is a non-NULL address, then the aggregate is emitted as u32[]
93  // or u64[].
94  //
95  // We first layout the aggregate in 'buffer' in bytes, except for
96  // those symbol addresses. For the i-th symbol address in the
97  //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer'
98  // are filled with 0s. symbolPosInBuffer[i-1] records its position
99  // in 'buffer', and Symbols[i-1] records the Value*.
100  //
101  // Once we have this AggBuffer setup, we can choose how to print
102  // it out.
103  public:
104  unsigned numSymbols; // number of symbol addresses
105 
106  private:
107  const unsigned size; // size of the buffer in bytes
108  std::vector<unsigned char> buffer; // the buffer
109  SmallVector<unsigned, 4> symbolPosInBuffer;
111  // SymbolsBeforeStripping[i] is the original form of Symbols[i] before
112  // stripping pointer casts, i.e.,
113  // Symbols[i] == SymbolsBeforeStripping[i]->stripPointerCasts().
114  //
115  // We need to keep these values because AggBuffer::print decides whether to
116  // emit a "generic()" cast for Symbols[i] depending on the address space of
117  // SymbolsBeforeStripping[i].
118  SmallVector<const Value *, 4> SymbolsBeforeStripping;
119  unsigned curpos;
120  raw_ostream &O;
121  NVPTXAsmPrinter &AP;
122  bool EmitGeneric;
123 
124  public:
125  AggBuffer(unsigned size, raw_ostream &O, NVPTXAsmPrinter &AP)
126  : size(size), buffer(size), O(O), AP(AP) {
127  curpos = 0;
128  numSymbols = 0;
129  EmitGeneric = AP.EmitGeneric;
130  }
131 
132  unsigned addBytes(unsigned char *Ptr, int Num, int Bytes) {
133  assert((curpos + Num) <= size);
134  assert((curpos + Bytes) <= size);
135  for (int i = 0; i < Num; ++i) {
136  buffer[curpos] = Ptr[i];
137  curpos++;
138  }
139  for (int i = Num; i < Bytes; ++i) {
140  buffer[curpos] = 0;
141  curpos++;
142  }
143  return curpos;
144  }
145 
146  unsigned addZeros(int Num) {
147  assert((curpos + Num) <= size);
148  for (int i = 0; i < Num; ++i) {
149  buffer[curpos] = 0;
150  curpos++;
151  }
152  return curpos;
153  }
154 
155  void addSymbol(const Value *GVar, const Value *GVarBeforeStripping) {
156  symbolPosInBuffer.push_back(curpos);
157  Symbols.push_back(GVar);
158  SymbolsBeforeStripping.push_back(GVarBeforeStripping);
159  numSymbols++;
160  }
161 
162  void print() {
163  if (numSymbols == 0) {
164  // print out in bytes
165  for (unsigned i = 0; i < size; i++) {
166  if (i)
167  O << ", ";
168  O << (unsigned int) buffer[i];
169  }
170  } else {
171  // print out in 4-bytes or 8-bytes
172  unsigned int pos = 0;
173  unsigned int nSym = 0;
174  unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
175  unsigned int nBytes = 4;
176  if (static_cast<const NVPTXTargetMachine &>(AP.TM).is64Bit())
177  nBytes = 8;
178  for (pos = 0; pos < size; pos += nBytes) {
179  if (pos)
180  O << ", ";
181  if (pos == nextSymbolPos) {
182  const Value *v = Symbols[nSym];
183  const Value *v0 = SymbolsBeforeStripping[nSym];
184  if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
185  MCSymbol *Name = AP.getSymbol(GVar);
186  PointerType *PTy = dyn_cast<PointerType>(v0->getType());
187  bool IsNonGenericPointer = false; // Is v0 a non-generic pointer?
188  if (PTy && PTy->getAddressSpace() != 0) {
189  IsNonGenericPointer = true;
190  }
191  if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
192  O << "generic(";
193  Name->print(O, AP.MAI);
194  O << ")";
195  } else {
196  Name->print(O, AP.MAI);
197  }
198  } else if (const ConstantExpr *CExpr = dyn_cast<ConstantExpr>(v0)) {
199  const MCExpr *Expr =
200  AP.lowerConstantForGV(cast<Constant>(CExpr), false);
201  AP.printMCExpr(*Expr, O);
202  } else
203  llvm_unreachable("symbol type unknown");
204  nSym++;
205  if (nSym >= numSymbols)
206  nextSymbolPos = size + 1;
207  else
208  nextSymbolPos = symbolPosInBuffer[nSym];
209  } else if (nBytes == 4)
210  O << *(unsigned int *)(&buffer[pos]);
211  else
212  O << *(unsigned long long *)(&buffer[pos]);
213  }
214  }
215  }
216  };
217 
218  friend class AggBuffer;
219 
220  void emitSrcInText(StringRef filename, unsigned line);
221 
222 private:
223  StringRef getPassName() const override { return "NVPTX Assembly Printer"; }
224 
225  const Function *F;
226  std::string CurrentFnName;
227 
228  void EmitBasicBlockStart(const MachineBasicBlock &MBB) const override;
229  void EmitFunctionEntryLabel() override;
230  void EmitFunctionBodyStart() override;
231  void EmitFunctionBodyEnd() override;
232  void emitImplicitDef(const MachineInstr *MI) const override;
233 
234  void EmitInstruction(const MachineInstr *) override;
235  void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
236  bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
238  unsigned encodeVirtualRegister(unsigned Reg);
239 
240  void printVecModifiedImmediate(const MachineOperand &MO, const char *Modifier,
241  raw_ostream &O);
242  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
243  const char *Modifier = nullptr);
244  void printModuleLevelGV(const GlobalVariable *GVar, raw_ostream &O,
245  bool = false);
246  void printParamName(Function::const_arg_iterator I, int paramIndex,
247  raw_ostream &O);
248  void emitGlobals(const Module &M);
249  void emitHeader(Module &M, raw_ostream &O, const NVPTXSubtarget &STI);
250  void emitKernelFunctionDirectives(const Function &F, raw_ostream &O) const;
251  void emitVirtualRegister(unsigned int vr, raw_ostream &);
252  void emitFunctionParamList(const Function *, raw_ostream &O);
253  void emitFunctionParamList(const MachineFunction &MF, raw_ostream &O);
254  void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
255  void printReturnValStr(const Function *, raw_ostream &O);
256  void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
257  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
258  unsigned AsmVariant, const char *ExtraCode,
259  raw_ostream &) override;
260  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
261  const char *Modifier = nullptr);
262  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
263  unsigned AsmVariant, const char *ExtraCode,
264  raw_ostream &) override;
265 
266  const MCExpr *lowerConstantForGV(const Constant *CV, bool ProcessingGeneric);
267  void printMCExpr(const MCExpr &Expr, raw_ostream &OS);
268 
269 protected:
270  bool doInitialization(Module &M) override;
271  bool doFinalization(Module &M) override;
272 
273 private:
274  std::string CurrentBankselLabelInBasicBlock;
275 
276  bool GlobalsEmitted;
277 
278  // This is specific per MachineFunction.
279  const MachineRegisterInfo *MRI;
280  // The contents are specific for each
281  // MachineFunction. But the size of the
282  // array is not.
285  VRegRCMap VRegMapping;
286 
287  // Cache the subtarget here.
288  const NVPTXSubtarget *nvptxSubtarget;
289 
290  // Build the map between type name and ID based on module's type
291  // symbol table.
292  std::map<Type *, std::string> TypeNameMap;
293 
294  // List of variables demoted to a function scope.
295  std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
296 
297  // To record filename to ID mapping
298  std::map<std::string, unsigned> filenameMap;
299  void recordAndEmitFilenames(Module &);
300 
301  void emitPTXGlobalVariable(const GlobalVariable *GVar, raw_ostream &O);
302  void emitPTXAddressSpace(unsigned int AddressSpace, raw_ostream &O) const;
303  std::string getPTXFundamentalTypeStr(Type *Ty, bool = true) const;
304  void printScalarConstant(const Constant *CPV, raw_ostream &O);
305  void printFPConstant(const ConstantFP *Fp, raw_ostream &O);
306  void bufferLEByte(const Constant *CPV, int Bytes, AggBuffer *aggBuffer);
307  void bufferAggregateConstant(const Constant *CV, AggBuffer *aggBuffer);
308 
309  void emitLinkageDirective(const GlobalValue *V, raw_ostream &O);
310  void emitDeclarations(const Module &, raw_ostream &O);
311  void emitDeclaration(const Function *, raw_ostream &O);
312  void emitDemotedVars(const Function *, raw_ostream &);
313 
314  bool lowerImageHandleOperand(const MachineInstr *MI, unsigned OpNo,
315  MCOperand &MCOp);
316  void lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp);
317 
318  bool isLoopHeaderOfNoUnroll(const MachineBasicBlock &MBB) const;
319 
320  LineReader *reader = nullptr;
321 
322  LineReader *getReader(const std::string &);
323 
324  // Used to control the need to emit .generic() in the initializer of
325  // module scope variables.
326  // Although ptx supports the hybrid mode like the following,
327  // .global .u32 a;
328  // .global .u32 b;
329  // .global .u32 addr[] = {a, generic(b)}
330  // we have difficulty representing the difference in the NVVM IR.
331  //
332  // Since the address value should always be generic in CUDA C and always
333  // be specific in OpenCL, we use this simple control here.
334  //
335  bool EmitGeneric;
336 
337 public:
338  NVPTXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
339  : AsmPrinter(TM, std::move(Streamer)),
340  EmitGeneric(static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() ==
341  NVPTX::CUDA) {}
342 
343  ~NVPTXAsmPrinter() override {
344  delete reader;
345  }
346 
348  nvptxSubtarget = &F.getSubtarget<NVPTXSubtarget>();
350  }
351 
352  void getAnalysisUsage(AnalysisUsage &AU) const override {
355  }
356 
357  bool ignoreLoc(const MachineInstr &);
358 
359  std::string getVirtualRegisterName(unsigned) const;
360 
362  void emitLineNumberAsDotLoc(const MachineInstr &);
363 };
364 
365 } // end namespace llvm
366 
367 #endif // LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
void push_back(const T &Elt)
Definition: SmallVector.h:212
This class represents an incoming formal argument to a Function.
Definition: Argument.h:30
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:63
A debug info location.
Definition: DebugLoc.h:34
F(f)
std::string readLine(unsigned line)
AnalysisUsage & addRequired()
Definition: BitVector.h:920
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Reg
All possible values of the reg field in the ModR/M byte.
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
Definition: AsmPrinter.cpp:231
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:862
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition: AsmPrinter.h:277
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:159
Class to represent pointers.
Definition: DerivedTypes.h:467
LineReader(std::string filename)
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
unsigned const MachineRegisterInfo * MRI
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:83
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This is an important base class in LLVM.
Definition: Constant.h:42
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol, HexagonAsmPrinter &Printer, bool MustExtend)
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:264
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:80
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:77
Represent the analysis usage information of a pass.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:495
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library...
Definition: Compiler.h:105
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
NVPTXAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:433
MachineOperand class - Representation of each machine instruction operand.
AddressSpace
Definition: NVPTXBaseInfo.h:22
bool runOnMachineFunction(MachineFunction &F) override
Emit the specified function out to the OutStreamer.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:59
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
NVPTXTargetMachine.
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:575
#define I(x, y, z)
Definition: MD5.cpp:58
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:57
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
std::string fileName()
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:59