LLVM  8.0.1
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 <map>
45 #include <memory>
46 #include <string>
47 #include <vector>
48 
49 // The ptx syntax and format is very different from that usually seem in a .s
50 // file,
51 // therefore we are not able to use the MCAsmStreamer interface here.
52 //
53 // We are handcrafting the output method here.
54 //
55 // A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer
56 // (subclass of MCStreamer).
57 
58 namespace llvm {
59 
60 class MCOperand;
61 
63 
64  class AggBuffer {
65  // Used to buffer the emitted string for initializing global
66  // aggregates.
67  //
68  // Normally an aggregate (array, vector or structure) is emitted
69  // as a u8[]. However, if one element/field of the aggregate
70  // is a non-NULL address, then the aggregate is emitted as u32[]
71  // or u64[].
72  //
73  // We first layout the aggregate in 'buffer' in bytes, except for
74  // those symbol addresses. For the i-th symbol address in the
75  //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer'
76  // are filled with 0s. symbolPosInBuffer[i-1] records its position
77  // in 'buffer', and Symbols[i-1] records the Value*.
78  //
79  // Once we have this AggBuffer setup, we can choose how to print
80  // it out.
81  public:
82  unsigned numSymbols; // number of symbol addresses
83 
84  private:
85  const unsigned size; // size of the buffer in bytes
86  std::vector<unsigned char> buffer; // the buffer
87  SmallVector<unsigned, 4> symbolPosInBuffer;
89  // SymbolsBeforeStripping[i] is the original form of Symbols[i] before
90  // stripping pointer casts, i.e.,
91  // Symbols[i] == SymbolsBeforeStripping[i]->stripPointerCasts().
92  //
93  // We need to keep these values because AggBuffer::print decides whether to
94  // emit a "generic()" cast for Symbols[i] depending on the address space of
95  // SymbolsBeforeStripping[i].
96  SmallVector<const Value *, 4> SymbolsBeforeStripping;
97  unsigned curpos;
98  raw_ostream &O;
99  NVPTXAsmPrinter &AP;
100  bool EmitGeneric;
101 
102  public:
103  AggBuffer(unsigned size, raw_ostream &O, NVPTXAsmPrinter &AP)
104  : size(size), buffer(size), O(O), AP(AP) {
105  curpos = 0;
106  numSymbols = 0;
107  EmitGeneric = AP.EmitGeneric;
108  }
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 
124  unsigned addZeros(int Num) {
125  assert((curpos + Num) <= size);
126  for (int i = 0; i < Num; ++i) {
127  buffer[curpos] = 0;
128  curpos++;
129  }
130  return curpos;
131  }
132 
133  void addSymbol(const Value *GVar, const Value *GVarBeforeStripping) {
134  symbolPosInBuffer.push_back(curpos);
135  Symbols.push_back(GVar);
136  SymbolsBeforeStripping.push_back(GVarBeforeStripping);
137  numSymbols++;
138  }
139 
140  void print() {
141  if (numSymbols == 0) {
142  // print out in bytes
143  for (unsigned i = 0; i < size; i++) {
144  if (i)
145  O << ", ";
146  O << (unsigned int) buffer[i];
147  }
148  } else {
149  // print out in 4-bytes or 8-bytes
150  unsigned int pos = 0;
151  unsigned int nSym = 0;
152  unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
153  unsigned int nBytes = 4;
154  if (static_cast<const NVPTXTargetMachine &>(AP.TM).is64Bit())
155  nBytes = 8;
156  for (pos = 0; pos < size; pos += nBytes) {
157  if (pos)
158  O << ", ";
159  if (pos == nextSymbolPos) {
160  const Value *v = Symbols[nSym];
161  const Value *v0 = SymbolsBeforeStripping[nSym];
162  if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
163  MCSymbol *Name = AP.getSymbol(GVar);
164  PointerType *PTy = dyn_cast<PointerType>(v0->getType());
165  bool IsNonGenericPointer = false; // Is v0 a non-generic pointer?
166  if (PTy && PTy->getAddressSpace() != 0) {
167  IsNonGenericPointer = true;
168  }
169  if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
170  O << "generic(";
171  Name->print(O, AP.MAI);
172  O << ")";
173  } else {
174  Name->print(O, AP.MAI);
175  }
176  } else if (const ConstantExpr *CExpr = dyn_cast<ConstantExpr>(v0)) {
177  const MCExpr *Expr =
178  AP.lowerConstantForGV(cast<Constant>(CExpr), false);
179  AP.printMCExpr(*Expr, O);
180  } else
181  llvm_unreachable("symbol type unknown");
182  nSym++;
183  if (nSym >= numSymbols)
184  nextSymbolPos = size + 1;
185  else
186  nextSymbolPos = symbolPosInBuffer[nSym];
187  } else if (nBytes == 4)
188  O << *(unsigned int *)(&buffer[pos]);
189  else
190  O << *(unsigned long long *)(&buffer[pos]);
191  }
192  }
193  }
194  };
195 
196  friend class AggBuffer;
197 
198 private:
199  StringRef getPassName() const override { return "NVPTX Assembly Printer"; }
200 
201  const Function *F;
202  std::string CurrentFnName;
203 
204  void EmitBasicBlockStart(const MachineBasicBlock &MBB) const override;
205  void EmitFunctionEntryLabel() override;
206  void EmitFunctionBodyStart() override;
207  void EmitFunctionBodyEnd() override;
208  void emitImplicitDef(const MachineInstr *MI) const override;
209 
210  void EmitInstruction(const MachineInstr *) override;
211  void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
212  bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
214  unsigned encodeVirtualRegister(unsigned Reg);
215 
216  void printVecModifiedImmediate(const MachineOperand &MO, const char *Modifier,
217  raw_ostream &O);
218  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
219  const char *Modifier = nullptr);
220  void printModuleLevelGV(const GlobalVariable *GVar, raw_ostream &O,
221  bool = false);
222  void printParamName(Function::const_arg_iterator I, int paramIndex,
223  raw_ostream &O);
224  void emitGlobals(const Module &M);
225  void emitHeader(Module &M, raw_ostream &O, const NVPTXSubtarget &STI);
226  void emitKernelFunctionDirectives(const Function &F, raw_ostream &O) const;
227  void emitVirtualRegister(unsigned int vr, raw_ostream &);
228  void emitFunctionParamList(const Function *, raw_ostream &O);
229  void emitFunctionParamList(const MachineFunction &MF, raw_ostream &O);
230  void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
231  void printReturnValStr(const Function *, raw_ostream &O);
232  void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
233  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
234  unsigned AsmVariant, const char *ExtraCode,
235  raw_ostream &) override;
236  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
237  const char *Modifier = nullptr);
238  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
239  unsigned AsmVariant, const char *ExtraCode,
240  raw_ostream &) override;
241 
242  const MCExpr *lowerConstantForGV(const Constant *CV, bool ProcessingGeneric);
243  void printMCExpr(const MCExpr &Expr, raw_ostream &OS);
244 
245 protected:
246  bool doInitialization(Module &M) override;
247  bool doFinalization(Module &M) override;
248 
249 private:
250  bool GlobalsEmitted;
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.
259  VRegRCMap VRegMapping;
260 
261  // List of variables demoted to a function scope.
262  std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
263 
264  void emitPTXGlobalVariable(const GlobalVariable *GVar, raw_ostream &O);
265  void emitPTXAddressSpace(unsigned int AddressSpace, raw_ostream &O) const;
266  std::string getPTXFundamentalTypeStr(Type *Ty, bool = true) const;
267  void printScalarConstant(const Constant *CPV, raw_ostream &O);
268  void printFPConstant(const ConstantFP *Fp, raw_ostream &O);
269  void bufferLEByte(const Constant *CPV, int Bytes, AggBuffer *aggBuffer);
270  void bufferAggregateConstant(const Constant *CV, AggBuffer *aggBuffer);
271 
272  void emitLinkageDirective(const GlobalValue *V, raw_ostream &O);
273  void emitDeclarations(const Module &, raw_ostream &O);
274  void emitDeclaration(const Function *, raw_ostream &O);
275  void emitDemotedVars(const Function *, raw_ostream &);
276 
277  bool lowerImageHandleOperand(const MachineInstr *MI, unsigned OpNo,
278  MCOperand &MCOp);
279  void lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp);
280 
281  bool isLoopHeaderOfNoUnroll(const MachineBasicBlock &MBB) const;
282 
283  // Used to control the need to emit .generic() in the initializer of
284  // module scope variables.
285  // Although ptx supports the hybrid mode like the following,
286  // .global .u32 a;
287  // .global .u32 b;
288  // .global .u32 addr[] = {a, generic(b)}
289  // we have difficulty representing the difference in the NVVM IR.
290  //
291  // Since the address value should always be generic in CUDA C and always
292  // be specific in OpenCL, we use this simple control here.
293  //
294  bool EmitGeneric;
295 
296 public:
297  NVPTXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
298  : AsmPrinter(TM, std::move(Streamer)),
299  EmitGeneric(static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() ==
300  NVPTX::CUDA) {}
301 
302  bool runOnMachineFunction(MachineFunction &F) override;
303 
304  void getAnalysisUsage(AnalysisUsage &AU) const override {
307  }
308 
309  std::string getVirtualRegisterName(unsigned) const;
310 
311  const MCSymbol *getFunctionFrameSymbol() const override;
312 };
313 
314 } // end namespace llvm
315 
316 #endif // LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
This class represents an incoming formal argument to a Function.
Definition: Argument.h:30
This class represents lattice values for constants.
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:65
void push_back(const T &Elt)
Definition: SmallVector.h:218
unsigned Reg
F(f)
AnalysisUsage & addRequired()
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Definition: BitVector.h:938
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
Definition: AsmPrinter.cpp:240
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:889
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
Class to represent pointers.
Definition: DerivedTypes.h:467
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
unsigned const MachineRegisterInfo * MRI
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:85
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:82
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:79
Represent the analysis usage information of a pass.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:495
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.
static void printMemOperand(raw_ostream &OS, const MachineMemOperand &MMO, const MachineFunction *MF, const Module *M, const MachineFrameInfo *MFI, const TargetInstrInfo *TII, LLVMContext &Ctx)
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
Definition: STLExtras.h:1167
static void printMCExpr(const MCExpr *E, raw_ostream &OS)
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:430
MachineOperand class - Representation of each machine instruction operand.
AddressSpace
Definition: NVPTXBaseInfo.h:22
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:64
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
NVPTXTargetMachine.
#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
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library...
Definition: Compiler.h:108
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:46
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:59
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
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:60