149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//===-- NVPTXAsmPrinter.h - NVPTX LLVM assembly writer --------------------===//
249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//                     The LLVM Compiler Infrastructure
449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// This file is distributed under the University of Illinois Open Source
649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// License. See LICENSE.TXT for details.
749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//===----------------------------------------------------------------------===//
949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
1049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// This file contains a printer that converts from our internal representation
1149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// of machine-dependent LLVM code to NVPTX assembly language.
1249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
1349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//===----------------------------------------------------------------------===//
1449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
1537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#ifndef LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
1637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines#define LLVM_LIB_TARGET_NVPTX_NVPTXASMPRINTER_H
1749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
1849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "NVPTX.h"
1949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "NVPTXSubtarget.h"
20a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#include "NVPTXTargetMachine.h"
21a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#include "llvm/ADT/SmallString.h"
22a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#include "llvm/ADT/StringExtras.h"
2349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "llvm/CodeGen/AsmPrinter.h"
240b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
2549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "llvm/MC/MCAsmInfo.h"
2649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "llvm/MC/MCExpr.h"
2749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "llvm/MC/MCSymbol.h"
28a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#include "llvm/Support/CommandLine.h"
2949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include "llvm/Support/FormattedStream.h"
30a1514e24cc24b050f53a12650e047799358833a1Chandler Carruth#include "llvm/Target/TargetMachine.h"
3149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#include <fstream>
3249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
3349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// The ptx syntax and format is very different from that usually seem in a .s
3449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// file,
3549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// therefore we are not able to use the MCAsmStreamer interface here.
3649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
3749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// We are handcrafting the output method here.
3849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski//
3949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// A better approach is to clone the MCAsmStreamer to a MCPTXAsmStreamer
4049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski// (subclass of MCStreamer).
4149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
4249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskinamespace llvm {
4349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
4449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskiclass LineReader {
4549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskiprivate:
463639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  unsigned theCurLine;
4749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::ifstream fstr;
4849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  char buff[512];
4949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::string theFileName;
5049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  SmallVector<unsigned, 32> lineOffset;
5149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskipublic:
5249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  LineReader(std::string filename) {
5349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    theCurLine = 0;
5449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    fstr.open(filename.c_str());
5549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    theFileName = filename;
5649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  }
5749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::string fileName() { return theFileName; }
583639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  ~LineReader() { fstr.close(); }
5949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::string readLine(unsigned line);
6049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski};
6149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
6249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskiclass LLVM_LIBRARY_VISIBILITY NVPTXAsmPrinter : public AsmPrinter {
6349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
6449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  class AggBuffer {
6549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // Used to buffer the emitted string for initializing global
6649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // aggregates.
6749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    //
6849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // Normally an aggregate (array, vector or structure) is emitted
6949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // as a u8[]. However, if one element/field of the aggregate
7049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // is a non-NULL address, then the aggregate is emitted as u32[]
7149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // or u64[].
7249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    //
7349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // We first layout the aggregate in 'buffer' in bytes, except for
7449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // those symbol addresses. For the i-th symbol address in the
7549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    //aggregate, its corresponding 4-byte or 8-byte elements in 'buffer'
7649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // are filled with 0s. symbolPosInBuffer[i-1] records its position
7749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // in 'buffer', and Symbols[i-1] records the Value*.
7849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    //
7949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // Once we have this AggBuffer setup, we can choose how to print
8049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    // it out.
8149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  public:
8249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    unsigned numSymbols;   // number of symbol addresses
8349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
8449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  private:
8537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    const unsigned size;   // size of the buffer in bytes
8637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    std::vector<unsigned char> buffer; // the buffer
8737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    SmallVector<unsigned, 4> symbolPosInBuffer;
8837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    SmallVector<const Value *, 4> Symbols;
8949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    unsigned curpos;
9049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    raw_ostream &O;
9149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    NVPTXAsmPrinter &AP;
92dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    bool EmitGeneric;
9349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
9449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  public:
954c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    AggBuffer(unsigned size, raw_ostream &O, NVPTXAsmPrinter &AP)
964c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar        : size(size), buffer(size), O(O), AP(AP) {
9749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      curpos = 0;
9849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      numSymbols = 0;
99dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      EmitGeneric = AP.EmitGeneric;
10049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    }
10149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    unsigned addBytes(unsigned char *Ptr, int Num, int Bytes) {
1023639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      assert((curpos + Num) <= size);
1033639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      assert((curpos + Bytes) <= size);
1043639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      for (int i = 0; i < Num; ++i) {
10549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        buffer[curpos] = Ptr[i];
1063639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        curpos++;
10749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      }
1083639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      for (int i = Num; i < Bytes; ++i) {
10949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        buffer[curpos] = 0;
1103639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        curpos++;
11149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      }
11249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      return curpos;
11349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    }
11449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    unsigned addZeros(int Num) {
1153639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      assert((curpos + Num) <= size);
1163639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski      for (int i = 0; i < Num; ++i) {
11749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        buffer[curpos] = 0;
1183639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        curpos++;
11949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      }
12049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      return curpos;
12149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    }
1227536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski    void addSymbol(const Value *GVar) {
12349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      symbolPosInBuffer.push_back(curpos);
12449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      Symbols.push_back(GVar);
12549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      numSymbols++;
12649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    }
12749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    void print() {
12849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      if (numSymbols == 0) {
12949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        // print out in bytes
1303639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        for (unsigned i = 0; i < size; i++) {
13149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          if (i)
13249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski            O << ", ";
1333639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski          O << (unsigned int) buffer[i];
13449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        }
1356366361998599a63a74ee7cc5f4ba900711c7e7aCraig Topper      } else {
13649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        // print out in 4-bytes or 8-bytes
13749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        unsigned int pos = 0;
13849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        unsigned int nSym = 0;
13949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        unsigned int nextSymbolPos = symbolPosInBuffer[nSym];
14049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        unsigned int nBytes = 4;
141ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines        if (static_cast<const NVPTXTargetMachine &>(AP.TM).is64Bit())
14249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          nBytes = 8;
1433639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski        for (pos = 0; pos < size; pos += nBytes) {
14449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          if (pos)
14549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski            O << ", ";
14649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski          if (pos == nextSymbolPos) {
1477536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski            const Value *v = Symbols[nSym];
1487536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski            if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
149ffc7dca885151ed42642c2d6733e8db75d276621Rafael Espindola              MCSymbol *Name = AP.getSymbol(GVar);
150dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              PointerType *PTy = dyn_cast<PointerType>(GVar->getType());
151dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              bool IsNonGenericPointer = false;
152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              if (PTy && PTy->getAddressSpace() != 0) {
153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                IsNonGenericPointer = true;
154dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              }
155dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
156dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                O << "generic(";
157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                O << *Name;
158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                O << ")";
159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              } else {
160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                O << *Name;
161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              }
1627536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski            } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(v)) {
163ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines              O << *AP.lowerConstant(Cexpr);
1646366361998599a63a74ee7cc5f4ba900711c7e7aCraig Topper            } else
1656366361998599a63a74ee7cc5f4ba900711c7e7aCraig Topper              llvm_unreachable("symbol type unknown");
16649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski            nSym++;
16749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski            if (nSym >= numSymbols)
1683639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski              nextSymbolPos = size + 1;
16949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski            else
17049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski              nextSymbolPos = symbolPosInBuffer[nSym];
1713639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski          } else if (nBytes == 4)
17237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            O << *(unsigned int *)(&buffer[pos]);
1733639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski          else
17437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines            O << *(unsigned long long *)(&buffer[pos]);
17549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski        }
17649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      }
17749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    }
17849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  };
17949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
18049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  friend class AggBuffer;
18149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
182dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void emitSrcInText(StringRef filename, unsigned line);
18349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
1843639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinskiprivate:
185dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  const char *getPassName() const override { return "NVPTX Assembly Printer"; }
18649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
18749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  const Function *F;
18849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::string CurrentFnName;
18949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
190ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  void EmitBasicBlockStart(const MachineBasicBlock &MBB) const override;
191dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void EmitFunctionEntryLabel() override;
192dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void EmitFunctionBodyStart() override;
193dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void EmitFunctionBodyEnd() override;
194dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void emitImplicitDef(const MachineInstr *MI) const override;
19549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
196dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void EmitInstruction(const MachineInstr *) override;
19782767327c59ede1f8663ec9b9a64a668993d501fJustin Holewinski  void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
19882767327c59ede1f8663ec9b9a64a668993d501fJustin Holewinski  bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp);
199dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  MCOperand GetSymbolRef(const MCSymbol *Symbol);
20082767327c59ede1f8663ec9b9a64a668993d501fJustin Holewinski  unsigned encodeVirtualRegister(unsigned Reg);
20149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
202dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void EmitAlignment(unsigned NumBits, const GlobalValue *GV = nullptr) const {}
20349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
2043639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  void printVecModifiedImmediate(const MachineOperand &MO, const char *Modifier,
2053639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski                                 raw_ostream &O);
20649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
207dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       const char *Modifier = nullptr);
20849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void printImplicitDef(const MachineInstr *MI, raw_ostream &O) const;
2097536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  void printModuleLevelGV(const GlobalVariable *GVar, raw_ostream &O,
2107536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski                          bool = false);
21149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void printParamName(int paramIndex, raw_ostream &O);
21249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void printParamName(Function::const_arg_iterator I, int paramIndex,
21349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski                      raw_ostream &O);
2147536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  void emitGlobals(const Module &M);
215ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  void emitHeader(Module &M, raw_ostream &O, const NVPTXSubtarget &STI);
2163639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  void emitKernelFunctionDirectives(const Function &F, raw_ostream &O) const;
21743777c3150c1dd12c661f62d5d7c95bf9b04c16aJustin Holewinski  void emitVirtualRegister(unsigned int vr, raw_ostream &);
21849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void emitFunctionExternParamList(const MachineFunction &MF);
21949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void emitFunctionParamList(const Function *, raw_ostream &O);
22049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void emitFunctionParamList(const MachineFunction &MF, raw_ostream &O);
22149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void setAndEmitFunctionVirtualRegisters(const MachineFunction &MF);
2223639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  void emitFunctionTempData(const MachineFunction &MF, unsigned &FrameSize);
22349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  bool isImageType(const Type *Ty);
22449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void printReturnValStr(const Function *, raw_ostream &O);
22549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void printReturnValStr(const MachineFunction &MF, raw_ostream &O);
22630632d2fbb3c46e552a68aa7961b12eb44cece01Justin Holewinski  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
22730632d2fbb3c46e552a68aa7961b12eb44cece01Justin Holewinski                       unsigned AsmVariant, const char *ExtraCode,
228dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       raw_ostream &) override;
22930632d2fbb3c46e552a68aa7961b12eb44cece01Justin Holewinski  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
230dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    const char *Modifier = nullptr);
23130632d2fbb3c46e552a68aa7961b12eb44cece01Justin Holewinski  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
23230632d2fbb3c46e552a68aa7961b12eb44cece01Justin Holewinski                             unsigned AsmVariant, const char *ExtraCode,
233dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                             raw_ostream &) override;
23449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskiprotected:
235dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool doInitialization(Module &M) override;
236dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool doFinalization(Module &M) override;
23749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
23849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskiprivate:
23949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::string CurrentBankselLabelInBasicBlock;
24049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
2417536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  bool GlobalsEmitted;
2427536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski
24349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // This is specific per MachineFunction.
24449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  const MachineRegisterInfo *MRI;
24549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // The contents are specific for each
24649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // MachineFunction. But the size of the
24749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // array is not.
2485443e7d79044f3198f2da044f1b389b40d9bea6fJustin Holewinski  typedef DenseMap<unsigned, unsigned> VRegMap;
2495443e7d79044f3198f2da044f1b389b40d9bea6fJustin Holewinski  typedef DenseMap<const TargetRegisterClass *, VRegMap> VRegRCMap;
2505443e7d79044f3198f2da044f1b389b40d9bea6fJustin Holewinski  VRegRCMap VRegMapping;
251ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines
252ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  // Cache the subtarget here.
253ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  const NVPTXSubtarget *nvptxSubtarget;
254ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines
25549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // Build the map between type name and ID based on module's type
25649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // symbol table.
25749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::map<const Type *, std::string> TypeNameMap;
25849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
25949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // List of variables demoted to a function scope.
2607536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  std::map<const Function *, std::vector<const GlobalVariable *> > localDecls;
26149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
26249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  // To record filename to ID mapping
26349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  std::map<std::string, unsigned> filenameMap;
26449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void recordAndEmitFilenames(Module &);
26549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
26649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void emitPTXGlobalVariable(const GlobalVariable *GVar, raw_ostream &O);
2673639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  void emitPTXAddressSpace(unsigned int AddressSpace, raw_ostream &O) const;
2683639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  std::string getPTXFundamentalTypeStr(const Type *Ty, bool = true) const;
2697536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  void printScalarConstant(const Constant *CPV, raw_ostream &O);
2703639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  void printFPConstant(const ConstantFP *Fp, raw_ostream &O);
2717536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  void bufferLEByte(const Constant *CPV, int Bytes, AggBuffer *aggBuffer);
2727536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  void bufferAggregateConstant(const Constant *CV, AggBuffer *aggBuffer);
27349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
27449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void printOperandProper(const MachineOperand &MO);
27549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
2763639ce2575660a0e6938d2e84e8bd9a738fd7051Justin Holewinski  void emitLinkageDirective(const GlobalValue *V, raw_ostream &O);
2777536ecf2916a6a986f0d328069e3a210f34d5ea7Justin Holewinski  void emitDeclarations(const Module &, raw_ostream &O);
27849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void emitDeclaration(const Function *, raw_ostream &O);
27949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
28049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  static const char *getRegisterName(unsigned RegNo);
28149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void emitDemotedVars(const Function *, raw_ostream &);
28249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
283dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool lowerImageHandleOperand(const MachineInstr *MI, unsigned OpNo,
284dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                               MCOperand &MCOp);
285dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  void lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp);
286dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
287ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  bool isLoopHeaderOfNoUnroll(const MachineBasicBlock &MBB) const;
288ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines
28949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  LineReader *reader;
29049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  LineReader *getReader(std::string);
291dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
292dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Used to control the need to emit .generic() in the initializer of
293dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // module scope variables.
294dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Although ptx supports the hybrid mode like the following,
295dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  //    .global .u32 a;
296dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  //    .global .u32 b;
297dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  //    .global .u32 addr[] = {a, generic(b)}
298dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // we have difficulty representing the difference in the NVVM IR.
299dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  //
300dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Since the address value should always be generic in CUDA C and always
301dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // be specific in OpenCL, we use this simple control here.
302dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  //
303dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  bool EmitGeneric;
304dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
30549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinskipublic:
306ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  NVPTXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
307ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      : AsmPrinter(TM, std::move(Streamer)),
308ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines        EmitGeneric(static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() ==
309ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines                    NVPTX::CUDA) {
31049683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    CurrentBankselLabelInBasicBlock = "";
311dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    reader = nullptr;
31249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  }
31349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
31449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  ~NVPTXAsmPrinter() {
31549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski    if (!reader)
31649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski      delete reader;
31749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  }
31849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
319ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  bool runOnMachineFunction(MachineFunction &F) override {
320ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    nvptxSubtarget = &F.getSubtarget<NVPTXSubtarget>();
321ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    return AsmPrinter::runOnMachineFunction(F);
322ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  }
323ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  void getAnalysisUsage(AnalysisUsage &AU) const override {
324ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    AU.addRequired<MachineLoopInfo>();
325ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    AsmPrinter::getAnalysisUsage(AU);
326ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  }
327ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines
32849683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  bool ignoreLoc(const MachineInstr &);
32949683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
33043777c3150c1dd12c661f62d5d7c95bf9b04c16aJustin Holewinski  std::string getVirtualRegisterName(unsigned) const;
33149683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
33249683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  DebugLoc prevDebugLoc;
33349683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski  void emitLineNumberAsDotLoc(const MachineInstr &);
33449683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski};
33549683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski} // end of namespace
33649683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski
33749683f3c961379fbc088871a5d6304950f1f1cbcJustin Holewinski#endif
338