blob: 35ba4f1481defb887a3bc8bcdb893850b78a2b66 [file] [log] [blame]
Justin Holewinskiae556d32012-05-04 20:18:50 +00001//===-- NVPTXAsmPrinter.cpp - NVPTX LLVM assembly writer ------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a printer that converts from our internal representation
11// of machine-dependent LLVM code to NVPTX assembly language.
12//
13//===----------------------------------------------------------------------===//
14
Bill Wendlinge38859d2012-06-28 00:05:13 +000015#include "NVPTXAsmPrinter.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000016#include "InstPrinter/NVPTXInstPrinter.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000017#include "MCTargetDesc/NVPTXMCAsmInfo.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000018#include "NVPTX.h"
19#include "NVPTXInstrInfo.h"
Justin Holewinski30d56a72014-04-09 15:39:15 +000020#include "NVPTXMachineFunctionInfo.h"
Justin Holewinskia2a63d22013-08-06 14:13:27 +000021#include "NVPTXMCExpr.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "NVPTXRegisterInfo.h"
23#include "NVPTXTargetMachine.h"
24#include "NVPTXUtilities.h"
25#include "cl_common_defines.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000026#include "llvm/ADT/StringExtras.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000027#include "llvm/Analysis/ConstantFolding.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000028#include "llvm/CodeGen/Analysis.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000029#include "llvm/CodeGen/MachineFrameInfo.h"
30#include "llvm/CodeGen/MachineModuleInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000031#include "llvm/CodeGen/MachineRegisterInfo.h"
Chandler Carruth9a4c9e52014-03-06 00:46:21 +000032#include "llvm/IR/DebugInfo.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000033#include "llvm/IR/DerivedTypes.h"
34#include "llvm/IR/Function.h"
35#include "llvm/IR/GlobalVariable.h"
Rafael Espindola894843c2014-01-07 21:19:40 +000036#include "llvm/IR/Mangler.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000037#include "llvm/IR/Module.h"
38#include "llvm/IR/Operator.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000039#include "llvm/MC/MCStreamer.h"
40#include "llvm/MC/MCSymbol.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000041#include "llvm/Support/CommandLine.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000042#include "llvm/Support/ErrorHandling.h"
43#include "llvm/Support/FormattedStream.h"
Justin Holewinskiae556d32012-05-04 20:18:50 +000044#include "llvm/Support/Path.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000045#include "llvm/Support/TargetRegistry.h"
46#include "llvm/Support/TimeValue.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000047#include "llvm/Target/TargetLoweringObjectFile.h"
Bill Wendlinge38859d2012-06-28 00:05:13 +000048#include <sstream>
Justin Holewinskiae556d32012-05-04 20:18:50 +000049using namespace llvm;
50
Justin Holewinskiae556d32012-05-04 20:18:50 +000051#define DEPOTNAME "__local_depot"
52
53static cl::opt<bool>
Nadav Rotem7f27e0b2013-10-18 23:38:13 +000054EmitLineNumbers("nvptx-emit-line-numbers", cl::Hidden,
Justin Holewinskiae556d32012-05-04 20:18:50 +000055 cl::desc("NVPTX Specific: Emit Line numbers even without -G"),
56 cl::init(true));
57
Benjamin Kramer7ad41002013-10-27 11:31:46 +000058static cl::opt<bool>
Nadav Rotem7f27e0b2013-10-18 23:38:13 +000059InterleaveSrc("nvptx-emit-src", cl::ZeroOrMore, cl::Hidden,
Justin Holewinski0497ab12013-03-30 14:29:21 +000060 cl::desc("NVPTX Specific: Emit source line in ptx file"),
Benjamin Kramer7ad41002013-10-27 11:31:46 +000061 cl::init(false));
Justin Holewinskiae556d32012-05-04 20:18:50 +000062
Justin Holewinski2c5ac702012-11-16 21:03:51 +000063namespace {
64/// DiscoverDependentGlobals - Return a set of GlobalVariables on which \p V
65/// depends.
Justin Holewinski01f89f02013-05-20 12:13:32 +000066void DiscoverDependentGlobals(const Value *V,
67 DenseSet<const GlobalVariable *> &Globals) {
68 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
Justin Holewinski2c5ac702012-11-16 21:03:51 +000069 Globals.insert(GV);
70 else {
Justin Holewinski01f89f02013-05-20 12:13:32 +000071 if (const User *U = dyn_cast<User>(V)) {
Justin Holewinski2c5ac702012-11-16 21:03:51 +000072 for (unsigned i = 0, e = U->getNumOperands(); i != e; ++i) {
73 DiscoverDependentGlobals(U->getOperand(i), Globals);
74 }
75 }
76 }
77}
Justin Holewinskiae556d32012-05-04 20:18:50 +000078
Justin Holewinski2c5ac702012-11-16 21:03:51 +000079/// VisitGlobalVariableForEmission - Add \p GV to the list of GlobalVariable
80/// instances to be emitted, but only after any dependents have been added
81/// first.
Justin Holewinski0497ab12013-03-30 14:29:21 +000082void VisitGlobalVariableForEmission(
Justin Holewinski01f89f02013-05-20 12:13:32 +000083 const GlobalVariable *GV, SmallVectorImpl<const GlobalVariable *> &Order,
84 DenseSet<const GlobalVariable *> &Visited,
85 DenseSet<const GlobalVariable *> &Visiting) {
Justin Holewinski2c5ac702012-11-16 21:03:51 +000086 // Have we already visited this one?
Justin Holewinski0497ab12013-03-30 14:29:21 +000087 if (Visited.count(GV))
88 return;
Justin Holewinski2c5ac702012-11-16 21:03:51 +000089
90 // Do we have a circular dependency?
Benjamin Kramer2c99e412014-10-10 15:32:50 +000091 if (!Visiting.insert(GV).second)
Justin Holewinski2c5ac702012-11-16 21:03:51 +000092 report_fatal_error("Circular dependency found in global variable set");
93
Justin Holewinski2c5ac702012-11-16 21:03:51 +000094 // Make sure we visit all dependents first
Justin Holewinski01f89f02013-05-20 12:13:32 +000095 DenseSet<const GlobalVariable *> Others;
Justin Holewinski2c5ac702012-11-16 21:03:51 +000096 for (unsigned i = 0, e = GV->getNumOperands(); i != e; ++i)
97 DiscoverDependentGlobals(GV->getOperand(i), Others);
Justin Holewinski0497ab12013-03-30 14:29:21 +000098
Justin Holewinski01f89f02013-05-20 12:13:32 +000099 for (DenseSet<const GlobalVariable *>::iterator I = Others.begin(),
100 E = Others.end();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000101 I != E; ++I)
Justin Holewinski2c5ac702012-11-16 21:03:51 +0000102 VisitGlobalVariableForEmission(*I, Order, Visited, Visiting);
103
104 // Now we can visit ourself
105 Order.push_back(GV);
106 Visited.insert(GV);
107 Visiting.erase(GV);
108}
109}
Justin Holewinskiae556d32012-05-04 20:18:50 +0000110
111// @TODO: This is a copy from AsmPrinter.cpp. The function is static, so we
112// cannot just link to the existing version.
113/// LowerConstant - Lower the specified LLVM Constant to an MCExpr.
114///
115using namespace nvptx;
116const MCExpr *nvptx::LowerConstant(const Constant *CV, AsmPrinter &AP) {
117 MCContext &Ctx = AP.OutContext;
118
119 if (CV->isNullValue() || isa<UndefValue>(CV))
120 return MCConstantExpr::Create(0, Ctx);
121
122 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV))
123 return MCConstantExpr::Create(CI->getZExtValue(), Ctx);
124
125 if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
Rafael Espindola79858aa2013-10-29 17:07:16 +0000126 return MCSymbolRefExpr::Create(AP.getSymbol(GV), Ctx);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000127
128 if (const BlockAddress *BA = dyn_cast<BlockAddress>(CV))
129 return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx);
130
131 const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
Craig Topper062a2ba2014-04-25 05:30:21 +0000132 if (!CE)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000133 llvm_unreachable("Unknown constant value to lower!");
134
Justin Holewinskiae556d32012-05-04 20:18:50 +0000135 switch (CE->getOpcode()) {
136 default:
137 // If the code isn't optimized, there may be outstanding folding
Micah Villmowcdfe20b2012-10-08 16:38:25 +0000138 // opportunities. Attempt to fold the expression using DataLayout as a
Justin Holewinskiae556d32012-05-04 20:18:50 +0000139 // last resort before giving up.
Eric Christopherd9134482014-08-04 21:25:23 +0000140 if (Constant *C = ConstantFoldConstantExpression(
141 CE, AP.TM.getSubtargetImpl()->getDataLayout()))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000142 if (C != CE)
143 return LowerConstant(C, AP);
144
145 // Otherwise report the problem to the user.
146 {
Alp Tokere69170a2014-06-26 22:52:05 +0000147 std::string S;
148 raw_string_ostream OS(S);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000149 OS << "Unsupported expression in static initializer: ";
Chandler Carruthd48cdbf2014-01-09 02:29:41 +0000150 CE->printAsOperand(OS, /*PrintType=*/ false,
Craig Topper062a2ba2014-04-25 05:30:21 +0000151 !AP.MF ? nullptr : AP.MF->getFunction()->getParent());
Justin Holewinski0497ab12013-03-30 14:29:21 +0000152 report_fatal_error(OS.str());
Justin Holewinskiae556d32012-05-04 20:18:50 +0000153 }
Justin Holewinski9d852a82014-04-09 15:39:11 +0000154 case Instruction::AddrSpaceCast: {
155 // Strip any addrspace(1)->addrspace(0) addrspace casts. These will be
156 // handled by the generic() logic in the MCExpr printer
157 PointerType *DstTy = cast<PointerType>(CE->getType());
158 PointerType *SrcTy = cast<PointerType>(CE->getOperand(0)->getType());
159 if (SrcTy->getAddressSpace() == 1 && DstTy->getAddressSpace() == 0) {
160 return LowerConstant(cast<const Constant>(CE->getOperand(0)), AP);
161 }
162 std::string S;
163 raw_string_ostream OS(S);
164 OS << "Unsupported expression in static initializer: ";
165 CE->printAsOperand(OS, /*PrintType=*/ false,
Craig Topper062a2ba2014-04-25 05:30:21 +0000166 !AP.MF ? nullptr : AP.MF->getFunction()->getParent());
Justin Holewinski9d852a82014-04-09 15:39:11 +0000167 report_fatal_error(OS.str());
168 }
Justin Holewinskiae556d32012-05-04 20:18:50 +0000169 case Instruction::GetElementPtr: {
Eric Christopherd9134482014-08-04 21:25:23 +0000170 const DataLayout &TD = *AP.TM.getSubtargetImpl()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000171 // Generate a symbolic expression for the byte address
Nuno Lopesb6ad9822012-12-30 16:25:48 +0000172 APInt OffsetAI(TD.getPointerSizeInBits(), 0);
173 cast<GEPOperator>(CE)->accumulateConstantOffset(TD, OffsetAI);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000174
175 const MCExpr *Base = LowerConstant(CE->getOperand(0), AP);
Nuno Lopesb6ad9822012-12-30 16:25:48 +0000176 if (!OffsetAI)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000177 return Base;
178
Nuno Lopesb6ad9822012-12-30 16:25:48 +0000179 int64_t Offset = OffsetAI.getSExtValue();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000180 return MCBinaryExpr::CreateAdd(Base, MCConstantExpr::Create(Offset, Ctx),
181 Ctx);
182 }
183
184 case Instruction::Trunc:
185 // We emit the value and depend on the assembler to truncate the generated
186 // expression properly. This is important for differences between
187 // blockaddress labels. Since the two labels are in the same function, it
188 // is reasonable to treat their delta as a 32-bit value.
Justin Holewinski0497ab12013-03-30 14:29:21 +0000189 // FALL THROUGH.
Justin Holewinskiae556d32012-05-04 20:18:50 +0000190 case Instruction::BitCast:
191 return LowerConstant(CE->getOperand(0), AP);
192
193 case Instruction::IntToPtr: {
Eric Christopherd9134482014-08-04 21:25:23 +0000194 const DataLayout &TD = *AP.TM.getSubtargetImpl()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000195 // Handle casts to pointers by changing them into casts to the appropriate
196 // integer type. This promotes constant folding and simplifies this code.
197 Constant *Op = CE->getOperand(0);
Chandler Carruth7ec50852012-11-01 08:07:29 +0000198 Op = ConstantExpr::getIntegerCast(Op, TD.getIntPtrType(CV->getContext()),
Justin Holewinski0497ab12013-03-30 14:29:21 +0000199 false /*ZExt*/);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000200 return LowerConstant(Op, AP);
201 }
202
203 case Instruction::PtrToInt: {
Eric Christopherd9134482014-08-04 21:25:23 +0000204 const DataLayout &TD = *AP.TM.getSubtargetImpl()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000205 // Support only foldable casts to/from pointers that can be eliminated by
206 // changing the pointer to the appropriately sized integer type.
207 Constant *Op = CE->getOperand(0);
208 Type *Ty = CE->getType();
209
210 const MCExpr *OpExpr = LowerConstant(Op, AP);
211
212 // We can emit the pointer value into this slot if the slot is an
213 // integer slot equal to the size of the pointer.
214 if (TD.getTypeAllocSize(Ty) == TD.getTypeAllocSize(Op->getType()))
215 return OpExpr;
216
217 // Otherwise the pointer is smaller than the resultant integer, mask off
218 // the high bits so we are sure to get a proper truncation if the input is
219 // a constant expr.
220 unsigned InBits = TD.getTypeAllocSizeInBits(Op->getType());
Justin Holewinski0497ab12013-03-30 14:29:21 +0000221 const MCExpr *MaskExpr =
222 MCConstantExpr::Create(~0ULL >> (64 - InBits), Ctx);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000223 return MCBinaryExpr::CreateAnd(OpExpr, MaskExpr, Ctx);
224 }
225
Justin Holewinski0497ab12013-03-30 14:29:21 +0000226 // The MC library also has a right-shift operator, but it isn't consistently
Justin Holewinskiae556d32012-05-04 20:18:50 +0000227 // signed or unsigned between different targets.
228 case Instruction::Add:
229 case Instruction::Sub:
230 case Instruction::Mul:
231 case Instruction::SDiv:
232 case Instruction::SRem:
233 case Instruction::Shl:
234 case Instruction::And:
235 case Instruction::Or:
236 case Instruction::Xor: {
237 const MCExpr *LHS = LowerConstant(CE->getOperand(0), AP);
238 const MCExpr *RHS = LowerConstant(CE->getOperand(1), AP);
239 switch (CE->getOpcode()) {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000240 default:
241 llvm_unreachable("Unknown binary operator constant cast expr");
242 case Instruction::Add:
243 return MCBinaryExpr::CreateAdd(LHS, RHS, Ctx);
244 case Instruction::Sub:
245 return MCBinaryExpr::CreateSub(LHS, RHS, Ctx);
246 case Instruction::Mul:
247 return MCBinaryExpr::CreateMul(LHS, RHS, Ctx);
248 case Instruction::SDiv:
249 return MCBinaryExpr::CreateDiv(LHS, RHS, Ctx);
250 case Instruction::SRem:
251 return MCBinaryExpr::CreateMod(LHS, RHS, Ctx);
252 case Instruction::Shl:
253 return MCBinaryExpr::CreateShl(LHS, RHS, Ctx);
254 case Instruction::And:
255 return MCBinaryExpr::CreateAnd(LHS, RHS, Ctx);
256 case Instruction::Or:
257 return MCBinaryExpr::CreateOr(LHS, RHS, Ctx);
258 case Instruction::Xor:
259 return MCBinaryExpr::CreateXor(LHS, RHS, Ctx);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000260 }
261 }
262 }
263}
264
Justin Holewinski0497ab12013-03-30 14:29:21 +0000265void NVPTXAsmPrinter::emitLineNumberAsDotLoc(const MachineInstr &MI) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000266 if (!EmitLineNumbers)
267 return;
268 if (ignoreLoc(MI))
269 return;
270
271 DebugLoc curLoc = MI.getDebugLoc();
272
273 if (prevDebugLoc.isUnknown() && curLoc.isUnknown())
274 return;
275
276 if (prevDebugLoc == curLoc)
277 return;
278
279 prevDebugLoc = curLoc;
280
281 if (curLoc.isUnknown())
282 return;
283
Justin Holewinskiae556d32012-05-04 20:18:50 +0000284 const MachineFunction *MF = MI.getParent()->getParent();
285 //const TargetMachine &TM = MF->getTarget();
286
287 const LLVMContext &ctx = MF->getFunction()->getContext();
288 DIScope Scope(curLoc.getScope(ctx));
289
Manman Ren983a16c2013-06-28 05:43:10 +0000290 assert((!Scope || Scope.isScope()) &&
291 "Scope of a DebugLoc should be null or a DIScope.");
292 if (!Scope)
293 return;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000294
295 StringRef fileName(Scope.getFilename());
296 StringRef dirName(Scope.getDirectory());
297 SmallString<128> FullPathName = dirName;
298 if (!dirName.empty() && !sys::path::is_absolute(fileName)) {
299 sys::path::append(FullPathName, fileName);
300 fileName = FullPathName.str();
301 }
302
303 if (filenameMap.find(fileName.str()) == filenameMap.end())
304 return;
305
Justin Holewinskiae556d32012-05-04 20:18:50 +0000306 // Emit the line from the source file.
Benjamin Kramer7ad41002013-10-27 11:31:46 +0000307 if (InterleaveSrc)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000308 this->emitSrcInText(fileName.str(), curLoc.getLine());
309
310 std::stringstream temp;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000311 temp << "\t.loc " << filenameMap[fileName.str()] << " " << curLoc.getLine()
312 << " " << curLoc.getCol();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000313 OutStreamer.EmitRawText(Twine(temp.str().c_str()));
314}
315
316void NVPTXAsmPrinter::EmitInstruction(const MachineInstr *MI) {
317 SmallString<128> Str;
318 raw_svector_ostream OS(Str);
319 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA)
320 emitLineNumberAsDotLoc(*MI);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000321
322 MCInst Inst;
323 lowerToMCInst(MI, Inst);
David Woodhousee6c13e42014-01-28 23:12:42 +0000324 EmitToStreamer(OutStreamer, Inst);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000325}
326
Justin Holewinski30d56a72014-04-09 15:39:15 +0000327// Handle symbol backtracking for targets that do not support image handles
328bool NVPTXAsmPrinter::lowerImageHandleOperand(const MachineInstr *MI,
329 unsigned OpNo, MCOperand &MCOp) {
330 const MachineOperand &MO = MI->getOperand(OpNo);
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000331 const MCInstrDesc &MCID = MI->getDesc();
Justin Holewinski30d56a72014-04-09 15:39:15 +0000332
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000333 if (MCID.TSFlags & NVPTXII::IsTexFlag) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000334 // This is a texture fetch, so operand 4 is a texref and operand 5 is
335 // a samplerref
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000336 if (OpNo == 4 && MO.isImm()) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000337 lowerImageHandleSymbol(MO.getImm(), MCOp);
338 return true;
339 }
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000340 if (OpNo == 5 && MO.isImm() && !(MCID.TSFlags & NVPTXII::IsTexModeUnifiedFlag)) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000341 lowerImageHandleSymbol(MO.getImm(), MCOp);
342 return true;
343 }
344
345 return false;
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000346 } else if (MCID.TSFlags & NVPTXII::IsSuldMask) {
347 unsigned VecSize =
348 1 << (((MCID.TSFlags & NVPTXII::IsSuldMask) >> NVPTXII::IsSuldShift) - 1);
349
350 // For a surface load of vector size N, the Nth operand will be the surfref
351 if (OpNo == VecSize && MO.isImm()) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000352 lowerImageHandleSymbol(MO.getImm(), MCOp);
353 return true;
354 }
355
356 return false;
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000357 } else if (MCID.TSFlags & NVPTXII::IsSustFlag) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000358 // This is a surface store, so operand 0 is a surfref
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000359 if (OpNo == 0 && MO.isImm()) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000360 lowerImageHandleSymbol(MO.getImm(), MCOp);
361 return true;
362 }
363
364 return false;
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000365 } else if (MCID.TSFlags & NVPTXII::IsSurfTexQueryFlag) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000366 // This is a query, so operand 1 is a surfref/texref
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000367 if (OpNo == 1 && MO.isImm()) {
Justin Holewinski30d56a72014-04-09 15:39:15 +0000368 lowerImageHandleSymbol(MO.getImm(), MCOp);
369 return true;
370 }
371
372 return false;
373 }
Justin Holewinski9a2350e2014-07-17 11:59:04 +0000374
375 return false;
Justin Holewinski30d56a72014-04-09 15:39:15 +0000376}
377
378void NVPTXAsmPrinter::lowerImageHandleSymbol(unsigned Index, MCOperand &MCOp) {
379 // Ewwww
380 TargetMachine &TM = const_cast<TargetMachine&>(MF->getTarget());
381 NVPTXTargetMachine &nvTM = static_cast<NVPTXTargetMachine&>(TM);
382 const NVPTXMachineFunctionInfo *MFI = MF->getInfo<NVPTXMachineFunctionInfo>();
383 const char *Sym = MFI->getImageHandleSymbol(Index);
384 std::string *SymNamePtr =
385 nvTM.getManagedStrPool()->getManagedString(Sym);
386 MCOp = GetSymbolRef(OutContext.GetOrCreateSymbol(
387 StringRef(SymNamePtr->c_str())));
388}
389
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000390void NVPTXAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
391 OutMI.setOpcode(MI->getOpcode());
Justin Holewinski30d56a72014-04-09 15:39:15 +0000392 const NVPTXSubtarget &ST = TM.getSubtarget<NVPTXSubtarget>();
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000393
Justin Holewinski3d49e5c2013-11-15 12:30:04 +0000394 // Special: Do not mangle symbol operand of CALL_PROTOTYPE
395 if (MI->getOpcode() == NVPTX::CALL_PROTOTYPE) {
396 const MachineOperand &MO = MI->getOperand(0);
Justin Holewinski30d56a72014-04-09 15:39:15 +0000397 OutMI.addOperand(GetSymbolRef(
Justin Holewinski3d49e5c2013-11-15 12:30:04 +0000398 OutContext.GetOrCreateSymbol(Twine(MO.getSymbolName()))));
399 return;
400 }
401
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000402 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
403 const MachineOperand &MO = MI->getOperand(i);
404
405 MCOperand MCOp;
Justin Holewinski30d56a72014-04-09 15:39:15 +0000406 if (!ST.hasImageHandles()) {
407 if (lowerImageHandleOperand(MI, i, MCOp)) {
408 OutMI.addOperand(MCOp);
409 continue;
410 }
411 }
412
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000413 if (lowerOperand(MO, MCOp))
414 OutMI.addOperand(MCOp);
415 }
416}
417
418bool NVPTXAsmPrinter::lowerOperand(const MachineOperand &MO,
419 MCOperand &MCOp) {
420 switch (MO.getType()) {
421 default: llvm_unreachable("unknown operand type");
422 case MachineOperand::MO_Register:
423 MCOp = MCOperand::CreateReg(encodeVirtualRegister(MO.getReg()));
424 break;
425 case MachineOperand::MO_Immediate:
426 MCOp = MCOperand::CreateImm(MO.getImm());
427 break;
428 case MachineOperand::MO_MachineBasicBlock:
429 MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
430 MO.getMBB()->getSymbol(), OutContext));
431 break;
432 case MachineOperand::MO_ExternalSymbol:
Justin Holewinski30d56a72014-04-09 15:39:15 +0000433 MCOp = GetSymbolRef(GetExternalSymbolSymbol(MO.getSymbolName()));
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000434 break;
435 case MachineOperand::MO_GlobalAddress:
Justin Holewinski30d56a72014-04-09 15:39:15 +0000436 MCOp = GetSymbolRef(getSymbol(MO.getGlobal()));
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000437 break;
438 case MachineOperand::MO_FPImmediate: {
439 const ConstantFP *Cnt = MO.getFPImm();
440 APFloat Val = Cnt->getValueAPF();
441
442 switch (Cnt->getType()->getTypeID()) {
443 default: report_fatal_error("Unsupported FP type"); break;
444 case Type::FloatTyID:
445 MCOp = MCOperand::CreateExpr(
446 NVPTXFloatMCExpr::CreateConstantFPSingle(Val, OutContext));
447 break;
448 case Type::DoubleTyID:
449 MCOp = MCOperand::CreateExpr(
450 NVPTXFloatMCExpr::CreateConstantFPDouble(Val, OutContext));
451 break;
452 }
453 break;
454 }
455 }
456 return true;
457}
458
459unsigned NVPTXAsmPrinter::encodeVirtualRegister(unsigned Reg) {
Justin Holewinski871ec932013-08-06 14:13:31 +0000460 if (TargetRegisterInfo::isVirtualRegister(Reg)) {
461 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000462
Justin Holewinski871ec932013-08-06 14:13:31 +0000463 DenseMap<unsigned, unsigned> &RegMap = VRegMapping[RC];
464 unsigned RegNum = RegMap[Reg];
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000465
Justin Holewinski871ec932013-08-06 14:13:31 +0000466 // Encode the register class in the upper 4 bits
467 // Must be kept in sync with NVPTXInstPrinter::printRegName
468 unsigned Ret = 0;
469 if (RC == &NVPTX::Int1RegsRegClass) {
470 Ret = (1 << 28);
471 } else if (RC == &NVPTX::Int16RegsRegClass) {
472 Ret = (2 << 28);
473 } else if (RC == &NVPTX::Int32RegsRegClass) {
474 Ret = (3 << 28);
475 } else if (RC == &NVPTX::Int64RegsRegClass) {
476 Ret = (4 << 28);
477 } else if (RC == &NVPTX::Float32RegsRegClass) {
478 Ret = (5 << 28);
479 } else if (RC == &NVPTX::Float64RegsRegClass) {
480 Ret = (6 << 28);
481 } else {
482 report_fatal_error("Bad register class");
483 }
484
485 // Insert the vreg number
486 Ret |= (RegNum & 0x0FFFFFFF);
487 return Ret;
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000488 } else {
Justin Holewinski871ec932013-08-06 14:13:31 +0000489 // Some special-use registers are actually physical registers.
490 // Encode this as the register class ID of 0 and the real register ID.
491 return Reg & 0x0FFFFFFF;
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000492 }
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000493}
494
Justin Holewinski30d56a72014-04-09 15:39:15 +0000495MCOperand NVPTXAsmPrinter::GetSymbolRef(const MCSymbol *Symbol) {
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000496 const MCExpr *Expr;
Justin Holewinski8b24e1e2013-08-06 23:06:42 +0000497 Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
498 OutContext);
Justin Holewinskia2a63d22013-08-06 14:13:27 +0000499 return MCOperand::CreateExpr(Expr);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000500}
501
Justin Holewinski0497ab12013-03-30 14:29:21 +0000502void NVPTXAsmPrinter::printReturnValStr(const Function *F, raw_ostream &O) {
Eric Christopherd9134482014-08-04 21:25:23 +0000503 const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
504 const TargetLowering *TLI = TM.getSubtargetImpl()->getTargetLowering();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000505
506 Type *Ty = F->getReturnType();
507
508 bool isABI = (nvptxSubtarget.getSmVersion() >= 20);
509
510 if (Ty->getTypeID() == Type::VoidTyID)
511 return;
512
513 O << " (";
514
515 if (isABI) {
Rafael Espindola08013342013-12-07 19:34:20 +0000516 if (Ty->isFloatingPointTy() || Ty->isIntegerTy()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000517 unsigned size = 0;
518 if (const IntegerType *ITy = dyn_cast<IntegerType>(Ty)) {
519 size = ITy->getBitWidth();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000520 if (size < 32)
521 size = 32;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000522 } else {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000523 assert(Ty->isFloatingPointTy() && "Floating point type expected here");
Justin Holewinskiae556d32012-05-04 20:18:50 +0000524 size = Ty->getPrimitiveSizeInBits();
525 }
526
527 O << ".param .b" << size << " func_retval0";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000528 } else if (isa<PointerType>(Ty)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000529 O << ".param .b" << TLI->getPointerTy().getSizeInBits()
Justin Holewinski0497ab12013-03-30 14:29:21 +0000530 << " func_retval0";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000531 } else {
Justin Holewinski0497ab12013-03-30 14:29:21 +0000532 if ((Ty->getTypeID() == Type::StructTyID) || isa<VectorType>(Ty)) {
Justin Holewinski0da75852014-06-27 18:35:08 +0000533 unsigned totalsz = TD->getTypeAllocSize(Ty);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000534 unsigned retAlignment = 0;
535 if (!llvm::getAlign(*F, 0, retAlignment))
536 retAlignment = TD->getABITypeAlignment(Ty);
Justin Holewinski0497ab12013-03-30 14:29:21 +0000537 O << ".param .align " << retAlignment << " .b8 func_retval0[" << totalsz
538 << "]";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000539 } else
Justin Holewinski0497ab12013-03-30 14:29:21 +0000540 assert(false && "Unknown return type");
Justin Holewinskiae556d32012-05-04 20:18:50 +0000541 }
542 } else {
543 SmallVector<EVT, 16> vtparts;
544 ComputeValueVTs(*TLI, Ty, vtparts);
545 unsigned idx = 0;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000546 for (unsigned i = 0, e = vtparts.size(); i != e; ++i) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000547 unsigned elems = 1;
548 EVT elemtype = vtparts[i];
549 if (vtparts[i].isVector()) {
550 elems = vtparts[i].getVectorNumElements();
551 elemtype = vtparts[i].getVectorElementType();
552 }
553
Justin Holewinski0497ab12013-03-30 14:29:21 +0000554 for (unsigned j = 0, je = elems; j != je; ++j) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000555 unsigned sz = elemtype.getSizeInBits();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000556 if (elemtype.isInteger() && (sz < 32))
557 sz = 32;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000558 O << ".reg .b" << sz << " func_retval" << idx;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000559 if (j < je - 1)
560 O << ", ";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000561 ++idx;
562 }
Justin Holewinski0497ab12013-03-30 14:29:21 +0000563 if (i < e - 1)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000564 O << ", ";
565 }
566 }
567 O << ") ";
568 return;
569}
570
571void NVPTXAsmPrinter::printReturnValStr(const MachineFunction &MF,
572 raw_ostream &O) {
573 const Function *F = MF.getFunction();
574 printReturnValStr(F, O);
575}
576
577void NVPTXAsmPrinter::EmitFunctionEntryLabel() {
578 SmallString<128> Str;
579 raw_svector_ostream O(Str);
580
Justin Holewinski01f89f02013-05-20 12:13:32 +0000581 if (!GlobalsEmitted) {
582 emitGlobals(*MF->getFunction()->getParent());
583 GlobalsEmitted = true;
584 }
585
Justin Holewinskiae556d32012-05-04 20:18:50 +0000586 // Set up
587 MRI = &MF->getRegInfo();
588 F = MF->getFunction();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000589 emitLinkageDirective(F, O);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000590 if (llvm::isKernelFunction(*F))
591 O << ".entry ";
592 else {
593 O << ".func ";
594 printReturnValStr(*MF, O);
595 }
596
597 O << *CurrentFnSym;
598
599 emitFunctionParamList(*MF, O);
600
601 if (llvm::isKernelFunction(*F))
602 emitKernelFunctionDirectives(*F, O);
603
604 OutStreamer.EmitRawText(O.str());
605
606 prevDebugLoc = DebugLoc();
607}
608
609void NVPTXAsmPrinter::EmitFunctionBodyStart() {
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +0000610 VRegMapping.clear();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000611 OutStreamer.EmitRawText(StringRef("{\n"));
612 setAndEmitFunctionVirtualRegisters(*MF);
613
614 SmallString<128> Str;
615 raw_svector_ostream O(Str);
616 emitDemotedVars(MF->getFunction(), O);
617 OutStreamer.EmitRawText(O.str());
618}
619
620void NVPTXAsmPrinter::EmitFunctionBodyEnd() {
621 OutStreamer.EmitRawText(StringRef("}\n"));
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +0000622 VRegMapping.clear();
Justin Holewinskiae556d32012-05-04 20:18:50 +0000623}
624
Justin Holewinski660597d2013-10-11 12:39:36 +0000625void NVPTXAsmPrinter::emitImplicitDef(const MachineInstr *MI) const {
626 unsigned RegNo = MI->getOperand(0).getReg();
Eric Christopherd9134482014-08-04 21:25:23 +0000627 const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo();
Justin Holewinski660597d2013-10-11 12:39:36 +0000628 if (TRI->isVirtualRegister(RegNo)) {
629 OutStreamer.AddComment(Twine("implicit-def: ") +
630 getVirtualRegisterName(RegNo));
631 } else {
Eric Christopherd9134482014-08-04 21:25:23 +0000632 OutStreamer.AddComment(
633 Twine("implicit-def: ") +
634 TM.getSubtargetImpl()->getRegisterInfo()->getName(RegNo));
Justin Holewinski660597d2013-10-11 12:39:36 +0000635 }
636 OutStreamer.AddBlankLine();
637}
638
Justin Holewinski0497ab12013-03-30 14:29:21 +0000639void NVPTXAsmPrinter::emitKernelFunctionDirectives(const Function &F,
640 raw_ostream &O) const {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000641 // If the NVVM IR has some of reqntid* specified, then output
642 // the reqntid directive, and set the unspecified ones to 1.
643 // If none of reqntid* is specified, don't output reqntid directive.
644 unsigned reqntidx, reqntidy, reqntidz;
645 bool specified = false;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000646 if (llvm::getReqNTIDx(F, reqntidx) == false)
647 reqntidx = 1;
648 else
649 specified = true;
650 if (llvm::getReqNTIDy(F, reqntidy) == false)
651 reqntidy = 1;
652 else
653 specified = true;
654 if (llvm::getReqNTIDz(F, reqntidz) == false)
655 reqntidz = 1;
656 else
657 specified = true;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000658
659 if (specified)
Justin Holewinski0497ab12013-03-30 14:29:21 +0000660 O << ".reqntid " << reqntidx << ", " << reqntidy << ", " << reqntidz
661 << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000662
663 // If the NVVM IR has some of maxntid* specified, then output
664 // the maxntid directive, and set the unspecified ones to 1.
665 // If none of maxntid* is specified, don't output maxntid directive.
666 unsigned maxntidx, maxntidy, maxntidz;
667 specified = false;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000668 if (llvm::getMaxNTIDx(F, maxntidx) == false)
669 maxntidx = 1;
670 else
671 specified = true;
672 if (llvm::getMaxNTIDy(F, maxntidy) == false)
673 maxntidy = 1;
674 else
675 specified = true;
676 if (llvm::getMaxNTIDz(F, maxntidz) == false)
677 maxntidz = 1;
678 else
679 specified = true;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000680
681 if (specified)
Justin Holewinski0497ab12013-03-30 14:29:21 +0000682 O << ".maxntid " << maxntidx << ", " << maxntidy << ", " << maxntidz
683 << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000684
685 unsigned mincta;
686 if (llvm::getMinCTASm(F, mincta))
687 O << ".minnctapersm " << mincta << "\n";
688}
689
Justin Holewinski660597d2013-10-11 12:39:36 +0000690std::string
691NVPTXAsmPrinter::getVirtualRegisterName(unsigned Reg) const {
692 const TargetRegisterClass *RC = MRI->getRegClass(Reg);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000693
Justin Holewinski660597d2013-10-11 12:39:36 +0000694 std::string Name;
695 raw_string_ostream NameStr(Name);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000696
Justin Holewinski660597d2013-10-11 12:39:36 +0000697 VRegRCMap::const_iterator I = VRegMapping.find(RC);
698 assert(I != VRegMapping.end() && "Bad register class");
699 const DenseMap<unsigned, unsigned> &RegMap = I->second;
700
701 VRegMap::const_iterator VI = RegMap.find(Reg);
702 assert(VI != RegMap.end() && "Bad virtual register");
703 unsigned MappedVR = VI->second;
704
705 NameStr << getNVPTXRegClassStr(RC) << MappedVR;
706
707 NameStr.flush();
708 return Name;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000709}
710
Justin Holewinski660597d2013-10-11 12:39:36 +0000711void NVPTXAsmPrinter::emitVirtualRegister(unsigned int vr,
Justin Holewinski0497ab12013-03-30 14:29:21 +0000712 raw_ostream &O) {
Justin Holewinski660597d2013-10-11 12:39:36 +0000713 O << getVirtualRegisterName(vr);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000714}
715
Justin Holewinski0497ab12013-03-30 14:29:21 +0000716void NVPTXAsmPrinter::printVecModifiedImmediate(
717 const MachineOperand &MO, const char *Modifier, raw_ostream &O) {
718 static const char vecelem[] = { '0', '1', '2', '3', '0', '1', '2', '3' };
719 int Imm = (int) MO.getImm();
720 if (0 == strcmp(Modifier, "vecelem"))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000721 O << "_" << vecelem[Imm];
Justin Holewinski0497ab12013-03-30 14:29:21 +0000722 else if (0 == strcmp(Modifier, "vecv4comm1")) {
723 if ((Imm < 0) || (Imm > 3))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000724 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000725 } else if (0 == strcmp(Modifier, "vecv4comm2")) {
726 if ((Imm < 4) || (Imm > 7))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000727 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000728 } else if (0 == strcmp(Modifier, "vecv4pos")) {
729 if (Imm < 0)
730 Imm = 0;
731 O << "_" << vecelem[Imm % 4];
732 } else if (0 == strcmp(Modifier, "vecv2comm1")) {
733 if ((Imm < 0) || (Imm > 1))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000734 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000735 } else if (0 == strcmp(Modifier, "vecv2comm2")) {
736 if ((Imm < 2) || (Imm > 3))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000737 O << "//";
Justin Holewinski0497ab12013-03-30 14:29:21 +0000738 } else if (0 == strcmp(Modifier, "vecv2pos")) {
739 if (Imm < 0)
740 Imm = 0;
741 O << "_" << vecelem[Imm % 2];
742 } else
Craig Topperbdf39a42012-05-24 07:02:50 +0000743 llvm_unreachable("Unknown Modifier on immediate operand");
Justin Holewinskiae556d32012-05-04 20:18:50 +0000744}
745
Justin Holewinskidc5e3b62013-06-28 17:58:04 +0000746
747
Justin Holewinski0497ab12013-03-30 14:29:21 +0000748void NVPTXAsmPrinter::emitDeclaration(const Function *F, raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000749
Justin Holewinski0497ab12013-03-30 14:29:21 +0000750 emitLinkageDirective(F, O);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000751 if (llvm::isKernelFunction(*F))
752 O << ".entry ";
753 else
754 O << ".func ";
755 printReturnValStr(F, O);
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +0000756 O << *getSymbol(F) << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +0000757 emitFunctionParamList(F, O);
758 O << ";\n";
759}
760
Justin Holewinski0497ab12013-03-30 14:29:21 +0000761static bool usedInGlobalVarDef(const Constant *C) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000762 if (!C)
763 return false;
764
765 if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
766 if (GV->getName().str() == "llvm.used")
767 return false;
768 return true;
769 }
770
Chandler Carruthcdf47882014-03-09 03:16:01 +0000771 for (const User *U : C->users())
772 if (const Constant *C = dyn_cast<Constant>(U))
773 if (usedInGlobalVarDef(C))
774 return true;
775
Justin Holewinskiae556d32012-05-04 20:18:50 +0000776 return false;
777}
778
Justin Holewinski0497ab12013-03-30 14:29:21 +0000779static bool usedInOneFunc(const User *U, Function const *&oneFunc) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000780 if (const GlobalVariable *othergv = dyn_cast<GlobalVariable>(U)) {
781 if (othergv->getName().str() == "llvm.used")
782 return true;
783 }
784
785 if (const Instruction *instr = dyn_cast<Instruction>(U)) {
786 if (instr->getParent() && instr->getParent()->getParent()) {
787 const Function *curFunc = instr->getParent()->getParent();
788 if (oneFunc && (curFunc != oneFunc))
789 return false;
790 oneFunc = curFunc;
791 return true;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000792 } else
Justin Holewinskiae556d32012-05-04 20:18:50 +0000793 return false;
794 }
795
796 if (const MDNode *md = dyn_cast<MDNode>(U))
797 if (md->hasName() && ((md->getName().str() == "llvm.dbg.gv") ||
Justin Holewinski0497ab12013-03-30 14:29:21 +0000798 (md->getName().str() == "llvm.dbg.sp")))
Justin Holewinskiae556d32012-05-04 20:18:50 +0000799 return true;
800
Chandler Carruthcdf47882014-03-09 03:16:01 +0000801 for (const User *UU : U->users())
802 if (usedInOneFunc(UU, oneFunc) == false)
Justin Holewinskiae556d32012-05-04 20:18:50 +0000803 return false;
Chandler Carruthcdf47882014-03-09 03:16:01 +0000804
Justin Holewinskiae556d32012-05-04 20:18:50 +0000805 return true;
806}
807
808/* Find out if a global variable can be demoted to local scope.
809 * Currently, this is valid for CUDA shared variables, which have local
810 * scope and global lifetime. So the conditions to check are :
811 * 1. Is the global variable in shared address space?
812 * 2. Does it have internal linkage?
813 * 3. Is the global variable referenced only in one function?
814 */
815static bool canDemoteGlobalVar(const GlobalVariable *gv, Function const *&f) {
816 if (gv->hasInternalLinkage() == false)
817 return false;
818 const PointerType *Pty = gv->getType();
819 if (Pty->getAddressSpace() != llvm::ADDRESS_SPACE_SHARED)
820 return false;
821
Craig Topper062a2ba2014-04-25 05:30:21 +0000822 const Function *oneFunc = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000823
824 bool flag = usedInOneFunc(gv, oneFunc);
825 if (flag == false)
826 return false;
827 if (!oneFunc)
828 return false;
829 f = oneFunc;
830 return true;
831}
832
833static bool useFuncSeen(const Constant *C,
834 llvm::DenseMap<const Function *, bool> &seenMap) {
Chandler Carruthcdf47882014-03-09 03:16:01 +0000835 for (const User *U : C->users()) {
836 if (const Constant *cu = dyn_cast<Constant>(U)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000837 if (useFuncSeen(cu, seenMap))
838 return true;
Chandler Carruthcdf47882014-03-09 03:16:01 +0000839 } else if (const Instruction *I = dyn_cast<Instruction>(U)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000840 const BasicBlock *bb = I->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000841 if (!bb)
842 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000843 const Function *caller = bb->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000844 if (!caller)
845 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000846 if (seenMap.find(caller) != seenMap.end())
847 return true;
848 }
849 }
850 return false;
851}
852
Justin Holewinski01f89f02013-05-20 12:13:32 +0000853void NVPTXAsmPrinter::emitDeclarations(const Module &M, raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000854 llvm::DenseMap<const Function *, bool> seenMap;
Justin Holewinski0497ab12013-03-30 14:29:21 +0000855 for (Module::const_iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000856 const Function *F = FI;
857
858 if (F->isDeclaration()) {
859 if (F->use_empty())
860 continue;
861 if (F->getIntrinsicID())
862 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000863 emitDeclaration(F, O);
864 continue;
865 }
Chandler Carruthcdf47882014-03-09 03:16:01 +0000866 for (const User *U : F->users()) {
867 if (const Constant *C = dyn_cast<Constant>(U)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000868 if (usedInGlobalVarDef(C)) {
869 // The use is in the initialization of a global variable
870 // that is a function pointer, so print a declaration
871 // for the original function
Justin Holewinskiae556d32012-05-04 20:18:50 +0000872 emitDeclaration(F, O);
873 break;
874 }
875 // Emit a declaration of this function if the function that
876 // uses this constant expr has already been seen.
877 if (useFuncSeen(C, seenMap)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000878 emitDeclaration(F, O);
879 break;
880 }
881 }
882
Chandler Carruthcdf47882014-03-09 03:16:01 +0000883 if (!isa<Instruction>(U))
Justin Holewinski0497ab12013-03-30 14:29:21 +0000884 continue;
Chandler Carruthcdf47882014-03-09 03:16:01 +0000885 const Instruction *instr = cast<Instruction>(U);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000886 const BasicBlock *bb = instr->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000887 if (!bb)
888 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000889 const Function *caller = bb->getParent();
Justin Holewinski0497ab12013-03-30 14:29:21 +0000890 if (!caller)
891 continue;
Justin Holewinskiae556d32012-05-04 20:18:50 +0000892
893 // If a caller has already been seen, then the caller is
894 // appearing in the module before the callee. so print out
895 // a declaration for the callee.
896 if (seenMap.find(caller) != seenMap.end()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000897 emitDeclaration(F, O);
898 break;
899 }
900 }
901 seenMap[F] = true;
902 }
903}
904
905void NVPTXAsmPrinter::recordAndEmitFilenames(Module &M) {
906 DebugInfoFinder DbgFinder;
907 DbgFinder.processModule(M);
908
Justin Holewinski0497ab12013-03-30 14:29:21 +0000909 unsigned i = 1;
Alon Mishnead312152014-03-18 09:41:07 +0000910 for (DICompileUnit DIUnit : DbgFinder.compile_units()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000911 StringRef Filename(DIUnit.getFilename());
912 StringRef Dirname(DIUnit.getDirectory());
913 SmallString<128> FullPathName = Dirname;
914 if (!Dirname.empty() && !sys::path::is_absolute(Filename)) {
915 sys::path::append(FullPathName, Filename);
916 Filename = FullPathName.str();
917 }
918 if (filenameMap.find(Filename.str()) != filenameMap.end())
919 continue;
920 filenameMap[Filename.str()] = i;
921 OutStreamer.EmitDwarfFileDirective(i, "", Filename.str());
922 ++i;
923 }
924
Alon Mishnead312152014-03-18 09:41:07 +0000925 for (DISubprogram SP : DbgFinder.subprograms()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000926 StringRef Filename(SP.getFilename());
927 StringRef Dirname(SP.getDirectory());
928 SmallString<128> FullPathName = Dirname;
929 if (!Dirname.empty() && !sys::path::is_absolute(Filename)) {
930 sys::path::append(FullPathName, Filename);
931 Filename = FullPathName.str();
932 }
933 if (filenameMap.find(Filename.str()) != filenameMap.end())
934 continue;
935 filenameMap[Filename.str()] = i;
936 ++i;
937 }
938}
939
Justin Holewinski0497ab12013-03-30 14:29:21 +0000940bool NVPTXAsmPrinter::doInitialization(Module &M) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000941
942 SmallString<128> Str1;
943 raw_svector_ostream OS1(Str1);
944
945 MMI = getAnalysisIfAvailable<MachineModuleInfo>();
946 MMI->AnalyzeModule(M);
947
948 // We need to call the parent's one explicitly.
949 //bool Result = AsmPrinter::doInitialization(M);
950
951 // Initialize TargetLoweringObjectFile.
Justin Holewinski0497ab12013-03-30 14:29:21 +0000952 const_cast<TargetLoweringObjectFile &>(getObjFileLowering())
953 .Initialize(OutContext, TM);
Justin Holewinskiae556d32012-05-04 20:18:50 +0000954
Eric Christopherd9134482014-08-04 21:25:23 +0000955 Mang = new Mangler(TM.getSubtargetImpl()->getDataLayout());
Justin Holewinskiae556d32012-05-04 20:18:50 +0000956
957 // Emit header before any dwarf directives are emitted below.
958 emitHeader(M, OS1);
959 OutStreamer.EmitRawText(OS1.str());
960
Justin Holewinskiae556d32012-05-04 20:18:50 +0000961 // Already commented out
962 //bool Result = AsmPrinter::doInitialization(M);
963
Justin Holewinskid2bbdf02013-07-01 13:00:14 +0000964 // Emit module-level inline asm if it exists.
965 if (!M.getModuleInlineAsm().empty()) {
966 OutStreamer.AddComment("Start of file scope inline assembly");
967 OutStreamer.AddBlankLine();
968 OutStreamer.EmitRawText(StringRef(M.getModuleInlineAsm()));
969 OutStreamer.AddBlankLine();
970 OutStreamer.AddComment("End of file scope inline assembly");
971 OutStreamer.AddBlankLine();
972 }
973
Justin Holewinskiae556d32012-05-04 20:18:50 +0000974 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA)
975 recordAndEmitFilenames(M);
976
Justin Holewinski01f89f02013-05-20 12:13:32 +0000977 GlobalsEmitted = false;
978
979 return false; // success
980}
981
982void NVPTXAsmPrinter::emitGlobals(const Module &M) {
Justin Holewinskiae556d32012-05-04 20:18:50 +0000983 SmallString<128> Str2;
984 raw_svector_ostream OS2(Str2);
985
986 emitDeclarations(M, OS2);
987
Justin Holewinski2c5ac702012-11-16 21:03:51 +0000988 // As ptxas does not support forward references of globals, we need to first
989 // sort the list of module-level globals in def-use order. We visit each
990 // global variable in order, and ensure that we emit it *after* its dependent
991 // globals. We use a little extra memory maintaining both a set and a list to
992 // have fast searches while maintaining a strict ordering.
Justin Holewinski01f89f02013-05-20 12:13:32 +0000993 SmallVector<const GlobalVariable *, 8> Globals;
994 DenseSet<const GlobalVariable *> GVVisited;
995 DenseSet<const GlobalVariable *> GVVisiting;
Justin Holewinski2c5ac702012-11-16 21:03:51 +0000996
997 // Visit each global variable, in order
Justin Holewinski01f89f02013-05-20 12:13:32 +0000998 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
999 I != E; ++I)
Justin Holewinski2c5ac702012-11-16 21:03:51 +00001000 VisitGlobalVariableForEmission(I, Globals, GVVisited, GVVisiting);
1001
Justin Holewinski0497ab12013-03-30 14:29:21 +00001002 assert(GVVisited.size() == M.getGlobalList().size() &&
Justin Holewinski2c5ac702012-11-16 21:03:51 +00001003 "Missed a global variable");
1004 assert(GVVisiting.size() == 0 && "Did not fully process a global variable");
1005
1006 // Print out module-level global variables in proper order
1007 for (unsigned i = 0, e = Globals.size(); i != e; ++i)
1008 printModuleLevelGV(Globals[i], OS2);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001009
1010 OS2 << '\n';
1011
1012 OutStreamer.EmitRawText(OS2.str());
Justin Holewinskiae556d32012-05-04 20:18:50 +00001013}
1014
Justin Holewinski0497ab12013-03-30 14:29:21 +00001015void NVPTXAsmPrinter::emitHeader(Module &M, raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001016 O << "//\n";
1017 O << "// Generated by LLVM NVPTX Back-End\n";
1018 O << "//\n";
1019 O << "\n";
1020
Justin Holewinski1812ee92012-11-12 03:16:43 +00001021 unsigned PTXVersion = nvptxSubtarget.getPTXVersion();
1022 O << ".version " << (PTXVersion / 10) << "." << (PTXVersion % 10) << "\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001023
1024 O << ".target ";
1025 O << nvptxSubtarget.getTargetName();
1026
1027 if (nvptxSubtarget.getDrvInterface() == NVPTX::NVCL)
1028 O << ", texmode_independent";
1029 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA) {
1030 if (!nvptxSubtarget.hasDouble())
1031 O << ", map_f64_to_f32";
1032 }
1033
1034 if (MAI->doesSupportDebugInformation())
1035 O << ", debug";
1036
1037 O << "\n";
1038
1039 O << ".address_size ";
1040 if (nvptxSubtarget.is64Bit())
1041 O << "64";
1042 else
1043 O << "32";
1044 O << "\n";
1045
1046 O << "\n";
1047}
1048
1049bool NVPTXAsmPrinter::doFinalization(Module &M) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001050
1051 // If we did not emit any functions, then the global declarations have not
1052 // yet been emitted.
1053 if (!GlobalsEmitted) {
1054 emitGlobals(M);
1055 GlobalsEmitted = true;
1056 }
1057
Justin Holewinskiae556d32012-05-04 20:18:50 +00001058 // XXX Temproarily remove global variables so that doFinalization() will not
1059 // emit them again (global variables are emitted at beginning).
1060
1061 Module::GlobalListType &global_list = M.getGlobalList();
1062 int i, n = global_list.size();
Dylan Noblesmithc9e2a272014-08-26 02:03:35 +00001063 GlobalVariable **gv_array = new GlobalVariable *[n];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001064
1065 // first, back-up GlobalVariable in gv_array
1066 i = 0;
1067 for (Module::global_iterator I = global_list.begin(), E = global_list.end();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001068 I != E; ++I)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001069 gv_array[i++] = &*I;
1070
1071 // second, empty global_list
1072 while (!global_list.empty())
1073 global_list.remove(global_list.begin());
1074
1075 // call doFinalization
1076 bool ret = AsmPrinter::doFinalization(M);
1077
1078 // now we restore global variables
Justin Holewinski0497ab12013-03-30 14:29:21 +00001079 for (i = 0; i < n; i++)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001080 global_list.insert(global_list.end(), gv_array[i]);
1081
Justin Holewinski59596952014-04-09 15:38:52 +00001082 clearAnnotationCache(&M);
Dylan Noblesmithc9e2a272014-08-26 02:03:35 +00001083
1084 delete[] gv_array;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001085 return ret;
1086
Justin Holewinskiae556d32012-05-04 20:18:50 +00001087 //bool Result = AsmPrinter::doFinalization(M);
1088 // Instead of calling the parents doFinalization, we may
1089 // clone parents doFinalization and customize here.
1090 // Currently, we if NVISA out the EmitGlobals() in
1091 // parent's doFinalization, which is too intrusive.
1092 //
1093 // Same for the doInitialization.
1094 //return Result;
1095}
1096
1097// This function emits appropriate linkage directives for
1098// functions and global variables.
1099//
1100// extern function declaration -> .extern
1101// extern function definition -> .visible
1102// external global variable with init -> .visible
1103// external without init -> .extern
1104// appending -> not allowed, assert.
Justin Holewinski7d5bf662014-06-27 18:35:10 +00001105// for any linkage other than
1106// internal, private, linker_private,
1107// linker_private_weak, linker_private_weak_def_auto,
1108// we emit -> .weak.
Justin Holewinskiae556d32012-05-04 20:18:50 +00001109
Justin Holewinski0497ab12013-03-30 14:29:21 +00001110void NVPTXAsmPrinter::emitLinkageDirective(const GlobalValue *V,
1111 raw_ostream &O) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001112 if (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA) {
1113 if (V->hasExternalLinkage()) {
1114 if (isa<GlobalVariable>(V)) {
1115 const GlobalVariable *GVar = cast<GlobalVariable>(V);
1116 if (GVar) {
1117 if (GVar->hasInitializer())
1118 O << ".visible ";
1119 else
1120 O << ".extern ";
1121 }
1122 } else if (V->isDeclaration())
1123 O << ".extern ";
1124 else
1125 O << ".visible ";
1126 } else if (V->hasAppendingLinkage()) {
1127 std::string msg;
1128 msg.append("Error: ");
1129 msg.append("Symbol ");
1130 if (V->hasName())
1131 msg.append(V->getName().str());
1132 msg.append("has unsupported appending linkage type");
1133 llvm_unreachable(msg.c_str());
Justin Holewinski7d5bf662014-06-27 18:35:10 +00001134 } else if (!V->hasInternalLinkage() &&
1135 !V->hasPrivateLinkage()) {
1136 O << ".weak ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001137 }
1138 }
1139}
1140
Justin Holewinski01f89f02013-05-20 12:13:32 +00001141void NVPTXAsmPrinter::printModuleLevelGV(const GlobalVariable *GVar,
1142 raw_ostream &O,
Justin Holewinskiae556d32012-05-04 20:18:50 +00001143 bool processDemoted) {
1144
1145 // Skip meta data
1146 if (GVar->hasSection()) {
Rafael Espindola64c1e182014-06-03 02:41:57 +00001147 if (GVar->getSection() == StringRef("llvm.metadata"))
Justin Holewinskiae556d32012-05-04 20:18:50 +00001148 return;
1149 }
1150
Justin Holewinski73cb5de2014-06-27 18:35:53 +00001151 // Skip LLVM intrinsic global variables
1152 if (GVar->getName().startswith("llvm.") ||
1153 GVar->getName().startswith("nvvm."))
1154 return;
1155
Eric Christopherd9134482014-08-04 21:25:23 +00001156 const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001157
1158 // GlobalVariables are always constant pointers themselves.
1159 const PointerType *PTy = GVar->getType();
1160 Type *ETy = PTy->getElementType();
1161
1162 if (GVar->hasExternalLinkage()) {
1163 if (GVar->hasInitializer())
1164 O << ".visible ";
1165 else
1166 O << ".extern ";
Justin Holewinskid73767a2014-06-27 18:35:56 +00001167 } else if (GVar->hasLinkOnceLinkage() || GVar->hasWeakLinkage() ||
1168 GVar->hasAvailableExternallyLinkage() ||
1169 GVar->hasCommonLinkage()) {
1170 O << ".weak ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001171 }
1172
1173 if (llvm::isTexture(*GVar)) {
1174 O << ".global .texref " << llvm::getTextureName(*GVar) << ";\n";
1175 return;
1176 }
1177
1178 if (llvm::isSurface(*GVar)) {
1179 O << ".global .surfref " << llvm::getSurfaceName(*GVar) << ";\n";
1180 return;
1181 }
1182
1183 if (GVar->isDeclaration()) {
1184 // (extern) declarations, no definition or initializer
1185 // Currently the only known declaration is for an automatic __local
1186 // (.shared) promoted to global.
1187 emitPTXGlobalVariable(GVar, O);
1188 O << ";\n";
1189 return;
1190 }
1191
1192 if (llvm::isSampler(*GVar)) {
1193 O << ".global .samplerref " << llvm::getSamplerName(*GVar);
1194
Craig Topper062a2ba2014-04-25 05:30:21 +00001195 const Constant *Initializer = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001196 if (GVar->hasInitializer())
1197 Initializer = GVar->getInitializer();
Craig Topper062a2ba2014-04-25 05:30:21 +00001198 const ConstantInt *CI = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001199 if (Initializer)
1200 CI = dyn_cast<ConstantInt>(Initializer);
1201 if (CI) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001202 unsigned sample = CI->getZExtValue();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001203
1204 O << " = { ";
1205
Justin Holewinski0497ab12013-03-30 14:29:21 +00001206 for (int i = 0,
1207 addr = ((sample & __CLK_ADDRESS_MASK) >> __CLK_ADDRESS_BASE);
1208 i < 3; i++) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001209 O << "addr_mode_" << i << " = ";
1210 switch (addr) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001211 case 0:
1212 O << "wrap";
1213 break;
1214 case 1:
1215 O << "clamp_to_border";
1216 break;
1217 case 2:
1218 O << "clamp_to_edge";
1219 break;
1220 case 3:
1221 O << "wrap";
1222 break;
1223 case 4:
1224 O << "mirror";
1225 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001226 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001227 O << ", ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001228 }
1229 O << "filter_mode = ";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001230 switch ((sample & __CLK_FILTER_MASK) >> __CLK_FILTER_BASE) {
1231 case 0:
1232 O << "nearest";
1233 break;
1234 case 1:
1235 O << "linear";
1236 break;
1237 case 2:
Craig Topper2a30d782014-06-18 05:05:13 +00001238 llvm_unreachable("Anisotropic filtering is not supported");
Justin Holewinski0497ab12013-03-30 14:29:21 +00001239 default:
1240 O << "nearest";
1241 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001242 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001243 if (!((sample & __CLK_NORMALIZED_MASK) >> __CLK_NORMALIZED_BASE)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001244 O << ", force_unnormalized_coords = 1";
1245 }
1246 O << " }";
1247 }
1248
1249 O << ";\n";
1250 return;
1251 }
1252
1253 if (GVar->hasPrivateLinkage()) {
1254
1255 if (!strncmp(GVar->getName().data(), "unrollpragma", 12))
1256 return;
1257
1258 // FIXME - need better way (e.g. Metadata) to avoid generating this global
1259 if (!strncmp(GVar->getName().data(), "filename", 8))
1260 return;
1261 if (GVar->use_empty())
1262 return;
1263 }
1264
Craig Topper062a2ba2014-04-25 05:30:21 +00001265 const Function *demotedFunc = nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001266 if (!processDemoted && canDemoteGlobalVar(GVar, demotedFunc)) {
1267 O << "// " << GVar->getName().str() << " has been demoted\n";
1268 if (localDecls.find(demotedFunc) != localDecls.end())
1269 localDecls[demotedFunc].push_back(GVar);
1270 else {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001271 std::vector<const GlobalVariable *> temp;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001272 temp.push_back(GVar);
1273 localDecls[demotedFunc] = temp;
1274 }
1275 return;
1276 }
1277
1278 O << ".";
1279 emitPTXAddressSpace(PTy->getAddressSpace(), O);
Justin Holewinski773ca402014-06-27 18:35:58 +00001280
1281 if (isManaged(*GVar)) {
1282 O << " .attribute(.managed)";
1283 }
1284
Justin Holewinskiae556d32012-05-04 20:18:50 +00001285 if (GVar->getAlignment() == 0)
1286 O << " .align " << (int) TD->getPrefTypeAlignment(ETy);
1287 else
1288 O << " .align " << GVar->getAlignment();
1289
Rafael Espindola08013342013-12-07 19:34:20 +00001290 if (ETy->isSingleValueType()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001291 O << " .";
Justin Holewinski700b6fa2013-05-20 12:13:28 +00001292 // Special case: ABI requires that we use .u8 for predicates
1293 if (ETy->isIntegerTy(1))
1294 O << "u8";
1295 else
1296 O << getPTXFundamentalTypeStr(ETy, false);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001297 O << " ";
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001298 O << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001299
1300 // Ptx allows variable initilization only for constant and global state
1301 // spaces.
Justin Holewinski549c7732014-06-27 18:36:01 +00001302 if (GVar->hasInitializer()) {
1303 if ((PTy->getAddressSpace() == llvm::ADDRESS_SPACE_GLOBAL) ||
1304 (PTy->getAddressSpace() == llvm::ADDRESS_SPACE_CONST)) {
1305 const Constant *Initializer = GVar->getInitializer();
1306 // 'undef' is treated as there is no value spefied.
1307 if (!Initializer->isNullValue() && !isa<UndefValue>(Initializer)) {
1308 O << " = ";
1309 printScalarConstant(Initializer, O);
1310 }
1311 } else {
1312 // The frontend adds zero-initializer to variables that don't have an
1313 // initial value, so skip warning for this case.
1314 if (!GVar->getInitializer()->isNullValue()) {
1315 std::string warnMsg = "initial value of '" + GVar->getName().str() +
1316 "' is not allowed in addrspace(" +
1317 llvm::utostr_32(PTy->getAddressSpace()) + ")";
1318 report_fatal_error(warnMsg.c_str());
1319 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001320 }
1321 }
1322 } else {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001323 unsigned int ElementSize = 0;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001324
1325 // Although PTX has direct support for struct type and array type and
1326 // LLVM IR is very similar to PTX, the LLVM CodeGen does not support for
1327 // targets that support these high level field accesses. Structs, arrays
1328 // and vectors are lowered into arrays of bytes.
1329 switch (ETy->getTypeID()) {
1330 case Type::StructTyID:
1331 case Type::ArrayTyID:
1332 case Type::VectorTyID:
1333 ElementSize = TD->getTypeStoreSize(ETy);
1334 // Ptx allows variable initilization only for constant and
1335 // global state spaces.
1336 if (((PTy->getAddressSpace() == llvm::ADDRESS_SPACE_GLOBAL) ||
Justin Holewinski0497ab12013-03-30 14:29:21 +00001337 (PTy->getAddressSpace() == llvm::ADDRESS_SPACE_CONST)) &&
1338 GVar->hasInitializer()) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001339 const Constant *Initializer = GVar->getInitializer();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001340 if (!isa<UndefValue>(Initializer) && !Initializer->isNullValue()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001341 AggBuffer aggBuffer(ElementSize, O, *this);
1342 bufferAggregateConstant(Initializer, &aggBuffer);
1343 if (aggBuffer.numSymbols) {
1344 if (nvptxSubtarget.is64Bit()) {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001345 O << " .u64 " << *getSymbol(GVar) << "[";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001346 O << ElementSize / 8;
1347 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001348 O << " .u32 " << *getSymbol(GVar) << "[";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001349 O << ElementSize / 4;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001350 }
1351 O << "]";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001352 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001353 O << " .b8 " << *getSymbol(GVar) << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001354 O << ElementSize;
1355 O << "]";
1356 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001357 O << " = {";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001358 aggBuffer.print();
1359 O << "}";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001360 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001361 O << " .b8 " << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001362 if (ElementSize) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001363 O << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001364 O << ElementSize;
1365 O << "]";
1366 }
1367 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001368 } else {
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001369 O << " .b8 " << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001370 if (ElementSize) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001371 O << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001372 O << ElementSize;
1373 O << "]";
1374 }
1375 }
1376 break;
1377 default:
Craig Topper2a30d782014-06-18 05:05:13 +00001378 llvm_unreachable("type not supported yet");
Justin Holewinskiae556d32012-05-04 20:18:50 +00001379 }
1380
1381 }
1382 O << ";\n";
1383}
1384
1385void NVPTXAsmPrinter::emitDemotedVars(const Function *f, raw_ostream &O) {
1386 if (localDecls.find(f) == localDecls.end())
1387 return;
1388
Justin Holewinski01f89f02013-05-20 12:13:32 +00001389 std::vector<const GlobalVariable *> &gvars = localDecls[f];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001390
Justin Holewinski0497ab12013-03-30 14:29:21 +00001391 for (unsigned i = 0, e = gvars.size(); i != e; ++i) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001392 O << "\t// demoted variable\n\t";
1393 printModuleLevelGV(gvars[i], O, true);
1394 }
1395}
1396
1397void NVPTXAsmPrinter::emitPTXAddressSpace(unsigned int AddressSpace,
1398 raw_ostream &O) const {
1399 switch (AddressSpace) {
1400 case llvm::ADDRESS_SPACE_LOCAL:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001401 O << "local";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001402 break;
1403 case llvm::ADDRESS_SPACE_GLOBAL:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001404 O << "global";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001405 break;
1406 case llvm::ADDRESS_SPACE_CONST:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001407 O << "const";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001408 break;
1409 case llvm::ADDRESS_SPACE_SHARED:
Justin Holewinski0497ab12013-03-30 14:29:21 +00001410 O << "shared";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001411 break;
1412 default:
Justin Holewinski36a50992013-02-09 13:34:15 +00001413 report_fatal_error("Bad address space found while emitting PTX");
1414 break;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001415 }
1416}
1417
Justin Holewinski0497ab12013-03-30 14:29:21 +00001418std::string
1419NVPTXAsmPrinter::getPTXFundamentalTypeStr(const Type *Ty, bool useB4PTR) const {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001420 switch (Ty->getTypeID()) {
1421 default:
1422 llvm_unreachable("unexpected type");
1423 break;
1424 case Type::IntegerTyID: {
1425 unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth();
1426 if (NumBits == 1)
1427 return "pred";
1428 else if (NumBits <= 64) {
1429 std::string name = "u";
1430 return name + utostr(NumBits);
1431 } else {
1432 llvm_unreachable("Integer too large");
1433 break;
1434 }
1435 break;
1436 }
1437 case Type::FloatTyID:
1438 return "f32";
1439 case Type::DoubleTyID:
1440 return "f64";
1441 case Type::PointerTyID:
1442 if (nvptxSubtarget.is64Bit())
Justin Holewinski0497ab12013-03-30 14:29:21 +00001443 if (useB4PTR)
1444 return "b64";
1445 else
1446 return "u64";
1447 else if (useB4PTR)
1448 return "b32";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001449 else
Justin Holewinski0497ab12013-03-30 14:29:21 +00001450 return "u32";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001451 }
1452 llvm_unreachable("unexpected type");
Craig Topper062a2ba2014-04-25 05:30:21 +00001453 return nullptr;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001454}
1455
Justin Holewinski0497ab12013-03-30 14:29:21 +00001456void NVPTXAsmPrinter::emitPTXGlobalVariable(const GlobalVariable *GVar,
Justin Holewinskiae556d32012-05-04 20:18:50 +00001457 raw_ostream &O) {
1458
Eric Christopherd9134482014-08-04 21:25:23 +00001459 const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001460
1461 // GlobalVariables are always constant pointers themselves.
1462 const PointerType *PTy = GVar->getType();
1463 Type *ETy = PTy->getElementType();
1464
1465 O << ".";
1466 emitPTXAddressSpace(PTy->getAddressSpace(), O);
1467 if (GVar->getAlignment() == 0)
1468 O << " .align " << (int) TD->getPrefTypeAlignment(ETy);
1469 else
1470 O << " .align " << GVar->getAlignment();
1471
Rafael Espindola08013342013-12-07 19:34:20 +00001472 if (ETy->isSingleValueType()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001473 O << " .";
1474 O << getPTXFundamentalTypeStr(ETy);
1475 O << " ";
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001476 O << *getSymbol(GVar);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001477 return;
1478 }
1479
Justin Holewinski0497ab12013-03-30 14:29:21 +00001480 int64_t ElementSize = 0;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001481
1482 // Although PTX has direct support for struct type and array type and LLVM IR
1483 // is very similar to PTX, the LLVM CodeGen does not support for targets that
1484 // support these high level field accesses. Structs and arrays are lowered
1485 // into arrays of bytes.
1486 switch (ETy->getTypeID()) {
1487 case Type::StructTyID:
1488 case Type::ArrayTyID:
1489 case Type::VectorTyID:
1490 ElementSize = TD->getTypeStoreSize(ETy);
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001491 O << " .b8 " << *getSymbol(GVar) << "[";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001492 if (ElementSize) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001493 O << itostr(ElementSize);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001494 }
1495 O << "]";
1496 break;
1497 default:
Craig Topper2a30d782014-06-18 05:05:13 +00001498 llvm_unreachable("type not supported yet");
Justin Holewinskiae556d32012-05-04 20:18:50 +00001499 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001500 return;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001501}
1502
Justin Holewinski0497ab12013-03-30 14:29:21 +00001503static unsigned int getOpenCLAlignment(const DataLayout *TD, Type *Ty) {
Rafael Espindola08013342013-12-07 19:34:20 +00001504 if (Ty->isSingleValueType())
Justin Holewinskiae556d32012-05-04 20:18:50 +00001505 return TD->getPrefTypeAlignment(Ty);
1506
1507 const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
1508 if (ATy)
1509 return getOpenCLAlignment(TD, ATy->getElementType());
1510
1511 const VectorType *VTy = dyn_cast<VectorType>(Ty);
1512 if (VTy) {
1513 Type *ETy = VTy->getElementType();
1514 unsigned int numE = VTy->getNumElements();
1515 unsigned int alignE = TD->getPrefTypeAlignment(ETy);
1516 if (numE == 3)
Justin Holewinski0497ab12013-03-30 14:29:21 +00001517 return 4 * alignE;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001518 else
Justin Holewinski0497ab12013-03-30 14:29:21 +00001519 return numE * alignE;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001520 }
1521
1522 const StructType *STy = dyn_cast<StructType>(Ty);
1523 if (STy) {
1524 unsigned int alignStruct = 1;
1525 // Go through each element of the struct and find the
1526 // largest alignment.
Justin Holewinski0497ab12013-03-30 14:29:21 +00001527 for (unsigned i = 0, e = STy->getNumElements(); i != e; i++) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001528 Type *ETy = STy->getElementType(i);
1529 unsigned int align = getOpenCLAlignment(TD, ETy);
1530 if (align > alignStruct)
1531 alignStruct = align;
1532 }
1533 return alignStruct;
1534 }
1535
1536 const FunctionType *FTy = dyn_cast<FunctionType>(Ty);
1537 if (FTy)
Chandler Carruth5da3f052012-11-01 09:14:31 +00001538 return TD->getPointerPrefAlignment();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001539 return TD->getPrefTypeAlignment(Ty);
1540}
1541
1542void NVPTXAsmPrinter::printParamName(Function::const_arg_iterator I,
1543 int paramIndex, raw_ostream &O) {
1544 if ((nvptxSubtarget.getDrvInterface() == NVPTX::NVCL) ||
1545 (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA))
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00001546 O << *getSymbol(I->getParent()) << "_param_" << paramIndex;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001547 else {
1548 std::string argName = I->getName();
1549 const char *p = argName.c_str();
1550 while (*p) {
1551 if (*p == '.')
1552 O << "_";
1553 else
1554 O << *p;
1555 p++;
1556 }
1557 }
1558}
1559
1560void NVPTXAsmPrinter::printParamName(int paramIndex, raw_ostream &O) {
1561 Function::const_arg_iterator I, E;
1562 int i = 0;
1563
1564 if ((nvptxSubtarget.getDrvInterface() == NVPTX::NVCL) ||
1565 (nvptxSubtarget.getDrvInterface() == NVPTX::CUDA)) {
1566 O << *CurrentFnSym << "_param_" << paramIndex;
1567 return;
1568 }
1569
1570 for (I = F->arg_begin(), E = F->arg_end(); I != E; ++I, i++) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001571 if (i == paramIndex) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001572 printParamName(I, paramIndex, O);
1573 return;
1574 }
1575 }
1576 llvm_unreachable("paramIndex out of bound");
1577}
1578
Justin Holewinski0497ab12013-03-30 14:29:21 +00001579void NVPTXAsmPrinter::emitFunctionParamList(const Function *F, raw_ostream &O) {
Eric Christopherd9134482014-08-04 21:25:23 +00001580 const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
Bill Wendlinge94d8432012-12-07 23:16:57 +00001581 const AttributeSet &PAL = F->getAttributes();
Eric Christopherd9134482014-08-04 21:25:23 +00001582 const TargetLowering *TLI = TM.getSubtargetImpl()->getTargetLowering();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001583 Function::const_arg_iterator I, E;
1584 unsigned paramIndex = 0;
1585 bool first = true;
1586 bool isKernelFunc = llvm::isKernelFunction(*F);
1587 bool isABI = (nvptxSubtarget.getSmVersion() >= 20);
1588 MVT thePointerTy = TLI->getPointerTy();
1589
1590 O << "(\n";
1591
1592 for (I = F->arg_begin(), E = F->arg_end(); I != E; ++I, paramIndex++) {
Justin Holewinskie9884092013-03-24 21:17:47 +00001593 Type *Ty = I->getType();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001594
1595 if (!first)
1596 O << ",\n";
1597
1598 first = false;
1599
1600 // Handle image/sampler parameters
Justin Holewinski30d56a72014-04-09 15:39:15 +00001601 if (isKernelFunction(*F)) {
1602 if (isSampler(*I) || isImage(*I)) {
1603 if (isImage(*I)) {
1604 std::string sname = I->getName();
1605 if (isImageWriteOnly(*I) || isImageReadWrite(*I)) {
1606 if (nvptxSubtarget.hasImageHandles())
1607 O << "\t.param .u64 .ptr .surfref ";
1608 else
1609 O << "\t.param .surfref ";
1610 O << *CurrentFnSym << "_param_" << paramIndex;
1611 }
1612 else { // Default image is read_only
1613 if (nvptxSubtarget.hasImageHandles())
1614 O << "\t.param .u64 .ptr .texref ";
1615 else
1616 O << "\t.param .texref ";
1617 O << *CurrentFnSym << "_param_" << paramIndex;
1618 }
1619 } else {
1620 if (nvptxSubtarget.hasImageHandles())
1621 O << "\t.param .u64 .ptr .samplerref ";
1622 else
1623 O << "\t.param .samplerref ";
1624 O << *CurrentFnSym << "_param_" << paramIndex;
1625 }
1626 continue;
1627 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001628 }
1629
Justin Holewinski0497ab12013-03-30 14:29:21 +00001630 if (PAL.hasAttribute(paramIndex + 1, Attribute::ByVal) == false) {
Gautam Chakrabarti2c283402014-01-28 18:35:29 +00001631 if (Ty->isAggregateType() || Ty->isVectorTy()) {
1632 // Just print .param .align <a> .b8 .param[size];
Justin Holewinskie9884092013-03-24 21:17:47 +00001633 // <a> = PAL.getparamalignment
1634 // size = typeallocsize of element type
Justin Holewinski0497ab12013-03-30 14:29:21 +00001635 unsigned align = PAL.getParamAlignment(paramIndex + 1);
Justin Holewinskie9884092013-03-24 21:17:47 +00001636 if (align == 0)
1637 align = TD->getABITypeAlignment(Ty);
1638
1639 unsigned sz = TD->getTypeAllocSize(Ty);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001640 O << "\t.param .align " << align << " .b8 ";
Justin Holewinskie9884092013-03-24 21:17:47 +00001641 printParamName(I, paramIndex, O);
1642 O << "[" << sz << "]";
1643
1644 continue;
1645 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001646 // Just a scalar
1647 const PointerType *PTy = dyn_cast<PointerType>(Ty);
1648 if (isKernelFunc) {
1649 if (PTy) {
1650 // Special handling for pointer arguments to kernel
1651 O << "\t.param .u" << thePointerTy.getSizeInBits() << " ";
1652
1653 if (nvptxSubtarget.getDrvInterface() != NVPTX::CUDA) {
1654 Type *ETy = PTy->getElementType();
1655 int addrSpace = PTy->getAddressSpace();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001656 switch (addrSpace) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001657 default:
1658 O << ".ptr ";
1659 break;
Justin Holewinskib96d1392013-06-10 13:29:47 +00001660 case llvm::ADDRESS_SPACE_CONST:
Justin Holewinskiae556d32012-05-04 20:18:50 +00001661 O << ".ptr .const ";
1662 break;
1663 case llvm::ADDRESS_SPACE_SHARED:
1664 O << ".ptr .shared ";
1665 break;
1666 case llvm::ADDRESS_SPACE_GLOBAL:
Justin Holewinskiae556d32012-05-04 20:18:50 +00001667 O << ".ptr .global ";
1668 break;
1669 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001670 O << ".align " << (int) getOpenCLAlignment(TD, ETy) << " ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001671 }
1672 printParamName(I, paramIndex, O);
1673 continue;
1674 }
1675
1676 // non-pointer scalar to kernel func
Justin Holewinski700b6fa2013-05-20 12:13:28 +00001677 O << "\t.param .";
1678 // Special case: predicate operands become .u8 types
1679 if (Ty->isIntegerTy(1))
1680 O << "u8";
1681 else
1682 O << getPTXFundamentalTypeStr(Ty);
1683 O << " ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001684 printParamName(I, paramIndex, O);
1685 continue;
1686 }
1687 // Non-kernel function, just print .param .b<size> for ABI
Alp Tokerf907b892013-12-05 05:44:44 +00001688 // and .reg .b<size> for non-ABI
Justin Holewinskiae556d32012-05-04 20:18:50 +00001689 unsigned sz = 0;
1690 if (isa<IntegerType>(Ty)) {
1691 sz = cast<IntegerType>(Ty)->getBitWidth();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001692 if (sz < 32)
1693 sz = 32;
1694 } else if (isa<PointerType>(Ty))
Justin Holewinskiae556d32012-05-04 20:18:50 +00001695 sz = thePointerTy.getSizeInBits();
1696 else
1697 sz = Ty->getPrimitiveSizeInBits();
1698 if (isABI)
1699 O << "\t.param .b" << sz << " ";
1700 else
1701 O << "\t.reg .b" << sz << " ";
1702 printParamName(I, paramIndex, O);
1703 continue;
1704 }
1705
1706 // param has byVal attribute. So should be a pointer
1707 const PointerType *PTy = dyn_cast<PointerType>(Ty);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001708 assert(PTy && "Param with byval attribute should be a pointer type");
Justin Holewinskiae556d32012-05-04 20:18:50 +00001709 Type *ETy = PTy->getElementType();
1710
1711 if (isABI || isKernelFunc) {
Gautam Chakrabarti2c283402014-01-28 18:35:29 +00001712 // Just print .param .align <a> .b8 .param[size];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001713 // <a> = PAL.getparamalignment
1714 // size = typeallocsize of element type
Justin Holewinski0497ab12013-03-30 14:29:21 +00001715 unsigned align = PAL.getParamAlignment(paramIndex + 1);
Justin Holewinski2dc9d072012-11-09 23:50:24 +00001716 if (align == 0)
1717 align = TD->getABITypeAlignment(ETy);
1718
Justin Holewinskiae556d32012-05-04 20:18:50 +00001719 unsigned sz = TD->getTypeAllocSize(ETy);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001720 O << "\t.param .align " << align << " .b8 ";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001721 printParamName(I, paramIndex, O);
1722 O << "[" << sz << "]";
1723 continue;
1724 } else {
1725 // Split the ETy into constituent parts and
1726 // print .param .b<size> <name> for each part.
1727 // Further, if a part is vector, print the above for
1728 // each vector element.
1729 SmallVector<EVT, 16> vtparts;
1730 ComputeValueVTs(*TLI, ETy, vtparts);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001731 for (unsigned i = 0, e = vtparts.size(); i != e; ++i) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001732 unsigned elems = 1;
1733 EVT elemtype = vtparts[i];
1734 if (vtparts[i].isVector()) {
1735 elems = vtparts[i].getVectorNumElements();
1736 elemtype = vtparts[i].getVectorElementType();
1737 }
1738
Justin Holewinski0497ab12013-03-30 14:29:21 +00001739 for (unsigned j = 0, je = elems; j != je; ++j) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001740 unsigned sz = elemtype.getSizeInBits();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001741 if (elemtype.isInteger() && (sz < 32))
1742 sz = 32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001743 O << "\t.reg .b" << sz << " ";
1744 printParamName(I, paramIndex, O);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001745 if (j < je - 1)
1746 O << ",\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001747 ++paramIndex;
1748 }
Justin Holewinski0497ab12013-03-30 14:29:21 +00001749 if (i < e - 1)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001750 O << ",\n";
1751 }
1752 --paramIndex;
1753 continue;
1754 }
1755 }
1756
1757 O << "\n)\n";
1758}
1759
1760void NVPTXAsmPrinter::emitFunctionParamList(const MachineFunction &MF,
1761 raw_ostream &O) {
1762 const Function *F = MF.getFunction();
1763 emitFunctionParamList(F, O);
1764}
1765
Justin Holewinski0497ab12013-03-30 14:29:21 +00001766void NVPTXAsmPrinter::setAndEmitFunctionVirtualRegisters(
1767 const MachineFunction &MF) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001768 SmallString<128> Str;
1769 raw_svector_ostream O(Str);
1770
1771 // Map the global virtual register number to a register class specific
1772 // virtual register number starting from 1 with that class.
Eric Christopherfc6de422014-08-05 02:39:49 +00001773 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001774 //unsigned numRegClasses = TRI->getNumRegClasses();
1775
1776 // Emit the Fake Stack Object
1777 const MachineFrameInfo *MFI = MF.getFrameInfo();
1778 int NumBytes = (int) MFI->getStackSize();
1779 if (NumBytes) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001780 O << "\t.local .align " << MFI->getMaxAlignment() << " .b8 \t" << DEPOTNAME
1781 << getFunctionNumber() << "[" << NumBytes << "];\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001782 if (nvptxSubtarget.is64Bit()) {
1783 O << "\t.reg .b64 \t%SP;\n";
1784 O << "\t.reg .b64 \t%SPL;\n";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001785 } else {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001786 O << "\t.reg .b32 \t%SP;\n";
1787 O << "\t.reg .b32 \t%SPL;\n";
1788 }
1789 }
1790
1791 // Go through all virtual registers to establish the mapping between the
1792 // global virtual
1793 // register number and the per class virtual register number.
1794 // We use the per class virtual register number in the ptx output.
1795 unsigned int numVRs = MRI->getNumVirtRegs();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001796 for (unsigned i = 0; i < numVRs; i++) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001797 unsigned int vr = TRI->index2VirtReg(i);
1798 const TargetRegisterClass *RC = MRI->getRegClass(vr);
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00001799 DenseMap<unsigned, unsigned> &regmap = VRegMapping[RC];
Justin Holewinskiae556d32012-05-04 20:18:50 +00001800 int n = regmap.size();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001801 regmap.insert(std::make_pair(vr, n + 1));
Justin Holewinskiae556d32012-05-04 20:18:50 +00001802 }
1803
1804 // Emit register declarations
1805 // @TODO: Extract out the real register usage
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00001806 // O << "\t.reg .pred %p<" << NVPTXNumRegisters << ">;\n";
1807 // O << "\t.reg .s16 %rc<" << NVPTXNumRegisters << ">;\n";
1808 // O << "\t.reg .s16 %rs<" << NVPTXNumRegisters << ">;\n";
1809 // O << "\t.reg .s32 %r<" << NVPTXNumRegisters << ">;\n";
Justin Holewinski3e037d92014-07-16 16:26:58 +00001810 // O << "\t.reg .s64 %rd<" << NVPTXNumRegisters << ">;\n";
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00001811 // O << "\t.reg .f32 %f<" << NVPTXNumRegisters << ">;\n";
Justin Holewinski3e037d92014-07-16 16:26:58 +00001812 // O << "\t.reg .f64 %fd<" << NVPTXNumRegisters << ">;\n";
Justin Holewinskiae556d32012-05-04 20:18:50 +00001813
1814 // Emit declaration of the virtual registers or 'physical' registers for
1815 // each register class
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00001816 for (unsigned i=0; i< TRI->getNumRegClasses(); i++) {
1817 const TargetRegisterClass *RC = TRI->getRegClass(i);
1818 DenseMap<unsigned, unsigned> &regmap = VRegMapping[RC];
1819 std::string rcname = getNVPTXRegClassName(RC);
1820 std::string rcStr = getNVPTXRegClassStr(RC);
1821 int n = regmap.size();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001822
Justin Holewinskidbb3b2f2013-05-31 12:14:49 +00001823 // Only declare those registers that may be used.
1824 if (n) {
1825 O << "\t.reg " << rcname << " \t" << rcStr << "<" << (n+1)
1826 << ">;\n";
1827 }
1828 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001829
1830 OutStreamer.EmitRawText(O.str());
1831}
1832
Justin Holewinskiae556d32012-05-04 20:18:50 +00001833void NVPTXAsmPrinter::printFPConstant(const ConstantFP *Fp, raw_ostream &O) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001834 APFloat APF = APFloat(Fp->getValueAPF()); // make a copy
Justin Holewinskiae556d32012-05-04 20:18:50 +00001835 bool ignored;
1836 unsigned int numHex;
1837 const char *lead;
1838
Justin Holewinski0497ab12013-03-30 14:29:21 +00001839 if (Fp->getType()->getTypeID() == Type::FloatTyID) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001840 numHex = 8;
1841 lead = "0f";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001842 APF.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &ignored);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001843 } else if (Fp->getType()->getTypeID() == Type::DoubleTyID) {
1844 numHex = 16;
1845 lead = "0d";
Justin Holewinski0497ab12013-03-30 14:29:21 +00001846 APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored);
Justin Holewinskiae556d32012-05-04 20:18:50 +00001847 } else
1848 llvm_unreachable("unsupported fp type");
1849
1850 APInt API = APF.bitcastToAPInt();
1851 std::string hexstr(utohexstr(API.getZExtValue()));
1852 O << lead;
1853 if (hexstr.length() < numHex)
1854 O << std::string(numHex - hexstr.length(), '0');
1855 O << utohexstr(API.getZExtValue());
1856}
1857
Justin Holewinski01f89f02013-05-20 12:13:32 +00001858void NVPTXAsmPrinter::printScalarConstant(const Constant *CPV, raw_ostream &O) {
1859 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001860 O << CI->getValue();
1861 return;
1862 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00001863 if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001864 printFPConstant(CFP, O);
1865 return;
1866 }
1867 if (isa<ConstantPointerNull>(CPV)) {
1868 O << "0";
1869 return;
1870 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00001871 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
Justin Holewinski9d852a82014-04-09 15:39:11 +00001872 PointerType *PTy = dyn_cast<PointerType>(GVar->getType());
1873 bool IsNonGenericPointer = false;
1874 if (PTy && PTy->getAddressSpace() != 0) {
1875 IsNonGenericPointer = true;
1876 }
1877 if (EmitGeneric && !isa<Function>(CPV) && !IsNonGenericPointer) {
1878 O << "generic(";
1879 O << *getSymbol(GVar);
1880 O << ")";
1881 } else {
1882 O << *getSymbol(GVar);
1883 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001884 return;
1885 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00001886 if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1887 const Value *v = Cexpr->stripPointerCasts();
Justin Holewinski9d852a82014-04-09 15:39:11 +00001888 PointerType *PTy = dyn_cast<PointerType>(Cexpr->getType());
1889 bool IsNonGenericPointer = false;
1890 if (PTy && PTy->getAddressSpace() != 0) {
1891 IsNonGenericPointer = true;
1892 }
Justin Holewinski01f89f02013-05-20 12:13:32 +00001893 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(v)) {
Justin Holewinski9d852a82014-04-09 15:39:11 +00001894 if (EmitGeneric && !isa<Function>(v) && !IsNonGenericPointer) {
1895 O << "generic(";
1896 O << *getSymbol(GVar);
1897 O << ")";
1898 } else {
1899 O << *getSymbol(GVar);
1900 }
Justin Holewinskiae556d32012-05-04 20:18:50 +00001901 return;
1902 } else {
1903 O << *LowerConstant(CPV, *this);
1904 return;
1905 }
1906 }
1907 llvm_unreachable("Not scalar type found in printScalarConstant()");
1908}
1909
Justin Holewinski01f89f02013-05-20 12:13:32 +00001910void NVPTXAsmPrinter::bufferLEByte(const Constant *CPV, int Bytes,
Justin Holewinskiae556d32012-05-04 20:18:50 +00001911 AggBuffer *aggBuffer) {
1912
Eric Christopherd9134482014-08-04 21:25:23 +00001913 const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001914
1915 if (isa<UndefValue>(CPV) || CPV->isNullValue()) {
1916 int s = TD->getTypeAllocSize(CPV->getType());
Justin Holewinski0497ab12013-03-30 14:29:21 +00001917 if (s < Bytes)
Justin Holewinskiae556d32012-05-04 20:18:50 +00001918 s = Bytes;
1919 aggBuffer->addZeros(s);
1920 return;
1921 }
1922
1923 unsigned char *ptr;
1924 switch (CPV->getType()->getTypeID()) {
1925
1926 case Type::IntegerTyID: {
1927 const Type *ETy = CPV->getType();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001928 if (ETy == Type::getInt8Ty(CPV->getContext())) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001929 unsigned char c =
1930 (unsigned char)(dyn_cast<ConstantInt>(CPV))->getZExtValue();
1931 ptr = &c;
1932 aggBuffer->addBytes(ptr, 1, Bytes);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001933 } else if (ETy == Type::getInt16Ty(CPV->getContext())) {
1934 short int16 = (short)(dyn_cast<ConstantInt>(CPV))->getZExtValue();
1935 ptr = (unsigned char *)&int16;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001936 aggBuffer->addBytes(ptr, 2, Bytes);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001937 } else if (ETy == Type::getInt32Ty(CPV->getContext())) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001938 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(CPV)) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001939 int int32 = (int)(constInt->getZExtValue());
1940 ptr = (unsigned char *)&int32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001941 aggBuffer->addBytes(ptr, 4, Bytes);
1942 break;
Justin Holewinski01f89f02013-05-20 12:13:32 +00001943 } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1944 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
Justin Holewinski0497ab12013-03-30 14:29:21 +00001945 ConstantFoldConstantExpression(Cexpr, TD))) {
1946 int int32 = (int)(constInt->getZExtValue());
1947 ptr = (unsigned char *)&int32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001948 aggBuffer->addBytes(ptr, 4, Bytes);
1949 break;
1950 }
1951 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
1952 Value *v = Cexpr->getOperand(0)->stripPointerCasts();
1953 aggBuffer->addSymbol(v);
1954 aggBuffer->addZeros(4);
1955 break;
1956 }
1957 }
Craig Topperbdf39a42012-05-24 07:02:50 +00001958 llvm_unreachable("unsupported integer const type");
Justin Holewinski0497ab12013-03-30 14:29:21 +00001959 } else if (ETy == Type::getInt64Ty(CPV->getContext())) {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001960 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(CPV)) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001961 long long int64 = (long long)(constInt->getZExtValue());
1962 ptr = (unsigned char *)&int64;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001963 aggBuffer->addBytes(ptr, 8, Bytes);
1964 break;
Justin Holewinski01f89f02013-05-20 12:13:32 +00001965 } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
1966 if (const ConstantInt *constInt = dyn_cast<ConstantInt>(
Justin Holewinski0497ab12013-03-30 14:29:21 +00001967 ConstantFoldConstantExpression(Cexpr, TD))) {
1968 long long int64 = (long long)(constInt->getZExtValue());
1969 ptr = (unsigned char *)&int64;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001970 aggBuffer->addBytes(ptr, 8, Bytes);
1971 break;
1972 }
1973 if (Cexpr->getOpcode() == Instruction::PtrToInt) {
1974 Value *v = Cexpr->getOperand(0)->stripPointerCasts();
1975 aggBuffer->addSymbol(v);
1976 aggBuffer->addZeros(8);
1977 break;
1978 }
1979 }
1980 llvm_unreachable("unsupported integer const type");
Craig Topperbdf39a42012-05-24 07:02:50 +00001981 } else
Justin Holewinskiae556d32012-05-04 20:18:50 +00001982 llvm_unreachable("unsupported integer const type");
1983 break;
1984 }
1985 case Type::FloatTyID:
1986 case Type::DoubleTyID: {
Justin Holewinski01f89f02013-05-20 12:13:32 +00001987 const ConstantFP *CFP = dyn_cast<ConstantFP>(CPV);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001988 const Type *Ty = CFP->getType();
Justin Holewinskiae556d32012-05-04 20:18:50 +00001989 if (Ty == Type::getFloatTy(CPV->getContext())) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00001990 float float32 = (float) CFP->getValueAPF().convertToFloat();
1991 ptr = (unsigned char *)&float32;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001992 aggBuffer->addBytes(ptr, 4, Bytes);
1993 } else if (Ty == Type::getDoubleTy(CPV->getContext())) {
1994 double float64 = CFP->getValueAPF().convertToDouble();
Justin Holewinski0497ab12013-03-30 14:29:21 +00001995 ptr = (unsigned char *)&float64;
Justin Holewinskiae556d32012-05-04 20:18:50 +00001996 aggBuffer->addBytes(ptr, 8, Bytes);
Justin Holewinski0497ab12013-03-30 14:29:21 +00001997 } else {
Justin Holewinskiae556d32012-05-04 20:18:50 +00001998 llvm_unreachable("unsupported fp const type");
1999 }
2000 break;
2001 }
2002 case Type::PointerTyID: {
Justin Holewinski01f89f02013-05-20 12:13:32 +00002003 if (const GlobalValue *GVar = dyn_cast<GlobalValue>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002004 aggBuffer->addSymbol(GVar);
Justin Holewinski01f89f02013-05-20 12:13:32 +00002005 } else if (const ConstantExpr *Cexpr = dyn_cast<ConstantExpr>(CPV)) {
2006 const Value *v = Cexpr->stripPointerCasts();
Justin Holewinskiae556d32012-05-04 20:18:50 +00002007 aggBuffer->addSymbol(v);
2008 }
2009 unsigned int s = TD->getTypeAllocSize(CPV->getType());
2010 aggBuffer->addZeros(s);
2011 break;
2012 }
2013
2014 case Type::ArrayTyID:
2015 case Type::VectorTyID:
2016 case Type::StructTyID: {
2017 if (isa<ConstantArray>(CPV) || isa<ConstantVector>(CPV) ||
Justin Holewinski95564bd2013-09-19 12:51:46 +00002018 isa<ConstantStruct>(CPV) || isa<ConstantDataSequential>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002019 int ElementSize = TD->getTypeAllocSize(CPV->getType());
2020 bufferAggregateConstant(CPV, aggBuffer);
Justin Holewinski0497ab12013-03-30 14:29:21 +00002021 if (Bytes > ElementSize)
2022 aggBuffer->addZeros(Bytes - ElementSize);
2023 } else if (isa<ConstantAggregateZero>(CPV))
Justin Holewinskiae556d32012-05-04 20:18:50 +00002024 aggBuffer->addZeros(Bytes);
2025 else
2026 llvm_unreachable("Unexpected Constant type");
2027 break;
2028 }
2029
2030 default:
2031 llvm_unreachable("unsupported type");
2032 }
2033}
2034
Justin Holewinski01f89f02013-05-20 12:13:32 +00002035void NVPTXAsmPrinter::bufferAggregateConstant(const Constant *CPV,
Justin Holewinskiae556d32012-05-04 20:18:50 +00002036 AggBuffer *aggBuffer) {
Eric Christopherd9134482014-08-04 21:25:23 +00002037 const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
Justin Holewinskiae556d32012-05-04 20:18:50 +00002038 int Bytes;
2039
2040 // Old constants
2041 if (isa<ConstantArray>(CPV) || isa<ConstantVector>(CPV)) {
2042 if (CPV->getNumOperands())
2043 for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i)
2044 bufferLEByte(cast<Constant>(CPV->getOperand(i)), 0, aggBuffer);
2045 return;
2046 }
2047
2048 if (const ConstantDataSequential *CDS =
Justin Holewinski0497ab12013-03-30 14:29:21 +00002049 dyn_cast<ConstantDataSequential>(CPV)) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002050 if (CDS->getNumElements())
2051 for (unsigned i = 0; i < CDS->getNumElements(); ++i)
2052 bufferLEByte(cast<Constant>(CDS->getElementAsConstant(i)), 0,
2053 aggBuffer);
2054 return;
2055 }
2056
Justin Holewinskiae556d32012-05-04 20:18:50 +00002057 if (isa<ConstantStruct>(CPV)) {
2058 if (CPV->getNumOperands()) {
2059 StructType *ST = cast<StructType>(CPV->getType());
2060 for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002061 if (i == (e - 1))
Justin Holewinskiae556d32012-05-04 20:18:50 +00002062 Bytes = TD->getStructLayout(ST)->getElementOffset(0) +
Justin Holewinski0497ab12013-03-30 14:29:21 +00002063 TD->getTypeAllocSize(ST) -
2064 TD->getStructLayout(ST)->getElementOffset(i);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002065 else
Justin Holewinski0497ab12013-03-30 14:29:21 +00002066 Bytes = TD->getStructLayout(ST)->getElementOffset(i + 1) -
2067 TD->getStructLayout(ST)->getElementOffset(i);
2068 bufferLEByte(cast<Constant>(CPV->getOperand(i)), Bytes, aggBuffer);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002069 }
2070 }
2071 return;
2072 }
Craig Topperbdf39a42012-05-24 07:02:50 +00002073 llvm_unreachable("unsupported constant type in printAggregateConstant()");
Justin Holewinskiae556d32012-05-04 20:18:50 +00002074}
2075
2076// buildTypeNameMap - Run through symbol table looking for type names.
2077//
2078
Justin Holewinskiae556d32012-05-04 20:18:50 +00002079bool NVPTXAsmPrinter::isImageType(const Type *Ty) {
2080
2081 std::map<const Type *, std::string>::iterator PI = TypeNameMap.find(Ty);
2082
Justin Holewinski0497ab12013-03-30 14:29:21 +00002083 if (PI != TypeNameMap.end() && (!PI->second.compare("struct._image1d_t") ||
2084 !PI->second.compare("struct._image2d_t") ||
2085 !PI->second.compare("struct._image3d_t")))
Justin Holewinskiae556d32012-05-04 20:18:50 +00002086 return true;
2087
2088 return false;
2089}
2090
Justin Holewinskiae556d32012-05-04 20:18:50 +00002091
Justin Holewinski0497ab12013-03-30 14:29:21 +00002092bool NVPTXAsmPrinter::ignoreLoc(const MachineInstr &MI) {
2093 switch (MI.getOpcode()) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002094 default:
2095 return false;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002096 case NVPTX::CallArgBeginInst:
2097 case NVPTX::CallArgEndInst0:
2098 case NVPTX::CallArgEndInst1:
2099 case NVPTX::CallArgF32:
2100 case NVPTX::CallArgF64:
2101 case NVPTX::CallArgI16:
2102 case NVPTX::CallArgI32:
2103 case NVPTX::CallArgI32imm:
2104 case NVPTX::CallArgI64:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002105 case NVPTX::CallArgParam:
2106 case NVPTX::CallVoidInst:
2107 case NVPTX::CallVoidInstReg:
2108 case NVPTX::Callseq_End:
Justin Holewinskiae556d32012-05-04 20:18:50 +00002109 case NVPTX::CallVoidInstReg64:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002110 case NVPTX::DeclareParamInst:
2111 case NVPTX::DeclareRetMemInst:
2112 case NVPTX::DeclareRetRegInst:
2113 case NVPTX::DeclareRetScalarInst:
2114 case NVPTX::DeclareScalarParamInst:
2115 case NVPTX::DeclareScalarRegInst:
2116 case NVPTX::StoreParamF32:
2117 case NVPTX::StoreParamF64:
2118 case NVPTX::StoreParamI16:
2119 case NVPTX::StoreParamI32:
2120 case NVPTX::StoreParamI64:
2121 case NVPTX::StoreParamI8:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002122 case NVPTX::StoreRetvalF32:
2123 case NVPTX::StoreRetvalF64:
2124 case NVPTX::StoreRetvalI16:
2125 case NVPTX::StoreRetvalI32:
2126 case NVPTX::StoreRetvalI64:
2127 case NVPTX::StoreRetvalI8:
2128 case NVPTX::LastCallArgF32:
2129 case NVPTX::LastCallArgF64:
2130 case NVPTX::LastCallArgI16:
2131 case NVPTX::LastCallArgI32:
2132 case NVPTX::LastCallArgI32imm:
2133 case NVPTX::LastCallArgI64:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002134 case NVPTX::LastCallArgParam:
2135 case NVPTX::LoadParamMemF32:
2136 case NVPTX::LoadParamMemF64:
2137 case NVPTX::LoadParamMemI16:
2138 case NVPTX::LoadParamMemI32:
2139 case NVPTX::LoadParamMemI64:
2140 case NVPTX::LoadParamMemI8:
Justin Holewinski0497ab12013-03-30 14:29:21 +00002141 case NVPTX::PrototypeInst:
2142 case NVPTX::DBG_VALUE:
Justin Holewinskiae556d32012-05-04 20:18:50 +00002143 return true;
2144 }
2145 return false;
2146}
2147
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002148/// PrintAsmOperand - Print out an operand for an inline asm expression.
2149///
2150bool NVPTXAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
2151 unsigned AsmVariant,
2152 const char *ExtraCode, raw_ostream &O) {
2153 if (ExtraCode && ExtraCode[0]) {
2154 if (ExtraCode[1] != 0)
2155 return true; // Unknown modifier.
2156
2157 switch (ExtraCode[0]) {
2158 default:
2159 // See if this is a generic print operand
2160 return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
2161 case 'r':
2162 break;
2163 }
2164 }
2165
2166 printOperand(MI, OpNo, O);
2167
2168 return false;
2169}
2170
2171bool NVPTXAsmPrinter::PrintAsmMemoryOperand(
2172 const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant,
2173 const char *ExtraCode, raw_ostream &O) {
2174 if (ExtraCode && ExtraCode[0])
2175 return true; // Unknown modifier
2176
2177 O << '[';
2178 printMemOperand(MI, OpNo, O);
2179 O << ']';
2180
2181 return false;
2182}
2183
2184void NVPTXAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
2185 raw_ostream &O, const char *Modifier) {
2186 const MachineOperand &MO = MI->getOperand(opNum);
2187 switch (MO.getType()) {
2188 case MachineOperand::MO_Register:
2189 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
2190 if (MO.getReg() == NVPTX::VRDepot)
2191 O << DEPOTNAME << getFunctionNumber();
2192 else
2193 O << NVPTXInstPrinter::getRegisterName(MO.getReg());
2194 } else {
Justin Holewinski660597d2013-10-11 12:39:36 +00002195 emitVirtualRegister(MO.getReg(), O);
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002196 }
2197 return;
2198
2199 case MachineOperand::MO_Immediate:
2200 if (!Modifier)
2201 O << MO.getImm();
2202 else if (strstr(Modifier, "vec") == Modifier)
2203 printVecModifiedImmediate(MO, Modifier, O);
2204 else
2205 llvm_unreachable(
2206 "Don't know how to handle modifier on immediate operand");
2207 return;
2208
2209 case MachineOperand::MO_FPImmediate:
2210 printFPConstant(MO.getFPImm(), O);
2211 break;
2212
2213 case MachineOperand::MO_GlobalAddress:
Eli Bendersky6a0ccfb2014-03-31 16:11:57 +00002214 O << *getSymbol(MO.getGlobal());
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002215 break;
2216
Justin Holewinskiaaa8b6e2013-08-24 01:17:23 +00002217 case MachineOperand::MO_MachineBasicBlock:
2218 O << *MO.getMBB()->getSymbol();
2219 return;
2220
2221 default:
2222 llvm_unreachable("Operand type not supported.");
2223 }
2224}
2225
2226void NVPTXAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
2227 raw_ostream &O, const char *Modifier) {
2228 printOperand(MI, opNum, O);
2229
2230 if (Modifier && !strcmp(Modifier, "add")) {
2231 O << ", ";
2232 printOperand(MI, opNum + 1, O);
2233 } else {
2234 if (MI->getOperand(opNum + 1).isImm() &&
2235 MI->getOperand(opNum + 1).getImm() == 0)
2236 return; // don't print ',0' or '+0'
2237 O << "+";
2238 printOperand(MI, opNum + 1, O);
2239 }
2240}
2241
2242
Justin Holewinskiae556d32012-05-04 20:18:50 +00002243// Force static initialization.
2244extern "C" void LLVMInitializeNVPTXBackendAsmPrinter() {
2245 RegisterAsmPrinter<NVPTXAsmPrinter> X(TheNVPTXTarget32);
2246 RegisterAsmPrinter<NVPTXAsmPrinter> Y(TheNVPTXTarget64);
2247}
2248
Justin Holewinskiae556d32012-05-04 20:18:50 +00002249void NVPTXAsmPrinter::emitSrcInText(StringRef filename, unsigned line) {
2250 std::stringstream temp;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002251 LineReader *reader = this->getReader(filename.str());
Justin Holewinskiae556d32012-05-04 20:18:50 +00002252 temp << "\n//";
2253 temp << filename.str();
2254 temp << ":";
2255 temp << line;
2256 temp << " ";
2257 temp << reader->readLine(line);
2258 temp << "\n";
2259 this->OutStreamer.EmitRawText(Twine(temp.str()));
2260}
2261
Justin Holewinskiae556d32012-05-04 20:18:50 +00002262LineReader *NVPTXAsmPrinter::getReader(std::string filename) {
Craig Topper062a2ba2014-04-25 05:30:21 +00002263 if (!reader) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002264 reader = new LineReader(filename);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002265 }
2266
2267 if (reader->fileName() != filename) {
2268 delete reader;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002269 reader = new LineReader(filename);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002270 }
2271
2272 return reader;
2273}
2274
Justin Holewinski0497ab12013-03-30 14:29:21 +00002275std::string LineReader::readLine(unsigned lineNum) {
Justin Holewinskiae556d32012-05-04 20:18:50 +00002276 if (lineNum < theCurLine) {
2277 theCurLine = 0;
Justin Holewinski0497ab12013-03-30 14:29:21 +00002278 fstr.seekg(0, std::ios::beg);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002279 }
2280 while (theCurLine < lineNum) {
Justin Holewinski0497ab12013-03-30 14:29:21 +00002281 fstr.getline(buff, 500);
Justin Holewinskiae556d32012-05-04 20:18:50 +00002282 theCurLine++;
2283 }
2284 return buff;
2285}
2286
2287// Force static initialization.
2288extern "C" void LLVMInitializeNVPTXAsmPrinter() {
2289 RegisterAsmPrinter<NVPTXAsmPrinter> X(TheNVPTXTarget32);
2290 RegisterAsmPrinter<NVPTXAsmPrinter> Y(TheNVPTXTarget64);
2291}