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