1239310Sdim//===-- NVPTXAsmPrinter.h - NVPTX LLVM assembly writer --------------------===// 2239310Sdim// 3239310Sdim// The LLVM Compiler Infrastructure 4239310Sdim// 5239310Sdim// This file is distributed under the University of Illinois Open Source 6239310Sdim// License. See LICENSE.TXT for details. 7239310Sdim// 8239310Sdim//===----------------------------------------------------------------------===// 9239310Sdim// 10239310Sdim// This file contains a printer that converts from our internal representation 11239310Sdim// of machine-dependent LLVM code to NVPTX assembly language. 12239310Sdim// 13239310Sdim//===----------------------------------------------------------------------===// 14239310Sdim 15239310Sdim#ifndef NVPTXASMPRINTER_H 16239310Sdim#define NVPTXASMPRINTER_H 17239310Sdim 18239310Sdim#include "NVPTX.h" 19249423Sdim#include "NVPTXSubtarget.h" 20239310Sdim#include "NVPTXTargetMachine.h" 21249423Sdim#include "llvm/ADT/SmallString.h" 22249423Sdim#include "llvm/ADT/StringExtras.h" 23239310Sdim#include "llvm/CodeGen/AsmPrinter.h" 24249423Sdim#include "llvm/IR/Function.h" 25239310Sdim#include "llvm/MC/MCAsmInfo.h" 26239310Sdim#include "llvm/MC/MCExpr.h" 27239310Sdim#include "llvm/MC/MCSymbol.h" 28249423Sdim#include "llvm/Support/CommandLine.h" 29239310Sdim#include "llvm/Support/FormattedStream.h" 30239310Sdim#include "llvm/Target/Mangler.h" 31249423Sdim#include "llvm/Target/TargetMachine.h" 32239310Sdim#include <fstream> 33239310Sdim 34239310Sdim// The ptx syntax and format is very different from that usually seem in a .s 35239310Sdim// file, 36239310Sdim// therefore we are not able to use the MCAsmStreamer interface here. 37239310Sdim// 38239310Sdim// We are handcrafting the output method here. 39239310Sdim// 40239310Sdim// A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer 41239310Sdim// (subclass of MCStreamer). 42239310Sdim 43239310Sdim// This is defined in AsmPrinter.cpp. 44239310Sdim// Used to process the constant expressions in initializers. 45239310Sdimnamespace nvptx { 46249423Sdimconst llvm::MCExpr * 47249423SdimLowerConstant(const llvm::Constant *CV, llvm::AsmPrinter &AP); 48239310Sdim} 49239310Sdim 50239310Sdimnamespace llvm { 51239310Sdim 52239310Sdimclass LineReader { 53239310Sdimprivate: 54249423Sdim unsigned theCurLine; 55239310Sdim std::ifstream fstr; 56239310Sdim char buff[512]; 57239310Sdim std::string theFileName; 58239310Sdim SmallVector<unsigned, 32> lineOffset; 59239310Sdimpublic: 60239310Sdim LineReader(std::string filename) { 61239310Sdim theCurLine = 0; 62239310Sdim fstr.open(filename.c_str()); 63239310Sdim theFileName = filename; 64239310Sdim } 65239310Sdim std::string fileName() { return theFileName; } 66249423Sdim ~LineReader() { fstr.close(); } 67239310Sdim std::string readLine(unsigned line); 68239310Sdim}; 69239310Sdim 70239310Sdimclass LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter : public AsmPrinter { 71239310Sdim 72239310Sdim class AggBuffer { 73239310Sdim // Used to buffer the emitted string for initializing global 74239310Sdim // aggregates. 75239310Sdim // 76239310Sdim // Normally an aggregate (array, vector or structure) is emitted 77239310Sdim // as a u8[]. However, if one element/field of the aggregate 78239310Sdim // is a non-NULL address, then the aggregate is emitted as u32[] 79239310Sdim // or u64[]. 80239310Sdim // 81239310Sdim // We first layout the aggregate in 'buffer' in bytes, except for 82239310Sdim // those symbol addresses. For the i-th symbol address in the 83239310Sdim //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer' 84239310Sdim // are filled with 0s. symbolPosInBuffer[i-1] records its position 85239310Sdim // in 'buffer', and Symbols[i-1] records the Value*. 86239310Sdim // 87239310Sdim // Once we have this AggBuffer setup, we can choose how to print 88239310Sdim // it out. 89239310Sdim public: 90249423Sdim unsigned size; // size of the buffer in bytes 91239310Sdim unsigned char *buffer; // the buffer 92239310Sdim unsigned numSymbols; // number of symbol addresses 93239310Sdim SmallVector<unsigned, 4> symbolPosInBuffer; 94251662Sdim SmallVector<const Value *, 4> Symbols; 95239310Sdim 96239310Sdim private: 97239310Sdim unsigned curpos; 98239310Sdim raw_ostream &O; 99239310Sdim NVPTXAsmPrinter &AP; 100239310Sdim 101239310Sdim public: 102239310Sdim AggBuffer(unsigned _size, raw_ostream &_O, NVPTXAsmPrinter &_AP) 103249423Sdim : O(_O), AP(_AP) { 104239310Sdim buffer = new unsigned char[_size]; 105239310Sdim size = _size; 106239310Sdim curpos = 0; 107239310Sdim numSymbols = 0; 108239310Sdim } 109249423Sdim ~AggBuffer() { delete[] buffer; } 110239310Sdim unsigned addBytes(unsigned char *Ptr, int Num, int Bytes) { 111249423Sdim assert((curpos + Num) <= size); 112249423Sdim assert((curpos + Bytes) <= size); 113249423Sdim for (int i = 0; i < Num; ++i) { 114239310Sdim buffer[curpos] = Ptr[i]; 115249423Sdim curpos++; 116239310Sdim } 117249423Sdim for (int i = Num; i < Bytes; ++i) { 118239310Sdim buffer[curpos] = 0; 119249423Sdim curpos++; 120239310Sdim } 121239310Sdim return curpos; 122239310Sdim } 123239310Sdim unsigned addZeros(int Num) { 124249423Sdim assert((curpos + Num) <= size); 125249423Sdim for (int i = 0; i < Num; ++i) { 126239310Sdim buffer[curpos] = 0; 127249423Sdim curpos++; 128239310Sdim } 129239310Sdim return curpos; 130239310Sdim } 131251662Sdim void addSymbol(const Value *GVar) { 132239310Sdim symbolPosInBuffer.push_back(curpos); 133239310Sdim Symbols.push_back(GVar); 134239310Sdim numSymbols++; 135239310Sdim } 136239310Sdim void print() { 137239310Sdim if (numSymbols == 0) { 138239310Sdim // print out in bytes 139249423Sdim for (unsigned i = 0; i < size; i++) { 140239310Sdim if (i) 141239310Sdim O << ", "; 142249423Sdim O << (unsigned int) buffer[i]; 143239310Sdim } 144239310Sdim } else { 145239310Sdim // print out in 4-bytes or 8-bytes 146239310Sdim unsigned int pos = 0; 147239310Sdim unsigned int nSym = 0; 148239310Sdim unsigned int nextSymbolPos = symbolPosInBuffer[nSym]; 149239310Sdim unsigned int nBytes = 4; 150239310Sdim if (AP.nvptxSubtarget.is64Bit()) 151239310Sdim nBytes = 8; 152249423Sdim for (pos = 0; pos < size; pos += nBytes) { 153239310Sdim if (pos) 154239310Sdim O << ", "; 155239310Sdim if (pos == nextSymbolPos) { 156251662Sdim const Value *v = Symbols[nSym]; 157251662Sdim if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) { 158239310Sdim MCSymbol *Name = AP.Mang->getSymbol(GVar); 159239310Sdim O << *Name; 160251662Sdim } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(v)) { 161239310Sdim O << *nvptx::LowerConstant(Cexpr, AP); 162239310Sdim } else 163239310Sdim llvm_unreachable("symbol type unknown"); 164239310Sdim nSym++; 165239310Sdim if (nSym >= numSymbols) 166249423Sdim nextSymbolPos = size + 1; 167239310Sdim else 168239310Sdim nextSymbolPos = symbolPosInBuffer[nSym]; 169249423Sdim } else if (nBytes == 4) 170249423Sdim O << *(unsigned int *)(buffer + pos); 171249423Sdim else 172249423Sdim O << *(unsigned long long *)(buffer + pos); 173239310Sdim } 174239310Sdim } 175239310Sdim } 176239310Sdim }; 177239310Sdim 178239310Sdim friend class AggBuffer; 179239310Sdim 180239310Sdim virtual void emitSrcInText(StringRef filename, unsigned line); 181239310Sdim 182249423Sdimprivate: 183249423Sdim virtual const char *getPassName() const { return "NVPTX Assembly Printer"; } 184239310Sdim 185239310Sdim const Function *F; 186239310Sdim std::string CurrentFnName; 187239310Sdim 188239310Sdim void EmitFunctionEntryLabel(); 189239310Sdim void EmitFunctionBodyStart(); 190239310Sdim void EmitFunctionBodyEnd(); 191239310Sdim 192239310Sdim void EmitInstruction(const MachineInstr *); 193239310Sdim 194239310Sdim void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const {} 195239310Sdim 196239310Sdim void printGlobalVariable(const GlobalVariable *GVar); 197239310Sdim void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 198249423Sdim const char *Modifier = 0); 199239310Sdim void printLdStCode(const MachineInstr *MI, int opNum, raw_ostream &O, 200249423Sdim const char *Modifier = 0); 201249423Sdim void printVecModifiedImmediate(const MachineOperand &MO, const char *Modifier, 202249423Sdim raw_ostream &O); 203239310Sdim void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O, 204249423Sdim const char *Modifier = 0); 205239310Sdim void printImplicitDef(const MachineInstr *MI, raw_ostream &O) const; 206239310Sdim // definition autogenerated. 207239310Sdim void printInstruction(const MachineInstr *MI, raw_ostream &O); 208251662Sdim void printModuleLevelGV(const GlobalVariable *GVar, raw_ostream &O, 209251662Sdim bool = false); 210239310Sdim void printParamName(int paramIndex, raw_ostream &O); 211239310Sdim void printParamName(Function::const_arg_iterator I, int paramIndex, 212239310Sdim raw_ostream &O); 213251662Sdim void emitGlobals(const Module &M); 214239310Sdim void emitHeader(Module &M, raw_ostream &O); 215249423Sdim void emitKernelFunctionDirectives(const Function &F, raw_ostream &O) const; 216239310Sdim void emitVirtualRegister(unsigned int vr, bool isVec, raw_ostream &O); 217239310Sdim void emitFunctionExternParamList(const MachineFunction &MF); 218239310Sdim void emitFunctionParamList(const Function *, raw_ostream &O); 219239310Sdim void emitFunctionParamList(const MachineFunction &MF, raw_ostream &O); 220239310Sdim void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF); 221249423Sdim void emitFunctionTempData(const MachineFunction &MF, unsigned &FrameSize); 222239310Sdim bool isImageType(const Type *Ty); 223239310Sdim bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 224239310Sdim unsigned AsmVariant, const char *ExtraCode, 225239310Sdim raw_ostream &); 226239310Sdim bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 227239310Sdim unsigned AsmVariant, const char *ExtraCode, 228239310Sdim raw_ostream &); 229239310Sdim void printReturnValStr(const Function *, raw_ostream &O); 230239310Sdim void printReturnValStr(const MachineFunction &MF, raw_ostream &O); 231239310Sdim 232239310Sdimprotected: 233239310Sdim bool doInitialization(Module &M); 234239310Sdim bool doFinalization(Module &M); 235239310Sdim 236239310Sdimprivate: 237239310Sdim std::string CurrentBankselLabelInBasicBlock; 238239310Sdim 239251662Sdim bool GlobalsEmitted; 240251662Sdim 241239310Sdim // This is specific per MachineFunction. 242239310Sdim const MachineRegisterInfo *MRI; 243239310Sdim // The contents are specific for each 244239310Sdim // MachineFunction. But the size of the 245239310Sdim // array is not. 246239310Sdim std::map<unsigned, unsigned> *VRidGlobal2LocalMap; 247239310Sdim // cache the subtarget here. 248239310Sdim const NVPTXSubtarget &nvptxSubtarget; 249239310Sdim // Build the map between type name and ID based on module's type 250239310Sdim // symbol table. 251239310Sdim std::map<const Type *, std::string> TypeNameMap; 252239310Sdim 253239310Sdim // List of variables demoted to a function scope. 254251662Sdim std::map<const Function *, std::vector<const GlobalVariable *> > localDecls; 255239310Sdim 256239310Sdim // To record filename to ID mapping 257239310Sdim std::map<std::string, unsigned> filenameMap; 258239310Sdim void recordAndEmitFilenames(Module &); 259239310Sdim 260239310Sdim void emitPTXGlobalVariable(const GlobalVariable *GVar, raw_ostream &O); 261249423Sdim void emitPTXAddressSpace(unsigned int AddressSpace, raw_ostream &O) const; 262249423Sdim std::string getPTXFundamentalTypeStr(const Type *Ty, bool = true) const; 263251662Sdim void printScalarConstant(const Constant *CPV, raw_ostream &O); 264249423Sdim void printFPConstant(const ConstantFP *Fp, raw_ostream &O); 265251662Sdim void bufferLEByte(const Constant *CPV, int Bytes, AggBuffer *aggBuffer); 266251662Sdim void bufferAggregateConstant(const Constant *CV, AggBuffer *aggBuffer); 267239310Sdim 268239310Sdim void printOperandProper(const MachineOperand &MO); 269239310Sdim 270249423Sdim void emitLinkageDirective(const GlobalValue *V, raw_ostream &O); 271251662Sdim void emitDeclarations(const Module &, raw_ostream &O); 272239310Sdim void emitDeclaration(const Function *, raw_ostream &O); 273239310Sdim 274239310Sdim static const char *getRegisterName(unsigned RegNo); 275239310Sdim void emitDemotedVars(const Function *, raw_ostream &); 276239310Sdim 277239310Sdim LineReader *reader; 278239310Sdim LineReader *getReader(std::string); 279239310Sdimpublic: 280249423Sdim NVPTXAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) 281249423Sdim : AsmPrinter(TM, Streamer), 282249423Sdim nvptxSubtarget(TM.getSubtarget<NVPTXSubtarget>()) { 283239310Sdim CurrentBankselLabelInBasicBlock = ""; 284239310Sdim VRidGlobal2LocalMap = NULL; 285239310Sdim reader = NULL; 286239310Sdim } 287239310Sdim 288239310Sdim ~NVPTXAsmPrinter() { 289239310Sdim if (!reader) 290239310Sdim delete reader; 291239310Sdim } 292239310Sdim 293239310Sdim bool ignoreLoc(const MachineInstr &); 294239310Sdim 295239310Sdim virtual void getVirtualRegisterName(unsigned, bool, raw_ostream &); 296239310Sdim 297239310Sdim DebugLoc prevDebugLoc; 298239310Sdim void emitLineNumberAsDotLoc(const MachineInstr &); 299239310Sdim}; 300239310Sdim} // end of namespace 301239310Sdim 302239310Sdim#endif 303