1*9880d681SAndroid Build Coastguard Worker //===-- NVPTXAsmPrinter.cpp - NVPTX LLVM assembly writer ------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file contains a printer that converts from our internal representation
11*9880d681SAndroid Build Coastguard Worker // of machine-dependent LLVM code to NVPTX assembly language.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "NVPTXAsmPrinter.h"
16*9880d681SAndroid Build Coastguard Worker #include "InstPrinter/NVPTXInstPrinter.h"
17*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/NVPTXMCAsmInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "NVPTX.h"
19*9880d681SAndroid Build Coastguard Worker #include "NVPTXInstrInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "NVPTXMCExpr.h"
21*9880d681SAndroid Build Coastguard Worker #include "NVPTXMachineFunctionInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "NVPTXRegisterInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "NVPTXTargetMachine.h"
24*9880d681SAndroid Build Coastguard Worker #include "NVPTXUtilities.h"
25*9880d681SAndroid Build Coastguard Worker #include "cl_common_defines.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringExtras.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ConstantFolding.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Analysis.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineLoopInfo.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineModuleInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DebugInfo.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DerivedTypes.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/GlobalVariable.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Mangler.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Operator.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
41*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
42*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
43*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
44*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
45*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/FormattedStream.h"
46*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Path.h"
47*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
48*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TimeValue.h"
49*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetLoweringObjectFile.h"
50*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/UnrollLoop.h"
51*9880d681SAndroid Build Coastguard Worker #include <sstream>
52*9880d681SAndroid Build Coastguard Worker using namespace llvm;
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker #define DEPOTNAME "__local_depot"
55*9880d681SAndroid Build Coastguard Worker
56*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
57*9880d681SAndroid Build Coastguard Worker EmitLineNumbers("nvptx-emit-line-numbers", cl::Hidden,
58*9880d681SAndroid Build Coastguard Worker cl::desc("NVPTX Specific: Emit Line numbers even without -G"),
59*9880d681SAndroid Build Coastguard Worker cl::init(true));
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
62*9880d681SAndroid Build Coastguard Worker InterleaveSrc("nvptx-emit-src", cl::ZeroOrMore, cl::Hidden,
63*9880d681SAndroid Build Coastguard Worker cl::desc("NVPTX Specific: Emit source line in ptx file"),
64*9880d681SAndroid Build Coastguard Worker cl::init(false));
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker namespace {
67*9880d681SAndroid Build Coastguard Worker /// DiscoverDependentGlobals - Return a set of GlobalVariables on which \p V
68*9880d681SAndroid Build Coastguard Worker /// depends.
DiscoverDependentGlobals(const Value * V,DenseSet<const GlobalVariable * > & Globals)69*9880d681SAndroid Build Coastguard Worker void DiscoverDependentGlobals(const Value *V,
70*9880d681SAndroid Build Coastguard Worker DenseSet<const GlobalVariable *> &Globals) {
71*9880d681SAndroid Build Coastguard Worker if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
72*9880d681SAndroid Build Coastguard Worker Globals.insert(GV);
73*9880d681SAndroid Build Coastguard Worker else {
74*9880d681SAndroid Build Coastguard Worker if (const User *U = dyn_cast<User>(V)) {
75*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = U->getNumOperands(); i != e; ++i) {
76*9880d681SAndroid Build Coastguard Worker DiscoverDependentGlobals(U->getOperand(i), Globals);
77*9880d681SAndroid Build Coastguard Worker }
78*9880d681SAndroid Build Coastguard Worker }
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker
82*9880d681SAndroid Build Coastguard Worker /// VisitGlobalVariableForEmission - Add \p GV to the list of GlobalVariable
83*9880d681SAndroid Build Coastguard Worker /// instances to be emitted, but only after any dependents have been added
84*9880d681SAndroid Build Coastguard Worker /// first.
VisitGlobalVariableForEmission(const GlobalVariable * GV,SmallVectorImpl<const GlobalVariable * > & Order,DenseSet<const GlobalVariable * > & Visited,DenseSet<const GlobalVariable * > & Visiting)85*9880d681SAndroid Build Coastguard Worker void VisitGlobalVariableForEmission(
86*9880d681SAndroid Build Coastguard Worker const GlobalVariable *GV, SmallVectorImpl<const GlobalVariable *> &Order,
87*9880d681SAndroid Build Coastguard Worker DenseSet<const GlobalVariable *> &Visited,
88*9880d681SAndroid Build Coastguard Worker DenseSet<const GlobalVariable *> &Visiting) {
89*9880d681SAndroid Build Coastguard Worker // Have we already visited this one?
90*9880d681SAndroid Build Coastguard Worker if (Visited.count(GV))
91*9880d681SAndroid Build Coastguard Worker return;
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker // Do we have a circular dependency?
94*9880d681SAndroid Build Coastguard Worker if (!Visiting.insert(GV).second)
95*9880d681SAndroid Build Coastguard Worker report_fatal_error("Circular dependency found in global variable set");
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker // Make sure we visit all dependents first
98*9880d681SAndroid Build Coastguard Worker DenseSet<const GlobalVariable *> Others;
99*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = GV->getNumOperands(); i != e; ++i)
100*9880d681SAndroid Build Coastguard Worker DiscoverDependentGlobals(GV->getOperand(i), Others);
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker for (DenseSet<const GlobalVariable *>::iterator I = Others.begin(),
103*9880d681SAndroid Build Coastguard Worker E = Others.end();
104*9880d681SAndroid Build Coastguard Worker I != E; ++I)
105*9880d681SAndroid Build Coastguard Worker VisitGlobalVariableForEmission(*I, Order, Visited, Visiting);
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker // Now we can visit ourself
108*9880d681SAndroid Build Coastguard Worker Order.push_back(GV);
109*9880d681SAndroid Build Coastguard Worker Visited.insert(GV);
110*9880d681SAndroid Build Coastguard Worker Visiting.erase(GV);
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker }
113*9880d681SAndroid Build Coastguard Worker
emitLineNumberAsDotLoc(const MachineInstr & MI)114*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitLineNumberAsDotLoc(const MachineInstr &MI) {
115*9880d681SAndroid Build Coastguard Worker if (!EmitLineNumbers)
116*9880d681SAndroid Build Coastguard Worker return;
117*9880d681SAndroid Build Coastguard Worker if (ignoreLoc(MI))
118*9880d681SAndroid Build Coastguard Worker return;
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker const DebugLoc &curLoc = MI.getDebugLoc();
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker if (!prevDebugLoc && !curLoc)
123*9880d681SAndroid Build Coastguard Worker return;
124*9880d681SAndroid Build Coastguard Worker
125*9880d681SAndroid Build Coastguard Worker if (prevDebugLoc == curLoc)
126*9880d681SAndroid Build Coastguard Worker return;
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker prevDebugLoc = curLoc;
129*9880d681SAndroid Build Coastguard Worker
130*9880d681SAndroid Build Coastguard Worker if (!curLoc)
131*9880d681SAndroid Build Coastguard Worker return;
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker auto *Scope = cast_or_null<DIScope>(curLoc.getScope());
134*9880d681SAndroid Build Coastguard Worker if (!Scope)
135*9880d681SAndroid Build Coastguard Worker return;
136*9880d681SAndroid Build Coastguard Worker
137*9880d681SAndroid Build Coastguard Worker StringRef fileName(Scope->getFilename());
138*9880d681SAndroid Build Coastguard Worker StringRef dirName(Scope->getDirectory());
139*9880d681SAndroid Build Coastguard Worker SmallString<128> FullPathName = dirName;
140*9880d681SAndroid Build Coastguard Worker if (!dirName.empty() && !sys::path::is_absolute(fileName)) {
141*9880d681SAndroid Build Coastguard Worker sys::path::append(FullPathName, fileName);
142*9880d681SAndroid Build Coastguard Worker fileName = FullPathName;
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker if (filenameMap.find(fileName) == filenameMap.end())
146*9880d681SAndroid Build Coastguard Worker return;
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker // Emit the line from the source file.
149*9880d681SAndroid Build Coastguard Worker if (InterleaveSrc)
150*9880d681SAndroid Build Coastguard Worker this->emitSrcInText(fileName, curLoc.getLine());
151*9880d681SAndroid Build Coastguard Worker
152*9880d681SAndroid Build Coastguard Worker std::stringstream temp;
153*9880d681SAndroid Build Coastguard Worker temp << "\t.loc " << filenameMap[fileName] << " " << curLoc.getLine()
154*9880d681SAndroid Build Coastguard Worker << " " << curLoc.getCol();
155*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(temp.str());
156*9880d681SAndroid Build Coastguard Worker }
157*9880d681SAndroid Build Coastguard Worker
EmitInstruction(const MachineInstr * MI)158*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
159*9880d681SAndroid Build Coastguard Worker SmallString<128> Str;
160*9880d681SAndroid Build Coastguard Worker raw_svector_ostream OS(Str);
161*9880d681SAndroid Build Coastguard Worker if (static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() == NVPTX::CUDA)
162*9880d681SAndroid Build Coastguard Worker emitLineNumberAsDotLoc(*MI);
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker MCInst Inst;
165*9880d681SAndroid Build Coastguard Worker lowerToMCInst(MI, Inst);
166*9880d681SAndroid Build Coastguard Worker EmitToStreamer(*OutStreamer, Inst);
167*9880d681SAndroid Build Coastguard Worker }
168*9880d681SAndroid Build Coastguard Worker
169*9880d681SAndroid Build Coastguard Worker // Handle symbol backtracking for targets that do not support image handles
lowerImageHandleOperand(const MachineInstr * MI,unsigned OpNo,MCOperand & MCOp)170*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::lowerImageHandleOperand(const MachineInstr *MI,
171*9880d681SAndroid Build Coastguard Worker unsigned OpNo, MCOperand &MCOp) {
172*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(OpNo);
173*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &MCID = MI->getDesc();
174*9880d681SAndroid Build Coastguard Worker
175*9880d681SAndroid Build Coastguard Worker if (MCID.TSFlags & NVPTXII::IsTexFlag) {
176*9880d681SAndroid Build Coastguard Worker // This is a texture fetch, so operand 4 is a texref and operand 5 is
177*9880d681SAndroid Build Coastguard Worker // a samplerref
178*9880d681SAndroid Build Coastguard Worker if (OpNo == 4 && MO.isImm()) {
179*9880d681SAndroid Build Coastguard Worker lowerImageHandleSymbol(MO.getImm(), MCOp);
180*9880d681SAndroid Build Coastguard Worker return true;
181*9880d681SAndroid Build Coastguard Worker }
182*9880d681SAndroid Build Coastguard Worker if (OpNo == 5 && MO.isImm() && !(MCID.TSFlags & NVPTXII::IsTexModeUnifiedFlag)) {
183*9880d681SAndroid Build Coastguard Worker lowerImageHandleSymbol(MO.getImm(), MCOp);
184*9880d681SAndroid Build Coastguard Worker return true;
185*9880d681SAndroid Build Coastguard Worker }
186*9880d681SAndroid Build Coastguard Worker
187*9880d681SAndroid Build Coastguard Worker return false;
188*9880d681SAndroid Build Coastguard Worker } else if (MCID.TSFlags & NVPTXII::IsSuldMask) {
189*9880d681SAndroid Build Coastguard Worker unsigned VecSize =
190*9880d681SAndroid Build Coastguard Worker 1 << (((MCID.TSFlags & NVPTXII::IsSuldMask) >> NVPTXII::IsSuldShift) - 1);
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Worker // For a surface load of vector size N, the Nth operand will be the surfref
193*9880d681SAndroid Build Coastguard Worker if (OpNo == VecSize && MO.isImm()) {
194*9880d681SAndroid Build Coastguard Worker lowerImageHandleSymbol(MO.getImm(), MCOp);
195*9880d681SAndroid Build Coastguard Worker return true;
196*9880d681SAndroid Build Coastguard Worker }
197*9880d681SAndroid Build Coastguard Worker
198*9880d681SAndroid Build Coastguard Worker return false;
199*9880d681SAndroid Build Coastguard Worker } else if (MCID.TSFlags & NVPTXII::IsSustFlag) {
200*9880d681SAndroid Build Coastguard Worker // This is a surface store, so operand 0 is a surfref
201*9880d681SAndroid Build Coastguard Worker if (OpNo == 0 && MO.isImm()) {
202*9880d681SAndroid Build Coastguard Worker lowerImageHandleSymbol(MO.getImm(), MCOp);
203*9880d681SAndroid Build Coastguard Worker return true;
204*9880d681SAndroid Build Coastguard Worker }
205*9880d681SAndroid Build Coastguard Worker
206*9880d681SAndroid Build Coastguard Worker return false;
207*9880d681SAndroid Build Coastguard Worker } else if (MCID.TSFlags & NVPTXII::IsSurfTexQueryFlag) {
208*9880d681SAndroid Build Coastguard Worker // This is a query, so operand 1 is a surfref/texref
209*9880d681SAndroid Build Coastguard Worker if (OpNo == 1 && MO.isImm()) {
210*9880d681SAndroid Build Coastguard Worker lowerImageHandleSymbol(MO.getImm(), MCOp);
211*9880d681SAndroid Build Coastguard Worker return true;
212*9880d681SAndroid Build Coastguard Worker }
213*9880d681SAndroid Build Coastguard Worker
214*9880d681SAndroid Build Coastguard Worker return false;
215*9880d681SAndroid Build Coastguard Worker }
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker return false;
218*9880d681SAndroid Build Coastguard Worker }
219*9880d681SAndroid Build Coastguard Worker
lowerImageHandleSymbol(unsigned Index,MCOperand & MCOp)220*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp) {
221*9880d681SAndroid Build Coastguard Worker // Ewwww
222*9880d681SAndroid Build Coastguard Worker TargetMachine &TM = const_cast<TargetMachine&>(MF->getTarget());
223*9880d681SAndroid Build Coastguard Worker NVPTXTargetMachine &nvTM = static_cast<NVPTXTargetMachine&>(TM);
224*9880d681SAndroid Build Coastguard Worker const NVPTXMachineFunctionInfo *MFI = MF->getInfo<NVPTXMachineFunctionInfo>();
225*9880d681SAndroid Build Coastguard Worker const char *Sym = MFI->getImageHandleSymbol(Index);
226*9880d681SAndroid Build Coastguard Worker std::string *SymNamePtr =
227*9880d681SAndroid Build Coastguard Worker nvTM.getManagedStrPool()->getManagedString(Sym);
228*9880d681SAndroid Build Coastguard Worker MCOp = GetSymbolRef(OutContext.getOrCreateSymbol(
229*9880d681SAndroid Build Coastguard Worker StringRef(SymNamePtr->c_str())));
230*9880d681SAndroid Build Coastguard Worker }
231*9880d681SAndroid Build Coastguard Worker
lowerToMCInst(const MachineInstr * MI,MCInst & OutMI)232*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
233*9880d681SAndroid Build Coastguard Worker OutMI.setOpcode(MI->getOpcode());
234*9880d681SAndroid Build Coastguard Worker // Special: Do not mangle symbol operand of CALL_PROTOTYPE
235*9880d681SAndroid Build Coastguard Worker if (MI->getOpcode() == NVPTX::CALL_PROTOTYPE) {
236*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(0);
237*9880d681SAndroid Build Coastguard Worker OutMI.addOperand(GetSymbolRef(
238*9880d681SAndroid Build Coastguard Worker OutContext.getOrCreateSymbol(Twine(MO.getSymbolName()))));
239*9880d681SAndroid Build Coastguard Worker return;
240*9880d681SAndroid Build Coastguard Worker }
241*9880d681SAndroid Build Coastguard Worker
242*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
243*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(i);
244*9880d681SAndroid Build Coastguard Worker
245*9880d681SAndroid Build Coastguard Worker MCOperand MCOp;
246*9880d681SAndroid Build Coastguard Worker if (!nvptxSubtarget->hasImageHandles()) {
247*9880d681SAndroid Build Coastguard Worker if (lowerImageHandleOperand(MI, i, MCOp)) {
248*9880d681SAndroid Build Coastguard Worker OutMI.addOperand(MCOp);
249*9880d681SAndroid Build Coastguard Worker continue;
250*9880d681SAndroid Build Coastguard Worker }
251*9880d681SAndroid Build Coastguard Worker }
252*9880d681SAndroid Build Coastguard Worker
253*9880d681SAndroid Build Coastguard Worker if (lowerOperand(MO, MCOp))
254*9880d681SAndroid Build Coastguard Worker OutMI.addOperand(MCOp);
255*9880d681SAndroid Build Coastguard Worker }
256*9880d681SAndroid Build Coastguard Worker }
257*9880d681SAndroid Build Coastguard Worker
lowerOperand(const MachineOperand & MO,MCOperand & MCOp)258*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::lowerOperand(const MachineOperand &MO,
259*9880d681SAndroid Build Coastguard Worker MCOperand &MCOp) {
260*9880d681SAndroid Build Coastguard Worker switch (MO.getType()) {
261*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("unknown operand type");
262*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Register:
263*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createReg(encodeVirtualRegister(MO.getReg()));
264*9880d681SAndroid Build Coastguard Worker break;
265*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Immediate:
266*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createImm(MO.getImm());
267*9880d681SAndroid Build Coastguard Worker break;
268*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_MachineBasicBlock:
269*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(
270*9880d681SAndroid Build Coastguard Worker MO.getMBB()->getSymbol(), OutContext));
271*9880d681SAndroid Build Coastguard Worker break;
272*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_ExternalSymbol:
273*9880d681SAndroid Build Coastguard Worker MCOp = GetSymbolRef(GetExternalSymbolSymbol(MO.getSymbolName()));
274*9880d681SAndroid Build Coastguard Worker break;
275*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_GlobalAddress:
276*9880d681SAndroid Build Coastguard Worker MCOp = GetSymbolRef(getSymbol(MO.getGlobal()));
277*9880d681SAndroid Build Coastguard Worker break;
278*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_FPImmediate: {
279*9880d681SAndroid Build Coastguard Worker const ConstantFP *Cnt = MO.getFPImm();
280*9880d681SAndroid Build Coastguard Worker const APFloat &Val = Cnt->getValueAPF();
281*9880d681SAndroid Build Coastguard Worker
282*9880d681SAndroid Build Coastguard Worker switch (Cnt->getType()->getTypeID()) {
283*9880d681SAndroid Build Coastguard Worker default: report_fatal_error("Unsupported FP type"); break;
284*9880d681SAndroid Build Coastguard Worker case Type::FloatTyID:
285*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createExpr(
286*9880d681SAndroid Build Coastguard Worker NVPTXFloatMCExpr::createConstantFPSingle(Val, OutContext));
287*9880d681SAndroid Build Coastguard Worker break;
288*9880d681SAndroid Build Coastguard Worker case Type::DoubleTyID:
289*9880d681SAndroid Build Coastguard Worker MCOp = MCOperand::createExpr(
290*9880d681SAndroid Build Coastguard Worker NVPTXFloatMCExpr::createConstantFPDouble(Val, OutContext));
291*9880d681SAndroid Build Coastguard Worker break;
292*9880d681SAndroid Build Coastguard Worker }
293*9880d681SAndroid Build Coastguard Worker break;
294*9880d681SAndroid Build Coastguard Worker }
295*9880d681SAndroid Build Coastguard Worker }
296*9880d681SAndroid Build Coastguard Worker return true;
297*9880d681SAndroid Build Coastguard Worker }
298*9880d681SAndroid Build Coastguard Worker
encodeVirtualRegister(unsigned Reg)299*9880d681SAndroid Build Coastguard Worker unsigned NVPTXAsmPrinter::encodeVirtualRegister(unsigned Reg) {
300*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(Reg)) {
301*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = MRI->getRegClass(Reg);
302*9880d681SAndroid Build Coastguard Worker
303*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> &RegMap = VRegMapping[RC];
304*9880d681SAndroid Build Coastguard Worker unsigned RegNum = RegMap[Reg];
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker // Encode the register class in the upper 4 bits
307*9880d681SAndroid Build Coastguard Worker // Must be kept in sync with NVPTXInstPrinter::printRegName
308*9880d681SAndroid Build Coastguard Worker unsigned Ret = 0;
309*9880d681SAndroid Build Coastguard Worker if (RC == &NVPTX::Int1RegsRegClass) {
310*9880d681SAndroid Build Coastguard Worker Ret = (1 << 28);
311*9880d681SAndroid Build Coastguard Worker } else if (RC == &NVPTX::Int16RegsRegClass) {
312*9880d681SAndroid Build Coastguard Worker Ret = (2 << 28);
313*9880d681SAndroid Build Coastguard Worker } else if (RC == &NVPTX::Int32RegsRegClass) {
314*9880d681SAndroid Build Coastguard Worker Ret = (3 << 28);
315*9880d681SAndroid Build Coastguard Worker } else if (RC == &NVPTX::Int64RegsRegClass) {
316*9880d681SAndroid Build Coastguard Worker Ret = (4 << 28);
317*9880d681SAndroid Build Coastguard Worker } else if (RC == &NVPTX::Float32RegsRegClass) {
318*9880d681SAndroid Build Coastguard Worker Ret = (5 << 28);
319*9880d681SAndroid Build Coastguard Worker } else if (RC == &NVPTX::Float64RegsRegClass) {
320*9880d681SAndroid Build Coastguard Worker Ret = (6 << 28);
321*9880d681SAndroid Build Coastguard Worker } else {
322*9880d681SAndroid Build Coastguard Worker report_fatal_error("Bad register class");
323*9880d681SAndroid Build Coastguard Worker }
324*9880d681SAndroid Build Coastguard Worker
325*9880d681SAndroid Build Coastguard Worker // Insert the vreg number
326*9880d681SAndroid Build Coastguard Worker Ret |= (RegNum & 0x0FFFFFFF);
327*9880d681SAndroid Build Coastguard Worker return Ret;
328*9880d681SAndroid Build Coastguard Worker } else {
329*9880d681SAndroid Build Coastguard Worker // Some special-use registers are actually physical registers.
330*9880d681SAndroid Build Coastguard Worker // Encode this as the register class ID of 0 and the real register ID.
331*9880d681SAndroid Build Coastguard Worker return Reg & 0x0FFFFFFF;
332*9880d681SAndroid Build Coastguard Worker }
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker
GetSymbolRef(const MCSymbol * Symbol)335*9880d681SAndroid Build Coastguard Worker MCOperand NVPTXAsmPrinter::GetSymbolRef(const MCSymbol *Symbol) {
336*9880d681SAndroid Build Coastguard Worker const MCExpr *Expr;
337*9880d681SAndroid Build Coastguard Worker Expr = MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None,
338*9880d681SAndroid Build Coastguard Worker OutContext);
339*9880d681SAndroid Build Coastguard Worker return MCOperand::createExpr(Expr);
340*9880d681SAndroid Build Coastguard Worker }
341*9880d681SAndroid Build Coastguard Worker
printReturnValStr(const Function * F,raw_ostream & O)342*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printReturnValStr(const Function *F, raw_ostream &O) {
343*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
344*9880d681SAndroid Build Coastguard Worker const TargetLowering *TLI = nvptxSubtarget->getTargetLowering();
345*9880d681SAndroid Build Coastguard Worker
346*9880d681SAndroid Build Coastguard Worker Type *Ty = F->getReturnType();
347*9880d681SAndroid Build Coastguard Worker
348*9880d681SAndroid Build Coastguard Worker bool isABI = (nvptxSubtarget->getSmVersion() >= 20);
349*9880d681SAndroid Build Coastguard Worker
350*9880d681SAndroid Build Coastguard Worker if (Ty->getTypeID() == Type::VoidTyID)
351*9880d681SAndroid Build Coastguard Worker return;
352*9880d681SAndroid Build Coastguard Worker
353*9880d681SAndroid Build Coastguard Worker O << " (";
354*9880d681SAndroid Build Coastguard Worker
355*9880d681SAndroid Build Coastguard Worker if (isABI) {
356*9880d681SAndroid Build Coastguard Worker if (Ty->isFloatingPointTy() || Ty->isIntegerTy()) {
357*9880d681SAndroid Build Coastguard Worker unsigned size = 0;
358*9880d681SAndroid Build Coastguard Worker if (auto *ITy = dyn_cast<IntegerType>(Ty)) {
359*9880d681SAndroid Build Coastguard Worker size = ITy->getBitWidth();
360*9880d681SAndroid Build Coastguard Worker if (size < 32)
361*9880d681SAndroid Build Coastguard Worker size = 32;
362*9880d681SAndroid Build Coastguard Worker } else {
363*9880d681SAndroid Build Coastguard Worker assert(Ty->isFloatingPointTy() && "Floating point type expected here");
364*9880d681SAndroid Build Coastguard Worker size = Ty->getPrimitiveSizeInBits();
365*9880d681SAndroid Build Coastguard Worker }
366*9880d681SAndroid Build Coastguard Worker
367*9880d681SAndroid Build Coastguard Worker O << ".param .b" << size << " func_retval0";
368*9880d681SAndroid Build Coastguard Worker } else if (isa<PointerType>(Ty)) {
369*9880d681SAndroid Build Coastguard Worker O << ".param .b" << TLI->getPointerTy(DL).getSizeInBits()
370*9880d681SAndroid Build Coastguard Worker << " func_retval0";
371*9880d681SAndroid Build Coastguard Worker } else if ((Ty->getTypeID() == Type::StructTyID) || isa<VectorType>(Ty)) {
372*9880d681SAndroid Build Coastguard Worker unsigned totalsz = DL.getTypeAllocSize(Ty);
373*9880d681SAndroid Build Coastguard Worker unsigned retAlignment = 0;
374*9880d681SAndroid Build Coastguard Worker if (!llvm::getAlign(*F, 0, retAlignment))
375*9880d681SAndroid Build Coastguard Worker retAlignment = DL.getABITypeAlignment(Ty);
376*9880d681SAndroid Build Coastguard Worker O << ".param .align " << retAlignment << " .b8 func_retval0[" << totalsz
377*9880d681SAndroid Build Coastguard Worker << "]";
378*9880d681SAndroid Build Coastguard Worker } else
379*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown return type");
380*9880d681SAndroid Build Coastguard Worker } else {
381*9880d681SAndroid Build Coastguard Worker SmallVector<EVT, 16> vtparts;
382*9880d681SAndroid Build Coastguard Worker ComputeValueVTs(*TLI, DL, Ty, vtparts);
383*9880d681SAndroid Build Coastguard Worker unsigned idx = 0;
384*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = vtparts.size(); i != e; ++i) {
385*9880d681SAndroid Build Coastguard Worker unsigned elems = 1;
386*9880d681SAndroid Build Coastguard Worker EVT elemtype = vtparts[i];
387*9880d681SAndroid Build Coastguard Worker if (vtparts[i].isVector()) {
388*9880d681SAndroid Build Coastguard Worker elems = vtparts[i].getVectorNumElements();
389*9880d681SAndroid Build Coastguard Worker elemtype = vtparts[i].getVectorElementType();
390*9880d681SAndroid Build Coastguard Worker }
391*9880d681SAndroid Build Coastguard Worker
392*9880d681SAndroid Build Coastguard Worker for (unsigned j = 0, je = elems; j != je; ++j) {
393*9880d681SAndroid Build Coastguard Worker unsigned sz = elemtype.getSizeInBits();
394*9880d681SAndroid Build Coastguard Worker if (elemtype.isInteger() && (sz < 32))
395*9880d681SAndroid Build Coastguard Worker sz = 32;
396*9880d681SAndroid Build Coastguard Worker O << ".reg .b" << sz << " func_retval" << idx;
397*9880d681SAndroid Build Coastguard Worker if (j < je - 1)
398*9880d681SAndroid Build Coastguard Worker O << ", ";
399*9880d681SAndroid Build Coastguard Worker ++idx;
400*9880d681SAndroid Build Coastguard Worker }
401*9880d681SAndroid Build Coastguard Worker if (i < e - 1)
402*9880d681SAndroid Build Coastguard Worker O << ", ";
403*9880d681SAndroid Build Coastguard Worker }
404*9880d681SAndroid Build Coastguard Worker }
405*9880d681SAndroid Build Coastguard Worker O << ") ";
406*9880d681SAndroid Build Coastguard Worker return;
407*9880d681SAndroid Build Coastguard Worker }
408*9880d681SAndroid Build Coastguard Worker
printReturnValStr(const MachineFunction & MF,raw_ostream & O)409*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printReturnValStr(const MachineFunction &MF,
410*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
411*9880d681SAndroid Build Coastguard Worker const Function *F = MF.getFunction();
412*9880d681SAndroid Build Coastguard Worker printReturnValStr(F, O);
413*9880d681SAndroid Build Coastguard Worker }
414*9880d681SAndroid Build Coastguard Worker
415*9880d681SAndroid Build Coastguard Worker // Return true if MBB is the header of a loop marked with
416*9880d681SAndroid Build Coastguard Worker // llvm.loop.unroll.disable.
417*9880d681SAndroid Build Coastguard Worker // TODO: consider "#pragma unroll 1" which is equivalent to "#pragma nounroll".
isLoopHeaderOfNoUnroll(const MachineBasicBlock & MBB) const418*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::isLoopHeaderOfNoUnroll(
419*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock &MBB) const {
420*9880d681SAndroid Build Coastguard Worker MachineLoopInfo &LI = getAnalysis<MachineLoopInfo>();
421*9880d681SAndroid Build Coastguard Worker // We insert .pragma "nounroll" only to the loop header.
422*9880d681SAndroid Build Coastguard Worker if (!LI.isLoopHeader(&MBB))
423*9880d681SAndroid Build Coastguard Worker return false;
424*9880d681SAndroid Build Coastguard Worker
425*9880d681SAndroid Build Coastguard Worker // llvm.loop.unroll.disable is marked on the back edges of a loop. Therefore,
426*9880d681SAndroid Build Coastguard Worker // we iterate through each back edge of the loop with header MBB, and check
427*9880d681SAndroid Build Coastguard Worker // whether its metadata contains llvm.loop.unroll.disable.
428*9880d681SAndroid Build Coastguard Worker for (auto I = MBB.pred_begin(); I != MBB.pred_end(); ++I) {
429*9880d681SAndroid Build Coastguard Worker const MachineBasicBlock *PMBB = *I;
430*9880d681SAndroid Build Coastguard Worker if (LI.getLoopFor(PMBB) != LI.getLoopFor(&MBB)) {
431*9880d681SAndroid Build Coastguard Worker // Edges from other loops to MBB are not back edges.
432*9880d681SAndroid Build Coastguard Worker continue;
433*9880d681SAndroid Build Coastguard Worker }
434*9880d681SAndroid Build Coastguard Worker if (const BasicBlock *PBB = PMBB->getBasicBlock()) {
435*9880d681SAndroid Build Coastguard Worker if (MDNode *LoopID =
436*9880d681SAndroid Build Coastguard Worker PBB->getTerminator()->getMetadata(LLVMContext::MD_loop)) {
437*9880d681SAndroid Build Coastguard Worker if (GetUnrollMetadata(LoopID, "llvm.loop.unroll.disable"))
438*9880d681SAndroid Build Coastguard Worker return true;
439*9880d681SAndroid Build Coastguard Worker }
440*9880d681SAndroid Build Coastguard Worker }
441*9880d681SAndroid Build Coastguard Worker }
442*9880d681SAndroid Build Coastguard Worker return false;
443*9880d681SAndroid Build Coastguard Worker }
444*9880d681SAndroid Build Coastguard Worker
EmitBasicBlockStart(const MachineBasicBlock & MBB) const445*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
446*9880d681SAndroid Build Coastguard Worker AsmPrinter::EmitBasicBlockStart(MBB);
447*9880d681SAndroid Build Coastguard Worker if (isLoopHeaderOfNoUnroll(MBB))
448*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(StringRef("\t.pragma \"nounroll\";\n"));
449*9880d681SAndroid Build Coastguard Worker }
450*9880d681SAndroid Build Coastguard Worker
EmitFunctionEntryLabel()451*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::EmitFunctionEntryLabel() {
452*9880d681SAndroid Build Coastguard Worker SmallString<128> Str;
453*9880d681SAndroid Build Coastguard Worker raw_svector_ostream O(Str);
454*9880d681SAndroid Build Coastguard Worker
455*9880d681SAndroid Build Coastguard Worker if (!GlobalsEmitted) {
456*9880d681SAndroid Build Coastguard Worker emitGlobals(*MF->getFunction()->getParent());
457*9880d681SAndroid Build Coastguard Worker GlobalsEmitted = true;
458*9880d681SAndroid Build Coastguard Worker }
459*9880d681SAndroid Build Coastguard Worker
460*9880d681SAndroid Build Coastguard Worker // Set up
461*9880d681SAndroid Build Coastguard Worker MRI = &MF->getRegInfo();
462*9880d681SAndroid Build Coastguard Worker F = MF->getFunction();
463*9880d681SAndroid Build Coastguard Worker emitLinkageDirective(F, O);
464*9880d681SAndroid Build Coastguard Worker if (llvm::isKernelFunction(*F))
465*9880d681SAndroid Build Coastguard Worker O << ".entry ";
466*9880d681SAndroid Build Coastguard Worker else {
467*9880d681SAndroid Build Coastguard Worker O << ".func ";
468*9880d681SAndroid Build Coastguard Worker printReturnValStr(*MF, O);
469*9880d681SAndroid Build Coastguard Worker }
470*9880d681SAndroid Build Coastguard Worker
471*9880d681SAndroid Build Coastguard Worker CurrentFnSym->print(O, MAI);
472*9880d681SAndroid Build Coastguard Worker
473*9880d681SAndroid Build Coastguard Worker emitFunctionParamList(*MF, O);
474*9880d681SAndroid Build Coastguard Worker
475*9880d681SAndroid Build Coastguard Worker if (llvm::isKernelFunction(*F))
476*9880d681SAndroid Build Coastguard Worker emitKernelFunctionDirectives(*F, O);
477*9880d681SAndroid Build Coastguard Worker
478*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(O.str());
479*9880d681SAndroid Build Coastguard Worker
480*9880d681SAndroid Build Coastguard Worker prevDebugLoc = DebugLoc();
481*9880d681SAndroid Build Coastguard Worker }
482*9880d681SAndroid Build Coastguard Worker
EmitFunctionBodyStart()483*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::EmitFunctionBodyStart() {
484*9880d681SAndroid Build Coastguard Worker VRegMapping.clear();
485*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(StringRef("{\n"));
486*9880d681SAndroid Build Coastguard Worker setAndEmitFunctionVirtualRegisters(*MF);
487*9880d681SAndroid Build Coastguard Worker
488*9880d681SAndroid Build Coastguard Worker SmallString<128> Str;
489*9880d681SAndroid Build Coastguard Worker raw_svector_ostream O(Str);
490*9880d681SAndroid Build Coastguard Worker emitDemotedVars(MF->getFunction(), O);
491*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(O.str());
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker
EmitFunctionBodyEnd()494*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::EmitFunctionBodyEnd() {
495*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(StringRef("}\n"));
496*9880d681SAndroid Build Coastguard Worker VRegMapping.clear();
497*9880d681SAndroid Build Coastguard Worker }
498*9880d681SAndroid Build Coastguard Worker
emitImplicitDef(const MachineInstr * MI) const499*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
500*9880d681SAndroid Build Coastguard Worker unsigned RegNo = MI->getOperand(0).getReg();
501*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(RegNo)) {
502*9880d681SAndroid Build Coastguard Worker OutStreamer->AddComment(Twine("implicit-def: ") +
503*9880d681SAndroid Build Coastguard Worker getVirtualRegisterName(RegNo));
504*9880d681SAndroid Build Coastguard Worker } else {
505*9880d681SAndroid Build Coastguard Worker OutStreamer->AddComment(Twine("implicit-def: ") +
506*9880d681SAndroid Build Coastguard Worker nvptxSubtarget->getRegisterInfo()->getName(RegNo));
507*9880d681SAndroid Build Coastguard Worker }
508*9880d681SAndroid Build Coastguard Worker OutStreamer->AddBlankLine();
509*9880d681SAndroid Build Coastguard Worker }
510*9880d681SAndroid Build Coastguard Worker
emitKernelFunctionDirectives(const Function & F,raw_ostream & O) const511*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitKernelFunctionDirectives(const Function &F,
512*9880d681SAndroid Build Coastguard Worker raw_ostream &O) const {
513*9880d681SAndroid Build Coastguard Worker // If the NVVM IR has some of reqntid* specified, then output
514*9880d681SAndroid Build Coastguard Worker // the reqntid directive, and set the unspecified ones to 1.
515*9880d681SAndroid Build Coastguard Worker // If none of reqntid* is specified, don't output reqntid directive.
516*9880d681SAndroid Build Coastguard Worker unsigned reqntidx, reqntidy, reqntidz;
517*9880d681SAndroid Build Coastguard Worker bool specified = false;
518*9880d681SAndroid Build Coastguard Worker if (!llvm::getReqNTIDx(F, reqntidx))
519*9880d681SAndroid Build Coastguard Worker reqntidx = 1;
520*9880d681SAndroid Build Coastguard Worker else
521*9880d681SAndroid Build Coastguard Worker specified = true;
522*9880d681SAndroid Build Coastguard Worker if (!llvm::getReqNTIDy(F, reqntidy))
523*9880d681SAndroid Build Coastguard Worker reqntidy = 1;
524*9880d681SAndroid Build Coastguard Worker else
525*9880d681SAndroid Build Coastguard Worker specified = true;
526*9880d681SAndroid Build Coastguard Worker if (!llvm::getReqNTIDz(F, reqntidz))
527*9880d681SAndroid Build Coastguard Worker reqntidz = 1;
528*9880d681SAndroid Build Coastguard Worker else
529*9880d681SAndroid Build Coastguard Worker specified = true;
530*9880d681SAndroid Build Coastguard Worker
531*9880d681SAndroid Build Coastguard Worker if (specified)
532*9880d681SAndroid Build Coastguard Worker O << ".reqntid " << reqntidx << ", " << reqntidy << ", " << reqntidz
533*9880d681SAndroid Build Coastguard Worker << "\n";
534*9880d681SAndroid Build Coastguard Worker
535*9880d681SAndroid Build Coastguard Worker // If the NVVM IR has some of maxntid* specified, then output
536*9880d681SAndroid Build Coastguard Worker // the maxntid directive, and set the unspecified ones to 1.
537*9880d681SAndroid Build Coastguard Worker // If none of maxntid* is specified, don't output maxntid directive.
538*9880d681SAndroid Build Coastguard Worker unsigned maxntidx, maxntidy, maxntidz;
539*9880d681SAndroid Build Coastguard Worker specified = false;
540*9880d681SAndroid Build Coastguard Worker if (!llvm::getMaxNTIDx(F, maxntidx))
541*9880d681SAndroid Build Coastguard Worker maxntidx = 1;
542*9880d681SAndroid Build Coastguard Worker else
543*9880d681SAndroid Build Coastguard Worker specified = true;
544*9880d681SAndroid Build Coastguard Worker if (!llvm::getMaxNTIDy(F, maxntidy))
545*9880d681SAndroid Build Coastguard Worker maxntidy = 1;
546*9880d681SAndroid Build Coastguard Worker else
547*9880d681SAndroid Build Coastguard Worker specified = true;
548*9880d681SAndroid Build Coastguard Worker if (!llvm::getMaxNTIDz(F, maxntidz))
549*9880d681SAndroid Build Coastguard Worker maxntidz = 1;
550*9880d681SAndroid Build Coastguard Worker else
551*9880d681SAndroid Build Coastguard Worker specified = true;
552*9880d681SAndroid Build Coastguard Worker
553*9880d681SAndroid Build Coastguard Worker if (specified)
554*9880d681SAndroid Build Coastguard Worker O << ".maxntid " << maxntidx << ", " << maxntidy << ", " << maxntidz
555*9880d681SAndroid Build Coastguard Worker << "\n";
556*9880d681SAndroid Build Coastguard Worker
557*9880d681SAndroid Build Coastguard Worker unsigned mincta;
558*9880d681SAndroid Build Coastguard Worker if (llvm::getMinCTASm(F, mincta))
559*9880d681SAndroid Build Coastguard Worker O << ".minnctapersm " << mincta << "\n";
560*9880d681SAndroid Build Coastguard Worker }
561*9880d681SAndroid Build Coastguard Worker
562*9880d681SAndroid Build Coastguard Worker std::string
getVirtualRegisterName(unsigned Reg) const563*9880d681SAndroid Build Coastguard Worker NVPTXAsmPrinter::getVirtualRegisterName(unsigned Reg) const {
564*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = MRI->getRegClass(Reg);
565*9880d681SAndroid Build Coastguard Worker
566*9880d681SAndroid Build Coastguard Worker std::string Name;
567*9880d681SAndroid Build Coastguard Worker raw_string_ostream NameStr(Name);
568*9880d681SAndroid Build Coastguard Worker
569*9880d681SAndroid Build Coastguard Worker VRegRCMap::const_iterator I = VRegMapping.find(RC);
570*9880d681SAndroid Build Coastguard Worker assert(I != VRegMapping.end() && "Bad register class");
571*9880d681SAndroid Build Coastguard Worker const DenseMap<unsigned, unsigned> &RegMap = I->second;
572*9880d681SAndroid Build Coastguard Worker
573*9880d681SAndroid Build Coastguard Worker VRegMap::const_iterator VI = RegMap.find(Reg);
574*9880d681SAndroid Build Coastguard Worker assert(VI != RegMap.end() && "Bad virtual register");
575*9880d681SAndroid Build Coastguard Worker unsigned MappedVR = VI->second;
576*9880d681SAndroid Build Coastguard Worker
577*9880d681SAndroid Build Coastguard Worker NameStr << getNVPTXRegClassStr(RC) << MappedVR;
578*9880d681SAndroid Build Coastguard Worker
579*9880d681SAndroid Build Coastguard Worker NameStr.flush();
580*9880d681SAndroid Build Coastguard Worker return Name;
581*9880d681SAndroid Build Coastguard Worker }
582*9880d681SAndroid Build Coastguard Worker
emitVirtualRegister(unsigned int vr,raw_ostream & O)583*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitVirtualRegister(unsigned int vr,
584*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
585*9880d681SAndroid Build Coastguard Worker O << getVirtualRegisterName(vr);
586*9880d681SAndroid Build Coastguard Worker }
587*9880d681SAndroid Build Coastguard Worker
printVecModifiedImmediate(const MachineOperand & MO,const char * Modifier,raw_ostream & O)588*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printVecModifiedImmediate(
589*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO, const char *Modifier, raw_ostream &O) {
590*9880d681SAndroid Build Coastguard Worker static const char vecelem[] = { '0', '1', '2', '3', '0', '1', '2', '3' };
591*9880d681SAndroid Build Coastguard Worker int Imm = (int) MO.getImm();
592*9880d681SAndroid Build Coastguard Worker if (0 == strcmp(Modifier, "vecelem"))
593*9880d681SAndroid Build Coastguard Worker O << "_" << vecelem[Imm];
594*9880d681SAndroid Build Coastguard Worker else if (0 == strcmp(Modifier, "vecv4comm1")) {
595*9880d681SAndroid Build Coastguard Worker if ((Imm < 0) || (Imm > 3))
596*9880d681SAndroid Build Coastguard Worker O << "//";
597*9880d681SAndroid Build Coastguard Worker } else if (0 == strcmp(Modifier, "vecv4comm2")) {
598*9880d681SAndroid Build Coastguard Worker if ((Imm < 4) || (Imm > 7))
599*9880d681SAndroid Build Coastguard Worker O << "//";
600*9880d681SAndroid Build Coastguard Worker } else if (0 == strcmp(Modifier, "vecv4pos")) {
601*9880d681SAndroid Build Coastguard Worker if (Imm < 0)
602*9880d681SAndroid Build Coastguard Worker Imm = 0;
603*9880d681SAndroid Build Coastguard Worker O << "_" << vecelem[Imm % 4];
604*9880d681SAndroid Build Coastguard Worker } else if (0 == strcmp(Modifier, "vecv2comm1")) {
605*9880d681SAndroid Build Coastguard Worker if ((Imm < 0) || (Imm > 1))
606*9880d681SAndroid Build Coastguard Worker O << "//";
607*9880d681SAndroid Build Coastguard Worker } else if (0 == strcmp(Modifier, "vecv2comm2")) {
608*9880d681SAndroid Build Coastguard Worker if ((Imm < 2) || (Imm > 3))
609*9880d681SAndroid Build Coastguard Worker O << "//";
610*9880d681SAndroid Build Coastguard Worker } else if (0 == strcmp(Modifier, "vecv2pos")) {
611*9880d681SAndroid Build Coastguard Worker if (Imm < 0)
612*9880d681SAndroid Build Coastguard Worker Imm = 0;
613*9880d681SAndroid Build Coastguard Worker O << "_" << vecelem[Imm % 2];
614*9880d681SAndroid Build Coastguard Worker } else
615*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown Modifier on immediate operand");
616*9880d681SAndroid Build Coastguard Worker }
617*9880d681SAndroid Build Coastguard Worker
618*9880d681SAndroid Build Coastguard Worker
619*9880d681SAndroid Build Coastguard Worker
emitDeclaration(const Function * F,raw_ostream & O)620*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitDeclaration(const Function *F, raw_ostream &O) {
621*9880d681SAndroid Build Coastguard Worker
622*9880d681SAndroid Build Coastguard Worker emitLinkageDirective(F, O);
623*9880d681SAndroid Build Coastguard Worker if (llvm::isKernelFunction(*F))
624*9880d681SAndroid Build Coastguard Worker O << ".entry ";
625*9880d681SAndroid Build Coastguard Worker else
626*9880d681SAndroid Build Coastguard Worker O << ".func ";
627*9880d681SAndroid Build Coastguard Worker printReturnValStr(F, O);
628*9880d681SAndroid Build Coastguard Worker getSymbol(F)->print(O, MAI);
629*9880d681SAndroid Build Coastguard Worker O << "\n";
630*9880d681SAndroid Build Coastguard Worker emitFunctionParamList(F, O);
631*9880d681SAndroid Build Coastguard Worker O << ";\n";
632*9880d681SAndroid Build Coastguard Worker }
633*9880d681SAndroid Build Coastguard Worker
usedInGlobalVarDef(const Constant * C)634*9880d681SAndroid Build Coastguard Worker static bool usedInGlobalVarDef(const Constant *C) {
635*9880d681SAndroid Build Coastguard Worker if (!C)
636*9880d681SAndroid Build Coastguard Worker return false;
637*9880d681SAndroid Build Coastguard Worker
638*9880d681SAndroid Build Coastguard Worker if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
639*9880d681SAndroid Build Coastguard Worker return GV->getName() != "llvm.used";
640*9880d681SAndroid Build Coastguard Worker }
641*9880d681SAndroid Build Coastguard Worker
642*9880d681SAndroid Build Coastguard Worker for (const User *U : C->users())
643*9880d681SAndroid Build Coastguard Worker if (const Constant *C = dyn_cast<Constant>(U))
644*9880d681SAndroid Build Coastguard Worker if (usedInGlobalVarDef(C))
645*9880d681SAndroid Build Coastguard Worker return true;
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker return false;
648*9880d681SAndroid Build Coastguard Worker }
649*9880d681SAndroid Build Coastguard Worker
usedInOneFunc(const User * U,Function const * & oneFunc)650*9880d681SAndroid Build Coastguard Worker static bool usedInOneFunc(const User *U, Function const *&oneFunc) {
651*9880d681SAndroid Build Coastguard Worker if (const GlobalVariable *othergv = dyn_cast<GlobalVariable>(U)) {
652*9880d681SAndroid Build Coastguard Worker if (othergv->getName() == "llvm.used")
653*9880d681SAndroid Build Coastguard Worker return true;
654*9880d681SAndroid Build Coastguard Worker }
655*9880d681SAndroid Build Coastguard Worker
656*9880d681SAndroid Build Coastguard Worker if (const Instruction *instr = dyn_cast<Instruction>(U)) {
657*9880d681SAndroid Build Coastguard Worker if (instr->getParent() && instr->getParent()->getParent()) {
658*9880d681SAndroid Build Coastguard Worker const Function *curFunc = instr->getParent()->getParent();
659*9880d681SAndroid Build Coastguard Worker if (oneFunc && (curFunc != oneFunc))
660*9880d681SAndroid Build Coastguard Worker return false;
661*9880d681SAndroid Build Coastguard Worker oneFunc = curFunc;
662*9880d681SAndroid Build Coastguard Worker return true;
663*9880d681SAndroid Build Coastguard Worker } else
664*9880d681SAndroid Build Coastguard Worker return false;
665*9880d681SAndroid Build Coastguard Worker }
666*9880d681SAndroid Build Coastguard Worker
667*9880d681SAndroid Build Coastguard Worker for (const User *UU : U->users())
668*9880d681SAndroid Build Coastguard Worker if (!usedInOneFunc(UU, oneFunc))
669*9880d681SAndroid Build Coastguard Worker return false;
670*9880d681SAndroid Build Coastguard Worker
671*9880d681SAndroid Build Coastguard Worker return true;
672*9880d681SAndroid Build Coastguard Worker }
673*9880d681SAndroid Build Coastguard Worker
674*9880d681SAndroid Build Coastguard Worker /* Find out if a global variable can be demoted to local scope.
675*9880d681SAndroid Build Coastguard Worker * Currently, this is valid for CUDA shared variables, which have local
676*9880d681SAndroid Build Coastguard Worker * scope and global lifetime. So the conditions to check are :
677*9880d681SAndroid Build Coastguard Worker * 1. Is the global variable in shared address space?
678*9880d681SAndroid Build Coastguard Worker * 2. Does it have internal linkage?
679*9880d681SAndroid Build Coastguard Worker * 3. Is the global variable referenced only in one function?
680*9880d681SAndroid Build Coastguard Worker */
canDemoteGlobalVar(const GlobalVariable * gv,Function const * & f)681*9880d681SAndroid Build Coastguard Worker static bool canDemoteGlobalVar(const GlobalVariable *gv, Function const *&f) {
682*9880d681SAndroid Build Coastguard Worker if (!gv->hasInternalLinkage())
683*9880d681SAndroid Build Coastguard Worker return false;
684*9880d681SAndroid Build Coastguard Worker PointerType *Pty = gv->getType();
685*9880d681SAndroid Build Coastguard Worker if (Pty->getAddressSpace() != llvm::ADDRESS_SPACE_SHARED)
686*9880d681SAndroid Build Coastguard Worker return false;
687*9880d681SAndroid Build Coastguard Worker
688*9880d681SAndroid Build Coastguard Worker const Function *oneFunc = nullptr;
689*9880d681SAndroid Build Coastguard Worker
690*9880d681SAndroid Build Coastguard Worker bool flag = usedInOneFunc(gv, oneFunc);
691*9880d681SAndroid Build Coastguard Worker if (!flag)
692*9880d681SAndroid Build Coastguard Worker return false;
693*9880d681SAndroid Build Coastguard Worker if (!oneFunc)
694*9880d681SAndroid Build Coastguard Worker return false;
695*9880d681SAndroid Build Coastguard Worker f = oneFunc;
696*9880d681SAndroid Build Coastguard Worker return true;
697*9880d681SAndroid Build Coastguard Worker }
698*9880d681SAndroid Build Coastguard Worker
useFuncSeen(const Constant * C,llvm::DenseMap<const Function *,bool> & seenMap)699*9880d681SAndroid Build Coastguard Worker static bool useFuncSeen(const Constant *C,
700*9880d681SAndroid Build Coastguard Worker llvm::DenseMap<const Function *, bool> &seenMap) {
701*9880d681SAndroid Build Coastguard Worker for (const User *U : C->users()) {
702*9880d681SAndroid Build Coastguard Worker if (const Constant *cu = dyn_cast<Constant>(U)) {
703*9880d681SAndroid Build Coastguard Worker if (useFuncSeen(cu, seenMap))
704*9880d681SAndroid Build Coastguard Worker return true;
705*9880d681SAndroid Build Coastguard Worker } else if (const Instruction *I = dyn_cast<Instruction>(U)) {
706*9880d681SAndroid Build Coastguard Worker const BasicBlock *bb = I->getParent();
707*9880d681SAndroid Build Coastguard Worker if (!bb)
708*9880d681SAndroid Build Coastguard Worker continue;
709*9880d681SAndroid Build Coastguard Worker const Function *caller = bb->getParent();
710*9880d681SAndroid Build Coastguard Worker if (!caller)
711*9880d681SAndroid Build Coastguard Worker continue;
712*9880d681SAndroid Build Coastguard Worker if (seenMap.find(caller) != seenMap.end())
713*9880d681SAndroid Build Coastguard Worker return true;
714*9880d681SAndroid Build Coastguard Worker }
715*9880d681SAndroid Build Coastguard Worker }
716*9880d681SAndroid Build Coastguard Worker return false;
717*9880d681SAndroid Build Coastguard Worker }
718*9880d681SAndroid Build Coastguard Worker
emitDeclarations(const Module & M,raw_ostream & O)719*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitDeclarations(const Module &M, raw_ostream &O) {
720*9880d681SAndroid Build Coastguard Worker llvm::DenseMap<const Function *, bool> seenMap;
721*9880d681SAndroid Build Coastguard Worker for (Module::const_iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
722*9880d681SAndroid Build Coastguard Worker const Function *F = &*FI;
723*9880d681SAndroid Build Coastguard Worker
724*9880d681SAndroid Build Coastguard Worker if (F->isDeclaration()) {
725*9880d681SAndroid Build Coastguard Worker if (F->use_empty())
726*9880d681SAndroid Build Coastguard Worker continue;
727*9880d681SAndroid Build Coastguard Worker if (F->getIntrinsicID())
728*9880d681SAndroid Build Coastguard Worker continue;
729*9880d681SAndroid Build Coastguard Worker emitDeclaration(F, O);
730*9880d681SAndroid Build Coastguard Worker continue;
731*9880d681SAndroid Build Coastguard Worker }
732*9880d681SAndroid Build Coastguard Worker for (const User *U : F->users()) {
733*9880d681SAndroid Build Coastguard Worker if (const Constant *C = dyn_cast<Constant>(U)) {
734*9880d681SAndroid Build Coastguard Worker if (usedInGlobalVarDef(C)) {
735*9880d681SAndroid Build Coastguard Worker // The use is in the initialization of a global variable
736*9880d681SAndroid Build Coastguard Worker // that is a function pointer, so print a declaration
737*9880d681SAndroid Build Coastguard Worker // for the original function
738*9880d681SAndroid Build Coastguard Worker emitDeclaration(F, O);
739*9880d681SAndroid Build Coastguard Worker break;
740*9880d681SAndroid Build Coastguard Worker }
741*9880d681SAndroid Build Coastguard Worker // Emit a declaration of this function if the function that
742*9880d681SAndroid Build Coastguard Worker // uses this constant expr has already been seen.
743*9880d681SAndroid Build Coastguard Worker if (useFuncSeen(C, seenMap)) {
744*9880d681SAndroid Build Coastguard Worker emitDeclaration(F, O);
745*9880d681SAndroid Build Coastguard Worker break;
746*9880d681SAndroid Build Coastguard Worker }
747*9880d681SAndroid Build Coastguard Worker }
748*9880d681SAndroid Build Coastguard Worker
749*9880d681SAndroid Build Coastguard Worker if (!isa<Instruction>(U))
750*9880d681SAndroid Build Coastguard Worker continue;
751*9880d681SAndroid Build Coastguard Worker const Instruction *instr = cast<Instruction>(U);
752*9880d681SAndroid Build Coastguard Worker const BasicBlock *bb = instr->getParent();
753*9880d681SAndroid Build Coastguard Worker if (!bb)
754*9880d681SAndroid Build Coastguard Worker continue;
755*9880d681SAndroid Build Coastguard Worker const Function *caller = bb->getParent();
756*9880d681SAndroid Build Coastguard Worker if (!caller)
757*9880d681SAndroid Build Coastguard Worker continue;
758*9880d681SAndroid Build Coastguard Worker
759*9880d681SAndroid Build Coastguard Worker // If a caller has already been seen, then the caller is
760*9880d681SAndroid Build Coastguard Worker // appearing in the module before the callee. so print out
761*9880d681SAndroid Build Coastguard Worker // a declaration for the callee.
762*9880d681SAndroid Build Coastguard Worker if (seenMap.find(caller) != seenMap.end()) {
763*9880d681SAndroid Build Coastguard Worker emitDeclaration(F, O);
764*9880d681SAndroid Build Coastguard Worker break;
765*9880d681SAndroid Build Coastguard Worker }
766*9880d681SAndroid Build Coastguard Worker }
767*9880d681SAndroid Build Coastguard Worker seenMap[F] = true;
768*9880d681SAndroid Build Coastguard Worker }
769*9880d681SAndroid Build Coastguard Worker }
770*9880d681SAndroid Build Coastguard Worker
recordAndEmitFilenames(Module & M)771*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::recordAndEmitFilenames(Module &M) {
772*9880d681SAndroid Build Coastguard Worker DebugInfoFinder DbgFinder;
773*9880d681SAndroid Build Coastguard Worker DbgFinder.processModule(M);
774*9880d681SAndroid Build Coastguard Worker
775*9880d681SAndroid Build Coastguard Worker unsigned i = 1;
776*9880d681SAndroid Build Coastguard Worker for (const DICompileUnit *DIUnit : DbgFinder.compile_units()) {
777*9880d681SAndroid Build Coastguard Worker StringRef Filename = DIUnit->getFilename();
778*9880d681SAndroid Build Coastguard Worker StringRef Dirname = DIUnit->getDirectory();
779*9880d681SAndroid Build Coastguard Worker SmallString<128> FullPathName = Dirname;
780*9880d681SAndroid Build Coastguard Worker if (!Dirname.empty() && !sys::path::is_absolute(Filename)) {
781*9880d681SAndroid Build Coastguard Worker sys::path::append(FullPathName, Filename);
782*9880d681SAndroid Build Coastguard Worker Filename = FullPathName;
783*9880d681SAndroid Build Coastguard Worker }
784*9880d681SAndroid Build Coastguard Worker if (filenameMap.find(Filename) != filenameMap.end())
785*9880d681SAndroid Build Coastguard Worker continue;
786*9880d681SAndroid Build Coastguard Worker filenameMap[Filename] = i;
787*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitDwarfFileDirective(i, "", Filename);
788*9880d681SAndroid Build Coastguard Worker ++i;
789*9880d681SAndroid Build Coastguard Worker }
790*9880d681SAndroid Build Coastguard Worker
791*9880d681SAndroid Build Coastguard Worker for (DISubprogram *SP : DbgFinder.subprograms()) {
792*9880d681SAndroid Build Coastguard Worker StringRef Filename = SP->getFilename();
793*9880d681SAndroid Build Coastguard Worker StringRef Dirname = SP->getDirectory();
794*9880d681SAndroid Build Coastguard Worker SmallString<128> FullPathName = Dirname;
795*9880d681SAndroid Build Coastguard Worker if (!Dirname.empty() && !sys::path::is_absolute(Filename)) {
796*9880d681SAndroid Build Coastguard Worker sys::path::append(FullPathName, Filename);
797*9880d681SAndroid Build Coastguard Worker Filename = FullPathName;
798*9880d681SAndroid Build Coastguard Worker }
799*9880d681SAndroid Build Coastguard Worker if (filenameMap.find(Filename) != filenameMap.end())
800*9880d681SAndroid Build Coastguard Worker continue;
801*9880d681SAndroid Build Coastguard Worker filenameMap[Filename] = i;
802*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitDwarfFileDirective(i, "", Filename);
803*9880d681SAndroid Build Coastguard Worker ++i;
804*9880d681SAndroid Build Coastguard Worker }
805*9880d681SAndroid Build Coastguard Worker }
806*9880d681SAndroid Build Coastguard Worker
isEmptyXXStructor(GlobalVariable * GV)807*9880d681SAndroid Build Coastguard Worker static bool isEmptyXXStructor(GlobalVariable *GV) {
808*9880d681SAndroid Build Coastguard Worker if (!GV) return true;
809*9880d681SAndroid Build Coastguard Worker const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
810*9880d681SAndroid Build Coastguard Worker if (!InitList) return true; // Not an array; we don't know how to parse.
811*9880d681SAndroid Build Coastguard Worker return InitList->getNumOperands() == 0;
812*9880d681SAndroid Build Coastguard Worker }
813*9880d681SAndroid Build Coastguard Worker
doInitialization(Module & M)814*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::doInitialization(Module &M) {
815*9880d681SAndroid Build Coastguard Worker // Construct a default subtarget off of the TargetMachine defaults. The
816*9880d681SAndroid Build Coastguard Worker // rest of NVPTX isn't friendly to change subtargets per function and
817*9880d681SAndroid Build Coastguard Worker // so the default TargetMachine will have all of the options.
818*9880d681SAndroid Build Coastguard Worker const Triple &TT = TM.getTargetTriple();
819*9880d681SAndroid Build Coastguard Worker StringRef CPU = TM.getTargetCPU();
820*9880d681SAndroid Build Coastguard Worker StringRef FS = TM.getTargetFeatureString();
821*9880d681SAndroid Build Coastguard Worker const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
822*9880d681SAndroid Build Coastguard Worker const NVPTXSubtarget STI(TT, CPU, FS, NTM);
823*9880d681SAndroid Build Coastguard Worker
824*9880d681SAndroid Build Coastguard Worker if (M.alias_size()) {
825*9880d681SAndroid Build Coastguard Worker report_fatal_error("Module has aliases, which NVPTX does not support.");
826*9880d681SAndroid Build Coastguard Worker return true; // error
827*9880d681SAndroid Build Coastguard Worker }
828*9880d681SAndroid Build Coastguard Worker if (!isEmptyXXStructor(M.getNamedGlobal("llvm.global_ctors"))) {
829*9880d681SAndroid Build Coastguard Worker report_fatal_error(
830*9880d681SAndroid Build Coastguard Worker "Module has a nontrivial global ctor, which NVPTX does not support.");
831*9880d681SAndroid Build Coastguard Worker return true; // error
832*9880d681SAndroid Build Coastguard Worker }
833*9880d681SAndroid Build Coastguard Worker if (!isEmptyXXStructor(M.getNamedGlobal("llvm.global_dtors"))) {
834*9880d681SAndroid Build Coastguard Worker report_fatal_error(
835*9880d681SAndroid Build Coastguard Worker "Module has a nontrivial global dtor, which NVPTX does not support.");
836*9880d681SAndroid Build Coastguard Worker return true; // error
837*9880d681SAndroid Build Coastguard Worker }
838*9880d681SAndroid Build Coastguard Worker
839*9880d681SAndroid Build Coastguard Worker SmallString<128> Str1;
840*9880d681SAndroid Build Coastguard Worker raw_svector_ostream OS1(Str1);
841*9880d681SAndroid Build Coastguard Worker
842*9880d681SAndroid Build Coastguard Worker MMI = getAnalysisIfAvailable<MachineModuleInfo>();
843*9880d681SAndroid Build Coastguard Worker
844*9880d681SAndroid Build Coastguard Worker // We need to call the parent's one explicitly.
845*9880d681SAndroid Build Coastguard Worker //bool Result = AsmPrinter::doInitialization(M);
846*9880d681SAndroid Build Coastguard Worker
847*9880d681SAndroid Build Coastguard Worker // Initialize TargetLoweringObjectFile.
848*9880d681SAndroid Build Coastguard Worker const_cast<TargetLoweringObjectFile &>(getObjFileLowering())
849*9880d681SAndroid Build Coastguard Worker .Initialize(OutContext, TM);
850*9880d681SAndroid Build Coastguard Worker
851*9880d681SAndroid Build Coastguard Worker Mang = new Mangler();
852*9880d681SAndroid Build Coastguard Worker
853*9880d681SAndroid Build Coastguard Worker // Emit header before any dwarf directives are emitted below.
854*9880d681SAndroid Build Coastguard Worker emitHeader(M, OS1, STI);
855*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(OS1.str());
856*9880d681SAndroid Build Coastguard Worker
857*9880d681SAndroid Build Coastguard Worker // Already commented out
858*9880d681SAndroid Build Coastguard Worker //bool Result = AsmPrinter::doInitialization(M);
859*9880d681SAndroid Build Coastguard Worker
860*9880d681SAndroid Build Coastguard Worker // Emit module-level inline asm if it exists.
861*9880d681SAndroid Build Coastguard Worker if (!M.getModuleInlineAsm().empty()) {
862*9880d681SAndroid Build Coastguard Worker OutStreamer->AddComment("Start of file scope inline assembly");
863*9880d681SAndroid Build Coastguard Worker OutStreamer->AddBlankLine();
864*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(StringRef(M.getModuleInlineAsm()));
865*9880d681SAndroid Build Coastguard Worker OutStreamer->AddBlankLine();
866*9880d681SAndroid Build Coastguard Worker OutStreamer->AddComment("End of file scope inline assembly");
867*9880d681SAndroid Build Coastguard Worker OutStreamer->AddBlankLine();
868*9880d681SAndroid Build Coastguard Worker }
869*9880d681SAndroid Build Coastguard Worker
870*9880d681SAndroid Build Coastguard Worker // If we're not NVCL we're CUDA, go ahead and emit filenames.
871*9880d681SAndroid Build Coastguard Worker if (TM.getTargetTriple().getOS() != Triple::NVCL)
872*9880d681SAndroid Build Coastguard Worker recordAndEmitFilenames(M);
873*9880d681SAndroid Build Coastguard Worker
874*9880d681SAndroid Build Coastguard Worker GlobalsEmitted = false;
875*9880d681SAndroid Build Coastguard Worker
876*9880d681SAndroid Build Coastguard Worker return false; // success
877*9880d681SAndroid Build Coastguard Worker }
878*9880d681SAndroid Build Coastguard Worker
emitGlobals(const Module & M)879*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitGlobals(const Module &M) {
880*9880d681SAndroid Build Coastguard Worker SmallString<128> Str2;
881*9880d681SAndroid Build Coastguard Worker raw_svector_ostream OS2(Str2);
882*9880d681SAndroid Build Coastguard Worker
883*9880d681SAndroid Build Coastguard Worker emitDeclarations(M, OS2);
884*9880d681SAndroid Build Coastguard Worker
885*9880d681SAndroid Build Coastguard Worker // As ptxas does not support forward references of globals, we need to first
886*9880d681SAndroid Build Coastguard Worker // sort the list of module-level globals in def-use order. We visit each
887*9880d681SAndroid Build Coastguard Worker // global variable in order, and ensure that we emit it *after* its dependent
888*9880d681SAndroid Build Coastguard Worker // globals. We use a little extra memory maintaining both a set and a list to
889*9880d681SAndroid Build Coastguard Worker // have fast searches while maintaining a strict ordering.
890*9880d681SAndroid Build Coastguard Worker SmallVector<const GlobalVariable *, 8> Globals;
891*9880d681SAndroid Build Coastguard Worker DenseSet<const GlobalVariable *> GVVisited;
892*9880d681SAndroid Build Coastguard Worker DenseSet<const GlobalVariable *> GVVisiting;
893*9880d681SAndroid Build Coastguard Worker
894*9880d681SAndroid Build Coastguard Worker // Visit each global variable, in order
895*9880d681SAndroid Build Coastguard Worker for (const GlobalVariable &I : M.globals())
896*9880d681SAndroid Build Coastguard Worker VisitGlobalVariableForEmission(&I, Globals, GVVisited, GVVisiting);
897*9880d681SAndroid Build Coastguard Worker
898*9880d681SAndroid Build Coastguard Worker assert(GVVisited.size() == M.getGlobalList().size() &&
899*9880d681SAndroid Build Coastguard Worker "Missed a global variable");
900*9880d681SAndroid Build Coastguard Worker assert(GVVisiting.size() == 0 && "Did not fully process a global variable");
901*9880d681SAndroid Build Coastguard Worker
902*9880d681SAndroid Build Coastguard Worker // Print out module-level global variables in proper order
903*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Globals.size(); i != e; ++i)
904*9880d681SAndroid Build Coastguard Worker printModuleLevelGV(Globals[i], OS2);
905*9880d681SAndroid Build Coastguard Worker
906*9880d681SAndroid Build Coastguard Worker OS2 << '\n';
907*9880d681SAndroid Build Coastguard Worker
908*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(OS2.str());
909*9880d681SAndroid Build Coastguard Worker }
910*9880d681SAndroid Build Coastguard Worker
emitHeader(Module & M,raw_ostream & O,const NVPTXSubtarget & STI)911*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitHeader(Module &M, raw_ostream &O,
912*9880d681SAndroid Build Coastguard Worker const NVPTXSubtarget &STI) {
913*9880d681SAndroid Build Coastguard Worker O << "//\n";
914*9880d681SAndroid Build Coastguard Worker O << "// Generated by LLVM NVPTX Back-End\n";
915*9880d681SAndroid Build Coastguard Worker O << "//\n";
916*9880d681SAndroid Build Coastguard Worker O << "\n";
917*9880d681SAndroid Build Coastguard Worker
918*9880d681SAndroid Build Coastguard Worker unsigned PTXVersion = STI.getPTXVersion();
919*9880d681SAndroid Build Coastguard Worker O << ".version " << (PTXVersion / 10) << "." << (PTXVersion % 10) << "\n";
920*9880d681SAndroid Build Coastguard Worker
921*9880d681SAndroid Build Coastguard Worker O << ".target ";
922*9880d681SAndroid Build Coastguard Worker O << STI.getTargetName();
923*9880d681SAndroid Build Coastguard Worker
924*9880d681SAndroid Build Coastguard Worker const NVPTXTargetMachine &NTM = static_cast<const NVPTXTargetMachine &>(TM);
925*9880d681SAndroid Build Coastguard Worker if (NTM.getDrvInterface() == NVPTX::NVCL)
926*9880d681SAndroid Build Coastguard Worker O << ", texmode_independent";
927*9880d681SAndroid Build Coastguard Worker else {
928*9880d681SAndroid Build Coastguard Worker if (!STI.hasDouble())
929*9880d681SAndroid Build Coastguard Worker O << ", map_f64_to_f32";
930*9880d681SAndroid Build Coastguard Worker }
931*9880d681SAndroid Build Coastguard Worker
932*9880d681SAndroid Build Coastguard Worker if (MAI->doesSupportDebugInformation())
933*9880d681SAndroid Build Coastguard Worker O << ", debug";
934*9880d681SAndroid Build Coastguard Worker
935*9880d681SAndroid Build Coastguard Worker O << "\n";
936*9880d681SAndroid Build Coastguard Worker
937*9880d681SAndroid Build Coastguard Worker O << ".address_size ";
938*9880d681SAndroid Build Coastguard Worker if (NTM.is64Bit())
939*9880d681SAndroid Build Coastguard Worker O << "64";
940*9880d681SAndroid Build Coastguard Worker else
941*9880d681SAndroid Build Coastguard Worker O << "32";
942*9880d681SAndroid Build Coastguard Worker O << "\n";
943*9880d681SAndroid Build Coastguard Worker
944*9880d681SAndroid Build Coastguard Worker O << "\n";
945*9880d681SAndroid Build Coastguard Worker }
946*9880d681SAndroid Build Coastguard Worker
doFinalization(Module & M)947*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::doFinalization(Module &M) {
948*9880d681SAndroid Build Coastguard Worker // If we did not emit any functions, then the global declarations have not
949*9880d681SAndroid Build Coastguard Worker // yet been emitted.
950*9880d681SAndroid Build Coastguard Worker if (!GlobalsEmitted) {
951*9880d681SAndroid Build Coastguard Worker emitGlobals(M);
952*9880d681SAndroid Build Coastguard Worker GlobalsEmitted = true;
953*9880d681SAndroid Build Coastguard Worker }
954*9880d681SAndroid Build Coastguard Worker
955*9880d681SAndroid Build Coastguard Worker // XXX Temproarily remove global variables so that doFinalization() will not
956*9880d681SAndroid Build Coastguard Worker // emit them again (global variables are emitted at beginning).
957*9880d681SAndroid Build Coastguard Worker
958*9880d681SAndroid Build Coastguard Worker Module::GlobalListType &global_list = M.getGlobalList();
959*9880d681SAndroid Build Coastguard Worker int i, n = global_list.size();
960*9880d681SAndroid Build Coastguard Worker GlobalVariable **gv_array = new GlobalVariable *[n];
961*9880d681SAndroid Build Coastguard Worker
962*9880d681SAndroid Build Coastguard Worker // first, back-up GlobalVariable in gv_array
963*9880d681SAndroid Build Coastguard Worker i = 0;
964*9880d681SAndroid Build Coastguard Worker for (Module::global_iterator I = global_list.begin(), E = global_list.end();
965*9880d681SAndroid Build Coastguard Worker I != E; ++I)
966*9880d681SAndroid Build Coastguard Worker gv_array[i++] = &*I;
967*9880d681SAndroid Build Coastguard Worker
968*9880d681SAndroid Build Coastguard Worker // second, empty global_list
969*9880d681SAndroid Build Coastguard Worker while (!global_list.empty())
970*9880d681SAndroid Build Coastguard Worker global_list.remove(global_list.begin());
971*9880d681SAndroid Build Coastguard Worker
972*9880d681SAndroid Build Coastguard Worker // call doFinalization
973*9880d681SAndroid Build Coastguard Worker bool ret = AsmPrinter::doFinalization(M);
974*9880d681SAndroid Build Coastguard Worker
975*9880d681SAndroid Build Coastguard Worker // now we restore global variables
976*9880d681SAndroid Build Coastguard Worker for (i = 0; i < n; i++)
977*9880d681SAndroid Build Coastguard Worker global_list.insert(global_list.end(), gv_array[i]);
978*9880d681SAndroid Build Coastguard Worker
979*9880d681SAndroid Build Coastguard Worker clearAnnotationCache(&M);
980*9880d681SAndroid Build Coastguard Worker
981*9880d681SAndroid Build Coastguard Worker delete[] gv_array;
982*9880d681SAndroid Build Coastguard Worker return ret;
983*9880d681SAndroid Build Coastguard Worker
984*9880d681SAndroid Build Coastguard Worker //bool Result = AsmPrinter::doFinalization(M);
985*9880d681SAndroid Build Coastguard Worker // Instead of calling the parents doFinalization, we may
986*9880d681SAndroid Build Coastguard Worker // clone parents doFinalization and customize here.
987*9880d681SAndroid Build Coastguard Worker // Currently, we if NVISA out the EmitGlobals() in
988*9880d681SAndroid Build Coastguard Worker // parent's doFinalization, which is too intrusive.
989*9880d681SAndroid Build Coastguard Worker //
990*9880d681SAndroid Build Coastguard Worker // Same for the doInitialization.
991*9880d681SAndroid Build Coastguard Worker //return Result;
992*9880d681SAndroid Build Coastguard Worker }
993*9880d681SAndroid Build Coastguard Worker
994*9880d681SAndroid Build Coastguard Worker // This function emits appropriate linkage directives for
995*9880d681SAndroid Build Coastguard Worker // functions and global variables.
996*9880d681SAndroid Build Coastguard Worker //
997*9880d681SAndroid Build Coastguard Worker // extern function declaration -> .extern
998*9880d681SAndroid Build Coastguard Worker // extern function definition -> .visible
999*9880d681SAndroid Build Coastguard Worker // external global variable with init -> .visible
1000*9880d681SAndroid Build Coastguard Worker // external without init -> .extern
1001*9880d681SAndroid Build Coastguard Worker // appending -> not allowed, assert.
1002*9880d681SAndroid Build Coastguard Worker // for any linkage other than
1003*9880d681SAndroid Build Coastguard Worker // internal, private, linker_private,
1004*9880d681SAndroid Build Coastguard Worker // linker_private_weak, linker_private_weak_def_auto,
1005*9880d681SAndroid Build Coastguard Worker // we emit -> .weak.
1006*9880d681SAndroid Build Coastguard Worker
emitLinkageDirective(const GlobalValue * V,raw_ostream & O)1007*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitLinkageDirective(const GlobalValue *V,
1008*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
1009*9880d681SAndroid Build Coastguard Worker if (static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() == NVPTX::CUDA) {
1010*9880d681SAndroid Build Coastguard Worker if (V->hasExternalLinkage()) {
1011*9880d681SAndroid Build Coastguard Worker if (isa<GlobalVariable>(V)) {
1012*9880d681SAndroid Build Coastguard Worker const GlobalVariable *GVar = cast<GlobalVariable>(V);
1013*9880d681SAndroid Build Coastguard Worker if (GVar) {
1014*9880d681SAndroid Build Coastguard Worker if (GVar->hasInitializer())
1015*9880d681SAndroid Build Coastguard Worker O << ".visible ";
1016*9880d681SAndroid Build Coastguard Worker else
1017*9880d681SAndroid Build Coastguard Worker O << ".extern ";
1018*9880d681SAndroid Build Coastguard Worker }
1019*9880d681SAndroid Build Coastguard Worker } else if (V->isDeclaration())
1020*9880d681SAndroid Build Coastguard Worker O << ".extern ";
1021*9880d681SAndroid Build Coastguard Worker else
1022*9880d681SAndroid Build Coastguard Worker O << ".visible ";
1023*9880d681SAndroid Build Coastguard Worker } else if (V->hasAppendingLinkage()) {
1024*9880d681SAndroid Build Coastguard Worker std::string msg;
1025*9880d681SAndroid Build Coastguard Worker msg.append("Error: ");
1026*9880d681SAndroid Build Coastguard Worker msg.append("Symbol ");
1027*9880d681SAndroid Build Coastguard Worker if (V->hasName())
1028*9880d681SAndroid Build Coastguard Worker msg.append(V->getName());
1029*9880d681SAndroid Build Coastguard Worker msg.append("has unsupported appending linkage type");
1030*9880d681SAndroid Build Coastguard Worker llvm_unreachable(msg.c_str());
1031*9880d681SAndroid Build Coastguard Worker } else if (!V->hasInternalLinkage() &&
1032*9880d681SAndroid Build Coastguard Worker !V->hasPrivateLinkage()) {
1033*9880d681SAndroid Build Coastguard Worker O << ".weak ";
1034*9880d681SAndroid Build Coastguard Worker }
1035*9880d681SAndroid Build Coastguard Worker }
1036*9880d681SAndroid Build Coastguard Worker }
1037*9880d681SAndroid Build Coastguard Worker
printModuleLevelGV(const GlobalVariable * GVar,raw_ostream & O,bool processDemoted)1038*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar,
1039*9880d681SAndroid Build Coastguard Worker raw_ostream &O,
1040*9880d681SAndroid Build Coastguard Worker bool processDemoted) {
1041*9880d681SAndroid Build Coastguard Worker
1042*9880d681SAndroid Build Coastguard Worker // Skip meta data
1043*9880d681SAndroid Build Coastguard Worker if (GVar->hasSection()) {
1044*9880d681SAndroid Build Coastguard Worker if (GVar->getSection() == "llvm.metadata")
1045*9880d681SAndroid Build Coastguard Worker return;
1046*9880d681SAndroid Build Coastguard Worker }
1047*9880d681SAndroid Build Coastguard Worker
1048*9880d681SAndroid Build Coastguard Worker // Skip LLVM intrinsic global variables
1049*9880d681SAndroid Build Coastguard Worker if (GVar->getName().startswith("llvm.") ||
1050*9880d681SAndroid Build Coastguard Worker GVar->getName().startswith("nvvm."))
1051*9880d681SAndroid Build Coastguard Worker return;
1052*9880d681SAndroid Build Coastguard Worker
1053*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
1054*9880d681SAndroid Build Coastguard Worker
1055*9880d681SAndroid Build Coastguard Worker // GlobalVariables are always constant pointers themselves.
1056*9880d681SAndroid Build Coastguard Worker PointerType *PTy = GVar->getType();
1057*9880d681SAndroid Build Coastguard Worker Type *ETy = GVar->getValueType();
1058*9880d681SAndroid Build Coastguard Worker
1059*9880d681SAndroid Build Coastguard Worker if (GVar->hasExternalLinkage()) {
1060*9880d681SAndroid Build Coastguard Worker if (GVar->hasInitializer())
1061*9880d681SAndroid Build Coastguard Worker O << ".visible ";
1062*9880d681SAndroid Build Coastguard Worker else
1063*9880d681SAndroid Build Coastguard Worker O << ".extern ";
1064*9880d681SAndroid Build Coastguard Worker } else if (GVar->hasLinkOnceLinkage() || GVar->hasWeakLinkage() ||
1065*9880d681SAndroid Build Coastguard Worker GVar->hasAvailableExternallyLinkage() ||
1066*9880d681SAndroid Build Coastguard Worker GVar->hasCommonLinkage()) {
1067*9880d681SAndroid Build Coastguard Worker O << ".weak ";
1068*9880d681SAndroid Build Coastguard Worker }
1069*9880d681SAndroid Build Coastguard Worker
1070*9880d681SAndroid Build Coastguard Worker if (llvm::isTexture(*GVar)) {
1071*9880d681SAndroid Build Coastguard Worker O << ".global .texref " << llvm::getTextureName(*GVar) << ";\n";
1072*9880d681SAndroid Build Coastguard Worker return;
1073*9880d681SAndroid Build Coastguard Worker }
1074*9880d681SAndroid Build Coastguard Worker
1075*9880d681SAndroid Build Coastguard Worker if (llvm::isSurface(*GVar)) {
1076*9880d681SAndroid Build Coastguard Worker O << ".global .surfref " << llvm::getSurfaceName(*GVar) << ";\n";
1077*9880d681SAndroid Build Coastguard Worker return;
1078*9880d681SAndroid Build Coastguard Worker }
1079*9880d681SAndroid Build Coastguard Worker
1080*9880d681SAndroid Build Coastguard Worker if (GVar->isDeclaration()) {
1081*9880d681SAndroid Build Coastguard Worker // (extern) declarations, no definition or initializer
1082*9880d681SAndroid Build Coastguard Worker // Currently the only known declaration is for an automatic __local
1083*9880d681SAndroid Build Coastguard Worker // (.shared) promoted to global.
1084*9880d681SAndroid Build Coastguard Worker emitPTXGlobalVariable(GVar, O);
1085*9880d681SAndroid Build Coastguard Worker O << ";\n";
1086*9880d681SAndroid Build Coastguard Worker return;
1087*9880d681SAndroid Build Coastguard Worker }
1088*9880d681SAndroid Build Coastguard Worker
1089*9880d681SAndroid Build Coastguard Worker if (llvm::isSampler(*GVar)) {
1090*9880d681SAndroid Build Coastguard Worker O << ".global .samplerref " << llvm::getSamplerName(*GVar);
1091*9880d681SAndroid Build Coastguard Worker
1092*9880d681SAndroid Build Coastguard Worker const Constant *Initializer = nullptr;
1093*9880d681SAndroid Build Coastguard Worker if (GVar->hasInitializer())
1094*9880d681SAndroid Build Coastguard Worker Initializer = GVar->getInitializer();
1095*9880d681SAndroid Build Coastguard Worker const ConstantInt *CI = nullptr;
1096*9880d681SAndroid Build Coastguard Worker if (Initializer)
1097*9880d681SAndroid Build Coastguard Worker CI = dyn_cast<ConstantInt>(Initializer);
1098*9880d681SAndroid Build Coastguard Worker if (CI) {
1099*9880d681SAndroid Build Coastguard Worker unsigned sample = CI->getZExtValue();
1100*9880d681SAndroid Build Coastguard Worker
1101*9880d681SAndroid Build Coastguard Worker O << " = { ";
1102*9880d681SAndroid Build Coastguard Worker
1103*9880d681SAndroid Build Coastguard Worker for (int i = 0,
1104*9880d681SAndroid Build Coastguard Worker addr = ((sample & __CLK_ADDRESS_MASK) >> __CLK_ADDRESS_BASE);
1105*9880d681SAndroid Build Coastguard Worker i < 3; i++) {
1106*9880d681SAndroid Build Coastguard Worker O << "addr_mode_" << i << " = ";
1107*9880d681SAndroid Build Coastguard Worker switch (addr) {
1108*9880d681SAndroid Build Coastguard Worker case 0:
1109*9880d681SAndroid Build Coastguard Worker O << "wrap";
1110*9880d681SAndroid Build Coastguard Worker break;
1111*9880d681SAndroid Build Coastguard Worker case 1:
1112*9880d681SAndroid Build Coastguard Worker O << "clamp_to_border";
1113*9880d681SAndroid Build Coastguard Worker break;
1114*9880d681SAndroid Build Coastguard Worker case 2:
1115*9880d681SAndroid Build Coastguard Worker O << "clamp_to_edge";
1116*9880d681SAndroid Build Coastguard Worker break;
1117*9880d681SAndroid Build Coastguard Worker case 3:
1118*9880d681SAndroid Build Coastguard Worker O << "wrap";
1119*9880d681SAndroid Build Coastguard Worker break;
1120*9880d681SAndroid Build Coastguard Worker case 4:
1121*9880d681SAndroid Build Coastguard Worker O << "mirror";
1122*9880d681SAndroid Build Coastguard Worker break;
1123*9880d681SAndroid Build Coastguard Worker }
1124*9880d681SAndroid Build Coastguard Worker O << ", ";
1125*9880d681SAndroid Build Coastguard Worker }
1126*9880d681SAndroid Build Coastguard Worker O << "filter_mode = ";
1127*9880d681SAndroid Build Coastguard Worker switch ((sample & __CLK_FILTER_MASK) >> __CLK_FILTER_BASE) {
1128*9880d681SAndroid Build Coastguard Worker case 0:
1129*9880d681SAndroid Build Coastguard Worker O << "nearest";
1130*9880d681SAndroid Build Coastguard Worker break;
1131*9880d681SAndroid Build Coastguard Worker case 1:
1132*9880d681SAndroid Build Coastguard Worker O << "linear";
1133*9880d681SAndroid Build Coastguard Worker break;
1134*9880d681SAndroid Build Coastguard Worker case 2:
1135*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Anisotropic filtering is not supported");
1136*9880d681SAndroid Build Coastguard Worker default:
1137*9880d681SAndroid Build Coastguard Worker O << "nearest";
1138*9880d681SAndroid Build Coastguard Worker break;
1139*9880d681SAndroid Build Coastguard Worker }
1140*9880d681SAndroid Build Coastguard Worker if (!((sample & __CLK_NORMALIZED_MASK) >> __CLK_NORMALIZED_BASE)) {
1141*9880d681SAndroid Build Coastguard Worker O << ", force_unnormalized_coords = 1";
1142*9880d681SAndroid Build Coastguard Worker }
1143*9880d681SAndroid Build Coastguard Worker O << " }";
1144*9880d681SAndroid Build Coastguard Worker }
1145*9880d681SAndroid Build Coastguard Worker
1146*9880d681SAndroid Build Coastguard Worker O << ";\n";
1147*9880d681SAndroid Build Coastguard Worker return;
1148*9880d681SAndroid Build Coastguard Worker }
1149*9880d681SAndroid Build Coastguard Worker
1150*9880d681SAndroid Build Coastguard Worker if (GVar->hasPrivateLinkage()) {
1151*9880d681SAndroid Build Coastguard Worker
1152*9880d681SAndroid Build Coastguard Worker if (!strncmp(GVar->getName().data(), "unrollpragma", 12))
1153*9880d681SAndroid Build Coastguard Worker return;
1154*9880d681SAndroid Build Coastguard Worker
1155*9880d681SAndroid Build Coastguard Worker // FIXME - need better way (e.g. Metadata) to avoid generating this global
1156*9880d681SAndroid Build Coastguard Worker if (!strncmp(GVar->getName().data(), "filename", 8))
1157*9880d681SAndroid Build Coastguard Worker return;
1158*9880d681SAndroid Build Coastguard Worker if (GVar->use_empty())
1159*9880d681SAndroid Build Coastguard Worker return;
1160*9880d681SAndroid Build Coastguard Worker }
1161*9880d681SAndroid Build Coastguard Worker
1162*9880d681SAndroid Build Coastguard Worker const Function *demotedFunc = nullptr;
1163*9880d681SAndroid Build Coastguard Worker if (!processDemoted && canDemoteGlobalVar(GVar, demotedFunc)) {
1164*9880d681SAndroid Build Coastguard Worker O << "// " << GVar->getName() << " has been demoted\n";
1165*9880d681SAndroid Build Coastguard Worker if (localDecls.find(demotedFunc) != localDecls.end())
1166*9880d681SAndroid Build Coastguard Worker localDecls[demotedFunc].push_back(GVar);
1167*9880d681SAndroid Build Coastguard Worker else {
1168*9880d681SAndroid Build Coastguard Worker std::vector<const GlobalVariable *> temp;
1169*9880d681SAndroid Build Coastguard Worker temp.push_back(GVar);
1170*9880d681SAndroid Build Coastguard Worker localDecls[demotedFunc] = temp;
1171*9880d681SAndroid Build Coastguard Worker }
1172*9880d681SAndroid Build Coastguard Worker return;
1173*9880d681SAndroid Build Coastguard Worker }
1174*9880d681SAndroid Build Coastguard Worker
1175*9880d681SAndroid Build Coastguard Worker O << ".";
1176*9880d681SAndroid Build Coastguard Worker emitPTXAddressSpace(PTy->getAddressSpace(), O);
1177*9880d681SAndroid Build Coastguard Worker
1178*9880d681SAndroid Build Coastguard Worker if (isManaged(*GVar)) {
1179*9880d681SAndroid Build Coastguard Worker O << " .attribute(.managed)";
1180*9880d681SAndroid Build Coastguard Worker }
1181*9880d681SAndroid Build Coastguard Worker
1182*9880d681SAndroid Build Coastguard Worker if (GVar->getAlignment() == 0)
1183*9880d681SAndroid Build Coastguard Worker O << " .align " << (int)DL.getPrefTypeAlignment(ETy);
1184*9880d681SAndroid Build Coastguard Worker else
1185*9880d681SAndroid Build Coastguard Worker O << " .align " << GVar->getAlignment();
1186*9880d681SAndroid Build Coastguard Worker
1187*9880d681SAndroid Build Coastguard Worker if (ETy->isFloatingPointTy() || ETy->isIntegerTy() || ETy->isPointerTy()) {
1188*9880d681SAndroid Build Coastguard Worker O << " .";
1189*9880d681SAndroid Build Coastguard Worker // Special case: ABI requires that we use .u8 for predicates
1190*9880d681SAndroid Build Coastguard Worker if (ETy->isIntegerTy(1))
1191*9880d681SAndroid Build Coastguard Worker O << "u8";
1192*9880d681SAndroid Build Coastguard Worker else
1193*9880d681SAndroid Build Coastguard Worker O << getPTXFundamentalTypeStr(ETy, false);
1194*9880d681SAndroid Build Coastguard Worker O << " ";
1195*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1196*9880d681SAndroid Build Coastguard Worker
1197*9880d681SAndroid Build Coastguard Worker // Ptx allows variable initilization only for constant and global state
1198*9880d681SAndroid Build Coastguard Worker // spaces.
1199*9880d681SAndroid Build Coastguard Worker if (GVar->hasInitializer()) {
1200*9880d681SAndroid Build Coastguard Worker if ((PTy->getAddressSpace() == llvm::ADDRESS_SPACE_GLOBAL) ||
1201*9880d681SAndroid Build Coastguard Worker (PTy->getAddressSpace() == llvm::ADDRESS_SPACE_CONST)) {
1202*9880d681SAndroid Build Coastguard Worker const Constant *Initializer = GVar->getInitializer();
1203*9880d681SAndroid Build Coastguard Worker // 'undef' is treated as there is no value specified.
1204*9880d681SAndroid Build Coastguard Worker if (!Initializer->isNullValue() && !isa<UndefValue>(Initializer)) {
1205*9880d681SAndroid Build Coastguard Worker O << " = ";
1206*9880d681SAndroid Build Coastguard Worker printScalarConstant(Initializer, O);
1207*9880d681SAndroid Build Coastguard Worker }
1208*9880d681SAndroid Build Coastguard Worker } else {
1209*9880d681SAndroid Build Coastguard Worker // The frontend adds zero-initializer to device and constant variables
1210*9880d681SAndroid Build Coastguard Worker // that don't have an initial value, and UndefValue to shared
1211*9880d681SAndroid Build Coastguard Worker // variables, so skip warning for this case.
1212*9880d681SAndroid Build Coastguard Worker if (!GVar->getInitializer()->isNullValue() &&
1213*9880d681SAndroid Build Coastguard Worker !isa<UndefValue>(GVar->getInitializer())) {
1214*9880d681SAndroid Build Coastguard Worker report_fatal_error("initial value of '" + GVar->getName() +
1215*9880d681SAndroid Build Coastguard Worker "' is not allowed in addrspace(" +
1216*9880d681SAndroid Build Coastguard Worker Twine(PTy->getAddressSpace()) + ")");
1217*9880d681SAndroid Build Coastguard Worker }
1218*9880d681SAndroid Build Coastguard Worker }
1219*9880d681SAndroid Build Coastguard Worker }
1220*9880d681SAndroid Build Coastguard Worker } else {
1221*9880d681SAndroid Build Coastguard Worker unsigned int ElementSize = 0;
1222*9880d681SAndroid Build Coastguard Worker
1223*9880d681SAndroid Build Coastguard Worker // Although PTX has direct support for struct type and array type and
1224*9880d681SAndroid Build Coastguard Worker // LLVM IR is very similar to PTX, the LLVM CodeGen does not support for
1225*9880d681SAndroid Build Coastguard Worker // targets that support these high level field accesses. Structs, arrays
1226*9880d681SAndroid Build Coastguard Worker // and vectors are lowered into arrays of bytes.
1227*9880d681SAndroid Build Coastguard Worker switch (ETy->getTypeID()) {
1228*9880d681SAndroid Build Coastguard Worker case Type::StructTyID:
1229*9880d681SAndroid Build Coastguard Worker case Type::ArrayTyID:
1230*9880d681SAndroid Build Coastguard Worker case Type::VectorTyID:
1231*9880d681SAndroid Build Coastguard Worker ElementSize = DL.getTypeStoreSize(ETy);
1232*9880d681SAndroid Build Coastguard Worker // Ptx allows variable initilization only for constant and
1233*9880d681SAndroid Build Coastguard Worker // global state spaces.
1234*9880d681SAndroid Build Coastguard Worker if (((PTy->getAddressSpace() == llvm::ADDRESS_SPACE_GLOBAL) ||
1235*9880d681SAndroid Build Coastguard Worker (PTy->getAddressSpace() == llvm::ADDRESS_SPACE_CONST)) &&
1236*9880d681SAndroid Build Coastguard Worker GVar->hasInitializer()) {
1237*9880d681SAndroid Build Coastguard Worker const Constant *Initializer = GVar->getInitializer();
1238*9880d681SAndroid Build Coastguard Worker if (!isa<UndefValue>(Initializer) && !Initializer->isNullValue()) {
1239*9880d681SAndroid Build Coastguard Worker AggBuffer aggBuffer(ElementSize, O, *this);
1240*9880d681SAndroid Build Coastguard Worker bufferAggregateConstant(Initializer, &aggBuffer);
1241*9880d681SAndroid Build Coastguard Worker if (aggBuffer.numSymbols) {
1242*9880d681SAndroid Build Coastguard Worker if (static_cast<const NVPTXTargetMachine &>(TM).is64Bit()) {
1243*9880d681SAndroid Build Coastguard Worker O << " .u64 ";
1244*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1245*9880d681SAndroid Build Coastguard Worker O << "[";
1246*9880d681SAndroid Build Coastguard Worker O << ElementSize / 8;
1247*9880d681SAndroid Build Coastguard Worker } else {
1248*9880d681SAndroid Build Coastguard Worker O << " .u32 ";
1249*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1250*9880d681SAndroid Build Coastguard Worker O << "[";
1251*9880d681SAndroid Build Coastguard Worker O << ElementSize / 4;
1252*9880d681SAndroid Build Coastguard Worker }
1253*9880d681SAndroid Build Coastguard Worker O << "]";
1254*9880d681SAndroid Build Coastguard Worker } else {
1255*9880d681SAndroid Build Coastguard Worker O << " .b8 ";
1256*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1257*9880d681SAndroid Build Coastguard Worker O << "[";
1258*9880d681SAndroid Build Coastguard Worker O << ElementSize;
1259*9880d681SAndroid Build Coastguard Worker O << "]";
1260*9880d681SAndroid Build Coastguard Worker }
1261*9880d681SAndroid Build Coastguard Worker O << " = {";
1262*9880d681SAndroid Build Coastguard Worker aggBuffer.print();
1263*9880d681SAndroid Build Coastguard Worker O << "}";
1264*9880d681SAndroid Build Coastguard Worker } else {
1265*9880d681SAndroid Build Coastguard Worker O << " .b8 ";
1266*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1267*9880d681SAndroid Build Coastguard Worker if (ElementSize) {
1268*9880d681SAndroid Build Coastguard Worker O << "[";
1269*9880d681SAndroid Build Coastguard Worker O << ElementSize;
1270*9880d681SAndroid Build Coastguard Worker O << "]";
1271*9880d681SAndroid Build Coastguard Worker }
1272*9880d681SAndroid Build Coastguard Worker }
1273*9880d681SAndroid Build Coastguard Worker } else {
1274*9880d681SAndroid Build Coastguard Worker O << " .b8 ";
1275*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1276*9880d681SAndroid Build Coastguard Worker if (ElementSize) {
1277*9880d681SAndroid Build Coastguard Worker O << "[";
1278*9880d681SAndroid Build Coastguard Worker O << ElementSize;
1279*9880d681SAndroid Build Coastguard Worker O << "]";
1280*9880d681SAndroid Build Coastguard Worker }
1281*9880d681SAndroid Build Coastguard Worker }
1282*9880d681SAndroid Build Coastguard Worker break;
1283*9880d681SAndroid Build Coastguard Worker default:
1284*9880d681SAndroid Build Coastguard Worker llvm_unreachable("type not supported yet");
1285*9880d681SAndroid Build Coastguard Worker }
1286*9880d681SAndroid Build Coastguard Worker
1287*9880d681SAndroid Build Coastguard Worker }
1288*9880d681SAndroid Build Coastguard Worker O << ";\n";
1289*9880d681SAndroid Build Coastguard Worker }
1290*9880d681SAndroid Build Coastguard Worker
emitDemotedVars(const Function * f,raw_ostream & O)1291*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitDemotedVars(const Function *f, raw_ostream &O) {
1292*9880d681SAndroid Build Coastguard Worker if (localDecls.find(f) == localDecls.end())
1293*9880d681SAndroid Build Coastguard Worker return;
1294*9880d681SAndroid Build Coastguard Worker
1295*9880d681SAndroid Build Coastguard Worker std::vector<const GlobalVariable *> &gvars = localDecls[f];
1296*9880d681SAndroid Build Coastguard Worker
1297*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = gvars.size(); i != e; ++i) {
1298*9880d681SAndroid Build Coastguard Worker O << "\t// demoted variable\n\t";
1299*9880d681SAndroid Build Coastguard Worker printModuleLevelGV(gvars[i], O, true);
1300*9880d681SAndroid Build Coastguard Worker }
1301*9880d681SAndroid Build Coastguard Worker }
1302*9880d681SAndroid Build Coastguard Worker
emitPTXAddressSpace(unsigned int AddressSpace,raw_ostream & O) const1303*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitPTXAddressSpace(unsigned int AddressSpace,
1304*9880d681SAndroid Build Coastguard Worker raw_ostream &O) const {
1305*9880d681SAndroid Build Coastguard Worker switch (AddressSpace) {
1306*9880d681SAndroid Build Coastguard Worker case llvm::ADDRESS_SPACE_LOCAL:
1307*9880d681SAndroid Build Coastguard Worker O << "local";
1308*9880d681SAndroid Build Coastguard Worker break;
1309*9880d681SAndroid Build Coastguard Worker case llvm::ADDRESS_SPACE_GLOBAL:
1310*9880d681SAndroid Build Coastguard Worker O << "global";
1311*9880d681SAndroid Build Coastguard Worker break;
1312*9880d681SAndroid Build Coastguard Worker case llvm::ADDRESS_SPACE_CONST:
1313*9880d681SAndroid Build Coastguard Worker O << "const";
1314*9880d681SAndroid Build Coastguard Worker break;
1315*9880d681SAndroid Build Coastguard Worker case llvm::ADDRESS_SPACE_SHARED:
1316*9880d681SAndroid Build Coastguard Worker O << "shared";
1317*9880d681SAndroid Build Coastguard Worker break;
1318*9880d681SAndroid Build Coastguard Worker default:
1319*9880d681SAndroid Build Coastguard Worker report_fatal_error("Bad address space found while emitting PTX");
1320*9880d681SAndroid Build Coastguard Worker break;
1321*9880d681SAndroid Build Coastguard Worker }
1322*9880d681SAndroid Build Coastguard Worker }
1323*9880d681SAndroid Build Coastguard Worker
1324*9880d681SAndroid Build Coastguard Worker std::string
getPTXFundamentalTypeStr(Type * Ty,bool useB4PTR) const1325*9880d681SAndroid Build Coastguard Worker NVPTXAsmPrinter::getPTXFundamentalTypeStr(Type *Ty, bool useB4PTR) const {
1326*9880d681SAndroid Build Coastguard Worker switch (Ty->getTypeID()) {
1327*9880d681SAndroid Build Coastguard Worker default:
1328*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unexpected type");
1329*9880d681SAndroid Build Coastguard Worker break;
1330*9880d681SAndroid Build Coastguard Worker case Type::IntegerTyID: {
1331*9880d681SAndroid Build Coastguard Worker unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth();
1332*9880d681SAndroid Build Coastguard Worker if (NumBits == 1)
1333*9880d681SAndroid Build Coastguard Worker return "pred";
1334*9880d681SAndroid Build Coastguard Worker else if (NumBits <= 64) {
1335*9880d681SAndroid Build Coastguard Worker std::string name = "u";
1336*9880d681SAndroid Build Coastguard Worker return name + utostr(NumBits);
1337*9880d681SAndroid Build Coastguard Worker } else {
1338*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Integer too large");
1339*9880d681SAndroid Build Coastguard Worker break;
1340*9880d681SAndroid Build Coastguard Worker }
1341*9880d681SAndroid Build Coastguard Worker break;
1342*9880d681SAndroid Build Coastguard Worker }
1343*9880d681SAndroid Build Coastguard Worker case Type::FloatTyID:
1344*9880d681SAndroid Build Coastguard Worker return "f32";
1345*9880d681SAndroid Build Coastguard Worker case Type::DoubleTyID:
1346*9880d681SAndroid Build Coastguard Worker return "f64";
1347*9880d681SAndroid Build Coastguard Worker case Type::PointerTyID:
1348*9880d681SAndroid Build Coastguard Worker if (static_cast<const NVPTXTargetMachine &>(TM).is64Bit())
1349*9880d681SAndroid Build Coastguard Worker if (useB4PTR)
1350*9880d681SAndroid Build Coastguard Worker return "b64";
1351*9880d681SAndroid Build Coastguard Worker else
1352*9880d681SAndroid Build Coastguard Worker return "u64";
1353*9880d681SAndroid Build Coastguard Worker else if (useB4PTR)
1354*9880d681SAndroid Build Coastguard Worker return "b32";
1355*9880d681SAndroid Build Coastguard Worker else
1356*9880d681SAndroid Build Coastguard Worker return "u32";
1357*9880d681SAndroid Build Coastguard Worker }
1358*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unexpected type");
1359*9880d681SAndroid Build Coastguard Worker return nullptr;
1360*9880d681SAndroid Build Coastguard Worker }
1361*9880d681SAndroid Build Coastguard Worker
emitPTXGlobalVariable(const GlobalVariable * GVar,raw_ostream & O)1362*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitPTXGlobalVariable(const GlobalVariable *GVar,
1363*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
1364*9880d681SAndroid Build Coastguard Worker
1365*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
1366*9880d681SAndroid Build Coastguard Worker
1367*9880d681SAndroid Build Coastguard Worker // GlobalVariables are always constant pointers themselves.
1368*9880d681SAndroid Build Coastguard Worker Type *ETy = GVar->getValueType();
1369*9880d681SAndroid Build Coastguard Worker
1370*9880d681SAndroid Build Coastguard Worker O << ".";
1371*9880d681SAndroid Build Coastguard Worker emitPTXAddressSpace(GVar->getType()->getAddressSpace(), O);
1372*9880d681SAndroid Build Coastguard Worker if (GVar->getAlignment() == 0)
1373*9880d681SAndroid Build Coastguard Worker O << " .align " << (int)DL.getPrefTypeAlignment(ETy);
1374*9880d681SAndroid Build Coastguard Worker else
1375*9880d681SAndroid Build Coastguard Worker O << " .align " << GVar->getAlignment();
1376*9880d681SAndroid Build Coastguard Worker
1377*9880d681SAndroid Build Coastguard Worker if (ETy->isFloatingPointTy() || ETy->isIntegerTy() || ETy->isPointerTy()) {
1378*9880d681SAndroid Build Coastguard Worker O << " .";
1379*9880d681SAndroid Build Coastguard Worker O << getPTXFundamentalTypeStr(ETy);
1380*9880d681SAndroid Build Coastguard Worker O << " ";
1381*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1382*9880d681SAndroid Build Coastguard Worker return;
1383*9880d681SAndroid Build Coastguard Worker }
1384*9880d681SAndroid Build Coastguard Worker
1385*9880d681SAndroid Build Coastguard Worker int64_t ElementSize = 0;
1386*9880d681SAndroid Build Coastguard Worker
1387*9880d681SAndroid Build Coastguard Worker // Although PTX has direct support for struct type and array type and LLVM IR
1388*9880d681SAndroid Build Coastguard Worker // is very similar to PTX, the LLVM CodeGen does not support for targets that
1389*9880d681SAndroid Build Coastguard Worker // support these high level field accesses. Structs and arrays are lowered
1390*9880d681SAndroid Build Coastguard Worker // into arrays of bytes.
1391*9880d681SAndroid Build Coastguard Worker switch (ETy->getTypeID()) {
1392*9880d681SAndroid Build Coastguard Worker case Type::StructTyID:
1393*9880d681SAndroid Build Coastguard Worker case Type::ArrayTyID:
1394*9880d681SAndroid Build Coastguard Worker case Type::VectorTyID:
1395*9880d681SAndroid Build Coastguard Worker ElementSize = DL.getTypeStoreSize(ETy);
1396*9880d681SAndroid Build Coastguard Worker O << " .b8 ";
1397*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1398*9880d681SAndroid Build Coastguard Worker O << "[";
1399*9880d681SAndroid Build Coastguard Worker if (ElementSize) {
1400*9880d681SAndroid Build Coastguard Worker O << ElementSize;
1401*9880d681SAndroid Build Coastguard Worker }
1402*9880d681SAndroid Build Coastguard Worker O << "]";
1403*9880d681SAndroid Build Coastguard Worker break;
1404*9880d681SAndroid Build Coastguard Worker default:
1405*9880d681SAndroid Build Coastguard Worker llvm_unreachable("type not supported yet");
1406*9880d681SAndroid Build Coastguard Worker }
1407*9880d681SAndroid Build Coastguard Worker return;
1408*9880d681SAndroid Build Coastguard Worker }
1409*9880d681SAndroid Build Coastguard Worker
getOpenCLAlignment(const DataLayout & DL,Type * Ty)1410*9880d681SAndroid Build Coastguard Worker static unsigned int getOpenCLAlignment(const DataLayout &DL, Type *Ty) {
1411*9880d681SAndroid Build Coastguard Worker if (Ty->isSingleValueType())
1412*9880d681SAndroid Build Coastguard Worker return DL.getPrefTypeAlignment(Ty);
1413*9880d681SAndroid Build Coastguard Worker
1414*9880d681SAndroid Build Coastguard Worker auto *ATy = dyn_cast<ArrayType>(Ty);
1415*9880d681SAndroid Build Coastguard Worker if (ATy)
1416*9880d681SAndroid Build Coastguard Worker return getOpenCLAlignment(DL, ATy->getElementType());
1417*9880d681SAndroid Build Coastguard Worker
1418*9880d681SAndroid Build Coastguard Worker auto *STy = dyn_cast<StructType>(Ty);
1419*9880d681SAndroid Build Coastguard Worker if (STy) {
1420*9880d681SAndroid Build Coastguard Worker unsigned int alignStruct = 1;
1421*9880d681SAndroid Build Coastguard Worker // Go through each element of the struct and find the
1422*9880d681SAndroid Build Coastguard Worker // largest alignment.
1423*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = STy->getNumElements(); i != e; i++) {
1424*9880d681SAndroid Build Coastguard Worker Type *ETy = STy->getElementType(i);
1425*9880d681SAndroid Build Coastguard Worker unsigned int align = getOpenCLAlignment(DL, ETy);
1426*9880d681SAndroid Build Coastguard Worker if (align > alignStruct)
1427*9880d681SAndroid Build Coastguard Worker alignStruct = align;
1428*9880d681SAndroid Build Coastguard Worker }
1429*9880d681SAndroid Build Coastguard Worker return alignStruct;
1430*9880d681SAndroid Build Coastguard Worker }
1431*9880d681SAndroid Build Coastguard Worker
1432*9880d681SAndroid Build Coastguard Worker auto *FTy = dyn_cast<FunctionType>(Ty);
1433*9880d681SAndroid Build Coastguard Worker if (FTy)
1434*9880d681SAndroid Build Coastguard Worker return DL.getPointerPrefAlignment();
1435*9880d681SAndroid Build Coastguard Worker return DL.getPrefTypeAlignment(Ty);
1436*9880d681SAndroid Build Coastguard Worker }
1437*9880d681SAndroid Build Coastguard Worker
printParamName(Function::const_arg_iterator I,int paramIndex,raw_ostream & O)1438*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printParamName(Function::const_arg_iterator I,
1439*9880d681SAndroid Build Coastguard Worker int paramIndex, raw_ostream &O) {
1440*9880d681SAndroid Build Coastguard Worker getSymbol(I->getParent())->print(O, MAI);
1441*9880d681SAndroid Build Coastguard Worker O << "_param_" << paramIndex;
1442*9880d681SAndroid Build Coastguard Worker }
1443*9880d681SAndroid Build Coastguard Worker
emitFunctionParamList(const Function * F,raw_ostream & O)1444*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitFunctionParamList(const Function *F, raw_ostream &O) {
1445*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
1446*9880d681SAndroid Build Coastguard Worker const AttributeSet &PAL = F->getAttributes();
1447*9880d681SAndroid Build Coastguard Worker const TargetLowering *TLI = nvptxSubtarget->getTargetLowering();
1448*9880d681SAndroid Build Coastguard Worker Function::const_arg_iterator I, E;
1449*9880d681SAndroid Build Coastguard Worker unsigned paramIndex = 0;
1450*9880d681SAndroid Build Coastguard Worker bool first = true;
1451*9880d681SAndroid Build Coastguard Worker bool isKernelFunc = llvm::isKernelFunction(*F);
1452*9880d681SAndroid Build Coastguard Worker bool isABI = (nvptxSubtarget->getSmVersion() >= 20);
1453*9880d681SAndroid Build Coastguard Worker MVT thePointerTy = TLI->getPointerTy(DL);
1454*9880d681SAndroid Build Coastguard Worker
1455*9880d681SAndroid Build Coastguard Worker if (F->arg_empty()) {
1456*9880d681SAndroid Build Coastguard Worker O << "()\n";
1457*9880d681SAndroid Build Coastguard Worker return;
1458*9880d681SAndroid Build Coastguard Worker }
1459*9880d681SAndroid Build Coastguard Worker
1460*9880d681SAndroid Build Coastguard Worker O << "(\n";
1461*9880d681SAndroid Build Coastguard Worker
1462*9880d681SAndroid Build Coastguard Worker for (I = F->arg_begin(), E = F->arg_end(); I != E; ++I, paramIndex++) {
1463*9880d681SAndroid Build Coastguard Worker Type *Ty = I->getType();
1464*9880d681SAndroid Build Coastguard Worker
1465*9880d681SAndroid Build Coastguard Worker if (!first)
1466*9880d681SAndroid Build Coastguard Worker O << ",\n";
1467*9880d681SAndroid Build Coastguard Worker
1468*9880d681SAndroid Build Coastguard Worker first = false;
1469*9880d681SAndroid Build Coastguard Worker
1470*9880d681SAndroid Build Coastguard Worker // Handle image/sampler parameters
1471*9880d681SAndroid Build Coastguard Worker if (isKernelFunction(*F)) {
1472*9880d681SAndroid Build Coastguard Worker if (isSampler(*I) || isImage(*I)) {
1473*9880d681SAndroid Build Coastguard Worker if (isImage(*I)) {
1474*9880d681SAndroid Build Coastguard Worker std::string sname = I->getName();
1475*9880d681SAndroid Build Coastguard Worker if (isImageWriteOnly(*I) || isImageReadWrite(*I)) {
1476*9880d681SAndroid Build Coastguard Worker if (nvptxSubtarget->hasImageHandles())
1477*9880d681SAndroid Build Coastguard Worker O << "\t.param .u64 .ptr .surfref ";
1478*9880d681SAndroid Build Coastguard Worker else
1479*9880d681SAndroid Build Coastguard Worker O << "\t.param .surfref ";
1480*9880d681SAndroid Build Coastguard Worker CurrentFnSym->print(O, MAI);
1481*9880d681SAndroid Build Coastguard Worker O << "_param_" << paramIndex;
1482*9880d681SAndroid Build Coastguard Worker }
1483*9880d681SAndroid Build Coastguard Worker else { // Default image is read_only
1484*9880d681SAndroid Build Coastguard Worker if (nvptxSubtarget->hasImageHandles())
1485*9880d681SAndroid Build Coastguard Worker O << "\t.param .u64 .ptr .texref ";
1486*9880d681SAndroid Build Coastguard Worker else
1487*9880d681SAndroid Build Coastguard Worker O << "\t.param .texref ";
1488*9880d681SAndroid Build Coastguard Worker CurrentFnSym->print(O, MAI);
1489*9880d681SAndroid Build Coastguard Worker O << "_param_" << paramIndex;
1490*9880d681SAndroid Build Coastguard Worker }
1491*9880d681SAndroid Build Coastguard Worker } else {
1492*9880d681SAndroid Build Coastguard Worker if (nvptxSubtarget->hasImageHandles())
1493*9880d681SAndroid Build Coastguard Worker O << "\t.param .u64 .ptr .samplerref ";
1494*9880d681SAndroid Build Coastguard Worker else
1495*9880d681SAndroid Build Coastguard Worker O << "\t.param .samplerref ";
1496*9880d681SAndroid Build Coastguard Worker CurrentFnSym->print(O, MAI);
1497*9880d681SAndroid Build Coastguard Worker O << "_param_" << paramIndex;
1498*9880d681SAndroid Build Coastguard Worker }
1499*9880d681SAndroid Build Coastguard Worker continue;
1500*9880d681SAndroid Build Coastguard Worker }
1501*9880d681SAndroid Build Coastguard Worker }
1502*9880d681SAndroid Build Coastguard Worker
1503*9880d681SAndroid Build Coastguard Worker if (!PAL.hasAttribute(paramIndex + 1, Attribute::ByVal)) {
1504*9880d681SAndroid Build Coastguard Worker if (Ty->isAggregateType() || Ty->isVectorTy()) {
1505*9880d681SAndroid Build Coastguard Worker // Just print .param .align <a> .b8 .param[size];
1506*9880d681SAndroid Build Coastguard Worker // <a> = PAL.getparamalignment
1507*9880d681SAndroid Build Coastguard Worker // size = typeallocsize of element type
1508*9880d681SAndroid Build Coastguard Worker unsigned align = PAL.getParamAlignment(paramIndex + 1);
1509*9880d681SAndroid Build Coastguard Worker if (align == 0)
1510*9880d681SAndroid Build Coastguard Worker align = DL.getABITypeAlignment(Ty);
1511*9880d681SAndroid Build Coastguard Worker
1512*9880d681SAndroid Build Coastguard Worker unsigned sz = DL.getTypeAllocSize(Ty);
1513*9880d681SAndroid Build Coastguard Worker O << "\t.param .align " << align << " .b8 ";
1514*9880d681SAndroid Build Coastguard Worker printParamName(I, paramIndex, O);
1515*9880d681SAndroid Build Coastguard Worker O << "[" << sz << "]";
1516*9880d681SAndroid Build Coastguard Worker
1517*9880d681SAndroid Build Coastguard Worker continue;
1518*9880d681SAndroid Build Coastguard Worker }
1519*9880d681SAndroid Build Coastguard Worker // Just a scalar
1520*9880d681SAndroid Build Coastguard Worker auto *PTy = dyn_cast<PointerType>(Ty);
1521*9880d681SAndroid Build Coastguard Worker if (isKernelFunc) {
1522*9880d681SAndroid Build Coastguard Worker if (PTy) {
1523*9880d681SAndroid Build Coastguard Worker // Special handling for pointer arguments to kernel
1524*9880d681SAndroid Build Coastguard Worker O << "\t.param .u" << thePointerTy.getSizeInBits() << " ";
1525*9880d681SAndroid Build Coastguard Worker
1526*9880d681SAndroid Build Coastguard Worker if (static_cast<NVPTXTargetMachine &>(TM).getDrvInterface() !=
1527*9880d681SAndroid Build Coastguard Worker NVPTX::CUDA) {
1528*9880d681SAndroid Build Coastguard Worker Type *ETy = PTy->getElementType();
1529*9880d681SAndroid Build Coastguard Worker int addrSpace = PTy->getAddressSpace();
1530*9880d681SAndroid Build Coastguard Worker switch (addrSpace) {
1531*9880d681SAndroid Build Coastguard Worker default:
1532*9880d681SAndroid Build Coastguard Worker O << ".ptr ";
1533*9880d681SAndroid Build Coastguard Worker break;
1534*9880d681SAndroid Build Coastguard Worker case llvm::ADDRESS_SPACE_CONST:
1535*9880d681SAndroid Build Coastguard Worker O << ".ptr .const ";
1536*9880d681SAndroid Build Coastguard Worker break;
1537*9880d681SAndroid Build Coastguard Worker case llvm::ADDRESS_SPACE_SHARED:
1538*9880d681SAndroid Build Coastguard Worker O << ".ptr .shared ";
1539*9880d681SAndroid Build Coastguard Worker break;
1540*9880d681SAndroid Build Coastguard Worker case llvm::ADDRESS_SPACE_GLOBAL:
1541*9880d681SAndroid Build Coastguard Worker O << ".ptr .global ";
1542*9880d681SAndroid Build Coastguard Worker break;
1543*9880d681SAndroid Build Coastguard Worker }
1544*9880d681SAndroid Build Coastguard Worker O << ".align " << (int)getOpenCLAlignment(DL, ETy) << " ";
1545*9880d681SAndroid Build Coastguard Worker }
1546*9880d681SAndroid Build Coastguard Worker printParamName(I, paramIndex, O);
1547*9880d681SAndroid Build Coastguard Worker continue;
1548*9880d681SAndroid Build Coastguard Worker }
1549*9880d681SAndroid Build Coastguard Worker
1550*9880d681SAndroid Build Coastguard Worker // non-pointer scalar to kernel func
1551*9880d681SAndroid Build Coastguard Worker O << "\t.param .";
1552*9880d681SAndroid Build Coastguard Worker // Special case: predicate operands become .u8 types
1553*9880d681SAndroid Build Coastguard Worker if (Ty->isIntegerTy(1))
1554*9880d681SAndroid Build Coastguard Worker O << "u8";
1555*9880d681SAndroid Build Coastguard Worker else
1556*9880d681SAndroid Build Coastguard Worker O << getPTXFundamentalTypeStr(Ty);
1557*9880d681SAndroid Build Coastguard Worker O << " ";
1558*9880d681SAndroid Build Coastguard Worker printParamName(I, paramIndex, O);
1559*9880d681SAndroid Build Coastguard Worker continue;
1560*9880d681SAndroid Build Coastguard Worker }
1561*9880d681SAndroid Build Coastguard Worker // Non-kernel function, just print .param .b<size> for ABI
1562*9880d681SAndroid Build Coastguard Worker // and .reg .b<size> for non-ABI
1563*9880d681SAndroid Build Coastguard Worker unsigned sz = 0;
1564*9880d681SAndroid Build Coastguard Worker if (isa<IntegerType>(Ty)) {
1565*9880d681SAndroid Build Coastguard Worker sz = cast<IntegerType>(Ty)->getBitWidth();
1566*9880d681SAndroid Build Coastguard Worker if (sz < 32)
1567*9880d681SAndroid Build Coastguard Worker sz = 32;
1568*9880d681SAndroid Build Coastguard Worker } else if (isa<PointerType>(Ty))
1569*9880d681SAndroid Build Coastguard Worker sz = thePointerTy.getSizeInBits();
1570*9880d681SAndroid Build Coastguard Worker else
1571*9880d681SAndroid Build Coastguard Worker sz = Ty->getPrimitiveSizeInBits();
1572*9880d681SAndroid Build Coastguard Worker if (isABI)
1573*9880d681SAndroid Build Coastguard Worker O << "\t.param .b" << sz << " ";
1574*9880d681SAndroid Build Coastguard Worker else
1575*9880d681SAndroid Build Coastguard Worker O << "\t.reg .b" << sz << " ";
1576*9880d681SAndroid Build Coastguard Worker printParamName(I, paramIndex, O);
1577*9880d681SAndroid Build Coastguard Worker continue;
1578*9880d681SAndroid Build Coastguard Worker }
1579*9880d681SAndroid Build Coastguard Worker
1580*9880d681SAndroid Build Coastguard Worker // param has byVal attribute. So should be a pointer
1581*9880d681SAndroid Build Coastguard Worker auto *PTy = dyn_cast<PointerType>(Ty);
1582*9880d681SAndroid Build Coastguard Worker assert(PTy && "Param with byval attribute should be a pointer type");
1583*9880d681SAndroid Build Coastguard Worker Type *ETy = PTy->getElementType();
1584*9880d681SAndroid Build Coastguard Worker
1585*9880d681SAndroid Build Coastguard Worker if (isABI || isKernelFunc) {
1586*9880d681SAndroid Build Coastguard Worker // Just print .param .align <a> .b8 .param[size];
1587*9880d681SAndroid Build Coastguard Worker // <a> = PAL.getparamalignment
1588*9880d681SAndroid Build Coastguard Worker // size = typeallocsize of element type
1589*9880d681SAndroid Build Coastguard Worker unsigned align = PAL.getParamAlignment(paramIndex + 1);
1590*9880d681SAndroid Build Coastguard Worker if (align == 0)
1591*9880d681SAndroid Build Coastguard Worker align = DL.getABITypeAlignment(ETy);
1592*9880d681SAndroid Build Coastguard Worker
1593*9880d681SAndroid Build Coastguard Worker unsigned sz = DL.getTypeAllocSize(ETy);
1594*9880d681SAndroid Build Coastguard Worker O << "\t.param .align " << align << " .b8 ";
1595*9880d681SAndroid Build Coastguard Worker printParamName(I, paramIndex, O);
1596*9880d681SAndroid Build Coastguard Worker O << "[" << sz << "]";
1597*9880d681SAndroid Build Coastguard Worker continue;
1598*9880d681SAndroid Build Coastguard Worker } else {
1599*9880d681SAndroid Build Coastguard Worker // Split the ETy into constituent parts and
1600*9880d681SAndroid Build Coastguard Worker // print .param .b<size> <name> for each part.
1601*9880d681SAndroid Build Coastguard Worker // Further, if a part is vector, print the above for
1602*9880d681SAndroid Build Coastguard Worker // each vector element.
1603*9880d681SAndroid Build Coastguard Worker SmallVector<EVT, 16> vtparts;
1604*9880d681SAndroid Build Coastguard Worker ComputeValueVTs(*TLI, DL, ETy, vtparts);
1605*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = vtparts.size(); i != e; ++i) {
1606*9880d681SAndroid Build Coastguard Worker unsigned elems = 1;
1607*9880d681SAndroid Build Coastguard Worker EVT elemtype = vtparts[i];
1608*9880d681SAndroid Build Coastguard Worker if (vtparts[i].isVector()) {
1609*9880d681SAndroid Build Coastguard Worker elems = vtparts[i].getVectorNumElements();
1610*9880d681SAndroid Build Coastguard Worker elemtype = vtparts[i].getVectorElementType();
1611*9880d681SAndroid Build Coastguard Worker }
1612*9880d681SAndroid Build Coastguard Worker
1613*9880d681SAndroid Build Coastguard Worker for (unsigned j = 0, je = elems; j != je; ++j) {
1614*9880d681SAndroid Build Coastguard Worker unsigned sz = elemtype.getSizeInBits();
1615*9880d681SAndroid Build Coastguard Worker if (elemtype.isInteger() && (sz < 32))
1616*9880d681SAndroid Build Coastguard Worker sz = 32;
1617*9880d681SAndroid Build Coastguard Worker O << "\t.reg .b" << sz << " ";
1618*9880d681SAndroid Build Coastguard Worker printParamName(I, paramIndex, O);
1619*9880d681SAndroid Build Coastguard Worker if (j < je - 1)
1620*9880d681SAndroid Build Coastguard Worker O << ",\n";
1621*9880d681SAndroid Build Coastguard Worker ++paramIndex;
1622*9880d681SAndroid Build Coastguard Worker }
1623*9880d681SAndroid Build Coastguard Worker if (i < e - 1)
1624*9880d681SAndroid Build Coastguard Worker O << ",\n";
1625*9880d681SAndroid Build Coastguard Worker }
1626*9880d681SAndroid Build Coastguard Worker --paramIndex;
1627*9880d681SAndroid Build Coastguard Worker continue;
1628*9880d681SAndroid Build Coastguard Worker }
1629*9880d681SAndroid Build Coastguard Worker }
1630*9880d681SAndroid Build Coastguard Worker
1631*9880d681SAndroid Build Coastguard Worker O << "\n)\n";
1632*9880d681SAndroid Build Coastguard Worker }
1633*9880d681SAndroid Build Coastguard Worker
emitFunctionParamList(const MachineFunction & MF,raw_ostream & O)1634*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitFunctionParamList(const MachineFunction &MF,
1635*9880d681SAndroid Build Coastguard Worker raw_ostream &O) {
1636*9880d681SAndroid Build Coastguard Worker const Function *F = MF.getFunction();
1637*9880d681SAndroid Build Coastguard Worker emitFunctionParamList(F, O);
1638*9880d681SAndroid Build Coastguard Worker }
1639*9880d681SAndroid Build Coastguard Worker
setAndEmitFunctionVirtualRegisters(const MachineFunction & MF)1640*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
1641*9880d681SAndroid Build Coastguard Worker const MachineFunction &MF) {
1642*9880d681SAndroid Build Coastguard Worker SmallString<128> Str;
1643*9880d681SAndroid Build Coastguard Worker raw_svector_ostream O(Str);
1644*9880d681SAndroid Build Coastguard Worker
1645*9880d681SAndroid Build Coastguard Worker // Map the global virtual register number to a register class specific
1646*9880d681SAndroid Build Coastguard Worker // virtual register number starting from 1 with that class.
1647*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1648*9880d681SAndroid Build Coastguard Worker //unsigned numRegClasses = TRI->getNumRegClasses();
1649*9880d681SAndroid Build Coastguard Worker
1650*9880d681SAndroid Build Coastguard Worker // Emit the Fake Stack Object
1651*9880d681SAndroid Build Coastguard Worker const MachineFrameInfo *MFI = MF.getFrameInfo();
1652*9880d681SAndroid Build Coastguard Worker int NumBytes = (int) MFI->getStackSize();
1653*9880d681SAndroid Build Coastguard Worker if (NumBytes) {
1654*9880d681SAndroid Build Coastguard Worker O << "\t.local .align " << MFI->getMaxAlignment() << " .b8 \t" << DEPOTNAME
1655*9880d681SAndroid Build Coastguard Worker << getFunctionNumber() << "[" << NumBytes << "];\n";
1656*9880d681SAndroid Build Coastguard Worker if (static_cast<const NVPTXTargetMachine &>(MF.getTarget()).is64Bit()) {
1657*9880d681SAndroid Build Coastguard Worker O << "\t.reg .b64 \t%SP;\n";
1658*9880d681SAndroid Build Coastguard Worker O << "\t.reg .b64 \t%SPL;\n";
1659*9880d681SAndroid Build Coastguard Worker } else {
1660*9880d681SAndroid Build Coastguard Worker O << "\t.reg .b32 \t%SP;\n";
1661*9880d681SAndroid Build Coastguard Worker O << "\t.reg .b32 \t%SPL;\n";
1662*9880d681SAndroid Build Coastguard Worker }
1663*9880d681SAndroid Build Coastguard Worker }
1664*9880d681SAndroid Build Coastguard Worker
1665*9880d681SAndroid Build Coastguard Worker // Go through all virtual registers to establish the mapping between the
1666*9880d681SAndroid Build Coastguard Worker // global virtual
1667*9880d681SAndroid Build Coastguard Worker // register number and the per class virtual register number.
1668*9880d681SAndroid Build Coastguard Worker // We use the per class virtual register number in the ptx output.
1669*9880d681SAndroid Build Coastguard Worker unsigned int numVRs = MRI->getNumVirtRegs();
1670*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < numVRs; i++) {
1671*9880d681SAndroid Build Coastguard Worker unsigned int vr = TRI->index2VirtReg(i);
1672*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = MRI->getRegClass(vr);
1673*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> ®map = VRegMapping[RC];
1674*9880d681SAndroid Build Coastguard Worker int n = regmap.size();
1675*9880d681SAndroid Build Coastguard Worker regmap.insert(std::make_pair(vr, n + 1));
1676*9880d681SAndroid Build Coastguard Worker }
1677*9880d681SAndroid Build Coastguard Worker
1678*9880d681SAndroid Build Coastguard Worker // Emit register declarations
1679*9880d681SAndroid Build Coastguard Worker // @TODO: Extract out the real register usage
1680*9880d681SAndroid Build Coastguard Worker // O << "\t.reg .pred %p<" << NVPTXNumRegisters << ">;\n";
1681*9880d681SAndroid Build Coastguard Worker // O << "\t.reg .s16 %rc<" << NVPTXNumRegisters << ">;\n";
1682*9880d681SAndroid Build Coastguard Worker // O << "\t.reg .s16 %rs<" << NVPTXNumRegisters << ">;\n";
1683*9880d681SAndroid Build Coastguard Worker // O << "\t.reg .s32 %r<" << NVPTXNumRegisters << ">;\n";
1684*9880d681SAndroid Build Coastguard Worker // O << "\t.reg .s64 %rd<" << NVPTXNumRegisters << ">;\n";
1685*9880d681SAndroid Build Coastguard Worker // O << "\t.reg .f32 %f<" << NVPTXNumRegisters << ">;\n";
1686*9880d681SAndroid Build Coastguard Worker // O << "\t.reg .f64 %fd<" << NVPTXNumRegisters << ">;\n";
1687*9880d681SAndroid Build Coastguard Worker
1688*9880d681SAndroid Build Coastguard Worker // Emit declaration of the virtual registers or 'physical' registers for
1689*9880d681SAndroid Build Coastguard Worker // each register class
1690*9880d681SAndroid Build Coastguard Worker for (unsigned i=0; i< TRI->getNumRegClasses(); i++) {
1691*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = TRI->getRegClass(i);
1692*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> ®map = VRegMapping[RC];
1693*9880d681SAndroid Build Coastguard Worker std::string rcname = getNVPTXRegClassName(RC);
1694*9880d681SAndroid Build Coastguard Worker std::string rcStr = getNVPTXRegClassStr(RC);
1695*9880d681SAndroid Build Coastguard Worker int n = regmap.size();
1696*9880d681SAndroid Build Coastguard Worker
1697*9880d681SAndroid Build Coastguard Worker // Only declare those registers that may be used.
1698*9880d681SAndroid Build Coastguard Worker if (n) {
1699*9880d681SAndroid Build Coastguard Worker O << "\t.reg " << rcname << " \t" << rcStr << "<" << (n+1)
1700*9880d681SAndroid Build Coastguard Worker << ">;\n";
1701*9880d681SAndroid Build Coastguard Worker }
1702*9880d681SAndroid Build Coastguard Worker }
1703*9880d681SAndroid Build Coastguard Worker
1704*9880d681SAndroid Build Coastguard Worker OutStreamer->EmitRawText(O.str());
1705*9880d681SAndroid Build Coastguard Worker }
1706*9880d681SAndroid Build Coastguard Worker
printFPConstant(const ConstantFP * Fp,raw_ostream & O)1707*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printFPConstant(const ConstantFP *Fp, raw_ostream &O) {
1708*9880d681SAndroid Build Coastguard Worker APFloat APF = APFloat(Fp->getValueAPF()); // make a copy
1709*9880d681SAndroid Build Coastguard Worker bool ignored;
1710*9880d681SAndroid Build Coastguard Worker unsigned int numHex;
1711*9880d681SAndroid Build Coastguard Worker const char *lead;
1712*9880d681SAndroid Build Coastguard Worker
1713*9880d681SAndroid Build Coastguard Worker if (Fp->getType()->getTypeID() == Type::FloatTyID) {
1714*9880d681SAndroid Build Coastguard Worker numHex = 8;
1715*9880d681SAndroid Build Coastguard Worker lead = "0f";
1716*9880d681SAndroid Build Coastguard Worker APF.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &ignored);
1717*9880d681SAndroid Build Coastguard Worker } else if (Fp->getType()->getTypeID() == Type::DoubleTyID) {
1718*9880d681SAndroid Build Coastguard Worker numHex = 16;
1719*9880d681SAndroid Build Coastguard Worker lead = "0d";
1720*9880d681SAndroid Build Coastguard Worker APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
1721*9880d681SAndroid Build Coastguard Worker } else
1722*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported fp type");
1723*9880d681SAndroid Build Coastguard Worker
1724*9880d681SAndroid Build Coastguard Worker APInt API = APF.bitcastToAPInt();
1725*9880d681SAndroid Build Coastguard Worker std::string hexstr(utohexstr(API.getZExtValue()));
1726*9880d681SAndroid Build Coastguard Worker O << lead;
1727*9880d681SAndroid Build Coastguard Worker if (hexstr.length() < numHex)
1728*9880d681SAndroid Build Coastguard Worker O << std::string(numHex - hexstr.length(), '0');
1729*9880d681SAndroid Build Coastguard Worker O << utohexstr(API.getZExtValue());
1730*9880d681SAndroid Build Coastguard Worker }
1731*9880d681SAndroid Build Coastguard Worker
printScalarConstant(const Constant * CPV,raw_ostream & O)1732*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printScalarConstant(const Constant *CPV, raw_ostream &O) {
1733*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
1734*9880d681SAndroid Build Coastguard Worker O << CI->getValue();
1735*9880d681SAndroid Build Coastguard Worker return;
1736*9880d681SAndroid Build Coastguard Worker }
1737*9880d681SAndroid Build Coastguard Worker if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV)) {
1738*9880d681SAndroid Build Coastguard Worker printFPConstant(CFP, O);
1739*9880d681SAndroid Build Coastguard Worker return;
1740*9880d681SAndroid Build Coastguard Worker }
1741*9880d681SAndroid Build Coastguard Worker if (isa<ConstantPointerNull>(CPV)) {
1742*9880d681SAndroid Build Coastguard Worker O << "0";
1743*9880d681SAndroid Build Coastguard Worker return;
1744*9880d681SAndroid Build Coastguard Worker }
1745*9880d681SAndroid Build Coastguard Worker if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
1746*9880d681SAndroid Build Coastguard Worker bool IsNonGenericPointer = false;
1747*9880d681SAndroid Build Coastguard Worker if (GVar->getType()->getAddressSpace() != 0) {
1748*9880d681SAndroid Build Coastguard Worker IsNonGenericPointer = true;
1749*9880d681SAndroid Build Coastguard Worker }
1750*9880d681SAndroid Build Coastguard Worker if (EmitGeneric && !isa<Function>(CPV) && !IsNonGenericPointer) {
1751*9880d681SAndroid Build Coastguard Worker O << "generic(";
1752*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1753*9880d681SAndroid Build Coastguard Worker O << ")";
1754*9880d681SAndroid Build Coastguard Worker } else {
1755*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1756*9880d681SAndroid Build Coastguard Worker }
1757*9880d681SAndroid Build Coastguard Worker return;
1758*9880d681SAndroid Build Coastguard Worker }
1759*9880d681SAndroid Build Coastguard Worker if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1760*9880d681SAndroid Build Coastguard Worker const Value *v = Cexpr->stripPointerCasts();
1761*9880d681SAndroid Build Coastguard Worker PointerType *PTy = dyn_cast<PointerType>(Cexpr->getType());
1762*9880d681SAndroid Build Coastguard Worker bool IsNonGenericPointer = false;
1763*9880d681SAndroid Build Coastguard Worker if (PTy && PTy->getAddressSpace() != 0) {
1764*9880d681SAndroid Build Coastguard Worker IsNonGenericPointer = true;
1765*9880d681SAndroid Build Coastguard Worker }
1766*9880d681SAndroid Build Coastguard Worker if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
1767*9880d681SAndroid Build Coastguard Worker if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
1768*9880d681SAndroid Build Coastguard Worker O << "generic(";
1769*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1770*9880d681SAndroid Build Coastguard Worker O << ")";
1771*9880d681SAndroid Build Coastguard Worker } else {
1772*9880d681SAndroid Build Coastguard Worker getSymbol(GVar)->print(O, MAI);
1773*9880d681SAndroid Build Coastguard Worker }
1774*9880d681SAndroid Build Coastguard Worker return;
1775*9880d681SAndroid Build Coastguard Worker } else {
1776*9880d681SAndroid Build Coastguard Worker lowerConstant(CPV)->print(O, MAI);
1777*9880d681SAndroid Build Coastguard Worker return;
1778*9880d681SAndroid Build Coastguard Worker }
1779*9880d681SAndroid Build Coastguard Worker }
1780*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Not scalar type found in printScalarConstant()");
1781*9880d681SAndroid Build Coastguard Worker }
1782*9880d681SAndroid Build Coastguard Worker
1783*9880d681SAndroid Build Coastguard Worker // These utility functions assure we get the right sequence of bytes for a given
1784*9880d681SAndroid Build Coastguard Worker // type even for big-endian machines
ConvertIntToBytes(unsigned char * p,T val)1785*9880d681SAndroid Build Coastguard Worker template <typename T> static void ConvertIntToBytes(unsigned char *p, T val) {
1786*9880d681SAndroid Build Coastguard Worker int64_t vp = (int64_t)val;
1787*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(T); ++i) {
1788*9880d681SAndroid Build Coastguard Worker p[i] = (unsigned char)vp;
1789*9880d681SAndroid Build Coastguard Worker vp >>= 8;
1790*9880d681SAndroid Build Coastguard Worker }
1791*9880d681SAndroid Build Coastguard Worker }
ConvertFloatToBytes(unsigned char * p,float val)1792*9880d681SAndroid Build Coastguard Worker static void ConvertFloatToBytes(unsigned char *p, float val) {
1793*9880d681SAndroid Build Coastguard Worker int32_t *vp = (int32_t *)&val;
1794*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(int32_t); ++i) {
1795*9880d681SAndroid Build Coastguard Worker p[i] = (unsigned char)*vp;
1796*9880d681SAndroid Build Coastguard Worker *vp >>= 8;
1797*9880d681SAndroid Build Coastguard Worker }
1798*9880d681SAndroid Build Coastguard Worker }
ConvertDoubleToBytes(unsigned char * p,double val)1799*9880d681SAndroid Build Coastguard Worker static void ConvertDoubleToBytes(unsigned char *p, double val) {
1800*9880d681SAndroid Build Coastguard Worker int64_t *vp = (int64_t *)&val;
1801*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < sizeof(int64_t); ++i) {
1802*9880d681SAndroid Build Coastguard Worker p[i] = (unsigned char)*vp;
1803*9880d681SAndroid Build Coastguard Worker *vp >>= 8;
1804*9880d681SAndroid Build Coastguard Worker }
1805*9880d681SAndroid Build Coastguard Worker }
1806*9880d681SAndroid Build Coastguard Worker
bufferLEByte(const Constant * CPV,int Bytes,AggBuffer * aggBuffer)1807*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes,
1808*9880d681SAndroid Build Coastguard Worker AggBuffer *aggBuffer) {
1809*9880d681SAndroid Build Coastguard Worker
1810*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
1811*9880d681SAndroid Build Coastguard Worker
1812*9880d681SAndroid Build Coastguard Worker if (isa<UndefValue>(CPV) || CPV->isNullValue()) {
1813*9880d681SAndroid Build Coastguard Worker int s = DL.getTypeAllocSize(CPV->getType());
1814*9880d681SAndroid Build Coastguard Worker if (s < Bytes)
1815*9880d681SAndroid Build Coastguard Worker s = Bytes;
1816*9880d681SAndroid Build Coastguard Worker aggBuffer->addZeros(s);
1817*9880d681SAndroid Build Coastguard Worker return;
1818*9880d681SAndroid Build Coastguard Worker }
1819*9880d681SAndroid Build Coastguard Worker
1820*9880d681SAndroid Build Coastguard Worker unsigned char ptr[8];
1821*9880d681SAndroid Build Coastguard Worker switch (CPV->getType()->getTypeID()) {
1822*9880d681SAndroid Build Coastguard Worker
1823*9880d681SAndroid Build Coastguard Worker case Type::IntegerTyID: {
1824*9880d681SAndroid Build Coastguard Worker Type *ETy = CPV->getType();
1825*9880d681SAndroid Build Coastguard Worker if (ETy == Type::getInt8Ty(CPV->getContext())) {
1826*9880d681SAndroid Build Coastguard Worker unsigned char c = (unsigned char)cast<ConstantInt>(CPV)->getZExtValue();
1827*9880d681SAndroid Build Coastguard Worker ConvertIntToBytes<>(ptr, c);
1828*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 1, Bytes);
1829*9880d681SAndroid Build Coastguard Worker } else if (ETy == Type::getInt16Ty(CPV->getContext())) {
1830*9880d681SAndroid Build Coastguard Worker short int16 = (short)cast<ConstantInt>(CPV)->getZExtValue();
1831*9880d681SAndroid Build Coastguard Worker ConvertIntToBytes<>(ptr, int16);
1832*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 2, Bytes);
1833*9880d681SAndroid Build Coastguard Worker } else if (ETy == Type::getInt32Ty(CPV->getContext())) {
1834*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *constInt = dyn_cast<ConstantInt>(CPV)) {
1835*9880d681SAndroid Build Coastguard Worker int int32 = (int)(constInt->getZExtValue());
1836*9880d681SAndroid Build Coastguard Worker ConvertIntToBytes<>(ptr, int32);
1837*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 4, Bytes);
1838*9880d681SAndroid Build Coastguard Worker break;
1839*9880d681SAndroid Build Coastguard Worker } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1840*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
1841*9880d681SAndroid Build Coastguard Worker ConstantFoldConstantExpression(Cexpr, DL))) {
1842*9880d681SAndroid Build Coastguard Worker int int32 = (int)(constInt->getZExtValue());
1843*9880d681SAndroid Build Coastguard Worker ConvertIntToBytes<>(ptr, int32);
1844*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 4, Bytes);
1845*9880d681SAndroid Build Coastguard Worker break;
1846*9880d681SAndroid Build Coastguard Worker }
1847*9880d681SAndroid Build Coastguard Worker if (Cexpr->getOpcode() == Instruction::PtrToInt) {
1848*9880d681SAndroid Build Coastguard Worker Value *v = Cexpr->getOperand(0)->stripPointerCasts();
1849*9880d681SAndroid Build Coastguard Worker aggBuffer->addSymbol(v, Cexpr->getOperand(0));
1850*9880d681SAndroid Build Coastguard Worker aggBuffer->addZeros(4);
1851*9880d681SAndroid Build Coastguard Worker break;
1852*9880d681SAndroid Build Coastguard Worker }
1853*9880d681SAndroid Build Coastguard Worker }
1854*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported integer const type");
1855*9880d681SAndroid Build Coastguard Worker } else if (ETy == Type::getInt64Ty(CPV->getContext())) {
1856*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *constInt = dyn_cast<ConstantInt>(CPV)) {
1857*9880d681SAndroid Build Coastguard Worker long long int64 = (long long)(constInt->getZExtValue());
1858*9880d681SAndroid Build Coastguard Worker ConvertIntToBytes<>(ptr, int64);
1859*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 8, Bytes);
1860*9880d681SAndroid Build Coastguard Worker break;
1861*9880d681SAndroid Build Coastguard Worker } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1862*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
1863*9880d681SAndroid Build Coastguard Worker ConstantFoldConstantExpression(Cexpr, DL))) {
1864*9880d681SAndroid Build Coastguard Worker long long int64 = (long long)(constInt->getZExtValue());
1865*9880d681SAndroid Build Coastguard Worker ConvertIntToBytes<>(ptr, int64);
1866*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 8, Bytes);
1867*9880d681SAndroid Build Coastguard Worker break;
1868*9880d681SAndroid Build Coastguard Worker }
1869*9880d681SAndroid Build Coastguard Worker if (Cexpr->getOpcode() == Instruction::PtrToInt) {
1870*9880d681SAndroid Build Coastguard Worker Value *v = Cexpr->getOperand(0)->stripPointerCasts();
1871*9880d681SAndroid Build Coastguard Worker aggBuffer->addSymbol(v, Cexpr->getOperand(0));
1872*9880d681SAndroid Build Coastguard Worker aggBuffer->addZeros(8);
1873*9880d681SAndroid Build Coastguard Worker break;
1874*9880d681SAndroid Build Coastguard Worker }
1875*9880d681SAndroid Build Coastguard Worker }
1876*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported integer const type");
1877*9880d681SAndroid Build Coastguard Worker } else
1878*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported integer const type");
1879*9880d681SAndroid Build Coastguard Worker break;
1880*9880d681SAndroid Build Coastguard Worker }
1881*9880d681SAndroid Build Coastguard Worker case Type::FloatTyID:
1882*9880d681SAndroid Build Coastguard Worker case Type::DoubleTyID: {
1883*9880d681SAndroid Build Coastguard Worker const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV);
1884*9880d681SAndroid Build Coastguard Worker Type *Ty = CFP->getType();
1885*9880d681SAndroid Build Coastguard Worker if (Ty == Type::getFloatTy(CPV->getContext())) {
1886*9880d681SAndroid Build Coastguard Worker float float32 = (float) CFP->getValueAPF().convertToFloat();
1887*9880d681SAndroid Build Coastguard Worker ConvertFloatToBytes(ptr, float32);
1888*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 4, Bytes);
1889*9880d681SAndroid Build Coastguard Worker } else if (Ty == Type::getDoubleTy(CPV->getContext())) {
1890*9880d681SAndroid Build Coastguard Worker double float64 = CFP->getValueAPF().convertToDouble();
1891*9880d681SAndroid Build Coastguard Worker ConvertDoubleToBytes(ptr, float64);
1892*9880d681SAndroid Build Coastguard Worker aggBuffer->addBytes(ptr, 8, Bytes);
1893*9880d681SAndroid Build Coastguard Worker } else {
1894*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported fp const type");
1895*9880d681SAndroid Build Coastguard Worker }
1896*9880d681SAndroid Build Coastguard Worker break;
1897*9880d681SAndroid Build Coastguard Worker }
1898*9880d681SAndroid Build Coastguard Worker case Type::PointerTyID: {
1899*9880d681SAndroid Build Coastguard Worker if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
1900*9880d681SAndroid Build Coastguard Worker aggBuffer->addSymbol(GVar, GVar);
1901*9880d681SAndroid Build Coastguard Worker } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1902*9880d681SAndroid Build Coastguard Worker const Value *v = Cexpr->stripPointerCasts();
1903*9880d681SAndroid Build Coastguard Worker aggBuffer->addSymbol(v, Cexpr);
1904*9880d681SAndroid Build Coastguard Worker }
1905*9880d681SAndroid Build Coastguard Worker unsigned int s = DL.getTypeAllocSize(CPV->getType());
1906*9880d681SAndroid Build Coastguard Worker aggBuffer->addZeros(s);
1907*9880d681SAndroid Build Coastguard Worker break;
1908*9880d681SAndroid Build Coastguard Worker }
1909*9880d681SAndroid Build Coastguard Worker
1910*9880d681SAndroid Build Coastguard Worker case Type::ArrayTyID:
1911*9880d681SAndroid Build Coastguard Worker case Type::VectorTyID:
1912*9880d681SAndroid Build Coastguard Worker case Type::StructTyID: {
1913*9880d681SAndroid Build Coastguard Worker if (isa<ConstantAggregate>(CPV) || isa<ConstantDataSequential>(CPV)) {
1914*9880d681SAndroid Build Coastguard Worker int ElementSize = DL.getTypeAllocSize(CPV->getType());
1915*9880d681SAndroid Build Coastguard Worker bufferAggregateConstant(CPV, aggBuffer);
1916*9880d681SAndroid Build Coastguard Worker if (Bytes > ElementSize)
1917*9880d681SAndroid Build Coastguard Worker aggBuffer->addZeros(Bytes - ElementSize);
1918*9880d681SAndroid Build Coastguard Worker } else if (isa<ConstantAggregateZero>(CPV))
1919*9880d681SAndroid Build Coastguard Worker aggBuffer->addZeros(Bytes);
1920*9880d681SAndroid Build Coastguard Worker else
1921*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected Constant type");
1922*9880d681SAndroid Build Coastguard Worker break;
1923*9880d681SAndroid Build Coastguard Worker }
1924*9880d681SAndroid Build Coastguard Worker
1925*9880d681SAndroid Build Coastguard Worker default:
1926*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported type");
1927*9880d681SAndroid Build Coastguard Worker }
1928*9880d681SAndroid Build Coastguard Worker }
1929*9880d681SAndroid Build Coastguard Worker
bufferAggregateConstant(const Constant * CPV,AggBuffer * aggBuffer)1930*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::bufferAggregateConstant(const Constant *CPV,
1931*9880d681SAndroid Build Coastguard Worker AggBuffer *aggBuffer) {
1932*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
1933*9880d681SAndroid Build Coastguard Worker int Bytes;
1934*9880d681SAndroid Build Coastguard Worker
1935*9880d681SAndroid Build Coastguard Worker // Old constants
1936*9880d681SAndroid Build Coastguard Worker if (isa<ConstantArray>(CPV) || isa<ConstantVector>(CPV)) {
1937*9880d681SAndroid Build Coastguard Worker if (CPV->getNumOperands())
1938*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i)
1939*9880d681SAndroid Build Coastguard Worker bufferLEByte(cast<Constant>(CPV->getOperand(i)), 0, aggBuffer);
1940*9880d681SAndroid Build Coastguard Worker return;
1941*9880d681SAndroid Build Coastguard Worker }
1942*9880d681SAndroid Build Coastguard Worker
1943*9880d681SAndroid Build Coastguard Worker if (const ConstantDataSequential *CDS =
1944*9880d681SAndroid Build Coastguard Worker dyn_cast<ConstantDataSequential>(CPV)) {
1945*9880d681SAndroid Build Coastguard Worker if (CDS->getNumElements())
1946*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < CDS->getNumElements(); ++i)
1947*9880d681SAndroid Build Coastguard Worker bufferLEByte(cast<Constant>(CDS->getElementAsConstant(i)), 0,
1948*9880d681SAndroid Build Coastguard Worker aggBuffer);
1949*9880d681SAndroid Build Coastguard Worker return;
1950*9880d681SAndroid Build Coastguard Worker }
1951*9880d681SAndroid Build Coastguard Worker
1952*9880d681SAndroid Build Coastguard Worker if (isa<ConstantStruct>(CPV)) {
1953*9880d681SAndroid Build Coastguard Worker if (CPV->getNumOperands()) {
1954*9880d681SAndroid Build Coastguard Worker StructType *ST = cast<StructType>(CPV->getType());
1955*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i) {
1956*9880d681SAndroid Build Coastguard Worker if (i == (e - 1))
1957*9880d681SAndroid Build Coastguard Worker Bytes = DL.getStructLayout(ST)->getElementOffset(0) +
1958*9880d681SAndroid Build Coastguard Worker DL.getTypeAllocSize(ST) -
1959*9880d681SAndroid Build Coastguard Worker DL.getStructLayout(ST)->getElementOffset(i);
1960*9880d681SAndroid Build Coastguard Worker else
1961*9880d681SAndroid Build Coastguard Worker Bytes = DL.getStructLayout(ST)->getElementOffset(i + 1) -
1962*9880d681SAndroid Build Coastguard Worker DL.getStructLayout(ST)->getElementOffset(i);
1963*9880d681SAndroid Build Coastguard Worker bufferLEByte(cast<Constant>(CPV->getOperand(i)), Bytes, aggBuffer);
1964*9880d681SAndroid Build Coastguard Worker }
1965*9880d681SAndroid Build Coastguard Worker }
1966*9880d681SAndroid Build Coastguard Worker return;
1967*9880d681SAndroid Build Coastguard Worker }
1968*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unsupported constant type in printAggregateConstant()");
1969*9880d681SAndroid Build Coastguard Worker }
1970*9880d681SAndroid Build Coastguard Worker
1971*9880d681SAndroid Build Coastguard Worker // buildTypeNameMap - Run through symbol table looking for type names.
1972*9880d681SAndroid Build Coastguard Worker //
1973*9880d681SAndroid Build Coastguard Worker
1974*9880d681SAndroid Build Coastguard Worker
ignoreLoc(const MachineInstr & MI)1975*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::ignoreLoc(const MachineInstr &MI) {
1976*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
1977*9880d681SAndroid Build Coastguard Worker default:
1978*9880d681SAndroid Build Coastguard Worker return false;
1979*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgBeginInst:
1980*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgEndInst0:
1981*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgEndInst1:
1982*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgF32:
1983*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgF64:
1984*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgI16:
1985*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgI32:
1986*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgI32imm:
1987*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgI64:
1988*9880d681SAndroid Build Coastguard Worker case NVPTX::CallArgParam:
1989*9880d681SAndroid Build Coastguard Worker case NVPTX::CallVoidInst:
1990*9880d681SAndroid Build Coastguard Worker case NVPTX::CallVoidInstReg:
1991*9880d681SAndroid Build Coastguard Worker case NVPTX::Callseq_End:
1992*9880d681SAndroid Build Coastguard Worker case NVPTX::CallVoidInstReg64:
1993*9880d681SAndroid Build Coastguard Worker case NVPTX::DeclareParamInst:
1994*9880d681SAndroid Build Coastguard Worker case NVPTX::DeclareRetMemInst:
1995*9880d681SAndroid Build Coastguard Worker case NVPTX::DeclareRetRegInst:
1996*9880d681SAndroid Build Coastguard Worker case NVPTX::DeclareRetScalarInst:
1997*9880d681SAndroid Build Coastguard Worker case NVPTX::DeclareScalarParamInst:
1998*9880d681SAndroid Build Coastguard Worker case NVPTX::DeclareScalarRegInst:
1999*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreParamF32:
2000*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreParamF64:
2001*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreParamI16:
2002*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreParamI32:
2003*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreParamI64:
2004*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreParamI8:
2005*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreRetvalF32:
2006*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreRetvalF64:
2007*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreRetvalI16:
2008*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreRetvalI32:
2009*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreRetvalI64:
2010*9880d681SAndroid Build Coastguard Worker case NVPTX::StoreRetvalI8:
2011*9880d681SAndroid Build Coastguard Worker case NVPTX::LastCallArgF32:
2012*9880d681SAndroid Build Coastguard Worker case NVPTX::LastCallArgF64:
2013*9880d681SAndroid Build Coastguard Worker case NVPTX::LastCallArgI16:
2014*9880d681SAndroid Build Coastguard Worker case NVPTX::LastCallArgI32:
2015*9880d681SAndroid Build Coastguard Worker case NVPTX::LastCallArgI32imm:
2016*9880d681SAndroid Build Coastguard Worker case NVPTX::LastCallArgI64:
2017*9880d681SAndroid Build Coastguard Worker case NVPTX::LastCallArgParam:
2018*9880d681SAndroid Build Coastguard Worker case NVPTX::LoadParamMemF32:
2019*9880d681SAndroid Build Coastguard Worker case NVPTX::LoadParamMemF64:
2020*9880d681SAndroid Build Coastguard Worker case NVPTX::LoadParamMemI16:
2021*9880d681SAndroid Build Coastguard Worker case NVPTX::LoadParamMemI32:
2022*9880d681SAndroid Build Coastguard Worker case NVPTX::LoadParamMemI64:
2023*9880d681SAndroid Build Coastguard Worker case NVPTX::LoadParamMemI8:
2024*9880d681SAndroid Build Coastguard Worker case NVPTX::PrototypeInst:
2025*9880d681SAndroid Build Coastguard Worker case NVPTX::DBG_VALUE:
2026*9880d681SAndroid Build Coastguard Worker return true;
2027*9880d681SAndroid Build Coastguard Worker }
2028*9880d681SAndroid Build Coastguard Worker return false;
2029*9880d681SAndroid Build Coastguard Worker }
2030*9880d681SAndroid Build Coastguard Worker
2031*9880d681SAndroid Build Coastguard Worker /// lowerConstantForGV - Return an MCExpr for the given Constant. This is mostly
2032*9880d681SAndroid Build Coastguard Worker /// a copy from AsmPrinter::lowerConstant, except customized to only handle
2033*9880d681SAndroid Build Coastguard Worker /// expressions that are representable in PTX and create
2034*9880d681SAndroid Build Coastguard Worker /// NVPTXGenericMCSymbolRefExpr nodes for addrspacecast instructions.
2035*9880d681SAndroid Build Coastguard Worker const MCExpr *
lowerConstantForGV(const Constant * CV,bool ProcessingGeneric)2036*9880d681SAndroid Build Coastguard Worker NVPTXAsmPrinter::lowerConstantForGV(const Constant *CV, bool ProcessingGeneric) {
2037*9880d681SAndroid Build Coastguard Worker MCContext &Ctx = OutContext;
2038*9880d681SAndroid Build Coastguard Worker
2039*9880d681SAndroid Build Coastguard Worker if (CV->isNullValue() || isa<UndefValue>(CV))
2040*9880d681SAndroid Build Coastguard Worker return MCConstantExpr::create(0, Ctx);
2041*9880d681SAndroid Build Coastguard Worker
2042*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
2043*9880d681SAndroid Build Coastguard Worker return MCConstantExpr::create(CI->getZExtValue(), Ctx);
2044*9880d681SAndroid Build Coastguard Worker
2045*9880d681SAndroid Build Coastguard Worker if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
2046*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr *Expr =
2047*9880d681SAndroid Build Coastguard Worker MCSymbolRefExpr::create(getSymbol(GV), Ctx);
2048*9880d681SAndroid Build Coastguard Worker if (ProcessingGeneric) {
2049*9880d681SAndroid Build Coastguard Worker return NVPTXGenericMCSymbolRefExpr::create(Expr, Ctx);
2050*9880d681SAndroid Build Coastguard Worker } else {
2051*9880d681SAndroid Build Coastguard Worker return Expr;
2052*9880d681SAndroid Build Coastguard Worker }
2053*9880d681SAndroid Build Coastguard Worker }
2054*9880d681SAndroid Build Coastguard Worker
2055*9880d681SAndroid Build Coastguard Worker const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
2056*9880d681SAndroid Build Coastguard Worker if (!CE) {
2057*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown constant value to lower!");
2058*9880d681SAndroid Build Coastguard Worker }
2059*9880d681SAndroid Build Coastguard Worker
2060*9880d681SAndroid Build Coastguard Worker switch (CE->getOpcode()) {
2061*9880d681SAndroid Build Coastguard Worker default:
2062*9880d681SAndroid Build Coastguard Worker // If the code isn't optimized, there may be outstanding folding
2063*9880d681SAndroid Build Coastguard Worker // opportunities. Attempt to fold the expression using DataLayout as a
2064*9880d681SAndroid Build Coastguard Worker // last resort before giving up.
2065*9880d681SAndroid Build Coastguard Worker if (Constant *C = ConstantFoldConstantExpression(CE, getDataLayout()))
2066*9880d681SAndroid Build Coastguard Worker if (C != CE)
2067*9880d681SAndroid Build Coastguard Worker return lowerConstantForGV(C, ProcessingGeneric);
2068*9880d681SAndroid Build Coastguard Worker
2069*9880d681SAndroid Build Coastguard Worker // Otherwise report the problem to the user.
2070*9880d681SAndroid Build Coastguard Worker {
2071*9880d681SAndroid Build Coastguard Worker std::string S;
2072*9880d681SAndroid Build Coastguard Worker raw_string_ostream OS(S);
2073*9880d681SAndroid Build Coastguard Worker OS << "Unsupported expression in static initializer: ";
2074*9880d681SAndroid Build Coastguard Worker CE->printAsOperand(OS, /*PrintType=*/false,
2075*9880d681SAndroid Build Coastguard Worker !MF ? nullptr : MF->getFunction()->getParent());
2076*9880d681SAndroid Build Coastguard Worker report_fatal_error(OS.str());
2077*9880d681SAndroid Build Coastguard Worker }
2078*9880d681SAndroid Build Coastguard Worker
2079*9880d681SAndroid Build Coastguard Worker case Instruction::AddrSpaceCast: {
2080*9880d681SAndroid Build Coastguard Worker // Strip the addrspacecast and pass along the operand
2081*9880d681SAndroid Build Coastguard Worker PointerType *DstTy = cast<PointerType>(CE->getType());
2082*9880d681SAndroid Build Coastguard Worker if (DstTy->getAddressSpace() == 0) {
2083*9880d681SAndroid Build Coastguard Worker return lowerConstantForGV(cast<const Constant>(CE->getOperand(0)), true);
2084*9880d681SAndroid Build Coastguard Worker }
2085*9880d681SAndroid Build Coastguard Worker std::string S;
2086*9880d681SAndroid Build Coastguard Worker raw_string_ostream OS(S);
2087*9880d681SAndroid Build Coastguard Worker OS << "Unsupported expression in static initializer: ";
2088*9880d681SAndroid Build Coastguard Worker CE->printAsOperand(OS, /*PrintType=*/ false,
2089*9880d681SAndroid Build Coastguard Worker !MF ? 0 : MF->getFunction()->getParent());
2090*9880d681SAndroid Build Coastguard Worker report_fatal_error(OS.str());
2091*9880d681SAndroid Build Coastguard Worker }
2092*9880d681SAndroid Build Coastguard Worker
2093*9880d681SAndroid Build Coastguard Worker case Instruction::GetElementPtr: {
2094*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
2095*9880d681SAndroid Build Coastguard Worker
2096*9880d681SAndroid Build Coastguard Worker // Generate a symbolic expression for the byte address
2097*9880d681SAndroid Build Coastguard Worker APInt OffsetAI(DL.getPointerTypeSizeInBits(CE->getType()), 0);
2098*9880d681SAndroid Build Coastguard Worker cast<GEPOperator>(CE)->accumulateConstantOffset(DL, OffsetAI);
2099*9880d681SAndroid Build Coastguard Worker
2100*9880d681SAndroid Build Coastguard Worker const MCExpr *Base = lowerConstantForGV(CE->getOperand(0),
2101*9880d681SAndroid Build Coastguard Worker ProcessingGeneric);
2102*9880d681SAndroid Build Coastguard Worker if (!OffsetAI)
2103*9880d681SAndroid Build Coastguard Worker return Base;
2104*9880d681SAndroid Build Coastguard Worker
2105*9880d681SAndroid Build Coastguard Worker int64_t Offset = OffsetAI.getSExtValue();
2106*9880d681SAndroid Build Coastguard Worker return MCBinaryExpr::createAdd(Base, MCConstantExpr::create(Offset, Ctx),
2107*9880d681SAndroid Build Coastguard Worker Ctx);
2108*9880d681SAndroid Build Coastguard Worker }
2109*9880d681SAndroid Build Coastguard Worker
2110*9880d681SAndroid Build Coastguard Worker case Instruction::Trunc:
2111*9880d681SAndroid Build Coastguard Worker // We emit the value and depend on the assembler to truncate the generated
2112*9880d681SAndroid Build Coastguard Worker // expression properly. This is important for differences between
2113*9880d681SAndroid Build Coastguard Worker // blockaddress labels. Since the two labels are in the same function, it
2114*9880d681SAndroid Build Coastguard Worker // is reasonable to treat their delta as a 32-bit value.
2115*9880d681SAndroid Build Coastguard Worker // FALL THROUGH.
2116*9880d681SAndroid Build Coastguard Worker case Instruction::BitCast:
2117*9880d681SAndroid Build Coastguard Worker return lowerConstantForGV(CE->getOperand(0), ProcessingGeneric);
2118*9880d681SAndroid Build Coastguard Worker
2119*9880d681SAndroid Build Coastguard Worker case Instruction::IntToPtr: {
2120*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
2121*9880d681SAndroid Build Coastguard Worker
2122*9880d681SAndroid Build Coastguard Worker // Handle casts to pointers by changing them into casts to the appropriate
2123*9880d681SAndroid Build Coastguard Worker // integer type. This promotes constant folding and simplifies this code.
2124*9880d681SAndroid Build Coastguard Worker Constant *Op = CE->getOperand(0);
2125*9880d681SAndroid Build Coastguard Worker Op = ConstantExpr::getIntegerCast(Op, DL.getIntPtrType(CV->getType()),
2126*9880d681SAndroid Build Coastguard Worker false/*ZExt*/);
2127*9880d681SAndroid Build Coastguard Worker return lowerConstantForGV(Op, ProcessingGeneric);
2128*9880d681SAndroid Build Coastguard Worker }
2129*9880d681SAndroid Build Coastguard Worker
2130*9880d681SAndroid Build Coastguard Worker case Instruction::PtrToInt: {
2131*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = getDataLayout();
2132*9880d681SAndroid Build Coastguard Worker
2133*9880d681SAndroid Build Coastguard Worker // Support only foldable casts to/from pointers that can be eliminated by
2134*9880d681SAndroid Build Coastguard Worker // changing the pointer to the appropriately sized integer type.
2135*9880d681SAndroid Build Coastguard Worker Constant *Op = CE->getOperand(0);
2136*9880d681SAndroid Build Coastguard Worker Type *Ty = CE->getType();
2137*9880d681SAndroid Build Coastguard Worker
2138*9880d681SAndroid Build Coastguard Worker const MCExpr *OpExpr = lowerConstantForGV(Op, ProcessingGeneric);
2139*9880d681SAndroid Build Coastguard Worker
2140*9880d681SAndroid Build Coastguard Worker // We can emit the pointer value into this slot if the slot is an
2141*9880d681SAndroid Build Coastguard Worker // integer slot equal to the size of the pointer.
2142*9880d681SAndroid Build Coastguard Worker if (DL.getTypeAllocSize(Ty) == DL.getTypeAllocSize(Op->getType()))
2143*9880d681SAndroid Build Coastguard Worker return OpExpr;
2144*9880d681SAndroid Build Coastguard Worker
2145*9880d681SAndroid Build Coastguard Worker // Otherwise the pointer is smaller than the resultant integer, mask off
2146*9880d681SAndroid Build Coastguard Worker // the high bits so we are sure to get a proper truncation if the input is
2147*9880d681SAndroid Build Coastguard Worker // a constant expr.
2148*9880d681SAndroid Build Coastguard Worker unsigned InBits = DL.getTypeAllocSizeInBits(Op->getType());
2149*9880d681SAndroid Build Coastguard Worker const MCExpr *MaskExpr = MCConstantExpr::create(~0ULL >> (64-InBits), Ctx);
2150*9880d681SAndroid Build Coastguard Worker return MCBinaryExpr::createAnd(OpExpr, MaskExpr, Ctx);
2151*9880d681SAndroid Build Coastguard Worker }
2152*9880d681SAndroid Build Coastguard Worker
2153*9880d681SAndroid Build Coastguard Worker // The MC library also has a right-shift operator, but it isn't consistently
2154*9880d681SAndroid Build Coastguard Worker // signed or unsigned between different targets.
2155*9880d681SAndroid Build Coastguard Worker case Instruction::Add: {
2156*9880d681SAndroid Build Coastguard Worker const MCExpr *LHS = lowerConstantForGV(CE->getOperand(0), ProcessingGeneric);
2157*9880d681SAndroid Build Coastguard Worker const MCExpr *RHS = lowerConstantForGV(CE->getOperand(1), ProcessingGeneric);
2158*9880d681SAndroid Build Coastguard Worker switch (CE->getOpcode()) {
2159*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unknown binary operator constant cast expr");
2160*9880d681SAndroid Build Coastguard Worker case Instruction::Add: return MCBinaryExpr::createAdd(LHS, RHS, Ctx);
2161*9880d681SAndroid Build Coastguard Worker }
2162*9880d681SAndroid Build Coastguard Worker }
2163*9880d681SAndroid Build Coastguard Worker }
2164*9880d681SAndroid Build Coastguard Worker }
2165*9880d681SAndroid Build Coastguard Worker
2166*9880d681SAndroid Build Coastguard Worker // Copy of MCExpr::print customized for NVPTX
printMCExpr(const MCExpr & Expr,raw_ostream & OS)2167*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printMCExpr(const MCExpr &Expr, raw_ostream &OS) {
2168*9880d681SAndroid Build Coastguard Worker switch (Expr.getKind()) {
2169*9880d681SAndroid Build Coastguard Worker case MCExpr::Target:
2170*9880d681SAndroid Build Coastguard Worker return cast<MCTargetExpr>(&Expr)->printImpl(OS, MAI);
2171*9880d681SAndroid Build Coastguard Worker case MCExpr::Constant:
2172*9880d681SAndroid Build Coastguard Worker OS << cast<MCConstantExpr>(Expr).getValue();
2173*9880d681SAndroid Build Coastguard Worker return;
2174*9880d681SAndroid Build Coastguard Worker
2175*9880d681SAndroid Build Coastguard Worker case MCExpr::SymbolRef: {
2176*9880d681SAndroid Build Coastguard Worker const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Expr);
2177*9880d681SAndroid Build Coastguard Worker const MCSymbol &Sym = SRE.getSymbol();
2178*9880d681SAndroid Build Coastguard Worker Sym.print(OS, MAI);
2179*9880d681SAndroid Build Coastguard Worker return;
2180*9880d681SAndroid Build Coastguard Worker }
2181*9880d681SAndroid Build Coastguard Worker
2182*9880d681SAndroid Build Coastguard Worker case MCExpr::Unary: {
2183*9880d681SAndroid Build Coastguard Worker const MCUnaryExpr &UE = cast<MCUnaryExpr>(Expr);
2184*9880d681SAndroid Build Coastguard Worker switch (UE.getOpcode()) {
2185*9880d681SAndroid Build Coastguard Worker case MCUnaryExpr::LNot: OS << '!'; break;
2186*9880d681SAndroid Build Coastguard Worker case MCUnaryExpr::Minus: OS << '-'; break;
2187*9880d681SAndroid Build Coastguard Worker case MCUnaryExpr::Not: OS << '~'; break;
2188*9880d681SAndroid Build Coastguard Worker case MCUnaryExpr::Plus: OS << '+'; break;
2189*9880d681SAndroid Build Coastguard Worker }
2190*9880d681SAndroid Build Coastguard Worker printMCExpr(*UE.getSubExpr(), OS);
2191*9880d681SAndroid Build Coastguard Worker return;
2192*9880d681SAndroid Build Coastguard Worker }
2193*9880d681SAndroid Build Coastguard Worker
2194*9880d681SAndroid Build Coastguard Worker case MCExpr::Binary: {
2195*9880d681SAndroid Build Coastguard Worker const MCBinaryExpr &BE = cast<MCBinaryExpr>(Expr);
2196*9880d681SAndroid Build Coastguard Worker
2197*9880d681SAndroid Build Coastguard Worker // Only print parens around the LHS if it is non-trivial.
2198*9880d681SAndroid Build Coastguard Worker if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS()) ||
2199*9880d681SAndroid Build Coastguard Worker isa<NVPTXGenericMCSymbolRefExpr>(BE.getLHS())) {
2200*9880d681SAndroid Build Coastguard Worker printMCExpr(*BE.getLHS(), OS);
2201*9880d681SAndroid Build Coastguard Worker } else {
2202*9880d681SAndroid Build Coastguard Worker OS << '(';
2203*9880d681SAndroid Build Coastguard Worker printMCExpr(*BE.getLHS(), OS);
2204*9880d681SAndroid Build Coastguard Worker OS<< ')';
2205*9880d681SAndroid Build Coastguard Worker }
2206*9880d681SAndroid Build Coastguard Worker
2207*9880d681SAndroid Build Coastguard Worker switch (BE.getOpcode()) {
2208*9880d681SAndroid Build Coastguard Worker case MCBinaryExpr::Add:
2209*9880d681SAndroid Build Coastguard Worker // Print "X-42" instead of "X+-42".
2210*9880d681SAndroid Build Coastguard Worker if (const MCConstantExpr *RHSC = dyn_cast<MCConstantExpr>(BE.getRHS())) {
2211*9880d681SAndroid Build Coastguard Worker if (RHSC->getValue() < 0) {
2212*9880d681SAndroid Build Coastguard Worker OS << RHSC->getValue();
2213*9880d681SAndroid Build Coastguard Worker return;
2214*9880d681SAndroid Build Coastguard Worker }
2215*9880d681SAndroid Build Coastguard Worker }
2216*9880d681SAndroid Build Coastguard Worker
2217*9880d681SAndroid Build Coastguard Worker OS << '+';
2218*9880d681SAndroid Build Coastguard Worker break;
2219*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Unhandled binary operator");
2220*9880d681SAndroid Build Coastguard Worker }
2221*9880d681SAndroid Build Coastguard Worker
2222*9880d681SAndroid Build Coastguard Worker // Only print parens around the LHS if it is non-trivial.
2223*9880d681SAndroid Build Coastguard Worker if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
2224*9880d681SAndroid Build Coastguard Worker printMCExpr(*BE.getRHS(), OS);
2225*9880d681SAndroid Build Coastguard Worker } else {
2226*9880d681SAndroid Build Coastguard Worker OS << '(';
2227*9880d681SAndroid Build Coastguard Worker printMCExpr(*BE.getRHS(), OS);
2228*9880d681SAndroid Build Coastguard Worker OS << ')';
2229*9880d681SAndroid Build Coastguard Worker }
2230*9880d681SAndroid Build Coastguard Worker return;
2231*9880d681SAndroid Build Coastguard Worker }
2232*9880d681SAndroid Build Coastguard Worker }
2233*9880d681SAndroid Build Coastguard Worker
2234*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid expression kind!");
2235*9880d681SAndroid Build Coastguard Worker }
2236*9880d681SAndroid Build Coastguard Worker
2237*9880d681SAndroid Build Coastguard Worker /// PrintAsmOperand - Print out an operand for an inline asm expression.
2238*9880d681SAndroid Build Coastguard Worker ///
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)2239*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
2240*9880d681SAndroid Build Coastguard Worker unsigned AsmVariant,
2241*9880d681SAndroid Build Coastguard Worker const char *ExtraCode, raw_ostream &O) {
2242*9880d681SAndroid Build Coastguard Worker if (ExtraCode && ExtraCode[0]) {
2243*9880d681SAndroid Build Coastguard Worker if (ExtraCode[1] != 0)
2244*9880d681SAndroid Build Coastguard Worker return true; // Unknown modifier.
2245*9880d681SAndroid Build Coastguard Worker
2246*9880d681SAndroid Build Coastguard Worker switch (ExtraCode[0]) {
2247*9880d681SAndroid Build Coastguard Worker default:
2248*9880d681SAndroid Build Coastguard Worker // See if this is a generic print operand
2249*9880d681SAndroid Build Coastguard Worker return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
2250*9880d681SAndroid Build Coastguard Worker case 'r':
2251*9880d681SAndroid Build Coastguard Worker break;
2252*9880d681SAndroid Build Coastguard Worker }
2253*9880d681SAndroid Build Coastguard Worker }
2254*9880d681SAndroid Build Coastguard Worker
2255*9880d681SAndroid Build Coastguard Worker printOperand(MI, OpNo, O);
2256*9880d681SAndroid Build Coastguard Worker
2257*9880d681SAndroid Build Coastguard Worker return false;
2258*9880d681SAndroid Build Coastguard Worker }
2259*9880d681SAndroid Build Coastguard Worker
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)2260*9880d681SAndroid Build Coastguard Worker bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
2261*9880d681SAndroid Build Coastguard Worker const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant,
2262*9880d681SAndroid Build Coastguard Worker const char *ExtraCode, raw_ostream &O) {
2263*9880d681SAndroid Build Coastguard Worker if (ExtraCode && ExtraCode[0])
2264*9880d681SAndroid Build Coastguard Worker return true; // Unknown modifier
2265*9880d681SAndroid Build Coastguard Worker
2266*9880d681SAndroid Build Coastguard Worker O << '[';
2267*9880d681SAndroid Build Coastguard Worker printMemOperand(MI, OpNo, O);
2268*9880d681SAndroid Build Coastguard Worker O << ']';
2269*9880d681SAndroid Build Coastguard Worker
2270*9880d681SAndroid Build Coastguard Worker return false;
2271*9880d681SAndroid Build Coastguard Worker }
2272*9880d681SAndroid Build Coastguard Worker
printOperand(const MachineInstr * MI,int opNum,raw_ostream & O,const char * Modifier)2273*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
2274*9880d681SAndroid Build Coastguard Worker raw_ostream &O, const char *Modifier) {
2275*9880d681SAndroid Build Coastguard Worker const MachineOperand &MO = MI->getOperand(opNum);
2276*9880d681SAndroid Build Coastguard Worker switch (MO.getType()) {
2277*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Register:
2278*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
2279*9880d681SAndroid Build Coastguard Worker if (MO.getReg() == NVPTX::VRDepot)
2280*9880d681SAndroid Build Coastguard Worker O << DEPOTNAME << getFunctionNumber();
2281*9880d681SAndroid Build Coastguard Worker else
2282*9880d681SAndroid Build Coastguard Worker O << NVPTXInstPrinter::getRegisterName(MO.getReg());
2283*9880d681SAndroid Build Coastguard Worker } else {
2284*9880d681SAndroid Build Coastguard Worker emitVirtualRegister(MO.getReg(), O);
2285*9880d681SAndroid Build Coastguard Worker }
2286*9880d681SAndroid Build Coastguard Worker return;
2287*9880d681SAndroid Build Coastguard Worker
2288*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_Immediate:
2289*9880d681SAndroid Build Coastguard Worker if (!Modifier)
2290*9880d681SAndroid Build Coastguard Worker O << MO.getImm();
2291*9880d681SAndroid Build Coastguard Worker else if (strstr(Modifier, "vec") == Modifier)
2292*9880d681SAndroid Build Coastguard Worker printVecModifiedImmediate(MO, Modifier, O);
2293*9880d681SAndroid Build Coastguard Worker else
2294*9880d681SAndroid Build Coastguard Worker llvm_unreachable(
2295*9880d681SAndroid Build Coastguard Worker "Don't know how to handle modifier on immediate operand");
2296*9880d681SAndroid Build Coastguard Worker return;
2297*9880d681SAndroid Build Coastguard Worker
2298*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_FPImmediate:
2299*9880d681SAndroid Build Coastguard Worker printFPConstant(MO.getFPImm(), O);
2300*9880d681SAndroid Build Coastguard Worker break;
2301*9880d681SAndroid Build Coastguard Worker
2302*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_GlobalAddress:
2303*9880d681SAndroid Build Coastguard Worker getSymbol(MO.getGlobal())->print(O, MAI);
2304*9880d681SAndroid Build Coastguard Worker break;
2305*9880d681SAndroid Build Coastguard Worker
2306*9880d681SAndroid Build Coastguard Worker case MachineOperand::MO_MachineBasicBlock:
2307*9880d681SAndroid Build Coastguard Worker MO.getMBB()->getSymbol()->print(O, MAI);
2308*9880d681SAndroid Build Coastguard Worker return;
2309*9880d681SAndroid Build Coastguard Worker
2310*9880d681SAndroid Build Coastguard Worker default:
2311*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Operand type not supported.");
2312*9880d681SAndroid Build Coastguard Worker }
2313*9880d681SAndroid Build Coastguard Worker }
2314*9880d681SAndroid Build Coastguard Worker
printMemOperand(const MachineInstr * MI,int opNum,raw_ostream & O,const char * Modifier)2315*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
2316*9880d681SAndroid Build Coastguard Worker raw_ostream &O, const char *Modifier) {
2317*9880d681SAndroid Build Coastguard Worker printOperand(MI, opNum, O);
2318*9880d681SAndroid Build Coastguard Worker
2319*9880d681SAndroid Build Coastguard Worker if (Modifier && !strcmp(Modifier, "add")) {
2320*9880d681SAndroid Build Coastguard Worker O << ", ";
2321*9880d681SAndroid Build Coastguard Worker printOperand(MI, opNum + 1, O);
2322*9880d681SAndroid Build Coastguard Worker } else {
2323*9880d681SAndroid Build Coastguard Worker if (MI->getOperand(opNum + 1).isImm() &&
2324*9880d681SAndroid Build Coastguard Worker MI->getOperand(opNum + 1).getImm() == 0)
2325*9880d681SAndroid Build Coastguard Worker return; // don't print ',0' or '+0'
2326*9880d681SAndroid Build Coastguard Worker O << "+";
2327*9880d681SAndroid Build Coastguard Worker printOperand(MI, opNum + 1, O);
2328*9880d681SAndroid Build Coastguard Worker }
2329*9880d681SAndroid Build Coastguard Worker }
2330*9880d681SAndroid Build Coastguard Worker
emitSrcInText(StringRef filename,unsigned line)2331*9880d681SAndroid Build Coastguard Worker void NVPTXAsmPrinter::emitSrcInText(StringRef filename, unsigned line) {
2332*9880d681SAndroid Build Coastguard Worker std::stringstream temp;
2333*9880d681SAndroid Build Coastguard Worker LineReader *reader = this->getReader(filename);
2334*9880d681SAndroid Build Coastguard Worker temp << "\n//";
2335*9880d681SAndroid Build Coastguard Worker temp << filename.str();
2336*9880d681SAndroid Build Coastguard Worker temp << ":";
2337*9880d681SAndroid Build Coastguard Worker temp << line;
2338*9880d681SAndroid Build Coastguard Worker temp << " ";
2339*9880d681SAndroid Build Coastguard Worker temp << reader->readLine(line);
2340*9880d681SAndroid Build Coastguard Worker temp << "\n";
2341*9880d681SAndroid Build Coastguard Worker this->OutStreamer->EmitRawText(temp.str());
2342*9880d681SAndroid Build Coastguard Worker }
2343*9880d681SAndroid Build Coastguard Worker
getReader(const std::string & filename)2344*9880d681SAndroid Build Coastguard Worker LineReader *NVPTXAsmPrinter::getReader(const std::string &filename) {
2345*9880d681SAndroid Build Coastguard Worker if (!reader) {
2346*9880d681SAndroid Build Coastguard Worker reader = new LineReader(filename);
2347*9880d681SAndroid Build Coastguard Worker }
2348*9880d681SAndroid Build Coastguard Worker
2349*9880d681SAndroid Build Coastguard Worker if (reader->fileName() != filename) {
2350*9880d681SAndroid Build Coastguard Worker delete reader;
2351*9880d681SAndroid Build Coastguard Worker reader = new LineReader(filename);
2352*9880d681SAndroid Build Coastguard Worker }
2353*9880d681SAndroid Build Coastguard Worker
2354*9880d681SAndroid Build Coastguard Worker return reader;
2355*9880d681SAndroid Build Coastguard Worker }
2356*9880d681SAndroid Build Coastguard Worker
readLine(unsigned lineNum)2357*9880d681SAndroid Build Coastguard Worker std::string LineReader::readLine(unsigned lineNum) {
2358*9880d681SAndroid Build Coastguard Worker if (lineNum < theCurLine) {
2359*9880d681SAndroid Build Coastguard Worker theCurLine = 0;
2360*9880d681SAndroid Build Coastguard Worker fstr.seekg(0, std::ios::beg);
2361*9880d681SAndroid Build Coastguard Worker }
2362*9880d681SAndroid Build Coastguard Worker while (theCurLine < lineNum) {
2363*9880d681SAndroid Build Coastguard Worker fstr.getline(buff, 500);
2364*9880d681SAndroid Build Coastguard Worker theCurLine++;
2365*9880d681SAndroid Build Coastguard Worker }
2366*9880d681SAndroid Build Coastguard Worker return buff;
2367*9880d681SAndroid Build Coastguard Worker }
2368*9880d681SAndroid Build Coastguard Worker
2369*9880d681SAndroid Build Coastguard Worker // Force static initialization.
LLVMInitializeNVPTXAsmPrinter()2370*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeNVPTXAsmPrinter() {
2371*9880d681SAndroid Build Coastguard Worker RegisterAsmPrinter<NVPTXAsmPrinter> X(TheNVPTXTarget32);
2372*9880d681SAndroid Build Coastguard Worker RegisterAsmPrinter<NVPTXAsmPrinter> Y(TheNVPTXTarget64);
2373*9880d681SAndroid Build Coastguard Worker }
2374