LLVM  9.0.0svn
NVPTXAsmPrinter.h
Go to the documentation of this file.
1 //===-- NVPTXAsmPrinter.h - NVPTX LLVM assembly writer ----------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to NVPTX assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
15 #define LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
16 
17 #include "NVPTX.h"
18 #include "NVPTXSubtarget.h"
19 #include "NVPTXTargetMachine.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DebugLoc.h"
28 #include "llvm/IR/DerivedTypes.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/GlobalValue.h"
31 #include "llvm/IR/Value.h"
32 #include "llvm/MC/MCExpr.h"
33 #include "llvm/MC/MCStreamer.h"
34 #include "llvm/MC/MCSymbol.h"
36 #include "llvm/Support/Casting.h"
37 #include "llvm/Support/Compiler.h"
41 #include <algorithm>
42 #include <cassert>
43 #include <map>
44 #include <memory>
45 #include <string>
46 #include <vector>
47 
48 // The ptx syntax and format is very different from that usually seem in a .s
49 // file,
50 // therefore we are not able to use the MCAsmStreamer interface here.
51 //
52 // We are handcrafting the output method here.
53 //
54 // A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer
55 // (subclass of MCStreamer).
56 
57 namespace llvm {
58 
59 class MCOperand;
60 
62 
63  class AggBuffer {
64  // Used to buffer the emitted string for initializing global
65  // aggregates.
66  //
67  // Normally an aggregate (array, vector or structure) is emitted
68  // as a u8[]. However, if one element/field of the aggregate
69  // is a non-NULL address, then the aggregate is emitted as u32[]
70  // or u64[].
71  //
72  // We first layout the aggregate in 'buffer' in bytes, except for
73  // those symbol addresses. For the i-th symbol address in the
74  //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer'
75  // are filled with 0s. symbolPosInBuffer[i-1] records its position
76  // in 'buffer', and Symbols[i-1] records the Value*.
77  //
78  // Once we have this AggBuffer setup, we can choose how to print
79  // it out.
80  public:
81  unsigned numSymbols; // number of symbol addresses
82 
83  private:
84  const unsigned size; // size of the buffer in bytes
85  std::vector<unsigned char> buffer; // the buffer
86  SmallVector<unsigned, 4> symbolPosInBuffer;
88  // SymbolsBeforeStripping[i] is the original form of Symbols[i] before
89  // stripping pointer casts, i.e.,
90  // Symbols[i] == SymbolsBeforeStripping[i]->stripPointerCasts().
91  //
92  // We need to keep these values because AggBuffer::print decides whether to
93  // emit a "generic()" cast for Symbols[i] depending on the address space of
94  // SymbolsBeforeStripping[i].
95  SmallVector<const Value *, 4> SymbolsBeforeStripping;
96  unsigned curpos;
97  raw_ostream &O;
98  NVPTXAsmPrinter &AP;
99  bool EmitGeneric;
100 
101  public:
102  AggBuffer(unsigned size, raw_ostream &O, NVPTXAsmPrinter &AP)
103  : size(size), buffer(size), O(O), AP(AP) {
104  curpos = 0;
105  numSymbols = 0;
106  EmitGeneric = AP.EmitGeneric;
107  }
108 
109  unsigned addBytes(unsigned char *Ptr, int Num, int Bytes) {
110  assert((curpos + Num) <= size);
111  assert((curpos + Bytes) <= size);
112  for (int i = 0; i < Num; ++i) {
113  buffer[curpos] = Ptr[i];
114  curpos++;
115  }
116  for (int i = Num; i < Bytes; ++i) {
117  buffer[curpos] = 0;
118  curpos++;
119  }
120  return curpos;
121  }
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 
132  void addSymbol(const Value *GVar, const Value *GVarBeforeStripping) {
133  symbolPosInBuffer.push_back(curpos);
134  Symbols.push_back(GVar);
135  SymbolsBeforeStripping.push_back(GVarBeforeStripping);
136  numSymbols++;
137  }
138 
139  void print() {
140  if (numSymbols == 0) {
141  // print out in bytes
142  for (unsigned i = 0; i < size; i++) {
143  if (i)
144  O << ", ";
145  O << (unsigned int) buffer[i];
146  }
147  } else {
148  // print out in 4-bytes or 8-bytes
149  unsigned int pos = 0;
150  unsigned int nSym = 0;
151  unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
152  unsigned int nBytes = 4;
153  if (static_cast<const NVPTXTargetMachine &>(AP.TM).is64Bit())
154  nBytes = 8;
155  for (pos = 0; pos < size; pos += nBytes) {
156  if (pos)
157  O << ", ";
158  if (pos == nextSymbolPos) {
159  const Value *v = Symbols[nSym];
160  const Value *v0 = SymbolsBeforeStripping[nSym];
161  if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
162  MCSymbol *Name = AP.getSymbol(GVar);
163  PointerType *PTy = dyn_cast<PointerType>(v0->getType());
164  bool IsNonGenericPointer = false; // Is v0 a non-generic pointer?
165  if (PTy && PTy->getAddressSpace() != 0) {
166  IsNonGenericPointer = true;
167  }
168  if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
169  O << "generic(";
170  Name->print(O, AP.MAI);
171  O << ")";
172  } else {
173  Name->print(O, AP.MAI);
174  }
175  } else if (const ConstantExpr *CExpr = dyn_cast<ConstantExpr>(v0)) {
176  const MCExpr *Expr =
177  AP.lowerConstantForGV(cast<Constant>(CExpr), false);
178  AP.printMCExpr(*Expr, O);
179  } else
180  llvm_unreachable("symbol type unknown");
181  nSym++;
182  if (nSym >= numSymbols)
183  nextSymbolPos = size + 1;
184  else
185  nextSymbolPos = symbolPosInBuffer[nSym];
186  } else if (nBytes == 4)
187  O << *(unsigned int *)(&buffer[pos]);
188  else
189  O << *(unsigned long long *)(&buffer[pos]);
190  }
191  }
192  }
193  };
194 
195  friend class AggBuffer;
196 
197 private:
198  StringRef 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 printVecModifiedImmediate(const MachineOperand &MO, const char *Modifier,
216  raw_ostream &O);
217  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
218  const char *Modifier = nullptr);
219  void printModuleLevelGV(const GlobalVariable *GVar, raw_ostream &O,
220  bool = false);
221  void printParamName(Function::const_arg_iterator I, int paramIndex,
222  raw_ostream &O);
223  void emitGlobals(const Module &M);
224  void emitHeader(Module &M, raw_ostream &O, const NVPTXSubtarget &STI);
225  void emitKernelFunctionDirectives(const Function &F, raw_ostream &O) const;
226  void emitVirtualRegister(unsigned int vr, raw_ostream &);
227  void emitFunctionParamList(const Function *, raw_ostream &O);
228  void emitFunctionParamList(const MachineFunction &MF, raw_ostream &O);
229  void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
230  void printReturnValStr(const Function *, raw_ostream &O);
231  void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
232  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
233  unsigned AsmVariant, const char *ExtraCode,
234  raw_ostream &) override;
235  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
236  const char *Modifier = nullptr);
237  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
238  unsigned AsmVariant, const char *ExtraCode,
239  raw_ostream &) override;
240 
241  const MCExpr *lowerConstantForGV(const Constant *CV, bool ProcessingGeneric);
242  void printMCExpr(const MCExpr &Expr, raw_ostream &OS);
243 
244 protected:
245  bool doInitialization(Module &M) override;
246  bool doFinalization(Module &M) override;
247 
248 private:
249  bool GlobalsEmitted;
250 
251  // This is specific per MachineFunction.
252  const MachineRegisterInfo *MRI;
253  // The contents are specific for each
254  // MachineFunction. But the size of the
255  // array is not.
258  VRegRCMap VRegMapping;
259 
260  // List of variables demoted to a function scope.
261  std::map<const Function *, std::vector<const GlobalVariable *>> localDecls;
262 
263  void emitPTXGlobalVariable(const GlobalVariable *GVar, raw_ostream &O);
264  void emitPTXAddressSpace(unsigned int AddressSpace, raw_ostream &O) const;
265  std::string getPTXFundamentalTypeStr(Type *Ty, bool = true) const;
266  void printScalarConstant(const Constant *CPV, raw_ostream &O);
267  void printFPConstant(const ConstantFP *Fp, raw_ostream &O);
268  void bufferLEByte(const Constant *CPV, int Bytes, AggBuffer *aggBuffer);
269  void bufferAggregateConstant(const Constant *CV, AggBuffer *aggBuffer);
270 
271  void emitLinkageDirective(const GlobalValue *V, raw_ostream &O);
272  void emitDeclarations(const Module &, raw_ostream &O);
273  void emitDeclaration(const Function *, raw_ostream &O);
274  void emitDemotedVars(const Function *, raw_ostream &);
275 
276  bool lowerImageHandleOperand(const MachineInstr *MI, unsigned OpNo,
277  MCOperand &MCOp);
278  void lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp);
279 
280  bool isLoopHeaderOfNoUnroll(const MachineBasicBlock &MBB) const;
281 
282  // Used to control the need to emit .generic() in the initializer of
283  // module scope variables.
284  // Although ptx supports the hybrid mode like the following,
285  // .global .u32 a;
286  // .global .u32 b;
287  // .global .u32 addr[] = {a, generic(b)}
288  // we have difficulty representing the difference in the NVVM IR.
289  //
290  // Since the address value should always be generic in CUDA C and always
291  // be specific in OpenCL, we use this simple control here.
292  //
293  bool EmitGeneric;
294 
295 public:
296  NVPTXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
297  : AsmPrinter(TM, std::move(Streamer)),
298  EmitGeneric(static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() ==
299  NVPTX::CUDA) {}
300 
301  bool runOnMachineFunction(MachineFunction &F) override;
302 
303  void getAnalysisUsage(AnalysisUsage &AU) const override {
306  }
307 
308  std::string getVirtualRegisterName(unsigned) const;
309 
310  const MCSymbol *getFunctionFrameSymbol() const override;
311 };
312 
313 } // end namespace llvm
314 
315 #endif // LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
This class represents an incoming formal argument to a Function.
Definition: Argument.h:29
This class represents lattice values for constants.
Definition: AllocatorList.h:23
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:64
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
void push_back(const T &Elt)
Definition: SmallVector.h:211
unsigned Reg
F(f)
AnalysisUsage & addRequired()
Definition: BitVector.h:937
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
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:888
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:244
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
Class to represent pointers.
Definition: DerivedTypes.h:498
void getAnalysisUsage(AnalysisUsage &AU) const override
Record analysis usage.
unsigned const MachineRegisterInfo * MRI
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:84
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
This is an important base class in LLVM.
Definition: Constant.h:41
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:263
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:81
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:78
Represent the analysis usage information of a pass.
unsigned getAddressSpace() const
Return the address space of the Pointer type.
Definition: DerivedTypes.h:526
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library...
Definition: Compiler.h:107
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:1166
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:21
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:63
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:322
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:72
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:58
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:59