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. 45 namespace nvptx { 46 const llvm::MCExpr *LowerConstant(const llvm::Constant *CV, 47 llvm::AsmPrinter &AP) ; 48 } 49 50 namespace llvm { 51 52 class LineReader { 53 private: 54 unsigned theCurLine ; 55 std::ifstream fstr; 56 char buff[512]; 57 std::string theFileName; 58 SmallVector<unsigned, 32> lineOffset; 59 public: LineReader(std::string filename)60 LineReader(std::string filename) { 61 theCurLine = 0; 62 fstr.open(filename.c_str()); 63 theFileName = filename; 64 } fileName()65 std::string fileName() { return theFileName; } ~LineReader()66 ~LineReader() { 67 fstr.close(); 68 } 69 std::string readLine(unsigned line); 70 }; 71 72 73 74 class 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: AggBuffer(unsigned _size,raw_ostream & _O,NVPTXAsmPrinter & _AP)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 } ~AggBuffer()114 ~AggBuffer() { 115 delete [] buffer; 116 } addBytes(unsigned char * Ptr,int Num,int Bytes)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 } addZeros(int Num)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 } addSymbol(Value * GVar)138 void addSymbol(Value *GVar) { 139 symbolPosInBuffer.push_back(curpos); 140 Symbols.push_back(GVar); 141 numSymbols++; 142 } print()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 192 private : getPassName()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 245 protected: 246 bool doInitialization(Module &M); 247 bool doFinalization(Module &M); 248 249 private: 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); 291 public: NVPTXAsmPrinter(TargetMachine & TM,MCStreamer & Streamer)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 ~NVPTXAsmPrinter()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